import ConnectionExecutable from './ConnectionExecutable.ts' import {QueryResult, QueryRow} from '../../db/types.ts' import {Connection} from '../../db/Connection.ts' import {Collection} from '../../../../lib/src/collection/Collection.ts' import NoTargetOperatorError from '../../error/NoTargetOperatorError.ts' /** * Variant of the ConnectionExecutable used to build queries that mutate data. This * structure overrides methods to ensure that the query is run only once. * @extends ConnectionExecutable * @abstract */ export default abstract class ConnectionMutable extends ConnectionExecutable { /** * The cached execution result. * @type QueryResult */ __execution_result?: QueryResult async get_row(i: number): Promise { const result = await this.get_execution_result() const row = result.rows.at(i) if ( !this.__target_operator ) throw new NoTargetOperatorError() if ( row ) return this.__target_operator.inflate_row(row) } async get_range(start: number, end: number): Promise> { const result = await this.get_execution_result() const rows: Collection = result.rows.slice(start, end + 1) as Collection return rows.map(row => { if ( !this.__target_operator ) throw new NoTargetOperatorError() return this.__target_operator.inflate_row(row) }) } async count() { const result = await this.get_execution_result() return result.row_count } /** * Get the query result. Executes the query if it hasn't already. If it has, * return the cached query result. * @return Promise */ async get_execution_result(): Promise { if ( this.__execution_result ) return this.__execution_result else return this.execute() } async execute_in_connection(connection: string | Connection): Promise { const result = await super.execute_in_connection(connection) this.__execution_result = result return result } }