mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
added hash columns for faster sync check calculation
This commit is contained in:
parent
9fa6c0918c
commit
49a53f7a45
9
db/migrations/0093__add_hash_field.sql
Normal file
9
db/migrations/0093__add_hash_field.sql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
ALTER TABLE notes ADD hash TEXT DEFAULT "" NOT NULL;
|
||||||
|
ALTER TABLE branches ADD hash TEXT DEFAULT "" NOT NULL;
|
||||||
|
ALTER TABLE note_revisions ADD hash TEXT DEFAULT "" NOT NULL;
|
||||||
|
ALTER TABLE recent_notes ADD hash TEXT DEFAULT "" NOT NULL;
|
||||||
|
ALTER TABLE options ADD hash TEXT DEFAULT "" NOT NULL;
|
||||||
|
ALTER TABLE note_images ADD hash TEXT DEFAULT "" NOT NULL;
|
||||||
|
ALTER TABLE images ADD hash TEXT DEFAULT "" NOT NULL;
|
||||||
|
ALTER TABLE labels ADD hash TEXT DEFAULT "" NOT NULL;
|
||||||
|
ALTER TABLE api_tokens ADD hash TEXT DEFAULT "" NOT NULL;
|
@ -6,6 +6,7 @@ const dateUtils = require('../services/date_utils');
|
|||||||
class ApiToken extends Entity {
|
class ApiToken extends Entity {
|
||||||
static get tableName() { return "api_tokens"; }
|
static get tableName() { return "api_tokens"; }
|
||||||
static get primaryKeyName() { return "apiTokenId"; }
|
static get primaryKeyName() { return "apiTokenId"; }
|
||||||
|
static get syncedProperties() { return ["apiTokenId", "token", "dateCreated", "isDeleted"]; }
|
||||||
|
|
||||||
beforeSaving() {
|
beforeSaving() {
|
||||||
super.beforeSaving();
|
super.beforeSaving();
|
||||||
|
@ -8,6 +8,7 @@ const sql = require('../services/sql');
|
|||||||
class Branch extends Entity {
|
class Branch extends Entity {
|
||||||
static get tableName() { return "branches"; }
|
static get tableName() { return "branches"; }
|
||||||
static get primaryKeyName() { return "branchId"; }
|
static get primaryKeyName() { return "branchId"; }
|
||||||
|
static get syncedProperties() { return ["branchId", "noteId", "parentNoteId", "notePosition", "dateModified", "isDeleted", "prefix"]; }
|
||||||
|
|
||||||
async getNote() {
|
async getNote() {
|
||||||
return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]);
|
return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]);
|
||||||
|
@ -14,6 +14,14 @@ class Entity {
|
|||||||
if (!this[this.constructor.primaryKeyName]) {
|
if (!this[this.constructor.primaryKeyName]) {
|
||||||
this[this.constructor.primaryKeyName] = utils.newEntityId();
|
this[this.constructor.primaryKeyName] = utils.newEntityId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let contentToHash = "";
|
||||||
|
|
||||||
|
for (const propertyName of this.constructor.syncedProperties) {
|
||||||
|
contentToHash += "|" + this[propertyName];
|
||||||
|
}
|
||||||
|
|
||||||
|
this["hash"] = utils.hash(contentToHash).substr(0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
async save() {
|
async save() {
|
||||||
|
@ -6,6 +6,7 @@ const dateUtils = require('../services/date_utils');
|
|||||||
class Image extends Entity {
|
class Image extends Entity {
|
||||||
static get tableName() { return "images"; }
|
static get tableName() { return "images"; }
|
||||||
static get primaryKeyName() { return "imageId"; }
|
static get primaryKeyName() { return "imageId"; }
|
||||||
|
static get syncedProperties() { return ["imageId", "format", "checksum", "name", "isDeleted", "dateModified", "dateCreated"]; }
|
||||||
|
|
||||||
beforeSaving() {
|
beforeSaving() {
|
||||||
super.beforeSaving();
|
super.beforeSaving();
|
||||||
|
@ -8,6 +8,7 @@ const sql = require('../services/sql');
|
|||||||
class Label extends Entity {
|
class Label extends Entity {
|
||||||
static get tableName() { return "labels"; }
|
static get tableName() { return "labels"; }
|
||||||
static get primaryKeyName() { return "labelId"; }
|
static get primaryKeyName() { return "labelId"; }
|
||||||
|
static get syncedProperties() { return ["labelId", "noteId", "name", "value", "dateModified", "dateCreated"]; }
|
||||||
|
|
||||||
async getNote() {
|
async getNote() {
|
||||||
return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]);
|
return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]);
|
||||||
|
@ -8,6 +8,7 @@ const dateUtils = require('../services/date_utils');
|
|||||||
class Note extends Entity {
|
class Note extends Entity {
|
||||||
static get tableName() { return "notes"; }
|
static get tableName() { return "notes"; }
|
||||||
static get primaryKeyName() { return "noteId"; }
|
static get primaryKeyName() { return "noteId"; }
|
||||||
|
static get syncedProperties() { return ["noteId", "title", "content", "type", "dateModified", "isProtected", "isDeleted"]; }
|
||||||
|
|
||||||
constructor(row) {
|
constructor(row) {
|
||||||
super(row);
|
super(row);
|
||||||
|
@ -7,6 +7,7 @@ const dateUtils = require('../services/date_utils');
|
|||||||
class NoteImage extends Entity {
|
class NoteImage extends Entity {
|
||||||
static get tableName() { return "note_images"; }
|
static get tableName() { return "note_images"; }
|
||||||
static get primaryKeyName() { return "noteImageId"; }
|
static get primaryKeyName() { return "noteImageId"; }
|
||||||
|
static get syncedProperties() { return ["noteImageId", "noteId", "imageId", "isDeleted", "dateModified", "dateCreated"]; }
|
||||||
|
|
||||||
async getNote() {
|
async getNote() {
|
||||||
return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]);
|
return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]);
|
||||||
|
@ -7,6 +7,7 @@ const repository = require('../services/repository');
|
|||||||
class NoteRevision extends Entity {
|
class NoteRevision extends Entity {
|
||||||
static get tableName() { return "note_revisions"; }
|
static get tableName() { return "note_revisions"; }
|
||||||
static get primaryKeyName() { return "noteRevisionId"; }
|
static get primaryKeyName() { return "noteRevisionId"; }
|
||||||
|
static get syncedProperties() { return ["noteRevisionId", "noteId", "title", "content", "dateModifiedFrom", "dateModifiedTo"]; }
|
||||||
|
|
||||||
constructor(row) {
|
constructor(row) {
|
||||||
super(row);
|
super(row);
|
||||||
|
11
src/entities/option.js
Normal file
11
src/entities/option.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
const Entity = require('./entity');
|
||||||
|
|
||||||
|
class Option extends Entity {
|
||||||
|
static get tableName() { return "options"; }
|
||||||
|
static get primaryKeyName() { return "name"; }
|
||||||
|
static get syncedProperties() { return ["name", "value"]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Option;
|
@ -5,6 +5,7 @@ const Entity = require('./entity');
|
|||||||
class RecentNote extends Entity {
|
class RecentNote extends Entity {
|
||||||
static get tableName() { return "recent_notes"; }
|
static get tableName() { return "recent_notes"; }
|
||||||
static get primaryKeyName() { return "branchId"; }
|
static get primaryKeyName() { return "branchId"; }
|
||||||
|
static get syncedProperties() { return ["branchId", "notePath", "dateAccessed", "isDeleted"]; }
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = RecentNote;
|
module.exports = RecentNote;
|
@ -3,7 +3,7 @@
|
|||||||
const build = require('./build');
|
const build = require('./build');
|
||||||
const packageJson = require('../../package');
|
const packageJson = require('../../package');
|
||||||
|
|
||||||
const APP_DB_VERSION = 92;
|
const APP_DB_VERSION = 93;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
appVersion: packageJson.version,
|
appVersion: packageJson.version,
|
||||||
|
@ -5,117 +5,40 @@ const utils = require('./utils');
|
|||||||
const log = require('./log');
|
const log = require('./log');
|
||||||
const eventLogService = require('./event_log');
|
const eventLogService = require('./event_log');
|
||||||
const messagingService = require('./messaging');
|
const messagingService = require('./messaging');
|
||||||
|
const ApiToken = require('../entities/api_token');
|
||||||
|
const Branch = require('../entities/branch');
|
||||||
|
const Image = require('../entities/image');
|
||||||
|
const Note = require('../entities/note');
|
||||||
|
const NoteImage = require('../entities/note_image');
|
||||||
|
const Label = require('../entities/label');
|
||||||
|
const NoteRevision = require('../entities/note_revision');
|
||||||
|
const RecentNote = require('../entities/recent_note');
|
||||||
|
const Option = require('../entities/option');
|
||||||
|
|
||||||
function getHash(rows) {
|
async function getHash(entityConstructor, whereBranch) {
|
||||||
let hash = '';
|
let contentToHash = await sql.getValue(`SELECT GROUP_CONCAT(hash) FROM ${entityConstructor.tableName} `
|
||||||
|
+ (whereBranch ? `WHERE ${whereBranch} ` : '') + `ORDER BY ${entityConstructor.primaryKeyName}`);
|
||||||
|
|
||||||
for (const row of rows) {
|
if (!contentToHash) { // might be null in case of no rows
|
||||||
hash = utils.hash(hash + JSON.stringify(row));
|
contentToHash = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return hash;
|
return utils.hash(contentToHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getHashes() {
|
async function getHashes() {
|
||||||
const startTime = new Date();
|
const startTime = new Date();
|
||||||
|
|
||||||
const hashes = {
|
const hashes = {
|
||||||
notes: getHash(await sql.getRows(`
|
notes: await getHash(Note),
|
||||||
SELECT
|
branches: await getHash(Branch),
|
||||||
noteId,
|
note_revisions: await getHash(NoteRevision),
|
||||||
title,
|
recent_notes: await getHash(RecentNote),
|
||||||
content,
|
options: await getHash(Option, "isSynced = 1"),
|
||||||
type,
|
images: await getHash(Image),
|
||||||
dateModified,
|
note_images: await getHash(NoteImage),
|
||||||
isProtected,
|
labels: await getHash(Label),
|
||||||
isDeleted
|
api_tokens: await getHash(ApiToken)
|
||||||
FROM notes
|
|
||||||
ORDER BY noteId`)),
|
|
||||||
|
|
||||||
branches: getHash(await sql.getRows(`
|
|
||||||
SELECT
|
|
||||||
branchId,
|
|
||||||
noteId,
|
|
||||||
parentNoteId,
|
|
||||||
notePosition,
|
|
||||||
dateModified,
|
|
||||||
isDeleted,
|
|
||||||
prefix
|
|
||||||
FROM branches
|
|
||||||
ORDER BY branchId`)),
|
|
||||||
|
|
||||||
note_revisions: getHash(await sql.getRows(`
|
|
||||||
SELECT
|
|
||||||
noteRevisionId,
|
|
||||||
noteId,
|
|
||||||
title,
|
|
||||||
content,
|
|
||||||
dateModifiedFrom,
|
|
||||||
dateModifiedTo
|
|
||||||
FROM note_revisions
|
|
||||||
ORDER BY noteRevisionId`)),
|
|
||||||
|
|
||||||
recent_notes: getHash(await sql.getRows(`
|
|
||||||
SELECT
|
|
||||||
branchId,
|
|
||||||
notePath,
|
|
||||||
dateAccessed,
|
|
||||||
isDeleted
|
|
||||||
FROM recent_notes
|
|
||||||
ORDER BY notePath`)),
|
|
||||||
|
|
||||||
options: getHash(await sql.getRows(`
|
|
||||||
SELECT
|
|
||||||
name,
|
|
||||||
value
|
|
||||||
FROM options
|
|
||||||
WHERE isSynced = 1
|
|
||||||
ORDER BY name`)),
|
|
||||||
|
|
||||||
// we don't include image data on purpose because they are quite large, checksum is good enough
|
|
||||||
// to represent the data anyway
|
|
||||||
images: getHash(await sql.getRows(`
|
|
||||||
SELECT
|
|
||||||
imageId,
|
|
||||||
format,
|
|
||||||
checksum,
|
|
||||||
name,
|
|
||||||
isDeleted,
|
|
||||||
dateModified,
|
|
||||||
dateCreated
|
|
||||||
FROM images
|
|
||||||
ORDER BY imageId`)),
|
|
||||||
|
|
||||||
note_images: getHash(await sql.getRows(`
|
|
||||||
SELECT
|
|
||||||
noteImageId,
|
|
||||||
noteId,
|
|
||||||
imageId,
|
|
||||||
isDeleted,
|
|
||||||
dateModified,
|
|
||||||
dateCreated
|
|
||||||
FROM note_images
|
|
||||||
ORDER BY noteImageId`)),
|
|
||||||
|
|
||||||
labels: getHash(await sql.getRows(`
|
|
||||||
SELECT
|
|
||||||
labelId,
|
|
||||||
noteId,
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
dateModified,
|
|
||||||
dateCreated
|
|
||||||
FROM labels
|
|
||||||
ORDER BY labelId`)),
|
|
||||||
|
|
||||||
api_tokens: getHash(await sql.getRows(`
|
|
||||||
SELECT
|
|
||||||
apiTokenId,
|
|
||||||
token,
|
|
||||||
dateCreated,
|
|
||||||
isDeleted
|
|
||||||
FROM api_tokens
|
|
||||||
ORDER BY apiTokenId`))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const elapseTimeMs = new Date().getTime() - startTime.getTime();
|
const elapseTimeMs = new Date().getTime() - startTime.getTime();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user