import * as knex from 'knex' ; import { Hydrator } from './Hydrator' ; import { QueryBuilder } from './QueryBuilder' ; export class Query { type { Hydrator } private hydrator : Hydrator ; type { { } } private statement : knex . QueryBuilder ; type { { } } private parent : { column : string ; primaries : Array < number | string > ; } ; type { Array } private children : Array < QueryBuilder < { new ( ) ; } > > = [ ] ; param { knex . QueryBuilder } statement param { Hydrator } hydrator param { [ ] } children public constructor ( statement , hydrator , children = [ ] ) { this . statement = statement ; this . hydrator = hydrator ; this . children = children ; } param parent returns { Query } public setParent ( parent ) { this . parent = parent ; return this ; } returns { Promise < [ ] > } public execute ( ) { const query = this . restrictToParent ( ) ; if ( process . env . LOG_QUERIES ) { console . log ( 'Executing query:' , query . toString ( ) ) ; } return Promise . resolve ( query . then ( ) ) ; } returns { Promise < number > } public getSingleScalarResult ( ) { return this . execute ( ) . then ( result => { if ( ! result || typeof result [ 0 ] !== 'object' ) { return null ; } return result [ 0 ] [ Object . keys ( result [ 0 ] ) [ 0 ] ] ; } ) ; } returns { Promise < { } [ ] > } public getResult ( ) { return this . execute ( ) . then ( result => { if ( ! result || ! result . length ) { return null ; } const hydrated = this . hydrator . hydrateAll ( result ) ; return Promise . all ( this . children . map ( child => { return child . getQuery ( ) . getResult ( ) ; } ) ) . then ( ( ) => hydrated ) ; } ) ; } returns { string } public getSQL ( ) { return this . statement . toString ( ) ; } returns { knex . QueryBuilder } public getStatement ( ) { return this . statement ; } returns { any } private restrictToParent ( ) { const statement = this . statement ; if ( ! this . parent || ! this . parent . primaries . length ) { return statement ; } const parent = this . parent ; if ( parent . primaries . length === 1 ) { statement . where ( parent . column , parent . primaries [ 0 ] ) ; return statement ; } const client = statement [ 'client' ] ; const unionized = client . queryBuilder ( ) ; parent . primaries . forEach ( primary => { const toUnion = statement . clone ( ) . where ( parent . column , primary ) ; if ( client . config . client === 'sqlite3' || client . config . client === 'sqlite' ) { unionized . union ( client . queryBuilder ( ) . select ( '*' ) . from ( client . raw ( toUnion ) . wrap ( '(' , ')' ) ) ) ; return unionized ; } unionized . union ( toUnion , true ) ; } ) ; return unionized ; } }