mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	converted most dynamic SQL queries into prepared statement to avoid excessive statement caching
This commit is contained in:
		| @@ -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('/')); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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)) { | ||||
|   | ||||
| @@ -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(); | ||||
|   | ||||
| @@ -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.`); | ||||
|         } | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user