import * as sd from "type-mapping"; import {PrimitiveExpr} from "./primitive-expr"; import {IAnonymousTypedExpr, IExpr, ExprUtil} from "./expr"; import {IAnonymousTypedColumn, IColumn, ColumnUtil} from "./column"; import {ColumnRefUtil} from "./column-ref"; import {escape} from "sqlstring"; import {QueryTree} from "./query-tree"; import {ColumnRef} from "./column-ref"; import {OneSelectItemQuery, ZeroOrOneRowQuery, OneRowQuery, MainQuery} from "./query/util"; import {IQuery, QueryUtil} from "./query"; import {IJoin} from "./join"; import {DateTimeUtil} from "./data-type"; import * as dataType from "./data-type"; import {IAnonymousTypedExprSelectItem, IExprSelectItem, ExprSelectItemUtil} from "./expr-select-item"; import {Parentheses} from "./query-tree"; import {UnionToIntersection} from "./type"; export type RawExpr = ( ( TypeT extends PrimitiveExpr ? TypeT : never ) | IAnonymousTypedExpr | IAnonymousTypedColumn | ( null extends TypeT ? (OneSelectItemQuery & ZeroOrOneRowQuery) : (OneSelectItemQuery & OneRowQuery) ) | IAnonymousTypedExprSelectItem ); export type RawExprNoUsedRef = ( ( TypeT extends PrimitiveExpr ? TypeT : never ) | IExpr<{ usedRef : {}, assertDelegate : sd.SafeMapper, }> | ( null extends TypeT ? (OneSelectItemQuery & ZeroOrOneRowQuery & MainQuery) : (OneSelectItemQuery & OneRowQuery & MainQuery) ) | IExprSelectItem<{ usedRef : {}, assertDelegate : sd.SafeMapper, tableAlias : string, alias : string, }> ); export namespace RawExprUtil { export type UsedRef> = ( RawExprT extends PrimitiveExpr ? {} : RawExprT extends IExpr ? RawExprT["usedRef"] : RawExprT extends IColumn ? ColumnRefUtil.FromColumn : RawExprT extends IQuery ? ( RawExprT["_parentJoins"] extends IJoin[] ? ColumnRefUtil.FromJoinArray> : {} ) : RawExprT extends IExprSelectItem ? RawExprT["usedRef"] : never ); export function usedRef> ( rawExpr : RawExprT ) : UsedRef { //Check primitive cases first if (typeof rawExpr == "number") { return {} as any; } if (typeof rawExpr == "bigint") { return {} as any; } if (typeof rawExpr == "string") { return {} as any; } if (typeof rawExpr == "boolean") { return {} as any; } if (rawExpr instanceof Date) { return {} as any; } if (rawExpr instanceof Buffer) { return {} as any; } if (rawExpr === null) { return {} as any; } if (ExprUtil.isExpr(rawExpr)) { return rawExpr.usedRef as any; } if (ColumnUtil.isColumn(rawExpr)) { return ColumnRefUtil.fromColumn(rawExpr) as any; } if (QueryUtil.isQuery(rawExpr)) { if (rawExpr._parentJoins == undefined) { return {} as any; } else { return ColumnRefUtil.fromJoinArray(rawExpr._parentJoins) as any; } } if (ExprSelectItemUtil.isExprSelectItem(rawExpr)) { return rawExpr.usedRef as any; } throw new Error(`Unknown rawExpr ${sd.TypeUtil.toTypeStr(rawExpr)}`); } export type TypeOf> = ( RawExprT extends PrimitiveExpr ? RawExprT : RawExprT extends IExpr ? ReturnType : RawExprT extends IColumn ? ReturnType : RawExprT extends OneSelectItemQuery & ZeroOrOneRowQuery ? QueryUtil.TypeOf : RawExprT extends IExprSelectItem ? ReturnType : never ); export type AssertDelegate> = ( sd.SafeMapper> ); export function assertDelegate> ( rawExpr : RawExprT ) : AssertDelegate { //Check primitive cases first if (typeof rawExpr == "number") { return dataType.double() as any; } if (typeof rawExpr == "bigint") { return dataType.bigint() as any; } if (typeof rawExpr == "string") { return sd.literal(rawExpr) as any; } if (typeof rawExpr == "boolean") { return (rawExpr ? dataType.true() : dataType.false() ) as any; } if (rawExpr instanceof Date) { return dataType.dateTime(3) as any; } if (rawExpr instanceof Buffer) { return sd.instanceOfBuffer() as any; } if (rawExpr === null) { return sd.null() as any; } if (ExprUtil.isExpr(rawExpr)) { return rawExpr.assertDelegate as any; } if (ColumnUtil.isColumn(rawExpr)) { return rawExpr.assertDelegate as any; } if ( QueryUtil.isQuery(rawExpr) && QueryUtil.isOneSelectItemQuery(rawExpr) && QueryUtil.isZeroOrOneRowQuery(rawExpr) ) { return QueryUtil.assertDelegate(rawExpr) as any; } if (ExprSelectItemUtil.isExprSelectItem(rawExpr)) { return rawExpr.assertDelegate as any; } throw new Error(`Unknown rawExpr ${sd.TypeUtil.toTypeStr(rawExpr)}`); } export function queryTree (rawExpr : RawExpr) : QueryTree { //Check primitive cases first if (typeof rawExpr == "number") { //This technically gives us DECIMAL in MySQL, //Not double return rawExpr.toString(); } if (typeof rawExpr == "bigint") { return rawExpr.toString(); } if (typeof rawExpr == "string") { return escape(rawExpr); } if (typeof rawExpr == "boolean") { return escape(rawExpr); } if (rawExpr instanceof Date) { return DateTimeUtil.toSqlUtc(rawExpr, 3); } if (rawExpr instanceof Buffer) { //escape(Buffer.from("hello")) == "X'68656c6c6f'" return escape(rawExpr); } if (rawExpr === null) { return escape(rawExpr); } if (ExprUtil.isExpr(rawExpr)) { return rawExpr.queryTree; } if (ColumnUtil.isColumn(rawExpr)) { return ColumnUtil.queryTree(rawExpr); } if (QueryUtil.isQuery(rawExpr) && QueryUtil.isOneSelectItemQuery(rawExpr)) { return QueryUtil.queryTree_RawExpr(rawExpr); } if (ExprSelectItemUtil.isExprSelectItem(rawExpr)) { return Parentheses.Create(rawExpr.unaliasedQuery, false/*canUnwrap*/); } throw new Error(`Unknown rawExpr ${sd.TypeUtil.toTypeStr(rawExpr)}`); } export type IntersectUsedRefTuple[]> = ( ArrT[number] extends never ? {} : Extract< UnionToIntersection< RawExprUtil.UsedRef >, ColumnRef > /* ArrT["length"] extends 0 ? {} : ArrT["length"] extends 1 ? UsedRef : ArrT["length"] extends 2 ? UsedRef & UsedRef : ArrT["length"] extends 3 ? UsedRef & UsedRef & UsedRef : ArrT["length"] extends 4 ? UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 5 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 6 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 7 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 8 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 9 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 10 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 11 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 12 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 13 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 14 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 15 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 16 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 17 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 18 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 19 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : ArrT["length"] extends 20 ? UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef & UsedRef : //Add more lengths //Too many to handle... ColumnRef */ ); export function intersectUsedRefTuple[]> ( ...arr : ArrT ) : IntersectUsedRefTuple { return ColumnRefUtil.intersectTuple(...(arr.map(usedRef) as any)); } }