import {Model} from "./Model"; import {AbstractResultIterable} from "../builder/result/AbstractResultIterable"; import {Connection} from "../connection/Connection"; import {ModelBuilder} from "./ModelBuilder"; import {Container, Instantiable} from "../../di"; import {QueryRow} from "../types"; import {Collection} from "../../util"; /** * Implementation of the result iterable that returns query results as instances of the defined model. */ export class ModelResultIterable> extends AbstractResultIterable { constructor( public readonly builder: ModelBuilder, public readonly connection: Connection, /** The model that should be instantiated for each row. */ protected readonly ModelClass: Instantiable ) { super(builder, connection) } public get selectSQL() { return this.connection.dialect().renderSelect(this.builder) } async at(i: number) { const query = this.connection.dialect().renderRangedSelect(this.selectSQL, i, i + 1) const row = (await this.connection.query(query)).rows.first() if ( row ) { return this.inflateRow(row) } } async range(start: number, end: number): Promise> { const query = this.connection.dialect().renderRangedSelect(this.selectSQL, start, end) return (await this.connection.query(query)).rows.promiseMap(row => this.inflateRow(row)) } async count() { const query = this.connection.dialect().renderCount(this.selectSQL) const result = (await this.connection.query(query)).rows.first() return result?.extollo_render_count ?? 0 } async all(): Promise> { const result = await this.connection.query(this.selectSQL) return result.rows.promiseMap(row => this.inflateRow(row)) } /** * Given a query row, create an instance of the configured model class from it. * @param row * @protected */ protected async inflateRow(row: QueryRow): Promise { return Container.getContainer().make(this.ModelClass).assumeFromSource(row) } clone() { return new ModelResultIterable(this.builder, this.connection, this.ModelClass) } }