mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Better handling of db errors
This commit is contained in:
parent
a53ca42a92
commit
62c56044b0
@ -1,6 +1,5 @@
|
||||
import { time } from 'lib/time-utils.js';
|
||||
import { setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient } from 'test-utils.js';
|
||||
import { createFoldersAndNotes } from 'test-data.js';
|
||||
import { Folder } from 'lib/models/folder.js';
|
||||
import { Note } from 'lib/models/note.js';
|
||||
import { Setting } from 'lib/models/setting.js';
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { time } from 'lib/time-utils.js';
|
||||
import { setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient } from 'test-utils.js';
|
||||
import { createFoldersAndNotes } from 'test-data.js';
|
||||
import { Folder } from 'lib/models/folder.js';
|
||||
import { Note } from 'lib/models/note.js';
|
||||
import { Tag } from 'lib/models/tag.js';
|
||||
|
@ -1,58 +0,0 @@
|
||||
import { Note } from 'lib/models/note.js';
|
||||
import { Folder } from 'lib/models/folder.js';
|
||||
import { promiseChain } from 'lib/promise-utils.js';
|
||||
|
||||
function createNotes(id = 1, parentId) {
|
||||
let notes = [];
|
||||
if (id === 1) {
|
||||
notes.push({ parent_id: parentId, title: 'note one', body: 'content of note one' });
|
||||
notes.push({ parent_id: parentId, title: 'note two', body: 'content of note two' });
|
||||
} else {
|
||||
throw new Error('Invalid ID: ' + id);
|
||||
}
|
||||
|
||||
let output = [];
|
||||
let chain = [];
|
||||
for (let i = 0; i < notes.length; i++) {
|
||||
chain.push(() => {
|
||||
return Note.save(notes[i]).then((note) => {
|
||||
output.push(note);
|
||||
return output;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return promiseChain(chain, []);
|
||||
}
|
||||
|
||||
function createFolders(id = 1) {
|
||||
let folders = [];
|
||||
if (id === 1) {
|
||||
folders.push({ title: 'myfolder1' });
|
||||
folders.push({ title: 'myfolder2' });
|
||||
folders.push({ title: 'myfolder3' });
|
||||
} else {
|
||||
throw new Error('Invalid ID: ' + id);
|
||||
}
|
||||
|
||||
let output = [];
|
||||
let chain = [];
|
||||
for (let i = 0; i < folders.length; i++) {
|
||||
chain.push(() => {
|
||||
return Folder.save(folders[i]).then((folder) => {
|
||||
output.push(folder);
|
||||
return output;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return promiseChain(chain, []);
|
||||
}
|
||||
|
||||
function createFoldersAndNotes(id = 1) {
|
||||
return createFolders(id).then((folders) => {
|
||||
return createNotes(id, folders[0].id);
|
||||
});
|
||||
}
|
||||
|
||||
export { createNotes, createFolders, createFoldersAndNotes };
|
125
lib/database.js
125
lib/database.js
@ -121,11 +121,11 @@ class Database {
|
||||
// Converts the SQLite error to a regular JS error
|
||||
// so that it prints a stacktrace when passed to
|
||||
// console.error()
|
||||
sqliteErrorToJsError(error, sql, params = null) {
|
||||
let msg = sql;
|
||||
if (params) msg += ': ' + JSON.stringify(params);
|
||||
msg += ': ' + error.toString();
|
||||
let output = new Error(msg);
|
||||
sqliteErrorToJsError(error, sql = null, params = null) {
|
||||
let msg = [error.toString()];
|
||||
if (sql) msg.push(sql);
|
||||
if (params) msg.push(params);
|
||||
let output = new Error(msg.join(': '));
|
||||
if (error.code) output.code = error.code;
|
||||
return output;
|
||||
}
|
||||
@ -146,14 +146,10 @@ class Database {
|
||||
return this.driver_;
|
||||
}
|
||||
|
||||
open(options) {
|
||||
return this.driver().open(options).then((db) => {
|
||||
this.logger().info('Database was open successfully');
|
||||
return this.initialize();
|
||||
}).catch((error) => {
|
||||
this.logger().error('Cannot open database:');
|
||||
this.logger().error(error);
|
||||
});
|
||||
async open(options) {
|
||||
await this.driver().open(options);
|
||||
this.logger().info('Database was open successfully');
|
||||
return this.initialize();
|
||||
}
|
||||
|
||||
escapeField(field) {
|
||||
@ -416,71 +412,58 @@ class Database {
|
||||
});
|
||||
}
|
||||
|
||||
static defaultFolderData() {
|
||||
let now = time.unixMs();
|
||||
|
||||
return {
|
||||
id: uuid.create(),
|
||||
title: _('Notebook'),
|
||||
created_time: now,
|
||||
updated_time: now,
|
||||
};
|
||||
}
|
||||
|
||||
static defaultFolderQuery() {
|
||||
return Database.insertQuery('folders', this.defaultFolderData());
|
||||
}
|
||||
|
||||
|
||||
initialize() {
|
||||
async initialize() {
|
||||
this.logger().info('Checking for database schema update...');
|
||||
|
||||
return this.selectOne('SELECT * FROM version LIMIT 1').then((row) => {
|
||||
this.logger().info('Current database version', row);
|
||||
// TODO: version update logic
|
||||
for (let initLoopCount = 1; initLoopCount <= 2; initLoopCount++) {
|
||||
try {
|
||||
let row = await this.selectOne('SELECT * FROM version LIMIT 1');
|
||||
this.logger().info('Current database version', row);
|
||||
|
||||
// TODO: version update logic
|
||||
// TODO: only do this if db has been updated:
|
||||
// return this.refreshTableFields();
|
||||
} catch (error) {
|
||||
if (error && error.code != 0 && error.code != 'SQLITE_ERROR') throw this.sqliteErrorToJsError(error);
|
||||
|
||||
// Assume that error was:
|
||||
// { message: 'no such table: version (code 1): , while compiling: SELECT * FROM version', code: 0 }
|
||||
// which means the database is empty and the tables need to be created.
|
||||
// If it's any other error there's nothing we can do anyway.
|
||||
|
||||
this.logger().info('Database is new - creating the schema...');
|
||||
|
||||
let queries = this.wrapQueries(this.sqlStringToLines(structureSql));
|
||||
queries.push(this.wrapQuery('INSERT INTO settings (`key`, `value`, `type`) VALUES ("clientId", "' + uuid.create() + '", "' + Database.enumId('settings', 'string') + '")'));
|
||||
|
||||
try {
|
||||
await this.transactionExecBatch(queries);
|
||||
this.logger().info('Database schema created successfully');
|
||||
await this.refreshTableFields();
|
||||
} catch (error) {
|
||||
throw this.sqliteErrorToJsError(error);
|
||||
}
|
||||
|
||||
// Now that the database has been created, go through the normal initialisation process
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: only do this if db has been updated:
|
||||
// return this.refreshTableFields();
|
||||
}).then(() => {
|
||||
this.tableFields_ = {};
|
||||
|
||||
return this.selectAll('SELECT * FROM table_fields').then((rows) => {
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
let row = rows[i];
|
||||
if (!this.tableFields_[row.table_name]) this.tableFields_[row.table_name] = [];
|
||||
this.tableFields_[row.table_name].push({
|
||||
name: row.field_name,
|
||||
type: row.field_type,
|
||||
default: Database.formatValue(row.field_type, row.field_default),
|
||||
});
|
||||
}
|
||||
});
|
||||
}).catch((error) => {
|
||||
if (error && error.code != 0 && error.code != 'SQLITE_ERROR') {
|
||||
this.logger().error(error);
|
||||
return;
|
||||
let rows = await this.selectAll('SELECT * FROM table_fields');
|
||||
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
let row = rows[i];
|
||||
if (!this.tableFields_[row.table_name]) this.tableFields_[row.table_name] = [];
|
||||
this.tableFields_[row.table_name].push({
|
||||
name: row.field_name,
|
||||
type: row.field_type,
|
||||
default: Database.formatValue(row.field_type, row.field_default),
|
||||
});
|
||||
}
|
||||
|
||||
// Assume that error was:
|
||||
// { message: 'no such table: version (code 1): , while compiling: SELECT * FROM version', code: 0 }
|
||||
// which means the database is empty and the tables need to be created.
|
||||
// If it's any other error there's nothing we can do anyway.
|
||||
|
||||
this.logger().info('Database is new - creating the schema...');
|
||||
|
||||
let queries = this.wrapQueries(this.sqlStringToLines(structureSql));
|
||||
queries.push(this.wrapQuery('INSERT INTO settings (`key`, `value`, `type`) VALUES ("clientId", "' + uuid.create() + '", "' + Database.enumId('settings', 'string') + '")'));
|
||||
//queries.push(Database.defaultFolderQuery());
|
||||
|
||||
return this.transactionExecBatch(queries).then(() => {
|
||||
this.logger().info('Database schema created successfully');
|
||||
// Calling initialize() now that the db has been created will make it go through
|
||||
// the normal db update process (applying any additional patch).
|
||||
return this.refreshTableFields();
|
||||
}).then(() => {
|
||||
return this.initialize();
|
||||
});
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -76,11 +76,6 @@ class Folder extends BaseItem {
|
||||
return this.modelSelectOne('SELECT * FROM folders ORDER BY created_time DESC LIMIT 1');
|
||||
}
|
||||
|
||||
static createDefaultFolder() {
|
||||
let folder = Database.defaultFolderData();
|
||||
return Folder.save(folder, { isNew: true });
|
||||
}
|
||||
|
||||
static async save(o, options = null) {
|
||||
if (options && options.duplicateCheck === true && o.title) {
|
||||
let existingFolder = await Folder.loadByTitle(o.title);
|
||||
|
Loading…
Reference in New Issue
Block a user