converted most dynamic SQL queries into prepared statement to avoid excessive statement caching

This commit is contained in:
zadam 2020-06-20 23:24:34 +02:00
parent 969f31dde2
commit 5f699cc28c
6 changed files with 13 additions and 20 deletions

View file

@ -33,10 +33,12 @@ function getAutocomplete(req) {
function getRecentNotes(activeNoteId) {
let extraCondition = '';
const params = [activeNoteId];
const hoistedNoteId = optionService.getOption('hoistedNoteId');
if (hoistedNoteId !== 'root') {
extraCondition = `AND recent_notes.notePath LIKE '%${utils.sanitizeSql(hoistedNoteId)}%'`;
extraCondition = `AND recent_notes.notePath LIKE ?`;
params.push(hoistedNoteId + '%');
}
const recentNotes = repository.getEntities(`
@ -52,7 +54,7 @@ function getRecentNotes(activeNoteId) {
${extraCondition}
ORDER BY
utcDateCreated DESC
LIMIT 200`, [activeNoteId]);
LIMIT 200`, params);
return recentNotes.map(rn => {
const title = noteCacheService.getNoteTitleForPath(rn.notePath.split('/'));

View file

@ -119,21 +119,19 @@ function restoreNoteRevision(req) {
}
function getEditedNotesOnDate(req) {
const date = utils.sanitizeSql(req.params.date);
const notes = repository.getEntities(`
SELECT notes.*
FROM notes
WHERE noteId IN (
SELECT noteId FROM notes
WHERE notes.dateCreated LIKE '${date}%'
OR notes.dateModified LIKE '${date}%'
WHERE notes.dateCreated LIKE :date
OR notes.dateModified LIKE :date
UNION ALL
SELECT noteId FROM note_revisions
WHERE note_revisions.dateLastEdited LIKE '${date}%'
WHERE note_revisions.dateLastEdited LIKE :date
)
ORDER BY isDeleted
LIMIT 50`);
LIMIT 50`, {date: req.params.date + '%'});
for (const note of notes) {
const notePath = noteCacheService.getNotePath(note.noteId);

View file

@ -97,7 +97,7 @@ function getAttributeNames(type, nameLike) {
FROM attributes
WHERE isDeleted = 0
AND type = ?
AND name LIKE '%${utils.sanitizeSql(nameLike)}%'`, [type]);
AND name LIKE ?`, [type, '%' + nameLike + '%']);
for (const attr of BUILTIN_ATTRIBUTES) {
if (attr.type === type && attr.name.toLowerCase().includes(nameLike) && !names.includes(attr.name)) {

View file

@ -31,8 +31,6 @@ function periodBackup(optionName, fileName, periodInSeconds) {
}
}
const COPY_ATTEMPT_COUNT = 50;
async function copyFile(backupFile) {
const sql = require('./sql');
@ -78,7 +76,7 @@ async function anonymize() {
// on the other hand builtin/system attrs should not contain any sensitive info
const builtinAttrs = attributeService
.getBuiltinAttributeNames()
.map(name => "'" + utils.sanitizeSql(name) + "'").join(', ');
.map(name => "'" + name + "'").join(', ');
db.prepare(`UPDATE attributes SET name = 'name', value = 'value' WHERE type = 'label' AND name NOT IN(${builtinAttrs})`).run();
db.prepare(`UPDATE attributes SET name = 'name' WHERE type = 'relation' AND name NOT IN (${builtinAttrs})`).run();

View file

@ -127,7 +127,8 @@ function getManyRows(query, params) {
const questionMarks = curParams.map(() => ":param" + i++).join(",");
const curQuery = query.replace(/\?\?\?/g, questionMarks);
results = results.concat(getRows(curQuery, curParamsObj));
const subResults = dbConnection.prepare(curQuery).all(curParamsObj);
results = results.concat(subResults);
}
return results;
@ -200,7 +201,7 @@ function wrap(query, func) {
const milliseconds = Date.now() - startTimestamp;
if (milliseconds >= 100) {
if (milliseconds >= 20) {
if (query.includes("WITH RECURSIVE")) {
log.info(`Slow recursive query took ${milliseconds}ms.`);
}

View file

@ -50,11 +50,6 @@ function isEmptyOrWhitespace(str) {
return str === null || str.match(/^ *$/) !== null;
}
function sanitizeSql(str) {
// should be improved or usage eliminated
return str.replace(/'/g, "''");
}
function sanitizeSqlIdentifier(str) {
return str.replace(/[^A-Za-z0-9_]/g, "");
}
@ -286,7 +281,6 @@ module.exports = {
isElectron,
hash,
isEmptyOrWhitespace,
sanitizeSql,
sanitizeSqlIdentifier,
prepareSqlForLike,
stopWatch,