import {QueryResult} from '../../db/types.ts' import {make} from '../../../../di/src/global.ts' import Database from '../../service/Database.ts' import {logger} from '../../../../lib/src/service/logging/global.ts' import {Connection} from '../../db/Connection.ts' import {ResultCollection} from './result/ResultCollection.ts' import {ResultIterable} from './result/ResultIterable.ts' import ResultOperator from './result/ResultOperator.ts' import ObjectResultOperator from './result/ObjectResultOperator.ts' export default abstract class ConnectionExecutable { abstract sql(level: number): string to_count(): string { return `SELECT COUNT(*) AS to_count FROM (${this.sql(0)}) AS target_query` } async get_row(i: number) { if ( !(this.__target_connection instanceof Connection) ) { throw new Error('Unable to execute database item: no target connection.') } const query = `SELECT * FROM (${this.sql(0)}) AS target_query OFFSET ${i} LIMIT 1` const result = await this.__target_connection.query(query) const row = result.rows.first() if ( row ) return this.__target_operator.inflate_row(row) } async get_range(start: number, end: number) { if ( !(this.__target_connection instanceof Connection) ) { throw new Error('Unable to execute database item: no target connection.') } const query = `SELECT * FROM (${this.sql(0)}) AS target_query OFFSET ${start} LIMIT ${(end - start) + 1}` const result = await this.__target_connection.query(query) return result.rows.map(row => this.__target_operator.inflate_row(row)) } iterator() { return new ResultIterable(this) } results(chunk_size = 1000) { return new ResultCollection(this.iterator(), chunk_size) } __target_connection?: Connection __target_operator: ResultOperator = new ObjectResultOperator() target_connection(connection: string | Connection) { this.__target_connection = typeof connection === 'string' ? make(Database).connection(connection) : connection return this } target_operator(operator: ResultOperator) { this.__target_operator = operator return this } async execute(): Promise { if ( !(this.__target_connection instanceof Connection) ) { throw new Error('Unable to execute database item: no target connection.') } return this.execute_in_connection(this.__target_connection) } async count(): Promise { if ( !(this.__target_connection instanceof Connection) ) { throw new Error('Unable to execute database item: no target connection.') } const result = await this.__target_connection.query(this.to_count()) const row = result.rows.first() if ( row ) return Number(row.to_count) return 0 } async execute_in_connection(connection: string | Connection): Promise { const conn = typeof connection === 'string' ? make(Database).connection(connection) : connection logger.debug(`Executing statement in connection: ${conn.name}`) const sql = this.sql(0) logger.verbose(sql) return conn.query(sql) } }