import {IJoin} from "../join"; import {IAliasedTable} from "../aliased-table"; import {SelectItem} from "../select-item"; import {IAnonymousTypedExpr} from "../expr"; import * as QueryUtil from "./util"; import {ColumnIdentifier} from "../column-identifier"; import {Order} from "../order"; import {MapDelegate} from "../map-delegate"; import {DISTINCT} from "../constants"; import {NonEmptyTuple} from "../tuple"; import {ITable, TableWithPk} from "../table"; import {RawExpr, RawExprUtil} from "../raw-expr"; import {PrimitiveExpr, NonNullPrimitiveExpr} from "../primitive-expr"; import {IJoinDeclaration} from "../join-declaration"; import {IConnection} from "../execution"; import {InsertSelectRowDelegate} from "../insert-select"; import {UpdateUtil, UpdatableQuery} from "../update"; import {DeletableQuery, DeleteUtil, Delete, DeleteModifier} from "../delete"; import {Row} from "../row"; import {CandidateKey} from "../candidate-key"; import {PrimaryKey} from "../primary-key"; import {SuperKey} from "../super-key"; export interface UnionQuery { //Defaults to true readonly distinct : boolean, readonly query : QueryUtil.AfterSelectClause, } //TODO-DEBATE consider allowing this to be bigint? //A maxRowCount/offset of 3.141 would be weird export interface LimitData { //This is called "max"RowCount and not rowCount //(like MySQL calls it) because we can say //we want a maxRowCount of 10 and only get 3 rows. //Or a maxRowCount of 1 and get zero rows. readonly maxRowCount : number, readonly offset : number, } /* TODO-FEATURE Implement support for SQL_MODE=ONLY_FULL_GROUP_BY Supporting it will increase compile-time safety for queries. I don't know enough to implement this at the moment. Reject queries for which the + select list, + HAVING condition, or + ORDER BY list refer to nonaggregated columns that are neither 1. named in the GROUP BY clause nor are 2. functionally dependent on (uniquely determined by) GROUP BY columns. Part 1 seems "easy" enough. Part 2 is the challenging part. I *think* I have to look at the GROUP BY columns and also look at the candidate keys of the tables. 1. If the GROUP BY columns are a super-set of any candidate key of a table, then we can refer to any column of the table. 2. If the GROUP BY columns are used in the ON clause of a JOIN, then the columns they are equal to are also part of the GROUP BY columns. SELECT app.name FROM app JOIN user ON app.appId = user.appId GROUP BY user.appId In the above example, user.appId is in the GROUP BY columns. But we also have app.appId = user.appId in the ON clause. So, app.appId is implicitly part of the GROUP BY columns. And because app.appId is a super-set of a candidate key of the table app, then we can refer to any column of the app table. It seems like if I want to implement ONLY_FULL_GROUP_BY support, I'll need to also strongly type the ON clause of IJoin. My life is not going to be easy =/ ----- TODO-FEATURE Disable aggregate functions in WHERE clause This can probably be achieved by tagging certain interfaces with a `usesAggregateFunction` field. TODO-FEATURE Type narrowing where expressions + Same with WHERE, implemented internally with WHERE DISTINCT + Loose type (boolean) SQL_CALC_FOUND_ROWS + Loose type (boolean) FROM + Tight type JOIN + Tight type + Must be done after FROM clause + Uses joins SELECT + Tight type + Must be done after FROM clause + Uses joins/parentJoins WHERE + Loose type (IAnonymousTypedExpr, undefined) + Must be done after FROM clause + Uses joins + Aggregate functions NOT allowed GROUP_BY + Loose type (ColumnIdentifier[], undefined) + Must be done after FROM clause + Uses joins and selects HAVING + Loose type (IAnonymousTypedExpr, undefined) + Must be done after FROM clause + Uses joins and selects + Aggregate functions allowed + TECHNICALLY, can only use columns in GROUP BY, or columns in aggregate functions, But MySQL supports an extension that allows columns from SELECT As such, this library does not check for valid columns here ORDER_BY + Loose type (Order[], undefined) The actual type is a bit more complicated, it may allow a tuple with ASCENDING or DESCENDING + Must be done after FROM clause You can technically call this before FROM clause but there's little point in doing it... Why order one row? + Uses joins and selects LIMIT + Tight type Required so we know this query has a maxRowCount of 1 UNION + Loose type (UnionQuery[], undefined) + Must be done after SELECT clause + Selected columns of UNION must match SELECT clause UNION's ORDER BY (Uses selects) + Loose type (Order[], undefined) The actual type is a bit more complicated, it may allow a tuple with ASCENDING or DESCENDING + Must be done after FROM or UNION clause The rationale is that we want to order *more than one row*. We are guaranteed more than one row after a FROM or UNION. + Uses selects UNION's LIMIT + Tight type Required so we know this query has a maxRowCount of 1 Post-query map delegates + Must be done after SELECT clause */ export interface QueryData { /* Prefixed with underscore because, in general, you shouldn't need to access these fields directly. But if you need to, they're there. */ readonly _distinct : boolean; readonly _sqlCalcFoundRows : boolean; readonly _joins : IJoin[]|undefined; readonly _parentJoins : IJoin[]|undefined; readonly _selects : SelectItem[]|undefined; readonly _where : IAnonymousTypedExpr|undefined; //GROUP BY clause columns //They are properly referred to as "aggregated columns" readonly _grouped : ColumnIdentifier[]|undefined; readonly _having : IAnonymousTypedExpr|undefined; readonly _orders : Order[]|undefined; readonly _limit : LimitData|undefined; readonly _unions : UnionQuery[]|undefined; readonly _unionOrders : Order[]|undefined; readonly _unionLimit : LimitData|undefined; readonly _mapDelegate : MapDelegate|undefined; } export interface IQuery { readonly _distinct : DataT["_distinct"]; readonly _sqlCalcFoundRows : DataT["_sqlCalcFoundRows"]; readonly _joins : DataT["_joins"]; readonly _parentJoins : DataT["_parentJoins"]; readonly _selects : DataT["_selects"]; readonly _where : DataT["_where"]; readonly _grouped : DataT["_grouped"]; readonly _having : DataT["_having"]; readonly _orders : DataT["_orders"]; readonly _limit : DataT["_limit"]; readonly _unions : DataT["_unions"]; readonly _unionOrders : DataT["_unionOrders"]; readonly _unionLimit : DataT["_unionLimit"]; readonly _mapDelegate : DataT["_mapDelegate"]; } export class Query { readonly _distinct : DataT["_distinct"]; readonly _sqlCalcFoundRows : DataT["_sqlCalcFoundRows"]; readonly _joins : DataT["_joins"]; readonly _parentJoins : DataT["_parentJoins"]; readonly _selects : DataT["_selects"]; readonly _where : DataT["_where"]; readonly _grouped : DataT["_grouped"]; readonly _having : DataT["_having"]; readonly _orders : DataT["_orders"]; readonly _limit : DataT["_limit"]; readonly _unions : DataT["_unions"]; readonly _unionOrders : DataT["_unionOrders"]; readonly _unionLimit : DataT["_unionLimit"]; readonly _mapDelegate : DataT["_mapDelegate"]; constructor (data : DataT) { this._distinct = data._distinct; this._sqlCalcFoundRows = data._sqlCalcFoundRows; this._joins = data._joins; this._parentJoins = data._parentJoins; this._selects = data._selects; this._where = data._where; this._grouped = data._grouped; this._having = data._having; this._orders = data._orders; this._limit = data._limit; this._unions = data._unions; this._unionOrders = data._unionOrders; this._unionLimit = data._unionLimit; this._mapDelegate = data._mapDelegate; } from< AliasedTableT extends IAliasedTable > ( this : Extract, aliasedTable : QueryUtil.AssertValidJoinTarget< Extract, AliasedTableT > ) : ( QueryUtil.From< Extract, AliasedTableT > ) { return QueryUtil.from< Extract, AliasedTableT >( this, aliasedTable ); } innerJoin< AliasedTableT extends IAliasedTable, FromDelegateT extends QueryUtil.JoinFromDelegate< Extract["_joins"] > > ( this : Extract, aliasedTable : QueryUtil.AssertValidJoinTarget< Extract, AliasedTableT >, fromDelegate : FromDelegateT, toDelegate : QueryUtil.JoinToDelegate< Extract, AliasedTableT, FromDelegateT > ) : ( QueryUtil.InnerJoin< Extract, AliasedTableT > ) { return QueryUtil.innerJoin< Extract, AliasedTableT, FromDelegateT >( this, aliasedTable, fromDelegate, toDelegate ); } leftJoin< AliasedTableT extends IAliasedTable, FromDelegateT extends QueryUtil.JoinFromDelegate< Extract["_joins"] > > ( this : Extract, aliasedTable : QueryUtil.AssertValidJoinTarget< Extract, AliasedTableT >, fromDelegate : FromDelegateT, toDelegate : QueryUtil.JoinToDelegate< Extract, AliasedTableT, FromDelegateT > ) : ( QueryUtil.LeftJoin< Extract, AliasedTableT > ) { return QueryUtil.leftJoin< Extract, AliasedTableT, FromDelegateT >( this, aliasedTable, fromDelegate, toDelegate ); } rightJoin< AliasedTableT extends IAliasedTable, FromDelegateT extends QueryUtil.JoinFromDelegate< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >["_joins"] > > ( this : Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, aliasedTable : QueryUtil.AssertValidJoinTarget< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, AliasedTableT >, fromDelegate : FromDelegateT, toDelegate : QueryUtil.JoinToDelegate< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, AliasedTableT, FromDelegateT > ) : ( QueryUtil.RightJoin< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, AliasedTableT > ) { return QueryUtil.rightJoin< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, AliasedTableT, FromDelegateT >( this, aliasedTable, fromDelegate, toDelegate ); } innerJoinUsing< AliasedTableT extends IAliasedTable, UsingDelegateT extends QueryUtil.JoinUsingDelegate< Extract["_joins"], AliasedTableT > > ( this : Extract, aliasedTable : QueryUtil.AssertValidJoinTarget< Extract, AliasedTableT >, usingDelegate : UsingDelegateT ) : ( QueryUtil.InnerJoin< Extract, AliasedTableT > ) { return QueryUtil.innerJoinUsing< Extract, AliasedTableT, UsingDelegateT >( this, aliasedTable, usingDelegate ); } leftJoinUsing< AliasedTableT extends IAliasedTable, UsingDelegateT extends QueryUtil.JoinUsingDelegate< Extract["_joins"], AliasedTableT > > ( this : Extract, aliasedTable : QueryUtil.AssertValidJoinTarget< Extract, AliasedTableT >, usingDelegate : UsingDelegateT ) : ( QueryUtil.LeftJoin< Extract, AliasedTableT > ) { return QueryUtil.leftJoinUsing< Extract, AliasedTableT, UsingDelegateT >( this, aliasedTable, usingDelegate ); } rightJoinUsing< AliasedTableT extends IAliasedTable, UsingDelegateT extends QueryUtil.JoinUsingDelegate< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >["_joins"], AliasedTableT > > ( this : Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, aliasedTable : QueryUtil.AssertValidJoinTarget< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, AliasedTableT >, usingDelegate : UsingDelegateT ) : ( QueryUtil.RightJoin< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, AliasedTableT > ) { return QueryUtil.rightJoinUsing< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, AliasedTableT, UsingDelegateT >( this, aliasedTable, usingDelegate ); } innerJoinCk< TableT extends ITable, FromDelegateT extends QueryUtil.JoinFromDelegate< Extract["_joins"] >, ToDelegateT extends QueryUtil.JoinToDelegate< Extract, TableT, FromDelegateT > > ( this : Extract, table : QueryUtil.AssertValidJoinTarget< Extract, TableT >, fromDelegate : FromDelegateT, toDelegate : ToDelegateT ) : ( QueryUtil.AssertValidJoinCkDelegate_Hack< Extract, TableT, FromDelegateT, ToDelegateT, QueryUtil.InnerJoin< Extract, TableT > > ) { return QueryUtil.innerJoinCk< Extract, TableT, FromDelegateT, ToDelegateT >( this, table, fromDelegate, toDelegate ); } leftJoinCk< TableT extends ITable, FromDelegateT extends QueryUtil.JoinFromDelegate< Extract["_joins"] >, ToDelegateT extends QueryUtil.JoinToDelegate< Extract, TableT, FromDelegateT > > ( this : Extract, table : QueryUtil.AssertValidJoinTarget< Extract, TableT >, fromDelegate : FromDelegateT, toDelegate : ToDelegateT ) : ( QueryUtil.AssertValidJoinCkDelegate_Hack< Extract, TableT, FromDelegateT, ToDelegateT, QueryUtil.LeftJoin< Extract, TableT > > ) { return QueryUtil.leftJoinCk< Extract, TableT, FromDelegateT, ToDelegateT >( this, table, fromDelegate, toDelegate ); } rightJoinCk< TableT extends ITable, FromDelegateT extends QueryUtil.JoinFromDelegate< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >["_joins"] >, ToDelegateT extends QueryUtil.JoinToDelegate< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, TableT, FromDelegateT > > ( this : Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, table : QueryUtil.AssertValidJoinTarget< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, TableT >, fromDelegate : FromDelegateT, toDelegate : ToDelegateT ) : ( QueryUtil.AssertValidJoinCkDelegate_Hack< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, TableT, FromDelegateT, ToDelegateT, QueryUtil.RightJoin< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, TableT > > ) { return QueryUtil.rightJoinCk< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, TableT, FromDelegateT, ToDelegateT >( this, table, fromDelegate, toDelegate ); } innerJoinCkUsing< TableT extends ITable, UsingDelegateT extends QueryUtil.JoinUsingDelegate< Extract["_joins"], TableT > > ( this : Extract, table : QueryUtil.AssertValidJoinTarget< Extract, TableT >, usingDelegate : UsingDelegateT ) : ( QueryUtil.AssertValidJoinCkUsingDelegate_Hack< Extract, TableT, UsingDelegateT, QueryUtil.InnerJoin< Extract, TableT > > ) { return QueryUtil.innerJoinCkUsing< Extract, TableT, UsingDelegateT >( this, table, usingDelegate ); } leftJoinCkUsing< TableT extends ITable, UsingDelegateT extends QueryUtil.JoinUsingDelegate< Extract["_joins"], TableT > > ( this : Extract, table : QueryUtil.AssertValidJoinTarget< Extract, TableT >, usingDelegate : UsingDelegateT ) : ( QueryUtil.AssertValidJoinCkUsingDelegate_Hack< Extract, TableT, UsingDelegateT, QueryUtil.LeftJoin< Extract, TableT > > ) { return QueryUtil.leftJoinCkUsing< Extract, TableT, UsingDelegateT >( this, table, usingDelegate ); } rightJoinCkUsing< TableT extends ITable, UsingDelegateT extends QueryUtil.JoinUsingDelegate< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >["_joins"], TableT > > ( this : Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, table : QueryUtil.AssertValidJoinTarget< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, TableT >, usingDelegate : UsingDelegateT ) : ( QueryUtil.AssertValidJoinCkUsingDelegate_Hack< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, TableT, UsingDelegateT, QueryUtil.RightJoin< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, TableT > > ) { return QueryUtil.rightJoinCkUsing< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, TableT, UsingDelegateT >( this, table, usingDelegate ); } innerJoinPk< DelegateT extends QueryUtil.JoinPkDelegate< Extract >, ToTableT extends ITable & { primaryKey : string[] }, > ( this : Extract, delegate : DelegateT, toTable : QueryUtil.AssertValidJoinPk_FromDelegate< Extract, DelegateT, ToTableT > ) : ( QueryUtil.InnerJoin< Extract, ToTableT > ) { return QueryUtil.innerJoinPk< Extract, DelegateT, ToTableT >( this, delegate, toTable ); } leftJoinPk< DelegateT extends QueryUtil.JoinPkDelegate< Extract >, ToTableT extends ITable & { primaryKey : string[] }, > ( this : Extract, delegate : DelegateT, toTable : QueryUtil.AssertValidJoinPk_FromDelegate< Extract, DelegateT, ToTableT > ) : ( QueryUtil.LeftJoin< Extract, ToTableT > ) { return QueryUtil.leftJoinPk< Extract, DelegateT, ToTableT >( this, delegate, toTable ); } rightJoinPk< DelegateT extends QueryUtil.JoinPkDelegate< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes > >, ToTableT extends ITable & { primaryKey : string[] }, > ( this : Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, delegate : DelegateT, toTable : QueryUtil.AssertValidJoinPk_FromDelegate< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, DelegateT, ToTableT > ) : ( QueryUtil.RightJoin< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, ToTableT > ) { return QueryUtil.rightJoinPk< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, DelegateT, ToTableT >( this, delegate, toTable ); } innerJoinFromPk< DelegateT extends QueryUtil.JoinFromPkDelegate< Extract >, ToTableT extends IAliasedTable > ( this : Extract, delegate : DelegateT, toTable : QueryUtil.AssertValidJoinFromPk_FromDelegate< Extract, DelegateT, ToTableT > ) : ( QueryUtil.InnerJoin< Extract, ToTableT > ) { return QueryUtil.innerJoinFromPk< Extract, DelegateT, ToTableT >( this, delegate, toTable ); } leftJoinFromPk< DelegateT extends QueryUtil.JoinFromPkDelegate< Extract >, ToTableT extends IAliasedTable > ( this : Extract, delegate : DelegateT, toTable : QueryUtil.AssertValidJoinFromPk_FromDelegate< Extract, DelegateT, ToTableT > ) : ( QueryUtil.LeftJoin< Extract, ToTableT > ) { return QueryUtil.leftJoinFromPk< Extract, DelegateT, ToTableT >( this, delegate, toTable ); } rightJoinFromPk< DelegateT extends QueryUtil.JoinFromPkDelegate< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes > >, ToTableT extends IAliasedTable > ( this : Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, delegate : DelegateT, toTable : QueryUtil.AssertValidJoinFromPk_FromDelegate< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, DelegateT, ToTableT > ) : ( QueryUtil.RightJoin< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, ToTableT > ) { return QueryUtil.rightJoinFromPk< Extract< this, QueryUtil.AfterFromClause & QueryUtil.CanWidenColumnTypes >, DelegateT, ToTableT >( this, delegate, toTable ); } select< SelectDelegateT extends QueryUtil.SelectDelegate< Extract > > ( this : Extract, delegate : QueryUtil.AssertValidSelectDelegate< Extract, SelectDelegateT > ) : ( QueryUtil.Select< Extract, SelectDelegateT > ) { return QueryUtil.select< Extract, SelectDelegateT >( this, delegate ); } //Added to speed up compile-times. //Some complicated queries take 700+ seconds to compile! selectUnsafe< SelectDelegateT extends QueryUtil.SelectDelegate< Extract > > ( this : Extract, delegate : SelectDelegateT ) : ( QueryUtil.Select< Extract, SelectDelegateT > ) { return QueryUtil.select< Extract, SelectDelegateT >( this, delegate as any ); } selectExpr< SelectDelegateT extends QueryUtil.SelectExprDelegate< Extract > > ( this : Extract, delegate : QueryUtil.AssertValidSelectExprDelegate< Extract, SelectDelegateT > ) : ( QueryUtil.SelectExpr< Extract, SelectDelegateT > ) { return QueryUtil.selectExpr< Extract, SelectDelegateT >( this, delegate ); } where< WhereDelegateT extends QueryUtil.WhereDelegate< Extract > > ( this : Extract, delegate : QueryUtil.AssertValidWhereDelegate< Extract, WhereDelegateT > ) : QueryUtil.Where> { return QueryUtil.where< Extract, WhereDelegateT >(this, delegate); } groupBy< GroupByDelegateT extends QueryUtil.GroupByDelegate< Extract > > ( this : Extract, delegate : QueryUtil.AssertValidGroupByDelegate< Extract, GroupByDelegateT > ) : QueryUtil.GroupBy> { return QueryUtil.groupBy< Extract, GroupByDelegateT >(this, delegate); } having< HavingDelegateT extends QueryUtil.HavingDelegate< Extract > > ( this : Extract, delegate : QueryUtil.AssertValidHavingDelegate< Extract, HavingDelegateT > ) : QueryUtil.Having> { return QueryUtil.having< Extract, HavingDelegateT >(this, delegate); } orderBy< OrderByDelegateT extends QueryUtil.OrderByDelegate< Extract > > ( this : Extract, delegate : QueryUtil.AssertValidOrderByDelegate< Extract, OrderByDelegateT > ) : QueryUtil.OrderBy> { return QueryUtil.orderBy< Extract, OrderByDelegateT >(this, delegate); } /* One should be careful about using LIMIT, OFFSET without an ORDER BY clause. In general, if your WHERE condition uniquely identifies the row, then LIMIT and OFFSET are not required and can be safely used without an ORDER BY. The problem is when the WHERE condition *does not* uniquely identify a row. Then, LIMIT and OFFSET can return inconsistent results. */ limit ( maxRowCount : MaxRowCountT ) : QueryUtil.Limit { return QueryUtil.limit(this, maxRowCount); } offset ( offset : OffsetT ) : QueryUtil.Offset { return QueryUtil.offset(this, offset); } union( this : Extract, other : QueryUtil.AssertUnionCompatibleQuery< Extract, OtherT > ) : QueryUtil.Union>; union( this : Extract, unionType : QueryUtil.UnionType, other : QueryUtil.AssertUnionCompatibleQuery< Extract, OtherT > ) : QueryUtil.Union>; union (this : Extract, arg0 : any, arg1? : any) { if (arg1 == undefined) { //Only two args const other : QueryUtil.AssertUnionCompatibleQuery< Extract, OtherT > = arg0; return QueryUtil.union< Extract, OtherT >(this, other, DISTINCT); } else { //Three args //Yeap, it's arg*1*, then arg*0*. //Confusing. I know. I'm sorry. const other : QueryUtil.AssertUnionCompatibleQuery< Extract, OtherT > = arg1; const unionType : QueryUtil.UnionType = arg0; return QueryUtil.union< Extract, OtherT >(this, other, unionType); } } unionOrderBy< UnionOrderByDelegateT extends QueryUtil.UnionOrderByDelegate< Extract > > ( this : Extract, delegate : QueryUtil.AssertValidUnionOrderByDelegate< Extract, UnionOrderByDelegateT > ) : QueryUtil.UnionOrderBy< Extract > { return QueryUtil.unionOrderBy< Extract, UnionOrderByDelegateT >(this, delegate); } /* One should be careful about using UNION LIMIT, OFFSET without the UNION ORDER BY clause. */ unionLimit ( maxRowCount : MaxRowCountT ) : QueryUtil.UnionLimit { return QueryUtil.unionLimit(this, maxRowCount); } unionOffset ( offset : OffsetT ) : QueryUtil.UnionOffset { return QueryUtil.unionOffset(this, offset); } distinct ( this : Extract ) : QueryUtil.Distinct> { return QueryUtil.distinct(this); } sqlCalcFoundRows ( this : Extract ) : QueryUtil.SqlCalcFoundRows> { return QueryUtil.sqlCalcFoundRows(this); } crossJoin< AliasedTableT extends IAliasedTable > ( this : Extract, aliasedTable : QueryUtil.AssertValidJoinTarget< Extract, AliasedTableT > ) : ( QueryUtil.CrossJoin< Extract, AliasedTableT > ) { return QueryUtil.crossJoin< Extract, AliasedTableT >( this, aliasedTable ); } requireParentJoins< ArrT extends NonEmptyTuple > ( ...arr : QueryUtil.AssertValidParentJoins ) : ( QueryUtil.RequireParentJoins< this, false, ArrT > ) { return QueryUtil.requireParentJoins< this, false, ArrT >( this, false, //TODO-UNHACK Figure out what's wrong ...(arr as any) ); } requireNullableParentJoins< ArrT extends NonEmptyTuple > ( ...arr : QueryUtil.AssertValidParentJoins ) : ( QueryUtil.RequireParentJoins< this, true, ArrT > ) { return QueryUtil.requireParentJoins< this, true, ArrT >( this, true, //TODO-UNHACK Figure out what's wrong ...(arr as any) ); } as ( this : QueryUtil.AssertAliasableQuery< Extract >, alias : AliasT ) : ( QueryUtil.As< Extract, AliasT > ) { return QueryUtil.as< Extract, AliasT >(this, alias); } coalesce< DefaultT extends RawExpr> >> > ( this : Extract>, defaultExpr : DefaultT ) : ( QueryUtil.Coalesce< Extract>, DefaultT > ) { return QueryUtil.coalesce(this, defaultExpr); } map< DelegateT extends MapDelegate< QueryUtil.MappedType< Extract >, QueryUtil.UnmappedType< Extract >, any > > ( this : Extract, delegate : DelegateT ) : ( QueryUtil.Map< Extract, DelegateT > ) { return QueryUtil.map(this, delegate); } whereIsNull< DelegateT extends QueryUtil.WhereIsNullDelegate< Extract > > ( this : Extract, delegate : DelegateT ) : ( QueryUtil.WhereIsNull< Extract, DelegateT > ) { return QueryUtil.whereIsNull< Extract, DelegateT >(this, delegate) } whereIsNotNull< DelegateT extends QueryUtil.WhereIsNotNullDelegate< Extract > > ( this : Extract, delegate : DelegateT ) : ( QueryUtil.WhereIsNotNull< Extract, DelegateT > ) { return QueryUtil.whereIsNotNull< Extract, DelegateT >(this, delegate); } whereEq< DelegateT extends QueryUtil.WhereEqDelegate< Extract >, ValueT extends NonNullPrimitiveExpr > ( this : Extract, delegate : DelegateT, value : QueryUtil.AssertValidEqTarget< Extract, DelegateT, ValueT > ) : ( QueryUtil.WhereEq< Extract, DelegateT, ValueT > ) { return QueryUtil.whereEq< Extract, DelegateT, ValueT >(this, delegate, value); } whereNullSafeEq< DelegateT extends QueryUtil.WhereNullSafeEqDelegate< Extract >, ValueT extends PrimitiveExpr > ( this : Extract, delegate : DelegateT, value : QueryUtil.AssertValidNullSafeEqTarget< Extract, DelegateT, ValueT > ) : ( QueryUtil.WhereNullSafeEq< Extract, DelegateT, ValueT > ) { return QueryUtil.whereNullSafeEq< Extract, DelegateT, ValueT >(this, delegate, value); } //TODO Phase this out, prefer whereEqCk() instead whereEqCandidateKey< TableT extends ITable, > ( this : Extract, table : TableT & Extract["_joins"][number]["aliasedTable"], key : CandidateKey ) : QueryUtil.WhereEqCandidateKey> { return QueryUtil.whereEqCandidateKey( this, table, key ); } //Synonym for whereEqCandidateKey(), use whereEqCk() instead whereEqCk< TableT extends ITable, > ( this : Extract, table : TableT & Extract["_joins"][number]["aliasedTable"], key : CandidateKey ) : QueryUtil.WhereEqCandidateKey> { return QueryUtil.whereEqCandidateKey( this, table, key ); } whereEqColumns< TableT extends ITable, > ( this : Extract, table : TableT & Extract["_joins"][number]["aliasedTable"], columns : Partial> ) : QueryUtil.WhereEqColumns> { return QueryUtil.whereEqColumns< Extract, TableT >(this, table, columns); } whereEqPk< TableT extends TableWithPk, > ( this : Extract, table : TableT & Extract["_joins"][number]["aliasedTable"], key : PrimaryKey ) : QueryUtil.WhereEqPk> { return QueryUtil.whereEqPk( this, table, key ); } whereEqSk< TableT extends ITable, > ( this : Extract, table : TableT & Extract["_joins"][number]["aliasedTable"], key : SuperKey ) : QueryUtil.WhereEqSuperKey> { return QueryUtil.whereEqSuperKey( this, table, key ); } useJoin< JoinDeclT extends IJoinDeclaration > ( this : Extract, joinDecl : QueryUtil.AssertValidJoinDeclaration< Extract, JoinDeclT > ) : ( QueryUtil.UseJoin< Extract, JoinDeclT > ) { return QueryUtil.useJoin< Extract, JoinDeclT >(this, joinDecl); } useJoins< ArrT extends NonEmptyTuple > ( this : Extract, ...arr : QueryUtil.AssertValidJoinDeclarationArray< Extract, ArrT > ) : ( QueryUtil.UseJoins< Extract, ArrT > ) { return QueryUtil.useJoins< Extract, ArrT >(this, arr); } //Added to speed up compile-times. //Some complicated queries take 700+ seconds to compile! useJoinsUnsafe< ArrT extends NonEmptyTuple > ( this : Extract, ...arr : ArrT ) : ( QueryUtil.UseJoins< Extract, ArrT > ) { return QueryUtil.useJoins< Extract, ArrT >(this, arr as any); } assertExists ( this : Extract, connection : IConnection ) : Promise { return QueryUtil.assertExists(this, connection); } count ( this : Extract, connection : IConnection ) : Promise { return QueryUtil.count(this, connection); } cursor ( this : Extract, connection : IConnection ) : ( QueryUtil.Cursor< Extract > ) { return QueryUtil.cursor(this, connection); } exists( this : Extract, connection : IConnection ) : Promise { return QueryUtil.exists(this, connection); } fetchAllUnmapped ( this : Extract, connection : IConnection ) : ( Promise >> ) { return QueryUtil.fetchAllUnmapped(this, connection); } fetchAll ( this : Extract, connection : IConnection ) : ( Promise< QueryUtil.FetchAll< Extract > > ) { return QueryUtil.fetchAll(this, connection); } fetchOne ( this : Extract, connection : IConnection ) : ( Promise >> ) { return QueryUtil.fetchOne(this, connection); } fetchValueArray ( this : Extract>, connection : IConnection ) : ( Promise> >> ) { return QueryUtil.fetchValueArray(this, connection); } fetchValueOrUndefined ( this : Extract>, connection : IConnection ) : ( Promise> >> ) { return QueryUtil.fetchValueOrUndefined(this, connection); } fetchValueOrNull ( this : Extract>, connection : IConnection ) : ( Promise> >> ) { return QueryUtil.fetchValueOrUndefined(this, connection) .then(r => (r == undefined) ? null : r); } fetchValue ( this : Extract>, connection : IConnection ) : ( Promise> >> ) { return QueryUtil.fetchValue(this, connection); } fetchZeroOrOne ( this : Extract, connection : IConnection ) : ( Promise >> ) { return QueryUtil.fetchZeroOrOne(this, connection); } fetchOneOrNull ( this : Extract, connection : IConnection ) : ( Promise >> ) { return QueryUtil.fetchZeroOrOne(this, connection) .then(r => (r == undefined) ? null : r); } paginate ( this : Extract, connection : IConnection, rawArgs : QueryUtil.RawPaginateArgs ) : ( Promise >> ) { return QueryUtil.paginate(this, connection, rawArgs); } printSql ( this : Extract ) : this { QueryUtil.printSql(this); return this; } printSqlPretty ( this : Extract ) : this { QueryUtil.printSqlPretty(this); return this; } insertIgnoreInto< TableT extends ITable & { insertAllowed : true } > ( this : Extract, table : TableT, delegate : InsertSelectRowDelegate< Extract, TableT > ) : ( QueryUtil.InsertIgnoreInto< Extract, TableT > ) { return QueryUtil.insertIgnoreInto( this, table, delegate ); } insertInto< TableT extends ITable & { insertAllowed : true } > ( this : Extract, table : TableT, delegate : InsertSelectRowDelegate< Extract, TableT > ) : ( QueryUtil.InsertInto< Extract, TableT > ) { return QueryUtil.insertInto( this, table, delegate ); } replaceInto< TableT extends ITable & { insertAllowed : true } > ( this : Extract, table : TableT, delegate : InsertSelectRowDelegate< Extract, TableT > ) : ( QueryUtil.ReplaceInto< Extract, TableT > ) { return QueryUtil.replaceInto( this, table, delegate ); } set< DelegateT extends UpdateUtil.SingleTableSetDelegate< Extract > > ( this : ( Extract & UpdateUtil.AssertValidSingleTableSetDelegate_Hack< Extract, DelegateT > & UpdateUtil.AssertValidSingleTableUpdatableQuery< Extract > ), delegate : DelegateT ) : ( QueryUtil.Set> ); set< DelegateT extends UpdateUtil.SetDelegate< Extract > > ( this : ( Extract & UpdateUtil.AssertValidSetDelegate_Hack< Extract, DelegateT > ), delegate : DelegateT ) : ( QueryUtil.Set> ); set (delegate : () => any) : ( QueryUtil.Set> ) { return QueryUtil.set(this as any, delegate); } delete ( this : Extract, delegate : DeleteUtil.DeleteDelegate> ) : ( Delete<{ _query : DeletableQuery, _tables : (ITable & { deleteAllowed : true })[], _modifier : undefined, }> ) { return QueryUtil.delete(this, delegate); } deleteIgnore ( this : Extract, delegate : DeleteUtil.DeleteDelegate> ) : ( Delete<{ _query : DeletableQuery, _tables : (ITable & { deleteAllowed : true })[], _modifier : DeleteModifier.IGNORE, }> ) { return QueryUtil.deleteIgnore(this, delegate); } subQuery () : QueryUtil.SubQueryResult { return QueryUtil.subQuery(this); } } export function from ( aliasedTable : QueryUtil.AssertValidJoinTarget< QueryUtil.NewInstance, AliasedTableT > ) : ( QueryUtil.From ) { return QueryUtil.newInstance() .from(aliasedTable); } export function select< SelectDelegateT extends QueryUtil.SelectDelegate< QueryUtil.NewInstance > > ( delegate : QueryUtil.AssertValidSelectDelegate< QueryUtil.NewInstance, SelectDelegateT > ) : ( QueryUtil.Select< QueryUtil.NewInstance, SelectDelegateT > ) { return QueryUtil.newInstance() .select(delegate as any) as any; } export function selectExpr< SelectDelegateT extends QueryUtil.SelectExprDelegate< QueryUtil.NewInstance > > ( delegate : QueryUtil.AssertValidSelectExprDelegate< QueryUtil.NewInstance, SelectDelegateT > ) : ( QueryUtil.SelectExpr< QueryUtil.NewInstance, SelectDelegateT > ) { return QueryUtil.newInstance() .selectExpr(delegate); } export function requireParentJoins< ArrT extends NonEmptyTuple > ( ...arr : QueryUtil.AssertValidParentJoins ) : ( QueryUtil.RequireParentJoins< QueryUtil.NewInstance, false, ArrT > ) { return QueryUtil.newInstance() .requireParentJoins(...(arr as any)); } export function requireNullableParentJoins< ArrT extends NonEmptyTuple > ( ...arr : QueryUtil.AssertValidParentJoins ) : ( QueryUtil.RequireParentJoins< QueryUtil.NewInstance, true, ArrT > ) { return QueryUtil.newInstance() .requireNullableParentJoins(...(arr as any)); } export type UnmappedFetchRow = ( QueryUtil.UnmappedType ); export type FetchRow = ( QueryUtil.MappedType );