UNPKG

jeep-sqlite

Version:
511 lines (510 loc) 21 kB
import { UtilsSQLite } from "./utils-sqlite"; import { UtilsDrop } from "./utils-drop"; import { UtilsJSON } from "./utils-json"; export class UtilsImportJSON { static async createDatabaseSchema(mDB, jsonData) { let changes = -1; const version = jsonData.version; try { // set User Version PRAGMA await UtilsSQLite.setVersion(mDB.mDb, version); // DROP ALL when mode="full" if (jsonData.mode === 'full') { await UtilsDrop.dropAll(mDB.mDb); } // create database schema changes = await UtilsImportJSON.createSchema(mDB, jsonData); return Promise.resolve(changes); } catch (err) { return Promise.reject(new Error('CreateDatabaseSchema: ' + `${err.message}`)); } } static async createSchema(mDB, jsonData) { // create the database schema let changes = 0; const db = mDB.mDb; try { // start a transaction await UtilsSQLite.beginTransaction(db, true); mDB.setIsTransActive(true); } catch (err) { return Promise.reject(new Error(`CreateSchema: ${err.message}`)); } const stmts = await UtilsImportJSON.createSchemaStatement(jsonData); if (stmts.length > 0) { const schemaStmt = stmts.join('\n'); try { changes = await UtilsSQLite.execute(db, schemaStmt, true); if (changes < 0) { try { await UtilsSQLite.rollbackTransaction(db, true); mDB.setIsTransActive(false); } catch (err) { return Promise.reject(new Error('CreateSchema: changes < 0 ' + `${err.message}`)); } } } catch (err) { const msg = err.message; try { await UtilsSQLite.rollbackTransaction(db, true); mDB.setIsTransActive(false); return Promise.reject(new Error(`CreateSchema: ${msg}`)); } catch (err) { return Promise.reject(new Error('CreateSchema: changes < 0 ' + `${err.message}: ${msg}`)); } } } try { await UtilsSQLite.commitTransaction(db, true); mDB.setIsTransActive(false); return Promise.resolve(changes); } catch (err) { return Promise.reject(new Error('CreateSchema: commit ' + `${err.message}`)); } } static async createSchemaStatement(jsonData) { const statements = []; let isLastModified = false; let isSqlDeleted = false; // Prepare the statement to execute try { for (const jTable of jsonData.tables) { if (jTable.schema != null && jTable.schema.length >= 1) { // create table statements.push('CREATE TABLE IF NOT EXISTS ' + `${jTable.name} (`); for (let j = 0; j < jTable.schema.length; j++) { if (j === jTable.schema.length - 1) { if (jTable.schema[j].column) { statements.push(`${jTable.schema[j].column} ${jTable.schema[j].value}`); if (jTable.schema[j].column === "last_modified") { isLastModified = true; } if (jTable.schema[j].column === "sql_deleted") { isSqlDeleted = true; } } else if (jTable.schema[j].foreignkey) { statements.push(`FOREIGN KEY (${jTable.schema[j].foreignkey}) ${jTable.schema[j].value}`); } else if (jTable.schema[j].constraint) { statements.push(`CONSTRAINT ${jTable.schema[j].constraint} ${jTable.schema[j].value}`); } } else { if (jTable.schema[j].column) { statements.push(`${jTable.schema[j].column} ${jTable.schema[j].value},`); } else if (jTable.schema[j].foreignkey) { statements.push(`FOREIGN KEY (${jTable.schema[j].foreignkey}) ${jTable.schema[j].value},`); } else if (jTable.schema[j].primarykey) { statements.push(`FOREIGN KEY ${jTable.schema[j].value},`); } else if (jTable.schema[j].constraint) { statements.push(`CONSTRAINT ${jTable.schema[j].constraint} ${jTable.schema[j].value},`); } } } statements.push(');'); if (isLastModified && isSqlDeleted) { // create trigger last_modified associated with the table let trig = 'CREATE TRIGGER IF NOT EXISTS '; trig += `${jTable.name}`; trig += `_trigger_last_modified `; trig += `AFTER UPDATE ON ${jTable.name} `; trig += 'FOR EACH ROW WHEN NEW.last_modified < '; trig += 'OLD.last_modified BEGIN UPDATE '; trig += `${jTable.name} `; trig += `SET last_modified = `; trig += "(strftime('%s','now')) WHERE id=OLD.id; END;"; statements.push(trig); } } if (jTable.indexes != null && jTable.indexes.length >= 1) { for (const jIndex of jTable.indexes) { const tableName = jTable.name; let stmt = `CREATE ${Object.keys(jIndex).includes('mode') ? jIndex.mode + ' ' : ''} INDEX IF NOT EXISTS `; stmt += `${jIndex.name} ON ${tableName} (${jIndex.value});`; statements.push(stmt); } } if (jTable.triggers != null && jTable.triggers.length >= 1) { for (const jTrg of jTable.triggers) { const tableName = jTable.name; if (jTrg.timeevent.toUpperCase().endsWith(" ON")) { jTrg.timeevent = jTrg.timeevent.substring(0, jTrg.timeevent.length - 3); } let stmt = `CREATE TRIGGER IF NOT EXISTS `; stmt += `${jTrg.name} ${jTrg.timeevent} ON ${tableName} `; if (jTrg.condition) stmt += `${jTrg.condition} `; stmt += `${jTrg.logic};`; statements.push(stmt); } } } return Promise.resolve(statements); } catch (err) { return Promise.reject(err); } } static async createTablesData(mDB, jsonData, importProgress) { let changes = 0; let isValue = false; let lastId = -1; let msg = ''; let initChanges = -1; const db = mDB.mDb; try { initChanges = await UtilsSQLite.dbChanges(db); // start a transaction await UtilsSQLite.beginTransaction(db, true); mDB.setIsTransActive(true); } catch (err) { return Promise.reject(new Error(`createTablesData: ${err.message}`)); } for (const jTable of jsonData.tables) { if (jTable.values != null && jTable.values.length >= 1) { // Create the table's data try { lastId = await UtilsImportJSON.createTableData(db, jTable, jsonData.mode); const msg = `create table data ${jTable.name}`; importProgress.emit({ progress: msg }); if (lastId < 0) break; isValue = true; } catch (err) { msg = err.message; isValue = false; break; } } } if (isValue) { try { await UtilsSQLite.commitTransaction(db, true); mDB.setIsTransActive(false); changes = (await UtilsSQLite.dbChanges(db)) - initChanges; return Promise.resolve(changes); } catch (err) { return Promise.reject(new Error('CreateTablesData: ' + `${err.message}`)); } } else { if (msg.length > 0) { try { await UtilsSQLite.rollbackTransaction(db, true); mDB.setIsTransActive(false); return Promise.reject(new Error(`CreateTablesData: ${msg}`)); } catch (err) { return Promise.reject(new Error('CreateTablesData: ' + `${err.message}: ${msg}`)); } } else { // case were no values given return Promise.resolve(0); } } } static async createTableData(db, table, mode) { let lastId = -1; try { // Check if the table exists const tableExists = await UtilsSQLite.isTableExists(db, table.name); if (!tableExists) { return Promise.reject(new Error('CreateTableData: Table ' + `${table.name} does not exist`)); } // Get the column names and types const tableNamesTypes = await UtilsJSON .getTableColumnNamesTypes(db, table.name); const tableColumnTypes = tableNamesTypes.types; const tableColumnNames = tableNamesTypes.names; if (tableColumnTypes.length === 0) { return Promise.reject(new Error('CreateTableData: Table ' + `${table.name} info does not exist`)); } // Loop on Table Values for (let j = 0; j < table.values.length; j++) { let row = table.values[j]; let isRun = true; const stmt = await UtilsImportJSON .createRowStatement(db, tableColumnNames, row, j, table.name, mode); isRun = await UtilsImportJSON.checkUpdate(db, stmt, row, table.name, tableColumnNames); if (isRun) { if (stmt.substring(0, 6).toUpperCase() === "DELETE") { row = []; } lastId = await UtilsSQLite.run(db, stmt, row, true, 'no'); if (lastId < 0) { return Promise.reject(new Error('CreateTableData: lastId < 0')); } } else { lastId = 0; } } return Promise.resolve(lastId); } catch (err) { return Promise.reject(new Error(`CreateTableData: ${err.message}`)); } } static async createRowStatement(db, tColNames, row, j, tableName, mode) { // Check the row number of columns if (row.length != tColNames.length || row.length === 0 || tColNames.length === 0) { return Promise.reject(new Error(`CreateRowStatement: Table ${tableName} ` + `values row ${j} not correct length`)); } try { const retisIdExists = await UtilsImportJSON.isIdExists(db, tableName, tColNames[0], row[0]); let stmt; if (mode === 'full' || (mode === 'partial' && !retisIdExists)) { // Insert const nameString = tColNames.join(); const questionMarkString = await UtilsImportJSON.createQuestionMarkString(tColNames.length); stmt = `INSERT INTO ${tableName} (${nameString}) VALUES (`; stmt += `${questionMarkString});`; } else { // Update or Delete let isUpdate = true; const isColDeleted = (element) => element === `sql_deleted`; const idxDelete = tColNames.findIndex(isColDeleted); if (idxDelete >= 0) { if (row[idxDelete] === 1) { isUpdate = false; stmt = `DELETE FROM ${tableName} WHERE `; if (typeof row[0] == "string") { stmt += `${tColNames[0]} = '${row[0]}';`; } else { stmt += `${tColNames[0]} = ${row[0]};`; } } } if (isUpdate) { // Update const setString = await UtilsImportJSON.setNameForUpdate(tColNames); if (setString.length === 0) { return Promise.reject(new Error(`CreateRowStatement: Table ${tableName} ` + `values row ${j} not set to String`)); } stmt = `UPDATE ${tableName} SET ${setString} WHERE `; if (typeof row[0] == "string") { stmt += `${tColNames[0]} = '${row[0]}';`; } else { stmt += `${tColNames[0]} = ${row[0]};`; } } } return Promise.resolve(stmt); } catch (err) { return Promise.reject(new Error(`CreateRowStatement: ${err.message}`)); } } static async checkUpdate(db, stmt, values, tbName, tColNames) { let isRun = true; if (stmt.substring(0, 6) === "UPDATE") { try { let query = `SELECT * FROM ${tbName} WHERE `; if (typeof values[0] == "string") { query += `${tColNames[0]} = '${values[0]}';`; } else { query += `${tColNames[0]} = ${values[0]};`; } const resQuery = await UtilsJSON.getValues(db, query, tbName); let resValues = []; if (resQuery.length > 0) { resValues = resQuery[0]; } if (values.length > 0 && resValues.length > 0 && values.length === resValues.length) { for (let i = 0; i < values.length; i++) { if (values[i] !== resValues[i]) { return Promise.resolve(true); } } return Promise.resolve(false); } else { const msg = "Both arrays not the same length"; return Promise.reject(new Error(`CheckUpdate: ${msg}`)); } } catch (err) { return Promise.reject(new Error(`CheckUpdate: ${err.message}`)); } } else { return Promise.resolve(isRun); } } static async isIdExists(db, dbName, firstColumnName, key) { let ret = false; let query = `SELECT ${firstColumnName} FROM ` + `${dbName} WHERE ${firstColumnName} = `; if (typeof key === 'number') query += `${key};`; if (typeof key === 'string') query += `'${key}';`; try { const resQuery = await UtilsSQLite.queryAll(db, query, []); if (resQuery.length === 1) ret = true; return Promise.resolve(ret); } catch (err) { return Promise.reject(new Error(`IsIdExists: ${err.message}`)); } } static async isType(type, value) { let ret = false; if (type === 'NULL' && typeof value === 'object') ret = true; if (type === 'TEXT' && typeof value === 'string') ret = true; if (type === 'INTEGER' && typeof value === 'number') ret = true; if (type === 'REAL' && typeof value === 'number') ret = true; if (type === 'BLOB' && typeof value === 'string') ret = true; if (ret) { return Promise.resolve(); } else { return Promise.reject(new Error('IsType: not a SQL Type')); } } static async checkColumnTypes(tableTypes, rowValues) { for (let i = 0; i < rowValues.length; i++) { if (rowValues[i] != null) { try { await UtilsImportJSON.isType(tableTypes[i], rowValues[i]); } catch (err) { return Promise.reject(new Error('CheckColumnTypes: Type not found')); } } } return Promise.resolve(); } static async createQuestionMarkString(length) { let retString = ''; for (let i = 0; i < length; i++) { retString += '?,'; } if (retString.length > 1) { retString = retString.slice(0, -1); return Promise.resolve(retString); } else { return Promise.reject(new Error('CreateQuestionMarkString: length = 0')); } } static async setNameForUpdate(names) { let retString = ''; for (const name of names) { retString += `${name} = ? ,`; } if (retString.length > 1) { retString = retString.slice(0, -1); return Promise.resolve(retString); } else { return Promise.reject(new Error('SetNameForUpdate: length = 0')); } } static async createView(db, view) { const stmt = `CREATE VIEW IF NOT EXISTS ${view.name} AS ${view.value};`; try { const changes = await UtilsSQLite.execute(db, stmt, true); if (changes < 0) { return Promise.reject(new Error(`CreateView: ${view.name} failed`)); } return Promise.resolve(); } catch (err) { return Promise.reject(new Error(`CreateView: ${err.message}`)); } } static async createViews(mDB, jsonData) { const db = mDB.mDb; let isView = false; let msg = ''; let initChanges = -1; let changes = -1; try { initChanges = await UtilsSQLite.dbChanges(db); // start a transaction await UtilsSQLite.beginTransaction(db, true); mDB.setIsTransActive(true); } catch (err) { return Promise.reject(new Error(`createViews: ${err.message}`)); } for (const jView of jsonData.views) { if (jView.value != null) { // Create the view try { await UtilsImportJSON.createView(db, jView); isView = true; } catch (err) { msg = err.message; isView = false; break; } } } if (isView) { try { await UtilsSQLite.commitTransaction(db, true); mDB.setIsTransActive(false); changes = (await UtilsSQLite.dbChanges(db)) - initChanges; return Promise.resolve(changes); } catch (err) { return Promise.reject(new Error('createViews: ' + `${err.message}`)); } } else { if (msg.length > 0) { try { await UtilsSQLite.rollbackTransaction(db, true); mDB.setIsTransActive(false); return Promise.reject(new Error(`createViews: ${msg}`)); } catch (err) { return Promise.reject(new Error('createViews: ' + `${err.message}: ${msg}`)); } } else { // case were no views given return Promise.resolve(0); } } } } //# sourceMappingURL=utils-importJson.js.map