change in naming of SQL methods

added assert methods to note tree
This commit is contained in:
azivner 2017-12-23 11:02:38 -05:00
parent c07c18f08a
commit bd2a5f6d82
27 changed files with 139 additions and 85 deletions

View File

@ -17,7 +17,7 @@ module.exports = async () => {
const password = await question("Enter password: ");
const dataKey = await password_encryption.getDecryptedDataKey(password);
const protectedNotes = await sql.getResults("SELECT * FROM notes WHERE is_protected = 1");
const protectedNotes = await sql.getAll("SELECT * FROM notes WHERE is_protected = 1");
for (const note of protectedNotes) {
const decryptedTitle = data_encryption.decrypt(dataKey, note.note_title);
@ -30,7 +30,7 @@ module.exports = async () => {
await sql.execute("UPDATE notes SET note_title = ?, note_text = ? WHERE note_id = ?", [note.note_title, note.note_text, note.note_id]);
}
const protectedNotesHistory = await sql.getResults("SELECT * FROM notes_history WHERE is_protected = 1");
const protectedNotesHistory = await sql.getAll("SELECT * FROM notes_history WHERE is_protected = 1");
for (const noteHistory of protectedNotesHistory) {
const decryptedTitle = data_encryption.decrypt(dataKey, noteHistory.note_title);

View File

@ -15,6 +15,8 @@ const noteTree = (function() {
let noteIdToTitle = {};
function getNoteTreeId(parentNoteId, childNoteId) {
assertArguments(parentNoteId, childNoteId);
const key = parentNoteId + "-" + childNoteId;
// this can return undefined and client code should deal with it somehow
@ -23,6 +25,8 @@ const noteTree = (function() {
}
function getNoteTitle(noteId, parentNoteId = null) {
assertArguments(noteId);
let title = noteIdToTitle[noteId];
if (!title) {
@ -73,17 +77,23 @@ const noteTree = (function() {
}
function getNodesByNoteTreeId(noteTreeId) {
assertArguments(noteTreeId);
const noteTree = notesTreeMap[noteTreeId];
return getNodesByNoteId(noteTree.note_id).filter(node => node.data.note_tree_id === noteTreeId);
}
function getNodesByNoteId(noteId) {
assertArguments(noteId);
const list = getTree().getNodesByRef(noteId);
return list ? list : []; // if no nodes with this refKey are found, fancy tree returns null
}
function setPrefix(noteTreeId, prefix) {
assertArguments(noteTreeId);
notesTreeMap[noteTreeId].prefix = prefix;
getNodesByNoteTreeId(noteTreeId).map(node => {
@ -94,6 +104,8 @@ const noteTree = (function() {
}
function removeParentChildRelation(parentNoteId, childNoteId) {
assertArguments(parentNoteId, childNoteId);
const key = parentNoteId + "-" + childNoteId;
delete parentChildToNoteTreeId[key];
@ -103,6 +115,8 @@ const noteTree = (function() {
}
function setParentChildRelation(noteTreeId, parentNoteId, childNoteId) {
assertArguments(noteTreeId, parentNoteId, childNoteId);
const key = parentNoteId + "-" + childNoteId;
parentChildToNoteTreeId[key] = noteTreeId;
@ -121,6 +135,8 @@ const noteTree = (function() {
}
function prepareNoteTree(notes) {
assertArguments(notes);
parentToChildren = {};
childToParents = {};
notesTreeMap = {};
@ -139,6 +155,8 @@ const noteTree = (function() {
}
function getExtraClasses(note) {
assertArguments(note);
let extraClasses = '';
if (note.is_protected) {
@ -157,6 +175,8 @@ const noteTree = (function() {
}
function prepareNoteTreeInner(parentNoteId) {
assertArguments(parentNoteId);
const childNoteIds = parentToChildren[parentNoteId];
if (!childNoteIds) {
messaging.logError("No children for " + parentNoteId + ". This shouldn't happen.");
@ -199,6 +219,8 @@ const noteTree = (function() {
}
async function activateNode(notePath) {
assertArguments(notePath);
const runPath = getRunPath(notePath);
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
@ -225,6 +247,8 @@ const noteTree = (function() {
* path change) or other corruption, in that case this will try to get some other valid path to the correct note.
*/
function getRunPath(notePath) {
assertArguments(notePath);
const path = notePath.split("/").reverse();
path.push('root');
@ -251,6 +275,8 @@ const noteTree = (function() {
console.log(now(), "Did not find parent " + parentNoteId + " for child " + childNoteId);
if (parents.length > 0) {
console.log(now(), "Available parents:", parents);
const pathToRoot = getSomeNotePath(parents[0]).split("/").reverse();
for (const noteId of pathToRoot) {
@ -279,6 +305,8 @@ const noteTree = (function() {
}
function showParentList(noteId, node) {
assertArguments(noteId, node);
const parents = childToParents[noteId];
if (!parents) {
@ -313,6 +341,8 @@ const noteTree = (function() {
}
function getNotePathTitle(notePath) {
assertArguments(notePath);
const titlePath = [];
let parentNoteId = 'root';
@ -327,6 +357,8 @@ const noteTree = (function() {
}
function getSomeNotePath(noteId) {
assertArguments(noteId);
const path = [];
let cur = noteId;
@ -345,12 +377,16 @@ const noteTree = (function() {
}
async function setExpandedToServer(noteTreeId, isExpanded) {
assertArguments(noteTreeId);
const expandedNum = isExpanded ? 1 : 0;
await server.put('notes/' + noteTreeId + '/expanded/' + expandedNum);
}
function setCurrentNotePathToHash(node) {
assertArguments(node);
const currentNotePath = treeUtils.getNotePath(node);
const currentNoteTreeId = node.data.note_tree_id;
@ -360,6 +396,8 @@ const noteTree = (function() {
}
function initFancyTree(noteTree) {
assertArguments(noteTree);
const keybindings = {
"del": node => {
treeChanges.deleteNode(node);
@ -601,6 +639,8 @@ const noteTree = (function() {
}
function setNoteTitle(noteId, title) {
assertArguments(noteId);
noteIdToTitle[noteId] = title;
getNodesByNoteId(noteId).map(clone => treeUtils.setNodeTitleWithPrefix(clone));
@ -613,6 +653,8 @@ const noteTree = (function() {
}
async function createNote(node, parentNoteId, target, isProtected) {
assertArguments(node, parentNoteId, target);
// if isProtected isn't available (user didn't enter password yet), then note is created as unencrypted
// but this is quite weird since user doesn't see WHERE the note is being created so it shouldn't occur often
if (!isProtected || !protected_session.isProtectedSessionAvailable()) {

View File

@ -71,4 +71,16 @@ function now() {
function isElectron() {
return window && window.process && window.process.type;
}
function assertArguments() {
for (const i in arguments) {
assert(arguments[i], `argument ${i} should not be falsy. Argument list: ${arguments}`);
}
}
function assert(expr, message) {
if (!expr) {
throwError(message);
}
}

View File

@ -9,7 +9,7 @@ const auth = require('../../services/auth');
router.post('/cleanup-soft-deleted-items', auth.checkApiAuth, async (req, res, next) => {
await sql.doInTransaction(async () => {
const noteIdsToDelete = await sql.getFlattenedResults("SELECT note_id FROM notes WHERE is_deleted = 1");
const noteIdsToDelete = await sql.getFirstColumn("SELECT note_id FROM notes WHERE is_deleted = 1");
const noteIdsSql = noteIdsToDelete
.map(noteId => "'" + utils.sanitizeSql(noteId) + "'")
.join(', ');

View File

@ -8,13 +8,13 @@ const auth = require('../../services/auth');
router.get('', auth.checkApiAuth, async (req, res, next) => {
await deleteOld();
const result = await sql.getResults("SELECT * FROM event_log ORDER BY date_added DESC");
const result = await sql.getAll("SELECT * FROM event_log ORDER BY date_added DESC");
res.send(result);
});
async function deleteOld() {
const cutoffId = await sql.getSingleValue("SELECT id FROM event_log ORDER BY id DESC LIMIT 1000, 1");
const cutoffId = await sql.getFirstValue("SELECT id FROM event_log ORDER BY id DESC LIMIT 1000, 1");
if (cutoffId) {
await sql.doInTransaction(async () => {

View File

@ -25,7 +25,7 @@ router.get('/:noteId/to/:directory', auth.checkApiAuth, async (req, res, next) =
fs.mkdirSync(completeExportDir);
const noteTreeId = await sql.getSingleValue('SELECT note_tree_id FROM notes_tree WHERE note_id = ?', [noteId]);
const noteTreeId = await sql.getFirstValue('SELECT note_tree_id FROM notes_tree WHERE note_id = ?', [noteId]);
await exportNote(noteTreeId, completeExportDir);
@ -33,14 +33,14 @@ router.get('/:noteId/to/:directory', auth.checkApiAuth, async (req, res, next) =
});
async function exportNote(noteTreeId, dir) {
const noteTree = await sql.getSingleResult("SELECT * FROM notes_tree WHERE note_tree_id = ?", [noteTreeId]);
const note = await sql.getSingleResult("SELECT * FROM notes WHERE note_id = ?", [noteTree.note_id]);
const noteTree = await sql.getFirst("SELECT * FROM notes_tree WHERE note_tree_id = ?", [noteTreeId]);
const note = await sql.getFirst("SELECT * FROM notes WHERE note_id = ?", [noteTree.note_id]);
const pos = (noteTree.note_position + '').padStart(4, '0');
fs.writeFileSync(dir + '/' + pos + '-' + note.note_title + '.html', html.prettyPrint(note.note_text, {indent_size: 2}));
const children = await sql.getResults("SELECT * FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0", [note.note_id]);
const children = await sql.getAll("SELECT * FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0", [note.note_id]);
if (children.length > 0) {
const childrenDir = dir + '/' + pos + '-' + note.note_title;

View File

@ -21,7 +21,7 @@ router.get('/:directory/to/:parentNoteId', auth.checkApiAuth, async (req, res, n
});
async function importNotes(dir, parentNoteId) {
const parent = await sql.getSingleResult("SELECT * FROM notes WHERE note_id = ?", [parentNoteId]);
const parent = await sql.getFirst("SELECT * FROM notes WHERE note_id = ?", [parentNoteId]);
if (!parent) {
return;
@ -51,7 +51,7 @@ async function importNotes(dir, parentNoteId) {
noteTitle = match[2];
}
else {
let maxPos = await sql.getSingleValue("SELECT MAX(note_position) FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0", [parentNoteId]);
let maxPos = await sql.getFirstValue("SELECT MAX(note_position) FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0", [parentNoteId]);
if (maxPos) {
notePos = maxPos + 1;
}

View File

@ -10,7 +10,7 @@ const sync_table = require('../../services/sync_table');
router.get('/:noteId', auth.checkApiAuth, async (req, res, next) => {
const noteId = req.params.noteId;
const history = await sql.getResults("SELECT * FROM notes_history WHERE note_id = ? order by date_modified_to desc", [noteId]);
const history = await sql.getAll("SELECT * FROM notes_history WHERE note_id = ? order by date_modified_to desc", [noteId]);
const dataKey = protected_session.getDataKey(req);

View File

@ -12,7 +12,7 @@ const data_encryption = require('../../services/data_encryption');
router.get('/:noteId', auth.checkApiAuth, async (req, res, next) => {
const noteId = req.params.noteId;
const detail = await sql.getSingleResult("SELECT * FROM notes WHERE note_id = ?", [noteId]);
const detail = await sql.getFirst("SELECT * FROM notes WHERE note_id = ?", [noteId]);
if (!detail) {
log.info("Note " + noteId + " has not been found.");
@ -67,7 +67,7 @@ router.delete('/:noteTreeId', auth.checkApiAuth, async (req, res, next) => {
router.get('/', auth.checkApiAuth, async (req, res, next) => {
const search = '%' + req.query.search + '%';
const result = await sql.getResults("SELECT note_id FROM notes WHERE note_title liKE ? OR note_text LIKE ?", [search, search]);
const result = await sql.getAll("SELECT note_id FROM notes WHERE note_title liKE ? OR note_text LIKE ?", [search, search]);
const noteIdList = [];

View File

@ -12,7 +12,7 @@ router.put('/:noteTreeId/move-to/:parentNoteId', auth.checkApiAuth, async (req,
const parentNoteId = req.params.parentNoteId;
const sourceId = req.headers.source_id;
const maxNotePos = await sql.getSingleValue('SELECT MAX(note_position) FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0', [parentNoteId]);
const maxNotePos = await sql.getFirstValue('SELECT MAX(note_position) FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0', [parentNoteId]);
const newNotePos = maxNotePos === null ? 0 : maxNotePos + 1;
const now = utils.nowDate();
@ -32,7 +32,7 @@ router.put('/:noteTreeId/move-before/:beforeNoteTreeId', auth.checkApiAuth, asyn
const beforeNoteTreeId = req.params.beforeNoteTreeId;
const sourceId = req.headers.source_id;
const beforeNote = await sql.getSingleResult("SELECT * FROM notes_tree WHERE note_tree_id = ?", [beforeNoteTreeId]);
const beforeNote = await sql.getFirst("SELECT * FROM notes_tree WHERE note_tree_id = ?", [beforeNoteTreeId]);
if (beforeNote) {
await sql.doInTransaction(async () => {
@ -63,7 +63,7 @@ router.put('/:noteTreeId/move-after/:afterNoteTreeId', auth.checkApiAuth, async
const afterNoteTreeId = req.params.afterNoteTreeId;
const sourceId = req.headers.source_id;
const afterNote = await sql.getSingleResult("SELECT * FROM notes_tree WHERE note_tree_id = ?", [afterNoteTreeId]);
const afterNote = await sql.getFirst("SELECT * FROM notes_tree WHERE note_tree_id = ?", [afterNoteTreeId]);
if (afterNote) {
await sql.doInTransaction(async () => {
@ -93,7 +93,7 @@ router.put('/:childNoteId/clone-to/:parentNoteId', auth.checkApiAuth, async (req
const prefix = req.body.prefix;
const sourceId = req.headers.source_id;
const existing = await sql.getSingleValue('SELECT * FROM notes_tree WHERE note_id = ? AND parent_note_id = ?', [childNoteId, parentNoteId]);
const existing = await sql.getFirstValue('SELECT * FROM notes_tree WHERE note_id = ? AND parent_note_id = ?', [childNoteId, parentNoteId]);
if (existing && !existing.is_deleted) {
return res.send({
@ -109,7 +109,7 @@ router.put('/:childNoteId/clone-to/:parentNoteId', auth.checkApiAuth, async (req
});
}
const maxNotePos = await sql.getSingleValue('SELECT MAX(note_position) FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0', [parentNoteId]);
const maxNotePos = await sql.getFirstValue('SELECT MAX(note_position) FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0', [parentNoteId]);
const newNotePos = maxNotePos === null ? 0 : maxNotePos + 1;
await sql.doInTransaction(async () => {
@ -141,7 +141,7 @@ router.put('/:noteId/clone-after/:afterNoteTreeId', auth.checkApiAuth, async (re
const afterNoteTreeId = req.params.afterNoteTreeId;
const sourceId = req.headers.source_id;
const afterNote = await sql.getSingleResult("SELECT * FROM notes_tree WHERE note_tree_id = ?", [afterNoteTreeId]);
const afterNote = await sql.getFirst("SELECT * FROM notes_tree WHERE note_tree_id = ?", [afterNoteTreeId]);
if (!afterNote) {
return res.status(500).send("After note " + afterNoteTreeId + " doesn't exist.");
@ -154,7 +154,7 @@ router.put('/:noteId/clone-after/:afterNoteTreeId', auth.checkApiAuth, async (re
});
}
const existing = await sql.getSingleValue('SELECT * FROM notes_tree WHERE note_id = ? AND parent_note_id = ?', [noteId, afterNote.parent_note_id]);
const existing = await sql.getFirstValue('SELECT * FROM notes_tree WHERE note_id = ? AND parent_note_id = ?', [noteId, afterNote.parent_note_id]);
if (existing && !existing.is_deleted) {
return res.send({
@ -200,7 +200,7 @@ async function checkCycle(parentNoteId, childNoteId) {
return false;
}
const parentNoteIds = await sql.getFlattenedResults("SELECT DISTINCT parent_note_id FROM notes_tree WHERE note_id = ?", [parentNoteId]);
const parentNoteIds = await sql.getFirstColumn("SELECT DISTINCT parent_note_id FROM notes_tree WHERE note_id = ?", [parentNoteId]);
for (const pid of parentNoteIds) {
if (!await checkCycle(pid, childNoteId)) {

View File

@ -6,7 +6,7 @@ const sql = require('../../services/sql');
const auth = require('../../services/auth');
router.get('/', auth.checkApiAuth, async (req, res, next) => {
const recentChanges = await sql.getResults(
const recentChanges = await sql.getAll(
`SELECT
notes.is_deleted AS current_is_deleted,
notes.note_title AS current_note_title,

View File

@ -34,7 +34,7 @@ router.put('/:noteTreeId/:notePath', auth.checkApiAuth, async (req, res, next) =
});
async function getRecentNotes() {
return await sql.getResults(`
return await sql.getAll(`
SELECT
recent_notes.*
FROM

View File

@ -11,7 +11,7 @@ router.post('/execute', auth.checkApiAuth, async (req, res, next) => {
try {
res.send({
success: true,
rows: await sql.getResults(query)
rows: await sql.getAll(query)
});
}
catch (e) {

View File

@ -13,7 +13,7 @@ const content_hash = require('../../services/content_hash');
router.get('/check', auth.checkApiAuth, async (req, res, next) => {
res.send({
'hashes': await content_hash.getHashes(),
'max_sync_id': await sql.getSingleValue('SELECT MAX(id) FROM sync')
'max_sync_id': await sql.getFirstValue('SELECT MAX(id) FROM sync')
});
});
@ -47,27 +47,27 @@ router.post('/force-full-sync', auth.checkApiAuth, async (req, res, next) => {
router.get('/changed', auth.checkApiAuth, async (req, res, next) => {
const lastSyncId = parseInt(req.query.lastSyncId);
res.send(await sql.getResults("SELECT * FROM sync WHERE id > ?", [lastSyncId]));
res.send(await sql.getAll("SELECT * FROM sync WHERE id > ?", [lastSyncId]));
});
router.get('/notes/:noteId', auth.checkApiAuth, async (req, res, next) => {
const noteId = req.params.noteId;
res.send({
entity: await sql.getSingleResult("SELECT * FROM notes WHERE note_id = ?", [noteId])
entity: await sql.getFirst("SELECT * FROM notes WHERE note_id = ?", [noteId])
});
});
router.get('/notes_tree/:noteTreeId', auth.checkApiAuth, async (req, res, next) => {
const noteTreeId = req.params.noteTreeId;
res.send(await sql.getSingleResult("SELECT * FROM notes_tree WHERE note_tree_id = ?", [noteTreeId]));
res.send(await sql.getFirst("SELECT * FROM notes_tree WHERE note_tree_id = ?", [noteTreeId]));
});
router.get('/notes_history/:noteHistoryId', auth.checkApiAuth, async (req, res, next) => {
const noteHistoryId = req.params.noteHistoryId;
res.send(await sql.getSingleResult("SELECT * FROM notes_history WHERE note_history_id = ?", [noteHistoryId]));
res.send(await sql.getFirst("SELECT * FROM notes_history WHERE note_history_id = ?", [noteHistoryId]));
});
router.get('/options/:optName', auth.checkApiAuth, async (req, res, next) => {
@ -77,7 +77,7 @@ router.get('/options/:optName', auth.checkApiAuth, async (req, res, next) => {
res.send("This option can't be synced.");
}
else {
res.send(await sql.getSingleResult("SELECT * FROM options WHERE opt_name = ?", [optName]));
res.send(await sql.getFirst("SELECT * FROM options WHERE opt_name = ?", [optName]));
}
});
@ -93,7 +93,7 @@ router.get('/notes_reordering/:noteTreeParentId', auth.checkApiAuth, async (req,
router.get('/recent_notes/:noteTreeId', auth.checkApiAuth, async (req, res, next) => {
const noteTreeId = req.params.noteTreeId;
res.send(await sql.getSingleResult("SELECT * FROM recent_notes WHERE note_tree_id = ?", [noteTreeId]));
res.send(await sql.getFirst("SELECT * FROM recent_notes WHERE note_tree_id = ?", [noteTreeId]));
});
router.put('/notes', auth.checkApiAuth, async (req, res, next) => {

View File

@ -12,7 +12,7 @@ const notes = require('../../services/notes');
const sync_table = require('../../services/sync_table');
router.get('/', auth.checkApiAuth, async (req, res, next) => {
const notes = await sql.getResults("SELECT "
const notes = await sql.getAll("SELECT "
+ "notes_tree.*, "
+ "notes.note_title, "
+ "notes.is_protected "

View File

@ -9,7 +9,7 @@ const sql = require('../services/sql');
router.get('', auth.checkAuth, async (req, res, next) => {
res.render('index', {
sourceId: await source_id.generateSourceId(),
maxSyncIdAtLoad: await sql.getSingleValue("SELECT MAX(id) FROM sync")
maxSyncIdAtLoad: await sql.getFirstValue("SELECT MAX(id) FROM sync")
});
});

View File

@ -5,7 +5,7 @@ const log = require('./log');
const messaging = require('./messaging');
async function runCheck(query, errorText, errorList) {
const result = await sql.getFlattenedResults(query);
const result = await sql.getFirstColumn(query);
if (result.length > 0) {
const err = errorText + ": " + result;

View File

@ -16,7 +16,7 @@ async function getHashes() {
const optionsQuestionMarks = Array(options.SYNCED_OPTIONS.length).fill('?').join(',');
return {
notes: getHash(await sql.getResults(`SELECT
notes: getHash(await sql.getAll(`SELECT
note_id,
note_title,
note_text,
@ -26,7 +26,7 @@ async function getHashes() {
FROM notes
ORDER BY note_id`)),
notes_tree: getHash(await sql.getResults(`SELECT
notes_tree: getHash(await sql.getAll(`SELECT
note_tree_id,
note_id,
parent_note_id,
@ -37,7 +37,7 @@ async function getHashes() {
FROM notes_tree
ORDER BY note_tree_id`)),
notes_history: getHash(await sql.getResults(`SELECT
notes_history: getHash(await sql.getAll(`SELECT
note_history_id,
note_id,
note_title,
@ -47,7 +47,7 @@ async function getHashes() {
FROM notes_history
ORDER BY note_history_id`)),
recent_notes: getHash(await sql.getResults(`SELECT
recent_notes: getHash(await sql.getAll(`SELECT
note_tree_id,
note_path,
date_accessed,
@ -55,7 +55,7 @@ async function getHashes() {
FROM recent_notes
ORDER BY note_path`)),
options: getHash(await sql.getResults(`SELECT
options: getHash(await sql.getAll(`SELECT
opt_name,
opt_value
FROM options

View File

@ -62,11 +62,11 @@ async function sendMessageToAllClients(message) {
}
async function sendPing(client, lastSentSyncId) {
const syncData = await sql.getResults("SELECT * FROM sync WHERE id > ?", [lastSentSyncId]);
const syncData = await sql.getAll("SELECT * FROM sync WHERE id > ?", [lastSentSyncId]);
const lastSyncedPush = await options.getOption('last_synced_push');
const changesToPushCount = await sql.getSingleValue("SELECT COUNT(*) FROM sync WHERE id > ?", [lastSyncedPush]);
const changesToPushCount = await sql.getFirstValue("SELECT COUNT(*) FROM sync WHERE id > ?", [lastSyncedPush]);
await sendMessage(client, {
type: 'sync',

View File

@ -13,12 +13,12 @@ async function createNewNote(parentNoteId, note, sourceId) {
await sql.doInTransaction(async () => {
if (note.target === 'into') {
const maxNotePos = await sql.getSingleValue('SELECT MAX(note_position) FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0', [parentNoteId]);
const maxNotePos = await sql.getFirstValue('SELECT MAX(note_position) FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0', [parentNoteId]);
newNotePos = maxNotePos === null ? 0 : maxNotePos + 1;
}
else if (note.target === 'after') {
const afterNote = await sql.getSingleResult('SELECT note_position FROM notes_tree WHERE note_tree_id = ?', [note.target_note_tree_id]);
const afterNote = await sql.getFirst('SELECT note_position FROM notes_tree WHERE note_tree_id = ?', [note.target_note_tree_id]);
newNotePos = afterNote.note_position + 1;
@ -70,11 +70,11 @@ async function encryptNote(note, dataKey) {
}
async function protectNoteRecursively(noteId, dataKey, protect, sourceId) {
const note = await sql.getSingleResult("SELECT * FROM notes WHERE note_id = ?", [noteId]);
const note = await sql.getFirst("SELECT * FROM notes WHERE note_id = ?", [noteId]);
await protectNote(note, dataKey, protect, sourceId);
const children = await sql.getFlattenedResults("SELECT note_id FROM notes_tree WHERE parent_note_id = ?", [noteId]);
const children = await sql.getFirstColumn("SELECT note_id FROM notes_tree WHERE parent_note_id = ?", [noteId]);
for (const childNoteId of children) {
await protectNoteRecursively(childNoteId, dataKey, protect, sourceId);
@ -116,7 +116,7 @@ async function protectNote(note, dataKey, protect, sourceId) {
}
async function protectNoteHistory(noteId, dataKey, protect, sourceId) {
const historyToChange = await sql.getResults("SELECT * FROM notes_history WHERE note_id = ? AND is_protected != ?", [noteId, protect]);
const historyToChange = await sql.getAll("SELECT * FROM notes_history WHERE note_id = ? AND is_protected != ?", [noteId, protect]);
for (const history of historyToChange) {
if (protect) {
@ -149,14 +149,14 @@ async function updateNote(noteId, newNote, dataKey, sourceId) {
const historyCutoff = utils.dateStr(new Date(now.getTime() - historySnapshotTimeInterval * 1000));
const existingNoteHistoryId = await sql.getSingleValue(
const existingNoteHistoryId = await sql.getFirstValue(
"SELECT note_history_id FROM notes_history WHERE note_id = ? AND date_modified_to >= ?", [noteId, historyCutoff]);
await sql.doInTransaction(async () => {
const msSinceDateCreated = now.getTime() - utils.parseDate(newNote.detail.date_created).getTime();
if (!existingNoteHistoryId && msSinceDateCreated >= historySnapshotTimeInterval * 1000) {
const oldNote = await sql.getSingleResult("SELECT * FROM notes WHERE note_id = ?", [noteId]);
const oldNote = await sql.getFirst("SELECT * FROM notes WHERE note_id = ?", [noteId]);
if (oldNote.is_protected) {
decryptNote(oldNote, dataKey);
@ -197,15 +197,15 @@ async function deleteNote(noteTreeId, sourceId) {
await sql.execute("UPDATE notes_tree SET is_deleted = 1, date_modified = ? WHERE note_tree_id = ?", [now, noteTreeId]);
await sync_table.addNoteTreeSync(noteTreeId, sourceId);
const noteId = await sql.getSingleValue("SELECT note_id FROM notes_tree WHERE note_tree_id = ?", [noteTreeId]);
const noteId = await sql.getFirstValue("SELECT note_id FROM notes_tree WHERE note_tree_id = ?", [noteTreeId]);
const notDeletedNoteTreesCount = await sql.getSingleValue("SELECT COUNT(*) FROM notes_tree WHERE note_id = ? AND is_deleted = 0", [noteId]);
const notDeletedNoteTreesCount = await sql.getFirstValue("SELECT COUNT(*) FROM notes_tree WHERE note_id = ? AND is_deleted = 0", [noteId]);
if (!notDeletedNoteTreesCount) {
await sql.execute("UPDATE notes SET is_deleted = 1, date_modified = ? WHERE note_id = ?", [now, noteId]);
await sync_table.addNoteSync(noteId, sourceId);
const children = await sql.getResults("SELECT note_tree_id FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0", [noteId]);
const children = await sql.getAll("SELECT note_tree_id FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0", [noteId]);
for (const child of children) {
await deleteNote(child.note_tree_id, sourceId);

View File

@ -7,7 +7,7 @@ const SYNCED_OPTIONS = [ 'username', 'password_verification_hash', 'encrypted_da
'history_snapshot_time_interval' ];
async function getOption(optName) {
const row = await sql.getSingleResultOrNull("SELECT opt_value FROM options WHERE opt_name = ?", [optName]);
const row = await sql.getFirstOrNull("SELECT opt_value FROM options WHERE opt_name = ?", [optName]);
if (!row) {
throw new Error("Option " + optName + " doesn't exist");

View File

@ -20,7 +20,7 @@ async function generateSourceId() {
}
async function refreshSourceIds() {
allSourceIds = await sql.getFlattenedResults("SELECT source_id FROM source_ids ORDER BY date_created DESC");
allSourceIds = await sql.getFirstColumn("SELECT source_id FROM source_ids ORDER BY date_created DESC");
}
let allSourceIds = [];

View File

@ -24,7 +24,7 @@ const dbReady = new Promise((resolve, reject) => {
resolve(db);
};
const tableResults = await getResults("SELECT name FROM sqlite_master WHERE type='table' AND name='notes'");
const tableResults = await getAll("SELECT name FROM sqlite_master WHERE type='table' AND name='notes'");
if (tableResults.length !== 1) {
log.info("Connected to db, but schema doesn't exist. Initializing schema ...");
@ -62,7 +62,7 @@ const dbReady = new Promise((resolve, reject) => {
// the database
}
else {
const username = await getSingleValue("SELECT opt_value FROM options WHERE opt_name = 'username'");
const username = await getFirstValue("SELECT opt_value FROM options WHERE opt_name = 'username'");
if (!username) {
log.info("Login/password not initialized. DB not ready.");
@ -120,18 +120,18 @@ async function rollback() {
return await wrap(async db => db.run("ROLLBACK"));
}
async function getSingleResult(query, params = []) {
async function getFirst(query, params = []) {
return await wrap(async db => db.get(query, ...params));
}
async function getSingleResultOrNull(query, params = []) {
async function getFirstOrNull(query, params = []) {
const all = await wrap(async db => db.all(query, ...params));
return all.length > 0 ? all[0] : null;
}
async function getSingleValue(query, params = []) {
const row = await getSingleResultOrNull(query, params);
async function getFirstValue(query, params = []) {
const row = await getFirstOrNull(query, params);
if (!row) {
return null;
@ -140,13 +140,13 @@ async function getSingleValue(query, params = []) {
return row[Object.keys(row)[0]];
}
async function getResults(query, params = []) {
async function getAll(query, params = []) {
return await wrap(async db => db.all(query, ...params));
}
async function getMap(query, params = []) {
const map = {};
const results = await getResults(query, params);
const results = await getAll(query, params);
for (const row of results) {
const keys = Object.keys(row);
@ -157,9 +157,9 @@ async function getMap(query, params = []) {
return map;
}
async function getFlattenedResults(query, params = []) {
async function getFirstColumn(query, params = []) {
const list = [];
const result = await getResults(query, params);
const result = await getAll(query, params);
if (result.length === 0) {
return list;
@ -237,7 +237,7 @@ async function doInTransaction(func) {
}
async function isDbUpToDate() {
const dbVersion = parseInt(await getSingleValue("SELECT opt_value FROM options WHERE opt_name = 'db_version'"));
const dbVersion = parseInt(await getFirstValue("SELECT opt_value FROM options WHERE opt_name = 'db_version'"));
const upToDate = dbVersion >= app_info.db_version;
@ -252,12 +252,12 @@ module.exports = {
dbReady,
insert,
replace,
getSingleValue,
getSingleResult,
getSingleResultOrNull,
getResults,
getFirstValue,
getFirst,
getFirstOrNull,
getAll,
getMap,
getFlattenedResults,
getFirstColumn,
execute,
executeScript,
doInTransaction,

View File

@ -176,7 +176,7 @@ async function pushSync(syncContext) {
let lastSyncedPush = await getLastSyncedPush();
while (true) {
const sync = await sql.getSingleResultOrNull('SELECT * FROM sync WHERE id > ? LIMIT 1', [lastSyncedPush]);
const sync = await sql.getFirstOrNull('SELECT * FROM sync WHERE id > ? LIMIT 1', [lastSyncedPush]);
if (sync === null) {
// nothing to sync
@ -203,13 +203,13 @@ async function pushEntity(sync, syncContext) {
let entity;
if (sync.entity_name === 'notes') {
entity = await sql.getSingleResult('SELECT * FROM notes WHERE note_id = ?', [sync.entity_id]);
entity = await sql.getFirst('SELECT * FROM notes WHERE note_id = ?', [sync.entity_id]);
}
else if (sync.entity_name === 'notes_tree') {
entity = await sql.getSingleResult('SELECT * FROM notes_tree WHERE note_tree_id = ?', [sync.entity_id]);
entity = await sql.getFirst('SELECT * FROM notes_tree WHERE note_tree_id = ?', [sync.entity_id]);
}
else if (sync.entity_name === 'notes_history') {
entity = await sql.getSingleResult('SELECT * FROM notes_history WHERE note_history_id = ?', [sync.entity_id]);
entity = await sql.getFirst('SELECT * FROM notes_history WHERE note_history_id = ?', [sync.entity_id]);
}
else if (sync.entity_name === 'notes_reordering') {
entity = {
@ -218,10 +218,10 @@ async function pushEntity(sync, syncContext) {
};
}
else if (sync.entity_name === 'options') {
entity = await sql.getSingleResult('SELECT * FROM options WHERE opt_name = ?', [sync.entity_id]);
entity = await sql.getFirst('SELECT * FROM options WHERE opt_name = ?', [sync.entity_id]);
}
else if (sync.entity_name === 'recent_notes') {
entity = await sql.getSingleResult('SELECT * FROM recent_notes WHERE note_tree_id = ?', [sync.entity_id]);
entity = await sql.getFirst('SELECT * FROM recent_notes WHERE note_tree_id = ?', [sync.entity_id]);
}
else {
throw new Error(`Unrecognized entity type ${sync.entity_name} in sync #${sync.id}`);
@ -252,7 +252,7 @@ async function checkContentHash(syncContext) {
}
const lastSyncedPush = await getLastSyncedPush();
const notPushedSyncs = await sql.getSingleValue("SELECT COUNT(*) FROM sync WHERE id > ?", [lastSyncedPush]);
const notPushedSyncs = await sql.getFirstValue("SELECT COUNT(*) FROM sync WHERE id > ?", [lastSyncedPush]);
if (notPushedSyncs > 0) {
log.info("There's " + notPushedSyncs + " outstanding pushes, skipping content check.");

View File

@ -54,10 +54,10 @@ async function cleanupSyncRowsForMissingEntities(entityName, entityKey) {
async function fillSyncRows(entityName, entityKey) {
await cleanupSyncRowsForMissingEntities(entityName, entityKey);
const entityIds = await sql.getFlattenedResults(`SELECT ${entityKey} FROM ${entityName}`);
const entityIds = await sql.getFirstColumn(`SELECT ${entityKey} FROM ${entityName}`);
for (const entityId of entityIds) {
const existingRows = await sql.getSingleValue("SELECT COUNT(id) FROM sync WHERE entity_name = ? AND entity_id = ?", [entityName, entityId]);
const existingRows = await sql.getFirstValue("SELECT COUNT(id) FROM sync WHERE entity_name = ? AND entity_id = ?", [entityName, entityId]);
// we don't want to replace existing entities (which would effectively cause full resync)
if (existingRows === 0) {

View File

@ -6,7 +6,7 @@ const notes = require('./notes');
const sync_table = require('./sync_table');
async function updateNote(entity, sourceId) {
const origNote = await sql.getSingleResult("SELECT * FROM notes WHERE note_id = ?", [entity.note_id]);
const origNote = await sql.getFirst("SELECT * FROM notes WHERE note_id = ?", [entity.note_id]);
if (!origNote || origNote.date_modified <= entity.date_modified) {
await sql.doInTransaction(async () => {
@ -21,7 +21,7 @@ async function updateNote(entity, sourceId) {
}
async function updateNoteTree(entity, sourceId) {
const orig = await sql.getSingleResultOrNull("SELECT * FROM notes_tree WHERE note_tree_id = ?", [entity.note_tree_id]);
const orig = await sql.getFirstOrNull("SELECT * FROM notes_tree WHERE note_tree_id = ?", [entity.note_tree_id]);
await sql.doInTransaction(async () => {
if (orig === null || orig.date_modified < entity.date_modified) {
@ -37,7 +37,7 @@ async function updateNoteTree(entity, sourceId) {
}
async function updateNoteHistory(entity, sourceId) {
const orig = await sql.getSingleResultOrNull("SELECT * FROM notes_history WHERE note_history_id = ?", [entity.note_history_id]);
const orig = await sql.getFirstOrNull("SELECT * FROM notes_history WHERE note_history_id = ?", [entity.note_history_id]);
await sql.doInTransaction(async () => {
if (orig === null || orig.date_modified_to < entity.date_modified_to) {
@ -65,7 +65,7 @@ async function updateOptions(entity, sourceId) {
return;
}
const orig = await sql.getSingleResultOrNull("SELECT * FROM options WHERE opt_name = ?", [entity.opt_name]);
const orig = await sql.getFirstOrNull("SELECT * FROM options WHERE opt_name = ?", [entity.opt_name]);
await sql.doInTransaction(async () => {
if (orig === null || orig.date_modified < entity.date_modified) {
@ -79,7 +79,7 @@ async function updateOptions(entity, sourceId) {
}
async function updateRecentNotes(entity, sourceId) {
const orig = await sql.getSingleResultOrNull("SELECT * FROM recent_notes WHERE note_tree_id = ?", [entity.note_tree_id]);
const orig = await sql.getFirstOrNull("SELECT * FROM recent_notes WHERE note_tree_id = ?", [entity.note_tree_id]);
if (orig === null || orig.date_accessed < entity.date_accessed) {
await sql.doInTransaction(async () => {

View File

@ -249,7 +249,7 @@
<h4>Cleanup</h4>
<button id="cleanup-soft-deleted-items-button" class="btn btn-danger btn-sm">Permanently cleanup soft-deleted items</button>
<button id="cleanup-soft-deleted-items-button" class="btn btn-danger btn-sm">Permanently cleanup soft-deleted items</button> (should be executed in all synced instances)
<br/>
<br/>