import { ObjectLiteral } from "../../common/ObjectLiteral" import { QueryRunnerAlreadyReleasedError } from "../../error/QueryRunnerAlreadyReleasedError" import { QueryFailedError } from "../../error/QueryFailedError" import { AbstractSqliteQueryRunner } from "../sqlite-abstract/AbstractSqliteQueryRunner" import { NativescriptDriver } from "./NativescriptDriver" import { Broadcaster } from "../../subscriber/Broadcaster" import { QueryResult } from "../../query-runner/QueryResult" /** * Runs queries on a single sqlite database connection. */ export class NativescriptQueryRunner extends AbstractSqliteQueryRunner { /** * Database driver used by connection. */ driver: NativescriptDriver // ------------------------------------------------------------------------- // Constructor // ------------------------------------------------------------------------- constructor(driver: NativescriptDriver) { super() this.driver = driver this.connection = driver.connection this.broadcaster = new Broadcaster(this) } /** * Called before migrations are run. */ async beforeMigration(): Promise { await this.query(`PRAGMA foreign_keys = OFF`) } /** * Called after migrations are run. */ async afterMigration(): Promise { await this.query(`PRAGMA foreign_keys = ON`) } /** * Executes a given SQL query. */ async query( query: string, parameters?: any[], useStructuredResult = false, ): Promise { if (this.isReleased) { throw new QueryRunnerAlreadyReleasedError() } const connection = this.driver.connection return new Promise(async (ok, fail) => { const databaseConnection = await this.connect() const isInsertQuery = query.substr(0, 11) === "INSERT INTO" connection.logger.logQuery(query, parameters, this) const handler = (err: any, raw: any) => { // log slow queries if maxQueryExecution time is set const maxQueryExecutionTime = this.driver.options.maxQueryExecutionTime const queryEndTime = +new Date() const queryExecutionTime = queryEndTime - queryStartTime if ( maxQueryExecutionTime && queryExecutionTime > maxQueryExecutionTime ) { connection.logger.logQuerySlow( queryExecutionTime, query, parameters, this, ) } if (err) { connection.logger.logQueryError( err, query, parameters, this, ) fail(new QueryFailedError(query, parameters, err)) } const result = new QueryResult() result.raw = raw if (!isInsertQuery && Array.isArray(raw)) { result.records = raw } if (useStructuredResult) { ok(result) } else { ok(result.raw) } } const queryStartTime = +new Date() if (isInsertQuery) { databaseConnection.execSQL(query, parameters, handler) } else { databaseConnection.all(query, parameters, handler) } }) } // ------------------------------------------------------------------------- // Protected Methods // ------------------------------------------------------------------------- /** * Parametrizes given object of values. Used to create column=value queries. */ protected parametrize( objectLiteral: ObjectLiteral, startIndex: number = 0, ): string[] { return Object.keys(objectLiteral).map((key, index) => `"${key}"` + "=?") } }