From bd66b8a1c8d943a542b45a2aed9d8703fb17101d Mon Sep 17 00:00:00 2001 From: azivner Date: Wed, 30 May 2018 20:28:10 -0400 Subject: [PATCH] fix issue with limitation of number of SQLite parameters (999) which caused problems when loading tree which was too expanded --- src/routes/api/tree.js | 21 +++++++++------------ src/services/sql.js | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/routes/api/tree.js b/src/routes/api/tree.js index f1d0ac8d4..daeece1da 100644 --- a/src/routes/api/tree.js +++ b/src/routes/api/tree.js @@ -5,11 +5,9 @@ const optionService = require('../../services/options'); const protectedSessionService = require('../../services/protected_session'); async function getNotes(noteIds) { - const questionMarks = noteIds.map(() => "?").join(","); - - const notes = await sql.getRows(` + const notes = await sql.getManyRows(` SELECT noteId, title, isProtected, type, mime - FROM notes WHERE isDeleted = 0 AND noteId IN (${questionMarks})`, noteIds); + FROM notes WHERE isDeleted = 0 AND noteId IN (???)`, noteIds); protectedSessionService.decryptNotes(notes); @@ -18,11 +16,11 @@ async function getNotes(noteIds) { } async function getRelations(noteIds) { - const questionMarks = noteIds.map(() => "?").join(","); - const doubledNoteIds = noteIds.concat(noteIds); + // we need to fetch both parentNoteId and noteId matches because we can have loaded child + // of which only some of the parents has been loaded. - return await sql.getRows(`SELECT branchId, noteId AS 'childNoteId', parentNoteId FROM branches WHERE isDeleted = 0 - AND (parentNoteId IN (${questionMarks}) OR noteId IN (${questionMarks}))`, doubledNoteIds); + return await sql.getManyRows(`SELECT branchId, noteId AS 'childNoteId', parentNoteId FROM branches WHERE isDeleted = 0 + AND (parentNoteId IN (???) OR noteId IN (???))`, noteIds); } async function getTree() { @@ -58,12 +56,11 @@ async function load(req) { const branchIds = req.body.branchIds; if (branchIds && branchIds.length > 0) { - noteIds = await sql.getColumn(`SELECT noteId FROM branches WHERE isDeleted = 0 AND branchId IN(${branchIds.map(() => "?").join(",")})`, branchIds); + noteIds = (await sql.getColumn(`SELECT noteId FROM branches WHERE isDeleted = 0 AND branchId IN(???)`, branchIds)) + .map(note => note.noteId); } - const questionMarks = noteIds.map(() => "?").join(","); - - const branches = await sql.getRows(`SELECT * FROM branches WHERE isDeleted = 0 AND noteId IN (${questionMarks})`, noteIds); + const branches = await sql.getManyRows(`SELECT * FROM branches WHERE isDeleted = 0 AND noteId IN (???)`, noteIds); const notes = await getNotes(noteIds); diff --git a/src/services/sql.js b/src/services/sql.js index 465c8844d..da3e7827f 100644 --- a/src/services/sql.js +++ b/src/services/sql.js @@ -62,6 +62,26 @@ async function getValue(query, params = []) { return row[Object.keys(row)[0]]; } +const PARAM_LIMIT = 900; // actual limit is 999 + +// this is to overcome 999 limit of number of query parameters +async function getManyRows(query, params) { + let results = []; + + while (params.length > 0) { + const curParams = params.slice(0, Math.max(params.length, PARAM_LIMIT)); + params = params.slice(curParams.length); + + let i = 1; + const questionMarks = curParams.map(() => "?" + i++).join(","); + const curQuery = query.replace(/\?\?\?/g, questionMarks); + + results = results.concat(await getRows(curQuery, curParams)); + } + + return results; +} + async function getRows(query, params = []) { return await wrap(async db => db.all(query, ...params)); } @@ -179,6 +199,7 @@ module.exports = { getRow, getRowOrNull, getRows, + getManyRows, getMap, getColumn, execute,