import { CollectionToken , GroupToken , SeparatorToken , StringToken , Token } from './tokens' ; import { Expression , InternalExpression } from './expression' ; import { GetDataType , Maybe , QueryExecutorFn } from './types' ; import { DbConfig } from './config' ; import { Query } from './query' ; import { ResultSet } from './result-set' ; import { SelectQuery } from './select' ; import { wrapQuotes } from './naming' ; export type FromItem < Config extends DbConfig , Q > = Q extends Query < any > ? FromItemQuery < Config , Q > : Q extends ( args : any ) => infer R ? R extends Query < any > ? FromItemQuery < Config , R > : never : never ; type FromItemQuery < Config extends DbConfig , Q , Result = Q extends Query < any > ? ResultSet < Config , Q , true > : never > = { [ K in keyof Result ] : Result [ K ] extends Maybe < infer DataType > ? Expression < Config , DataType , false , K extends string ? K : never > : Expression < Config , Result [ K ] , true , K extends string ? K : never > ; } ; type QueryFn < T > = Query < any > | ( ( args : T ) => Query < any > ) ; export interface WithFn < Config extends DbConfig > { < N1 extends string , W1 extends QueryFn < never > , Q extends Query < any > > ( name1 , with1 , callback ) : Q ; < N1 extends string , W1 extends QueryFn < never > , N2 extends string , W2 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } > , Q extends Query < any > > ( name1 , with1 , name2 , with2 , callback ) : Q ; < N1 extends string , W1 extends QueryFn < never > , N2 extends string , W2 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } > , N3 extends string , W3 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } > , Q extends Query < any > > ( name1 , with1 , name2 , with2 , name3 , with3 , callback ) : Q ; < N1 extends string , W1 extends QueryFn < never > , N2 extends string , W2 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } > , N3 extends string , W3 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } > , N4 extends string , W4 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } > , Q extends Query < any > > ( name1 , with1 , name2 , with2 , name3 , with3 , name4 , with4 , callback ) : Q ; < N1 extends string , W1 extends QueryFn < never > , N2 extends string , W2 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } > , N3 extends string , W3 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } > , N4 extends string , W4 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } > , N5 extends string , W5 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } > , Q extends Query < any > > ( name1 , with1 , name2 , with2 , name3 , with3 , name4 , with4 , name5 , with5 , callback ) : Q ; < N1 extends string , W1 extends QueryFn < never > , N2 extends string , W2 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } > , N3 extends string , W3 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } > , N4 extends string , W4 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } > , N5 extends string , W5 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } > , N6 extends string , W6 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } > , Q extends Query < any > > ( name1 , with1 , name2 , with2 , name3 , with3 , name4 , with4 , name5 , with5 , name6 , with6 , callback ) : Q ; < N1 extends string , W1 extends QueryFn < never > , N2 extends string , W2 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } > , N3 extends string , W3 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } > , N4 extends string , W4 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } > , N5 extends string , W5 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } > , N6 extends string , W6 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } > , N7 extends string , W7 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } & { [ K in N6 ] : FromItem < Config , W6 > ; } > , Q extends Query < any > > ( name1 , with1 , name2 , with2 , name3 , with3 , name4 , with4 , name5 , with5 , name6 , with6 , name7 , with7 , callback ) : Q ; < N1 extends string , W1 extends QueryFn < never > , N2 extends string , W2 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } > , N3 extends string , W3 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } > , N4 extends string , W4 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } > , N5 extends string , W5 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } > , N6 extends string , W6 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } > , N7 extends string , W7 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } & { [ K in N6 ] : FromItem < Config , W6 > ; } > , N8 extends string , W8 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } & { [ K in N6 ] : FromItem < Config , W6 > ; } & { [ K in N7 ] : FromItem < Config , W7 > ; } > , Q extends Query < any > > ( name1 , with1 , name2 , with2 , name3 , with3 , name4 , with4 , name5 , with5 , name6 , with6 , name7 , with7 , name8 , with8 , callback ) : Q ; < N1 extends string , W1 extends QueryFn < never > , N2 extends string , W2 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } > , N3 extends string , W3 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } > , N4 extends string , W4 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } > , N5 extends string , W5 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } > , N6 extends string , W6 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } > , N7 extends string , W7 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } & { [ K in N6 ] : FromItem < Config , W6 > ; } > , N8 extends string , W8 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } & { [ K in N6 ] : FromItem < Config , W6 > ; } & { [ K in N7 ] : FromItem < Config , W7 > ; } > , N9 extends string , W9 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } & { [ K in N6 ] : FromItem < Config , W6 > ; } & { [ K in N7 ] : FromItem < Config , W7 > ; } & { [ K in N8 ] : FromItem < Config , W8 > ; } > , Q extends Query < any > > ( name1 , with1 , name2 , with2 , name3 , with3 , name4 , with4 , name5 , with5 , name6 , with6 , name7 , with7 , name8 , with8 , name9 , with9 , callback ) : Q ; < N1 extends string , W1 extends QueryFn < never > , N2 extends string , W2 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } > , N3 extends string , W3 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } > , N4 extends string , W4 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } > , N5 extends string , W5 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } > , N6 extends string , W6 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } > , N7 extends string , W7 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } & { [ K in N6 ] : FromItem < Config , W6 > ; } > , N8 extends string , W8 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } & { [ K in N6 ] : FromItem < Config , W6 > ; } & { [ K in N7 ] : FromItem < Config , W7 > ; } > , N9 extends string , W9 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } & { [ K in N6 ] : FromItem < Config , W6 > ; } & { [ K in N7 ] : FromItem < Config , W7 > ; } & { [ K in N8 ] : FromItem < Config , W8 > ; } > , N10 extends string , W10 extends QueryFn < { [ K in N1 ] : FromItem < Config , W1 > ; } & { [ K in N2 ] : FromItem < Config , W2 > ; } & { [ K in N3 ] : FromItem < Config , W3 > ; } & { [ K in N4 ] : FromItem < Config , W4 > ; } & { [ K in N5 ] : FromItem < Config , W5 > ; } & { [ K in N6 ] : FromItem < Config , W6 > ; } & { [ K in N7 ] : FromItem < Config , W7 > ; } & { [ K in N8 ] : FromItem < Config , W8 > ; } & { [ K in N9 ] : FromItem < Config , W9 > ; } > , Q extends Query < any > > ( name1 , with1 , name2 , with2 , name3 , with3 , name4 , with4 , name5 , with5 , name6 , with6 , name7 , with7 , name8 , with8 , name9 , with9 , name10 , with10 , callback ) : Q ; } const makeMakeWith = ( initialTokens ) => < Config extends DbConfig > ( queryExecutor ) : WithFn < Config > => ( ... args ) => { const queries = { } ; const createWith = ( withFn ) => { if ( withFn instanceof Query ) { return withFn ; } return withFn ( queries ) ; } ; const createFromItem = ( name , query ) => { const fromItem = { ... query . getReturningKeys ( ) . reduce ( ( fromItem , key ) => { fromItem [ key ] = new InternalExpression ( [ new StringToken ( `${ wrapQuotes ( name ) }.${ wrapQuotes ( key ) }` ) ] , key ) ; return fromItem ; } , { } as any ) , getName ( ) { return name ; } , getOriginalName ( ) { return undefined ; } , } ; return fromItem ; } ; const tokens = [ ] ; for ( let i = 0 ; i < args . length - 1 ; i += 2 ) { const name = args [ i ] ; const withQuery = createWith ( args [ i + 1 ] ) ; tokens . push ( new CollectionToken ( [ new StringToken ( wrapQuotes ( name ) ) , new StringToken ( `AS` ) , new GroupToken ( withQuery . toTokens ( ) ) , ] ) ) ; queries [ name ] = createFromItem ( name , withQuery ) ; } const callback = args [ args . length - 1 ] ; const query = callback ( queries ) ; return new SelectQuery ( queryExecutor , [ ] , false , [ ... initialTokens , new SeparatorToken ( `,` , tokens ) , ... query . toTokens ( ) , ] ) as any ; } ; export const makeWith = makeMakeWith ( [ new StringToken ( `WITH` ) ] ) ; export const makeWithRecursive = makeMakeWith ( [ new StringToken ( `WITH RECURSIVE` ) ] ) ;