1
0
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:
Laurent Cozic 2017-07-04 18:09:47 +00:00
parent a53ca42a92
commit 62c56044b0
5 changed files with 54 additions and 136 deletions

View File

@ -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';

View File

@ -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';

View File

@ -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 };

View File

@ -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;
}
}
}

View File

@ -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);