MOBILE classes: Fix sqlite linting

main
Pau Ferrer Ocaña 2020-10-09 12:25:24 +02:00
parent 7aaf213889
commit c8fda5d3ca
1 changed files with 160 additions and 147 deletions

View File

@ -131,6 +131,7 @@ export interface SQLiteDBForeignKeySchema {
* this.db = new SQLiteDB('MyDB'); * this.db = new SQLiteDB('MyDB');
*/ */
export class SQLiteDB { export class SQLiteDB {
db: SQLiteObject; db: SQLiteObject;
promise: Promise<void>; promise: Promise<void>;
@ -240,10 +241,10 @@ export class SQLiteDB {
* *
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
async close(): Promise<any> { async close(): Promise<void> {
await this.ready(); await this.ready();
return this.db.close(); await this.db.close();
} }
/** /**
@ -253,7 +254,7 @@ export class SQLiteDB {
* @param conditions The conditions to build the where clause. Must not contain numeric indexes. * @param conditions The conditions to build the where clause. Must not contain numeric indexes.
* @return Promise resolved with the count of records returned from the specified criteria. * @return Promise resolved with the count of records returned from the specified criteria.
*/ */
countRecords(table: string, conditions?: object): Promise<number> { async countRecords(table: string, conditions?: SQLiteDBRecordValues): Promise<number> {
const selectAndParams = this.whereClause(conditions); const selectAndParams = this.whereClause(conditions);
return this.countRecordsSelect(table, selectAndParams[0], selectAndParams[1]); return this.countRecordsSelect(table, selectAndParams[0], selectAndParams[1]);
@ -268,7 +269,8 @@ export class SQLiteDB {
* @param countItem The count string to be used in the SQL call. Default is COUNT('x'). * @param countItem The count string to be used in the SQL call. Default is COUNT('x').
* @return Promise resolved with the count of records returned from the specified criteria. * @return Promise resolved with the count of records returned from the specified criteria.
*/ */
countRecordsSelect(table: string, select: string = '', params?: any, countItem: string = 'COUNT(\'x\')'): Promise<number> { async countRecordsSelect(table: string, select: string = '', params?: SQLiteDBRecordValue[],
countItem: string = 'COUNT(\'x\')'): Promise<number> {
if (select) { if (select) {
select = 'WHERE ' + select; select = 'WHERE ' + select;
} }
@ -285,14 +287,13 @@ export class SQLiteDB {
* @param params An array of sql parameters. * @param params An array of sql parameters.
* @return Promise resolved with the count. * @return Promise resolved with the count.
*/ */
countRecordsSql(sql: string, params?: any): Promise<number> { async countRecordsSql(sql: string, params?: SQLiteDBRecordValue[]): Promise<number> {
return this.getFieldSql(sql, params).then((count) => { const count = await this.getFieldSql(sql, params);
if (typeof count != 'number' || count < 0) { if (typeof count != 'number' || count < 0) {
return 0; return 0;
} }
return count; return count;
});
} }
/** /**
@ -306,11 +307,11 @@ export class SQLiteDB {
* @param tableCheck Check constraint for the table. * @param tableCheck Check constraint for the table.
* @return Promise resolved when success. * @return Promise resolved when success.
*/ */
createTable(name: string, columns: SQLiteDBColumnSchema[], primaryKeys?: string[], uniqueKeys?: string[][], async createTable(name: string, columns: SQLiteDBColumnSchema[], primaryKeys?: string[], uniqueKeys?: string[][],
foreignKeys?: SQLiteDBForeignKeySchema[], tableCheck?: string): Promise<any> { foreignKeys?: SQLiteDBForeignKeySchema[], tableCheck?: string): Promise<void> {
const sql = this.buildCreateTableSql(name, columns, primaryKeys, uniqueKeys, foreignKeys, tableCheck); const sql = this.buildCreateTableSql(name, columns, primaryKeys, uniqueKeys, foreignKeys, tableCheck);
return this.execute(sql); await this.execute(sql);
} }
/** /**
@ -319,9 +320,8 @@ export class SQLiteDB {
* @param table Table schema. * @param table Table schema.
* @return Promise resolved when success. * @return Promise resolved when success.
*/ */
createTableFromSchema(table: SQLiteDBTableSchema): Promise<any> { async createTableFromSchema(table: SQLiteDBTableSchema): Promise<void> {
return this.createTable(table.name, table.columns, table.primaryKeys, table.uniqueKeys, await this.createTable(table.name, table.columns, table.primaryKeys, table.uniqueKeys, table.foreignKeys, table.tableCheck);
table.foreignKeys, table.tableCheck);
} }
/** /**
@ -330,13 +330,13 @@ export class SQLiteDB {
* @param tables List of table schema. * @param tables List of table schema.
* @return Promise resolved when success. * @return Promise resolved when success.
*/ */
createTablesFromSchema(tables: SQLiteDBTableSchema[]): Promise<any> { async createTablesFromSchema(tables: SQLiteDBTableSchema[]): Promise<void> {
const promises = []; const promises = [];
tables.forEach((table) => { tables.forEach((table) => {
promises.push(this.createTableFromSchema(table)); promises.push(this.createTableFromSchema(table));
}); });
return Promise.all(promises); await Promise.all(promises);
} }
/** /**
@ -345,12 +345,14 @@ export class SQLiteDB {
* *
* @param table The table to delete from. * @param table The table to delete from.
* @param conditions The conditions to build the where clause. Must not contain numeric indexes. * @param conditions The conditions to build the where clause. Must not contain numeric indexes.
* @return Promise resolved when done. * @return Promise resolved with the number of affected rows.
*/ */
deleteRecords(table: string, conditions?: object): Promise<any> { async deleteRecords(table: string, conditions?: SQLiteDBRecordValues): Promise<number> {
if (conditions === null || typeof conditions == 'undefined') { if (conditions === null || typeof conditions == 'undefined') {
// No conditions, delete the whole table. // No conditions, delete the whole table.
return this.execute(`DELETE FROM ${table}`); const result = await this.execute(`DELETE FROM ${table}`);
return result.rowsAffected;
} }
const selectAndParams = this.whereClause(conditions); const selectAndParams = this.whereClause(conditions);
@ -364,9 +366,9 @@ export class SQLiteDB {
* @param table The table to delete from. * @param table The table to delete from.
* @param field The name of a field. * @param field The name of a field.
* @param values The values field might take. * @param values The values field might take.
* @return Promise resolved when done. * @return Promise resolved with the number of affected rows.
*/ */
deleteRecordsList(table: string, field: string, values: any[]): Promise<any> { async deleteRecordsList(table: string, field: string, values: SQLiteDBRecordValue[]): Promise<number> {
const selectAndParams = this.whereClauseList(field, values); const selectAndParams = this.whereClauseList(field, values);
return this.deleteRecordsSelect(table, selectAndParams[0], selectAndParams[1]); return this.deleteRecordsSelect(table, selectAndParams[0], selectAndParams[1]);
@ -378,14 +380,16 @@ export class SQLiteDB {
* @param table The table to delete from. * @param table The table to delete from.
* @param select A fragment of SQL to be used in a where clause in the SQL call. * @param select A fragment of SQL to be used in a where clause in the SQL call.
* @param params Array of sql parameters. * @param params Array of sql parameters.
* @return Promise resolved when done. * @return Promise resolved with the number of affected rows.
*/ */
deleteRecordsSelect(table: string, select: string = '', params?: any[]): Promise<any> { async deleteRecordsSelect(table: string, select: string = '', params?: SQLiteDBRecordValue[]): Promise<number> {
if (select) { if (select) {
select = 'WHERE ' + select; select = 'WHERE ' + select;
} }
return this.execute(`DELETE FROM ${table} ${select}`, params); const result = await this.execute(`DELETE FROM ${table} ${select}`, params);
return result.rowsAffected;
} }
/** /**
@ -394,8 +398,8 @@ export class SQLiteDB {
* @param name The table name. * @param name The table name.
* @return Promise resolved when success. * @return Promise resolved when success.
*/ */
dropTable(name: string): Promise<any> { async dropTable(name: string): Promise<void> {
return this.execute(`DROP TABLE IF EXISTS ${name}`); await this.execute(`DROP TABLE IF EXISTS ${name}`);
} }
/** /**
@ -407,7 +411,7 @@ export class SQLiteDB {
* @param params Query parameters. * @param params Query parameters.
* @return Promise resolved with the result. * @return Promise resolved with the result.
*/ */
async execute(sql: string, params?: any[]): Promise<any> { async execute(sql: string, params?: SQLiteDBRecordValue[]): Promise<any> {
await this.ready(); await this.ready();
return this.db.executeSql(sql, params); return this.db.executeSql(sql, params);
@ -421,10 +425,10 @@ export class SQLiteDB {
* @param sqlStatements SQL statements to execute. * @param sqlStatements SQL statements to execute.
* @return Promise resolved with the result. * @return Promise resolved with the result.
*/ */
async executeBatch(sqlStatements: any[]): Promise<any> { async executeBatch(sqlStatements: (string | SQLiteDBRecordValue[])[][]): Promise<void> {
await this.ready(); await this.ready();
return this.db.sqlBatch(sqlStatements); await this.db.sqlBatch(sqlStatements);
} }
/** /**
@ -432,27 +436,35 @@ export class SQLiteDB {
* *
* @param data Data to insert. * @param data Data to insert.
*/ */
protected formatDataToInsert(data: object): void { protected formatDataToInsert(data: SQLiteDBRecordValues): void {
if (!data) { if (!data) {
return; return;
} }
// Remove undefined entries and convert null to "NULL". // Remove undefined entries and convert null to "NULL".
for (const name in data) { for (const name in data) {
const value = data[name]; if (typeof data[name] == 'undefined') {
if (typeof value == 'undefined') {
delete data[name]; delete data[name];
} }
} }
} }
/**
* Format the data to where params.
*
* @param data Object data.
*/
protected formatDataToSQLParams(data: SQLiteDBRecordValues): SQLiteDBRecordValue[] {
return Object.keys(data).map((key) => data[key]);
}
/** /**
* Get all the records from a table. * Get all the records from a table.
* *
* @param table The table to query. * @param table The table to query.
* @return Promise resolved with the records. * @return Promise resolved with the records.
*/ */
getAllRecords(table: string): Promise<any> { async getAllRecords(table: string): Promise<SQLiteDBRecordValues[]> {
return this.getRecords(table); return this.getRecords(table);
} }
@ -464,7 +476,7 @@ export class SQLiteDB {
* @param conditions The conditions to build the where clause. Must not contain numeric indexes. * @param conditions The conditions to build the where clause. Must not contain numeric indexes.
* @return Promise resolved with the field's value. * @return Promise resolved with the field's value.
*/ */
getField(table: string, field: string, conditions?: object): Promise<any> { async getField(table: string, field: string, conditions?: SQLiteDBRecordValues): Promise<SQLiteDBRecordValue> {
const selectAndParams = this.whereClause(conditions); const selectAndParams = this.whereClause(conditions);
return this.getFieldSelect(table, field, selectAndParams[0], selectAndParams[1]); return this.getFieldSelect(table, field, selectAndParams[0], selectAndParams[1]);
@ -479,7 +491,8 @@ export class SQLiteDB {
* @param params Array of sql parameters. * @param params Array of sql parameters.
* @return Promise resolved with the field's value. * @return Promise resolved with the field's value.
*/ */
getFieldSelect(table: string, field: string, select: string = '', params?: any[]): Promise<any> { async getFieldSelect(table: string, field: string, select: string = '', params?: SQLiteDBRecordValue[]):
Promise<SQLiteDBRecordValue> {
if (select) { if (select) {
select = 'WHERE ' + select; select = 'WHERE ' + select;
} }
@ -494,10 +507,10 @@ export class SQLiteDB {
* @param params An array of sql parameters. * @param params An array of sql parameters.
* @return Promise resolved with the field's value. * @return Promise resolved with the field's value.
*/ */
async getFieldSql(sql: string, params?: any[]): Promise<any> { async getFieldSql(sql: string, params?: SQLiteDBRecordValue[]): Promise<SQLiteDBRecordValue> {
const record = await this.getRecordSql(sql, params); const record = await this.getRecordSql(sql, params);
if (!record) { if (!record) {
return Promise.reject(null); throw null;
} }
return record[Object.keys(record)[0]]; return record[Object.keys(record)[0]];
@ -512,17 +525,14 @@ export class SQLiteDB {
* meaning return empty. Other values will become part of the returned SQL fragment. * meaning return empty. Other values will become part of the returned SQL fragment.
* @return A list containing the constructed sql fragment and an array of parameters. * @return A list containing the constructed sql fragment and an array of parameters.
*/ */
getInOrEqual(items: any, equal: boolean = true, onEmptyItems?: any): any[] { getInOrEqual(items: SQLiteDBRecordValue | SQLiteDBRecordValue[], equal: boolean = true, onEmptyItems?: SQLiteDBRecordValue):
let sql; SQLiteDBQueryParams {
let params; let sql = '';
let params: SQLiteDBRecordValue[];
if (typeof onEmptyItems == 'undefined') {
onEmptyItems = false;
}
// Default behavior, return empty data on empty array. // Default behavior, return empty data on empty array.
if (Array.isArray(items) && !items.length && onEmptyItems === false) { if (Array.isArray(items) && !items.length && typeof onEmptyItems == 'undefined') {
return ['', []]; return { sql: '', params: [] };
} }
// Handle onEmptyItems on empty array of items. // Handle onEmptyItems on empty array of items.
@ -530,7 +540,7 @@ export class SQLiteDB {
if (onEmptyItems === null) { // Special case, NULL value. if (onEmptyItems === null) { // Special case, NULL value.
sql = equal ? ' IS NULL' : ' IS NOT NULL'; sql = equal ? ' IS NULL' : ' IS NOT NULL';
return [sql, []]; return { sql, params: [] };
} else { } else {
items = [onEmptyItems]; // Rest of cases, prepare items for processing. items = [onEmptyItems]; // Rest of cases, prepare items for processing.
} }
@ -544,7 +554,7 @@ export class SQLiteDB {
params = items; params = items;
} }
return [sql, params]; return { sql, params };
} }
/** /**
@ -564,7 +574,7 @@ export class SQLiteDB {
* @param fields A comma separated list of fields to return. * @param fields A comma separated list of fields to return.
* @return Promise resolved with the record, rejected if not found. * @return Promise resolved with the record, rejected if not found.
*/ */
getRecord(table: string, conditions?: object, fields: string = '*'): Promise<any> { getRecord(table: string, conditions?: SQLiteDBRecordValues, fields: string = '*'): Promise<SQLiteDBRecordValues> {
const selectAndParams = this.whereClause(conditions); const selectAndParams = this.whereClause(conditions);
return this.getRecordSelect(table, selectAndParams[0], selectAndParams[1], fields); return this.getRecordSelect(table, selectAndParams[0], selectAndParams[1], fields);
@ -579,7 +589,8 @@ export class SQLiteDB {
* @param fields A comma separated list of fields to return. * @param fields A comma separated list of fields to return.
* @return Promise resolved with the record, rejected if not found. * @return Promise resolved with the record, rejected if not found.
*/ */
getRecordSelect(table: string, select: string = '', params: any[] = [], fields: string = '*'): Promise<any> { getRecordSelect(table: string, select: string = '', params: SQLiteDBRecordValue[] = [], fields: string = '*'):
Promise<SQLiteDBRecordValues> {
if (select) { if (select) {
select = ' WHERE ' + select; select = ' WHERE ' + select;
} }
@ -597,11 +608,11 @@ export class SQLiteDB {
* @param params List of sql parameters * @param params List of sql parameters
* @return Promise resolved with the records. * @return Promise resolved with the records.
*/ */
async getRecordSql(sql: string, params?: any[]): Promise<any> { async getRecordSql(sql: string, params?: SQLiteDBRecordValue[]): Promise<SQLiteDBRecordValues> {
const result = await this.getRecordsSql(sql, params, 0, 1); const result = await this.getRecordsSql(sql, params, 0, 1);
if (!result || !result.length) { if (!result || !result.length) {
// Not found, reject. // Not found, reject.
return Promise.reject(null); throw null;
} }
return result[0]; return result[0];
@ -618,8 +629,8 @@ export class SQLiteDB {
* @param limitNum Return a subset comprising this many records in total. * @param limitNum Return a subset comprising this many records in total.
* @return Promise resolved with the records. * @return Promise resolved with the records.
*/ */
getRecords(table: string, conditions?: object, sort: string = '', fields: string = '*', limitFrom: number = 0, getRecords(table: string, conditions?: SQLiteDBRecordValues, sort: string = '', fields: string = '*', limitFrom: number = 0,
limitNum: number = 0): Promise<any> { limitNum: number = 0): Promise<SQLiteDBRecordValues[]> {
const selectAndParams = this.whereClause(conditions); const selectAndParams = this.whereClause(conditions);
return this.getRecordsSelect(table, selectAndParams[0], selectAndParams[1], sort, fields, limitFrom, limitNum); return this.getRecordsSelect(table, selectAndParams[0], selectAndParams[1], sort, fields, limitFrom, limitNum);
@ -637,8 +648,8 @@ export class SQLiteDB {
* @param limitNum Return a subset comprising this many records in total. * @param limitNum Return a subset comprising this many records in total.
* @return Promise resolved with the records. * @return Promise resolved with the records.
*/ */
getRecordsList(table: string, field: string, values: any[], sort: string = '', fields: string = '*', limitFrom: number = 0, getRecordsList(table: string, field: string, values: SQLiteDBRecordValue[], sort: string = '', fields: string = '*',
limitNum: number = 0): Promise<any> { limitFrom: number = 0, limitNum: number = 0): Promise<SQLiteDBRecordValues[]> {
const selectAndParams = this.whereClauseList(field, values); const selectAndParams = this.whereClauseList(field, values);
return this.getRecordsSelect(table, selectAndParams[0], selectAndParams[1], sort, fields, limitFrom, limitNum); return this.getRecordsSelect(table, selectAndParams[0], selectAndParams[1], sort, fields, limitFrom, limitNum);
@ -656,8 +667,8 @@ export class SQLiteDB {
* @param limitNum Return a subset comprising this many records in total. * @param limitNum Return a subset comprising this many records in total.
* @return Promise resolved with the records. * @return Promise resolved with the records.
*/ */
getRecordsSelect(table: string, select: string = '', params: any[] = [], sort: string = '', fields: string = '*', getRecordsSelect(table: string, select: string = '', params: SQLiteDBRecordValue[] = [], sort: string = '',
limitFrom: number = 0, limitNum: number = 0): Promise<any> { fields: string = '*', limitFrom: number = 0, limitNum: number = 0): Promise<SQLiteDBRecordValues[]> {
if (select) { if (select) {
select = ' WHERE ' + select; select = ' WHERE ' + select;
} }
@ -679,7 +690,8 @@ export class SQLiteDB {
* @param limitNum Return a subset comprising this many records. * @param limitNum Return a subset comprising this many records.
* @return Promise resolved with the records. * @return Promise resolved with the records.
*/ */
async getRecordsSql(sql: string, params?: any[], limitFrom?: number, limitNum?: number): Promise<any> { async getRecordsSql(sql: string, params?: SQLiteDBRecordValue[], limitFrom?: number, limitNum?: number):
Promise<SQLiteDBRecordValues[]> {
const limits = this.normaliseLimitFromNum(limitFrom, limitNum); const limits = this.normaliseLimitFromNum(limitFrom, limitNum);
if (limits[0] || limits[1]) { if (limits[0] || limits[1]) {
@ -706,31 +718,31 @@ export class SQLiteDB {
* @param data A data object with values for one or more fields in the record. * @param data A data object with values for one or more fields in the record.
* @return Array with the SQL query and the params. * @return Array with the SQL query and the params.
*/ */
protected getSqlInsertQuery(table: string, data: object): any[] { protected getSqlInsertQuery(table: string, data: SQLiteDBRecordValues): SQLiteDBQueryParams {
this.formatDataToInsert(data); this.formatDataToInsert(data);
const keys = Object.keys(data); const keys = Object.keys(data);
const fields = keys.join(','); const fields = keys.join(',');
const questionMarks = ',?'.repeat(keys.length).substr(1); const questionMarks = ',?'.repeat(keys.length).substr(1);
return [ return {
`INSERT OR REPLACE INTO ${table} (${fields}) VALUES (${questionMarks})`, sql: `INSERT OR REPLACE INTO ${table} (${fields}) VALUES (${questionMarks})`,
keys.map((key) => data[key]) params: this.formatDataToSQLParams(data),
]; };
} }
/** /**
* Initialize the database. * Initialize the database.
*/ */
init(): void { init(): void {
this.promise = Platform.instance.ready().then(() => { this.promise = Platform.instance.ready()
return SQLite.instance.create({ .then(() => SQLite.instance.create({
name: this.name, name: this.name,
location: 'default' location: 'default',
}))
.then((db: SQLiteObject) => {
this.db = db;
}); });
}).then((db: SQLiteObject) => {
this.db = db;
});
} }
/** /**
@ -740,7 +752,7 @@ export class SQLiteDB {
* @param data A data object with values for one or more fields in the record. * @param data A data object with values for one or more fields in the record.
* @return Promise resolved with new rowId. Please notice this rowId is internal from SQLite. * @return Promise resolved with new rowId. Please notice this rowId is internal from SQLite.
*/ */
async insertRecord(table: string, data: object): Promise<number> { async insertRecord(table: string, data: SQLiteDBRecordValues): Promise<number> {
const sqlAndParams = this.getSqlInsertQuery(table, data); const sqlAndParams = this.getSqlInsertQuery(table, data);
const result = await this.execute(sqlAndParams[0], sqlAndParams[1]); const result = await this.execute(sqlAndParams[0], sqlAndParams[1]);
@ -754,18 +766,18 @@ export class SQLiteDB {
* @param dataObjects List of objects to be inserted. * @param dataObjects List of objects to be inserted.
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
insertRecords(table: string, dataObjects: object[]): Promise<any> { async insertRecords(table: string, dataObjects: SQLiteDBRecordValues[]): Promise<void> {
if (!Array.isArray(dataObjects)) { if (!Array.isArray(dataObjects)) {
return Promise.reject(null); throw null;
} }
const statements = []; const statements = dataObjects.map((dataObject) => {
const statement = this.getSqlInsertQuery(table, dataObject);
dataObjects.forEach((dataObject) => { return [statement.sql, statement.params];
statements.push(this.getSqlInsertQuery(table, dataObject));
}); });
return this.executeBatch(statements); await this.executeBatch(statements);
} }
/** /**
@ -777,12 +789,13 @@ export class SQLiteDB {
* @param fields A comma separated list of fields to return. * @param fields A comma separated list of fields to return.
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
insertRecordsFrom(table: string, source: string, conditions?: object, fields: string = '*'): Promise<any> { async insertRecordsFrom(table: string, source: string, conditions?: SQLiteDBRecordValues, fields: string = '*'):
Promise<void> {
const selectAndParams = this.whereClause(conditions); const selectAndParams = this.whereClause(conditions);
const select = selectAndParams[0] ? 'WHERE ' + selectAndParams[0] : ''; const select = selectAndParams[0] ? 'WHERE ' + selectAndParams[0] : '';
const params = selectAndParams[1]; const params = selectAndParams[1];
return this.execute(`INSERT INTO ${table} SELECT ${fields} FROM ${source} ${select}`, params); await this.execute(`INSERT INTO ${table} SELECT ${fields} FROM ${source} ${select}`, params);
} }
/** /**
@ -794,19 +807,19 @@ export class SQLiteDB {
* @param limitNum How many results to return. * @param limitNum How many results to return.
* @return Normalised limit params in array: [limitFrom, limitNum]. * @return Normalised limit params in array: [limitFrom, limitNum].
*/ */
normaliseLimitFromNum(limitFrom: any, limitNum: any): number[] { normaliseLimitFromNum(limitFrom: number, limitNum: number): number[] {
// We explicilty treat these cases as 0. // We explicilty treat these cases as 0.
if (typeof limitFrom == 'undefined' || limitFrom === null || limitFrom === '' || limitFrom === -1) { if (!limitFrom || limitFrom === -1) {
limitFrom = 0; limitFrom = 0;
} } else {
if (typeof limitNum == 'undefined' || limitNum === null || limitNum === '' || limitNum === -1) { limitFrom = Math.max(0, limitFrom);
limitNum = 0;
} }
limitFrom = parseInt(limitFrom, 10); if (!limitNum || limitNum === -1) {
limitNum = parseInt(limitNum, 10); limitNum = 0;
limitFrom = Math.max(0, limitFrom); } else {
limitNum = Math.max(0, limitNum); limitNum = Math.max(0, limitNum);
}
return [limitFrom, limitNum]; return [limitFrom, limitNum];
} }
@ -816,10 +829,10 @@ export class SQLiteDB {
* *
* @return Promise resolved when open. * @return Promise resolved when open.
*/ */
async open(): Promise<any> { async open(): Promise<void> {
await this.ready(); await this.ready();
return this.db.open(); await this.db.open();
} }
/** /**
@ -838,10 +851,10 @@ export class SQLiteDB {
* @param conditions The conditions to build the where clause. Must not contain numeric indexes. * @param conditions The conditions to build the where clause. Must not contain numeric indexes.
* @return Promise resolved if exists, rejected otherwise. * @return Promise resolved if exists, rejected otherwise.
*/ */
async recordExists(table: string, conditions?: object): Promise<void> { async recordExists(table: string, conditions?: SQLiteDBRecordValues): Promise<void> {
const record = await this.getRecord(table, conditions); const record = await this.getRecord(table, conditions);
if (!record) { if (!record) {
return Promise.reject(null); throw null;
} }
} }
@ -853,10 +866,10 @@ export class SQLiteDB {
* @param params An array of sql parameters. * @param params An array of sql parameters.
* @return Promise resolved if exists, rejected otherwise. * @return Promise resolved if exists, rejected otherwise.
*/ */
async recordExistsSelect(table: string, select: string = '', params: any[] = []): Promise<void> { async recordExistsSelect(table: string, select: string = '', params: SQLiteDBRecordValue[] = []): Promise<void> {
const record = await this.getRecordSelect(table, select, params); const record = await this.getRecordSelect(table, select, params);
if (!record) { if (!record) {
return Promise.reject(null); throw null;
} }
} }
@ -867,10 +880,10 @@ export class SQLiteDB {
* @param params An array of sql parameters. * @param params An array of sql parameters.
* @return Promise resolved if exists, rejected otherwise. * @return Promise resolved if exists, rejected otherwise.
*/ */
async recordExistsSql(sql: string, params?: any[]): Promise<void> { async recordExistsSql(sql: string, params?: SQLiteDBRecordValue[]): Promise<void> {
const record = await this.getRecordSql(sql, params); const record = await this.getRecordSql(sql, params);
if (!record) { if (!record) {
return Promise.reject(null); throw null;
} }
} }
@ -881,7 +894,8 @@ export class SQLiteDB {
* @return Promise resolved if exists, rejected otherwise. * @return Promise resolved if exists, rejected otherwise.
*/ */
async tableExists(name: string): Promise<void> { async tableExists(name: string): Promise<void> {
await this.recordExists('sqlite_master', {type: 'table', tbl_name: name}); // eslint-disable-next-line @typescript-eslint/naming-convention
await this.recordExists('sqlite_master', { type: 'table', tbl_name: name });
} }
/** /**
@ -890,31 +904,12 @@ export class SQLiteDB {
* @param string table The database table to update. * @param string table The database table to update.
* @param data An object with the fields to update: fieldname=>fieldvalue. * @param data An object with the fields to update: fieldname=>fieldvalue.
* @param conditions The conditions to build the where clause. Must not contain numeric indexes. * @param conditions The conditions to build the where clause. Must not contain numeric indexes.
* @return Promise resolved when updated. * @return Promise resolved with the number of affected rows.
*/ */
updateRecords(table: string, data: any, conditions?: any): Promise<any> { async updateRecords(table: string, data: SQLiteDBRecordValues, conditions?: SQLiteDBRecordValues): Promise<number> {
this.formatDataToInsert(data);
if (!data || !Object.keys(data).length) {
// No fields to update, consider it's done.
return Promise.resolve();
}
const whereAndParams = this.whereClause(conditions); const whereAndParams = this.whereClause(conditions);
const sets = [];
let sql;
let params;
for (const key in data) { return this.updateRecordsWhere(table, data, whereAndParams[0], whereAndParams[1]);
sets.push(`${key} = ?`);
}
sql = `UPDATE ${table} SET ${sets.join(', ')} WHERE ${whereAndParams[0]}`;
// Create the list of params using the "data" object and the params for the where clause.
params = Object.keys(data).map((key) => data[key]).concat(whereAndParams[1]);
return this.execute(sql, params);
} }
/** /**
@ -924,34 +919,35 @@ export class SQLiteDB {
* @param data An object with the fields to update: fieldname=>fieldvalue. * @param data An object with the fields to update: fieldname=>fieldvalue.
* @param where Where clause. Must not include the "WHERE" word. * @param where Where clause. Must not include the "WHERE" word.
* @param whereParams Params for the where clause. * @param whereParams Params for the where clause.
* @return Promise resolved when updated. * @return Promise resolved with the number of affected rows.
*/ */
updateRecordsWhere(table: string, data: any, where?: string, whereParams?: any[]): Promise<any> { async updateRecordsWhere(table: string, data: SQLiteDBRecordValues, where?: string, whereParams?: SQLiteDBRecordValue[]):
Promise<number> {
this.formatDataToInsert(data);
if (!data || !Object.keys(data).length) { if (!data || !Object.keys(data).length) {
// No fields to update, consider it's done. // No fields to update, consider it's done.
return Promise.resolve(); return 0;
} }
const sets = []; const sets = [];
let sql;
let params;
for (const key in data) { for (const key in data) {
sets.push(`${key} = ?`); sets.push(`${key} = ?`);
} }
sql = `UPDATE ${table} SET ${sets.join(', ')}`; let sql = `UPDATE ${table} SET ${sets.join(', ')}`;
if (where) { if (where) {
sql += ` WHERE ${where}`; sql += ` WHERE ${where}`;
} }
// Create the list of params using the "data" object and the params for the where clause. // Create the list of params using the "data" object and the params for the where clause.
params = Object.keys(data).map((key) => data[key]); let params = this.formatDataToSQLParams(data);
if (where && whereParams) { if (where && whereParams) {
params = params.concat(whereParams); params = params.concat(whereParams);
} }
return this.execute(sql, params); const result = await this.execute(sql, params);
return result.rowsAffected;
} }
/** /**
@ -960,9 +956,12 @@ export class SQLiteDB {
* @param conditions The conditions to build the where clause. Must not contain numeric indexes. * @param conditions The conditions to build the where clause. Must not contain numeric indexes.
* @return An array list containing sql 'where' part and 'params'. * @return An array list containing sql 'where' part and 'params'.
*/ */
whereClause(conditions: any = {}): any[] { whereClause(conditions: SQLiteDBRecordValues = {}): SQLiteDBQueryParams {
if (!conditions || !Object.keys(conditions).length) { if (!conditions || !Object.keys(conditions).length) {
return ['1 = 1', []]; return {
sql: '1 = 1',
params: [],
};
} }
const where = []; const where = [];
@ -979,7 +978,10 @@ export class SQLiteDB {
} }
} }
return [where.join(' AND '), params]; return {
sql: where.join(' AND '),
params,
};
} }
/** /**
@ -989,39 +991,50 @@ export class SQLiteDB {
* @param values The values field might take. * @param values The values field might take.
* @return An array containing sql 'where' part and 'params'. * @return An array containing sql 'where' part and 'params'.
*/ */
whereClauseList(field: string, values: any[]): any[] { whereClauseList(field: string, values: SQLiteDBRecordValue[]): SQLiteDBQueryParams {
if (!values || !values.length) { if (!values || !values.length) {
return ['1 = 2', []]; // Fake condition, won't return rows ever. return {
sql: '1 = 2', // Fake condition, won't return rows ever.
params: [],
};
} }
const params = []; const params = [];
let select = ''; let sql = '';
values.forEach((value) => { values.forEach((value) => {
if (typeof value == 'boolean') {
value = Number(value);
}
if (typeof value == 'undefined' || value === null) { if (typeof value == 'undefined' || value === null) {
select = field + ' IS NULL'; sql = field + ' IS NULL';
} else { } else {
params.push(value); params.push(value);
} }
}); });
if (params && params.length) { if (params && params.length) {
if (select !== '') { if (sql !== '') {
select = select + ' OR '; sql = sql + ' OR ';
} }
if (params.length == 1) { if (params.length == 1) {
select = select + field + ' = ?'; sql = sql + field + ' = ?';
} else { } else {
const questionMarks = ',?'.repeat(params.length).substr(1); const questionMarks = ',?'.repeat(params.length).substr(1);
select = select + field + ' IN (' + questionMarks + ')'; sql = sql + field + ' IN (' + questionMarks + ')';
} }
} }
return [select, params]; return { sql, params };
} }
} }
export type SQLiteDBRecordValues = {
[key in string ]: SQLiteDBRecordValue;
};
export type SQLiteDBQueryParams = {
sql: string;
params: SQLiteDBRecordValue[];
};
type SQLiteDBRecordValue = number | string;