2022-03-17 08:20:57 +00:00
|
|
|
import frappe from 'frappe';
|
|
|
|
import Database from './database';
|
2022-03-21 06:39:06 +00:00
|
|
|
import { sqliteTypeMap } from './helpers';
|
2018-01-12 12:25:07 +00:00
|
|
|
|
2022-03-17 08:20:57 +00:00
|
|
|
export default class SqliteDatabase extends Database {
|
2018-08-18 15:54:17 +00:00
|
|
|
constructor({ dbPath }) {
|
|
|
|
super();
|
|
|
|
this.dbPath = dbPath;
|
2019-12-09 19:57:26 +00:00
|
|
|
this.connectionParams = {
|
|
|
|
client: 'sqlite3',
|
|
|
|
connection: {
|
2021-12-01 09:07:35 +00:00
|
|
|
filename: this.dbPath,
|
2019-12-09 19:57:26 +00:00
|
|
|
},
|
|
|
|
pool: {
|
|
|
|
afterCreate(conn, done) {
|
|
|
|
conn.run('PRAGMA foreign_keys=ON');
|
|
|
|
done();
|
2021-12-01 09:07:35 +00:00
|
|
|
},
|
2019-12-09 19:57:26 +00:00
|
|
|
},
|
2019-12-11 12:27:25 +00:00
|
|
|
useNullAsDefault: true,
|
2021-12-01 09:07:35 +00:00
|
|
|
asyncStackTraces: process.env.NODE_ENV === 'development',
|
2019-12-09 19:57:26 +00:00
|
|
|
};
|
2018-08-18 15:54:17 +00:00
|
|
|
}
|
2018-01-31 13:04:46 +00:00
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
async addForeignKeys(doctype, newForeignKeys) {
|
2019-12-09 19:57:26 +00:00
|
|
|
await this.sql('PRAGMA foreign_keys=OFF');
|
|
|
|
await this.sql('BEGIN TRANSACTION');
|
2018-02-20 09:53:38 +00:00
|
|
|
|
2019-12-09 19:57:26 +00:00
|
|
|
const tempName = 'TEMP' + doctype;
|
2018-03-05 16:45:21 +00:00
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
// create temp table
|
|
|
|
await this.createTable(doctype, tempName);
|
2018-03-05 16:45:21 +00:00
|
|
|
|
2022-03-08 09:50:07 +00:00
|
|
|
try {
|
|
|
|
// copy from old to new table
|
|
|
|
await this.knex(tempName).insert(this.knex.select().from(doctype));
|
|
|
|
} catch (err) {
|
|
|
|
await this.sql('ROLLBACK');
|
|
|
|
await this.sql('PRAGMA foreign_keys=ON');
|
|
|
|
|
|
|
|
const rows = await this.knex.select().from(doctype);
|
|
|
|
await this.prestigeTheTable(doctype, rows);
|
|
|
|
return;
|
|
|
|
}
|
2018-02-20 09:53:38 +00:00
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
// drop old table
|
2019-12-09 19:57:26 +00:00
|
|
|
await this.knex.schema.dropTable(doctype);
|
2018-02-20 09:53:38 +00:00
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
// rename new table
|
2019-12-09 19:57:26 +00:00
|
|
|
await this.knex.schema.renameTable(tempName, doctype);
|
2018-02-20 09:53:38 +00:00
|
|
|
|
2019-12-09 19:57:26 +00:00
|
|
|
await this.sql('COMMIT');
|
|
|
|
await this.sql('PRAGMA foreign_keys=ON');
|
2018-08-18 15:54:17 +00:00
|
|
|
}
|
2018-02-20 09:53:38 +00:00
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
removeColumns() {
|
|
|
|
// pass
|
|
|
|
}
|
2018-03-05 16:45:21 +00:00
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
async getTableColumns(doctype) {
|
2021-12-01 09:07:35 +00:00
|
|
|
return (await this.sql(`PRAGMA table_info(${doctype})`)).map((d) => d.name);
|
2018-08-18 15:54:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async getForeignKeys(doctype) {
|
2019-12-09 19:57:26 +00:00
|
|
|
return (await this.sql(`PRAGMA foreign_key_list(${doctype})`)).map(
|
2021-12-01 09:07:35 +00:00
|
|
|
(d) => d.from
|
2019-12-09 19:57:26 +00:00
|
|
|
);
|
2018-08-18 15:54:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
initTypeMap() {
|
2022-03-21 06:39:06 +00:00
|
|
|
this.typeMap = sqliteTypeMap;
|
2018-08-18 15:54:17 +00:00
|
|
|
}
|
2019-11-15 07:44:45 +00:00
|
|
|
|
2019-11-20 09:38:32 +00:00
|
|
|
getError(err) {
|
2019-12-20 06:18:53 +00:00
|
|
|
let errorType = frappe.errors.DatabaseError;
|
2019-11-20 09:38:32 +00:00
|
|
|
if (err.message.includes('FOREIGN KEY')) {
|
2019-12-20 06:18:53 +00:00
|
|
|
errorType = frappe.errors.LinkValidationError;
|
2019-11-20 09:38:32 +00:00
|
|
|
}
|
|
|
|
if (err.message.includes('SQLITE_ERROR: cannot commit')) {
|
2019-12-20 06:18:53 +00:00
|
|
|
errorType = frappe.errors.CannotCommitError;
|
2019-11-20 09:38:32 +00:00
|
|
|
}
|
2019-12-20 06:18:53 +00:00
|
|
|
if (err.message.includes('SQLITE_CONSTRAINT: UNIQUE constraint failed:')) {
|
|
|
|
errorType = frappe.errors.DuplicateEntryError;
|
|
|
|
}
|
|
|
|
return errorType;
|
2019-11-15 07:44:45 +00:00
|
|
|
}
|
2021-12-01 09:07:35 +00:00
|
|
|
|
|
|
|
async prestigeTheTable(tableName, tableRows) {
|
2022-02-22 09:07:46 +00:00
|
|
|
const max = 200;
|
|
|
|
|
2021-12-01 09:07:35 +00:00
|
|
|
// Alter table hacx for sqlite in case of schema change.
|
|
|
|
const tempName = `__${tableName}`;
|
2022-01-10 09:35:29 +00:00
|
|
|
await this.knex.schema.dropTableIfExists(tempName);
|
2022-03-08 09:50:07 +00:00
|
|
|
|
2021-12-01 09:07:35 +00:00
|
|
|
await this.knex.raw('PRAGMA foreign_keys=OFF');
|
|
|
|
await this.createTable(tableName, tempName);
|
2022-02-22 09:07:46 +00:00
|
|
|
|
|
|
|
if (tableRows.length > 200) {
|
|
|
|
const fi = Math.floor(tableRows.length / max);
|
|
|
|
for (let i = 0; i <= fi; i++) {
|
|
|
|
const rowSlice = tableRows.slice(i * max, i + 1 * max);
|
|
|
|
if (rowSlice.length === 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
await this.knex.batchInsert(tempName, rowSlice);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
await this.knex.batchInsert(tempName, tableRows);
|
|
|
|
}
|
|
|
|
|
2021-12-01 09:07:35 +00:00
|
|
|
await this.knex.schema.dropTable(tableName);
|
|
|
|
await this.knex.schema.renameTable(tempName, tableName);
|
|
|
|
await this.knex.raw('PRAGMA foreign_keys=ON');
|
|
|
|
}
|
2018-01-12 12:25:07 +00:00
|
|
|
}
|