You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

90 lines
3.2 KiB

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<any> = new ObjectResultOperator()
target_connection(connection: string | Connection) {
this.__target_connection = typeof connection === 'string' ? make(Database).connection(connection) : connection
return this
}
target_operator(operator: ResultOperator<any>) {
this.__target_operator = operator
return this
}
async execute(): Promise<QueryResult> {
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<number> {
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<QueryResult> {
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)
}
}