mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	share improvements/cleanup
This commit is contained in:
		@@ -43,7 +43,7 @@ body {
 | 
				
			|||||||
    padding: 20px;
 | 
					    padding: 20px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.type-image img {
 | 
					img {
 | 
				
			||||||
    max-width: 100%;
 | 
					    max-width: 100%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @module sql
 | 
					 * @module sql
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * TODO: some methods (like getValue()) could use raw rows
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const log = require('./log');
 | 
					const log = require('./log');
 | 
				
			||||||
@@ -89,13 +91,7 @@ function getRowOrNull(query, params = []) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getValue(query, params = []) {
 | 
					function getValue(query, params = []) {
 | 
				
			||||||
    const row = getRowOrNull(query, params);
 | 
					    return wrap(query, s => s.pluck().get(params));
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!row) {
 | 
					 | 
				
			||||||
        return null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return row[Object.keys(row)[0]];
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// smaller values can result in better performance due to better usage of statement cache
 | 
					// smaller values can result in better performance due to better usage of statement cache
 | 
				
			||||||
@@ -144,32 +140,17 @@ function iterateRows(query, params = []) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
function getMap(query, params = []) {
 | 
					function getMap(query, params = []) {
 | 
				
			||||||
    const map = {};
 | 
					    const map = {};
 | 
				
			||||||
    const results = getRows(query, params);
 | 
					    const results = getRawRows(query, params);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const row of results) {
 | 
					    for (const row of results) {
 | 
				
			||||||
        const keys = Object.keys(row);
 | 
					        map[row[0]] = row[1];
 | 
				
			||||||
 | 
					 | 
				
			||||||
        map[row[keys[0]]] = row[keys[1]];
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return map;
 | 
					    return map;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getColumn(query, params = []) {
 | 
					function getColumn(query, params = []) {
 | 
				
			||||||
    const list = [];
 | 
					    return wrap(query, s => s.pluck().all(params));
 | 
				
			||||||
    const result = getRows(query, params);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (result.length === 0) {
 | 
					 | 
				
			||||||
        return list;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const key = Object.keys(result[0])[0];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (const row of result) {
 | 
					 | 
				
			||||||
        list.push(row[key]);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return list;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function execute(query, params = []) {
 | 
					function execute(query, params = []) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,15 +34,28 @@ function load() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const noteIdStr = noteIds.map(noteId => `'${noteId}'`).join(",");
 | 
					    const noteIdStr = noteIds.map(noteId => `'${noteId}'`).join(",");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const row of sql.getRawRows(`SELECT noteId, title, type, mime, utcDateModified FROM notes WHERE isDeleted = 0 AND noteId IN (${noteIdStr})`)) {
 | 
					    const rawNoteRows = sql.getRawRows(`
 | 
				
			||||||
 | 
					        SELECT noteId, title, type, mime, utcDateModified 
 | 
				
			||||||
 | 
					        FROM notes 
 | 
				
			||||||
 | 
					        WHERE isDeleted = 0 
 | 
				
			||||||
 | 
					          AND noteId IN (${noteIdStr})`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const row of rawNoteRows) {
 | 
				
			||||||
        new Note(row);
 | 
					        new Note(row);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const row of sql.getRawRows(`SELECT branchId, noteId, parentNoteId, prefix, isExpanded, utcDateModified FROM branches WHERE isDeleted = 0 AND parentNoteId IN (${noteIdStr}) ORDER BY notePosition`)) {
 | 
					    const rawBranchRows = sql.getRawRows(`
 | 
				
			||||||
 | 
					        SELECT branchId, noteId, parentNoteId, prefix, isExpanded, utcDateModified 
 | 
				
			||||||
 | 
					        FROM branches 
 | 
				
			||||||
 | 
					        WHERE isDeleted = 0 
 | 
				
			||||||
 | 
					          AND parentNoteId IN (${noteIdStr}) 
 | 
				
			||||||
 | 
					        ORDER BY notePosition`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const row of rawBranchRows) {
 | 
				
			||||||
        new Branch(row);
 | 
					        new Branch(row);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const attributes = sql.getRawRows(`
 | 
					    const rawAttributeRows = sql.getRawRows(`
 | 
				
			||||||
        SELECT attributeId, noteId, type, name, value, isInheritable, position, utcDateModified 
 | 
					        SELECT attributeId, noteId, type, name, value, isInheritable, position, utcDateModified 
 | 
				
			||||||
        FROM attributes 
 | 
					        FROM attributes 
 | 
				
			||||||
        WHERE isDeleted = 0 
 | 
					        WHERE isDeleted = 0 
 | 
				
			||||||
@@ -52,13 +65,13 @@ function load() {
 | 
				
			|||||||
              OR (type = 'relation' AND name IN ('imageLink', 'template', 'shareCss'))
 | 
					              OR (type = 'relation' AND name IN ('imageLink', 'template', 'shareCss'))
 | 
				
			||||||
          )`, []);
 | 
					          )`, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const row of attributes) {
 | 
					    for (const row of rawAttributeRows) {
 | 
				
			||||||
        new Attribute(row);
 | 
					        new Attribute(row);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shaca.loaded = true;
 | 
					    shaca.loaded = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    log.info(`Shaca load took ${Date.now() - start}ms`);
 | 
					    log.info(`Shaca loaded ${rawNoteRows.length} notes, ${rawBranchRows.length} branches, ${rawAttributeRows.length} attributes took ${Date.now() - start}ms`);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function ensureLoad() {
 | 
					function ensureLoad() {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										143
									
								
								src/share/sql.js
									
									
									
									
									
								
							
							
						
						
									
										143
									
								
								src/share/sql.js
									
									
									
									
									
								
							@@ -1,6 +1,5 @@
 | 
				
			|||||||
"use strict";
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const log = require('../services/log');
 | 
					 | 
				
			||||||
const Database = require('better-sqlite3');
 | 
					const Database = require('better-sqlite3');
 | 
				
			||||||
const dataDir = require('../services/data_dir');
 | 
					const dataDir = require('../services/data_dir');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,152 +15,20 @@ const dbConnection = new Database(dataDir.DOCUMENT_PATH, { readonly: true });
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const statementCache = {};
 | 
					function getRawRows(query, params = []) {
 | 
				
			||||||
 | 
					    return dbConnection.prepare(query).raw().all(params);
 | 
				
			||||||
function stmt(sql) {
 | 
					 | 
				
			||||||
    if (!(sql in statementCache)) {
 | 
					 | 
				
			||||||
        statementCache[sql] = dbConnection.prepare(sql);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return statementCache[sql];
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getRow(query, params = []) {
 | 
					function getRow(query, params = []) {
 | 
				
			||||||
    return wrap(query, s => s.get(params));
 | 
					    return dbConnection.prepare(query).get(params);
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function getRowOrNull(query, params = []) {
 | 
					 | 
				
			||||||
    const all = getRows(query, params);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return all.length > 0 ? all[0] : null;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function getValue(query, params = []) {
 | 
					 | 
				
			||||||
    const row = getRowOrNull(query, params);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!row) {
 | 
					 | 
				
			||||||
        return null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return row[Object.keys(row)[0]];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// smaller values can result in better performance due to better usage of statement cache
 | 
					 | 
				
			||||||
const PARAM_LIMIT = 100;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function getManyRows(query, params) {
 | 
					 | 
				
			||||||
    let results = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while (params.length > 0) {
 | 
					 | 
				
			||||||
        const curParams = params.slice(0, Math.min(params.length, PARAM_LIMIT));
 | 
					 | 
				
			||||||
        params = params.slice(curParams.length);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const curParamsObj = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let j = 1;
 | 
					 | 
				
			||||||
        for (const param of curParams) {
 | 
					 | 
				
			||||||
            curParamsObj['param' + j++] = param;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let i = 1;
 | 
					 | 
				
			||||||
        const questionMarks = curParams.map(() => ":param" + i++).join(",");
 | 
					 | 
				
			||||||
        const curQuery = query.replace(/\?\?\?/g, questionMarks);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const statement = curParams.length === PARAM_LIMIT
 | 
					 | 
				
			||||||
            ? stmt(curQuery)
 | 
					 | 
				
			||||||
            : dbConnection.prepare(curQuery);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const subResults = statement.all(curParamsObj);
 | 
					 | 
				
			||||||
        results = results.concat(subResults);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return results;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function getRows(query, params = []) {
 | 
					 | 
				
			||||||
    return wrap(query, s => s.all(params));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function getRawRows(query, params = []) {
 | 
					 | 
				
			||||||
    return wrap(query, s => s.raw().all(params));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function iterateRows(query, params = []) {
 | 
					 | 
				
			||||||
    return stmt(query).iterate(params);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function getMap(query, params = []) {
 | 
					 | 
				
			||||||
    const map = {};
 | 
					 | 
				
			||||||
    const results = getRows(query, params);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (const row of results) {
 | 
					 | 
				
			||||||
        const keys = Object.keys(row);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        map[row[keys[0]]] = row[keys[1]];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return map;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getColumn(query, params = []) {
 | 
					function getColumn(query, params = []) {
 | 
				
			||||||
    const list = [];
 | 
					    return dbConnection.prepare(query).pluck().all(params);
 | 
				
			||||||
    const result = getRows(query, params);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (result.length === 0) {
 | 
					 | 
				
			||||||
        return list;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const key = Object.keys(result[0])[0];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (const row of result) {
 | 
					 | 
				
			||||||
        list.push(row[key]);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return list;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function wrap(query, func) {
 | 
					 | 
				
			||||||
    const startTimestamp = Date.now();
 | 
					 | 
				
			||||||
    let result;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        result = func(stmt(query));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    catch (e) {
 | 
					 | 
				
			||||||
        if (e.message.includes("The database connection is not open")) {
 | 
					 | 
				
			||||||
            // this often happens on killing the app which puts these alerts in front of user
 | 
					 | 
				
			||||||
            // in these cases error should be simply ignored.
 | 
					 | 
				
			||||||
            console.log(e.message);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return null
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        throw e;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const milliseconds = Date.now() - startTimestamp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (milliseconds >= 20) {
 | 
					 | 
				
			||||||
        if (query.includes("WITH RECURSIVE")) {
 | 
					 | 
				
			||||||
            log.info(`Slow recursive query took ${milliseconds}ms.`);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
            log.info(`Slow query took ${milliseconds}ms: ${query.trim().replace(/\s+/g, " ")}`);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return result;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
    dbConnection,
 | 
					 | 
				
			||||||
    getValue,
 | 
					 | 
				
			||||||
    getRow,
 | 
					 | 
				
			||||||
    getRowOrNull,
 | 
					 | 
				
			||||||
    getRows,
 | 
					 | 
				
			||||||
    getRawRows,
 | 
					    getRawRows,
 | 
				
			||||||
    iterateRows,
 | 
					    getRow,
 | 
				
			||||||
    getManyRows,
 | 
					 | 
				
			||||||
    getMap,
 | 
					 | 
				
			||||||
    getColumn
 | 
					    getColumn
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user