@kuindji/typed-sql 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +227 -0
- package/dist/builder/assemble.d.ts +13 -0
- package/dist/builder/assemble.d.ts.map +1 -0
- package/dist/builder/assemble.js +86 -0
- package/dist/builder/assemble.js.map +1 -0
- package/dist/builder/condition-tree.d.ts +27 -0
- package/dist/builder/condition-tree.d.ts.map +1 -0
- package/dist/builder/condition-tree.js +91 -0
- package/dist/builder/condition-tree.js.map +1 -0
- package/dist/builder/conditional-sql.d.ts +80 -0
- package/dist/builder/conditional-sql.d.ts.map +1 -0
- package/dist/builder/conditional-sql.js +88 -0
- package/dist/builder/conditional-sql.js.map +1 -0
- package/dist/builder/db.d.ts +76 -0
- package/dist/builder/db.d.ts.map +1 -0
- package/dist/builder/db.js +12 -0
- package/dist/builder/db.js.map +1 -0
- package/dist/builder/delete.d.ts +39 -0
- package/dist/builder/delete.d.ts.map +1 -0
- package/dist/builder/delete.js +33 -0
- package/dist/builder/delete.js.map +1 -0
- package/dist/builder/extract-params.d.ts +97 -0
- package/dist/builder/extract-params.d.ts.map +1 -0
- package/dist/builder/extract-params.js +2 -0
- package/dist/builder/extract-params.js.map +1 -0
- package/dist/builder/index.d.ts +23 -0
- package/dist/builder/index.d.ts.map +1 -0
- package/dist/builder/index.js +14 -0
- package/dist/builder/index.js.map +1 -0
- package/dist/builder/insert.d.ts +51 -0
- package/dist/builder/insert.d.ts.map +1 -0
- package/dist/builder/insert.js +39 -0
- package/dist/builder/insert.js.map +1 -0
- package/dist/builder/mutate.d.ts +28 -0
- package/dist/builder/mutate.d.ts.map +1 -0
- package/dist/builder/mutate.js +17 -0
- package/dist/builder/mutate.js.map +1 -0
- package/dist/builder/params.d.ts +22 -0
- package/dist/builder/params.d.ts.map +1 -0
- package/dist/builder/params.js +65 -0
- package/dist/builder/params.js.map +1 -0
- package/dist/builder/return-type.d.ts +39 -0
- package/dist/builder/return-type.d.ts.map +1 -0
- package/dist/builder/return-type.js +2 -0
- package/dist/builder/return-type.js.map +1 -0
- package/dist/builder/scanner.d.ts +49 -0
- package/dist/builder/scanner.d.ts.map +1 -0
- package/dist/builder/scanner.js +240 -0
- package/dist/builder/scanner.js.map +1 -0
- package/dist/builder/select.d.ts +76 -0
- package/dist/builder/select.d.ts.map +1 -0
- package/dist/builder/select.js +240 -0
- package/dist/builder/select.js.map +1 -0
- package/dist/builder/sql-tag.d.ts +319 -0
- package/dist/builder/sql-tag.d.ts.map +1 -0
- package/dist/builder/sql-tag.js +3 -0
- package/dist/builder/sql-tag.js.map +1 -0
- package/dist/builder/sql.d.ts +17 -0
- package/dist/builder/sql.d.ts.map +1 -0
- package/dist/builder/sql.js +36 -0
- package/dist/builder/sql.js.map +1 -0
- package/dist/builder/state.d.ts +53 -0
- package/dist/builder/state.d.ts.map +1 -0
- package/dist/builder/state.js +18 -0
- package/dist/builder/state.js.map +1 -0
- package/dist/builder/update.d.ts +60 -0
- package/dist/builder/update.d.ts.map +1 -0
- package/dist/builder/update.js +40 -0
- package/dist/builder/update.js.map +1 -0
- package/dist/builder/write-assemble.d.ts +5 -0
- package/dist/builder/write-assemble.d.ts.map +1 -0
- package/dist/builder/write-assemble.js +57 -0
- package/dist/builder/write-assemble.js.map +1 -0
- package/dist/builder/write-state.d.ts +39 -0
- package/dist/builder/write-state.d.ts.map +1 -0
- package/dist/builder/write-state.js +6 -0
- package/dist/builder/write-state.js.map +1 -0
- package/dist/builder/write-tag.d.ts +91 -0
- package/dist/builder/write-tag.d.ts.map +1 -0
- package/dist/builder/write-tag.js +2 -0
- package/dist/builder/write-tag.js.map +1 -0
- package/dist/columns.d.ts +33 -0
- package/dist/columns.d.ts.map +1 -0
- package/dist/columns.js +2 -0
- package/dist/columns.js.map +1 -0
- package/dist/expressions.d.ts +71 -0
- package/dist/expressions.d.ts.map +1 -0
- package/dist/expressions.js +2 -0
- package/dist/expressions.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/parsing/extract.d.ts +47 -0
- package/dist/parsing/extract.d.ts.map +1 -0
- package/dist/parsing/extract.js +2 -0
- package/dist/parsing/extract.js.map +1 -0
- package/dist/parsing/normalize.d.ts +44 -0
- package/dist/parsing/normalize.d.ts.map +1 -0
- package/dist/parsing/normalize.js +2 -0
- package/dist/parsing/normalize.js.map +1 -0
- package/dist/parsing/pg-literals.d.ts +37 -0
- package/dist/parsing/pg-literals.d.ts.map +1 -0
- package/dist/parsing/pg-literals.js +2 -0
- package/dist/parsing/pg-literals.js.map +1 -0
- package/dist/parsing/split.d.ts +100 -0
- package/dist/parsing/split.d.ts.map +1 -0
- package/dist/parsing/split.js +2 -0
- package/dist/parsing/split.js.map +1 -0
- package/dist/parsing/string-utils.d.ts +29 -0
- package/dist/parsing/string-utils.d.ts.map +1 -0
- package/dist/parsing/string-utils.js +2 -0
- package/dist/parsing/string-utils.js.map +1 -0
- package/dist/parsing/tokenize.d.ts +27 -0
- package/dist/parsing/tokenize.d.ts.map +1 -0
- package/dist/parsing/tokenize.js +2 -0
- package/dist/parsing/tokenize.js.map +1 -0
- package/dist/parsing.d.ts +7 -0
- package/dist/parsing.d.ts.map +1 -0
- package/dist/parsing.js +9 -0
- package/dist/parsing.js.map +1 -0
- package/dist/partial.d.ts +30 -0
- package/dist/partial.d.ts.map +1 -0
- package/dist/partial.js +10 -0
- package/dist/partial.js.map +1 -0
- package/dist/schema.d.ts +28 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +2 -0
- package/dist/schema.js.map +1 -0
- package/dist/tables.d.ts +34 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +2 -0
- package/dist/tables.js.map +1 -0
- package/dist/utils.d.ts +13 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +3 -0
- package/dist/utils.js.map +1 -0
- package/dist/validation/cte.d.ts +54 -0
- package/dist/validation/cte.d.ts.map +1 -0
- package/dist/validation/cte.js +2 -0
- package/dist/validation/cte.js.map +1 -0
- package/dist/validation/dispatch.d.ts +31 -0
- package/dist/validation/dispatch.d.ts.map +1 -0
- package/dist/validation/dispatch.js +2 -0
- package/dist/validation/dispatch.js.map +1 -0
- package/dist/validation/joins.d.ts +16 -0
- package/dist/validation/joins.d.ts.map +1 -0
- package/dist/validation/joins.js +2 -0
- package/dist/validation/joins.js.map +1 -0
- package/dist/validation/return-derived.d.ts +67 -0
- package/dist/validation/return-derived.d.ts.map +1 -0
- package/dist/validation/return-derived.js +5 -0
- package/dist/validation/return-derived.js.map +1 -0
- package/dist/validation/return-types.d.ts +41 -0
- package/dist/validation/return-types.d.ts.map +1 -0
- package/dist/validation/return-types.js +2 -0
- package/dist/validation/return-types.js.map +1 -0
- package/dist/validation/validate-columns.d.ts +63 -0
- package/dist/validation/validate-columns.d.ts.map +1 -0
- package/dist/validation/validate-columns.js +2 -0
- package/dist/validation/validate-columns.js.map +1 -0
- package/dist/validation.d.ts +7 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +9 -0
- package/dist/validation.js.map +1 -0
- package/package.json +64 -0
- package/src/builder/assemble.ts +100 -0
- package/src/builder/condition-tree.ts +162 -0
- package/src/builder/conditional-sql.ts +325 -0
- package/src/builder/db.ts +281 -0
- package/src/builder/delete.ts +57 -0
- package/src/builder/extract-params.ts +507 -0
- package/src/builder/index.ts +58 -0
- package/src/builder/insert.ts +75 -0
- package/src/builder/mutate.ts +55 -0
- package/src/builder/params.ts +95 -0
- package/src/builder/return-type.ts +66 -0
- package/src/builder/scanner.ts +254 -0
- package/src/builder/select.ts +470 -0
- package/src/builder/sql-tag.ts +422 -0
- package/src/builder/sql.ts +51 -0
- package/src/builder/state.ts +55 -0
- package/src/builder/update.ts +77 -0
- package/src/builder/write-assemble.ts +52 -0
- package/src/builder/write-state.ts +43 -0
- package/src/builder/write-tag.ts +119 -0
- package/src/columns.ts +336 -0
- package/src/expressions.ts +745 -0
- package/src/index.ts +81 -0
- package/src/parsing/extract.ts +260 -0
- package/src/parsing/normalize.ts +243 -0
- package/src/parsing/pg-literals.ts +289 -0
- package/src/parsing/split.ts +288 -0
- package/src/parsing/string-utils.ts +172 -0
- package/src/parsing/tokenize.ts +321 -0
- package/src/parsing.ts +8 -0
- package/src/partial.ts +241 -0
- package/src/schema.ts +130 -0
- package/src/tables.ts +278 -0
- package/src/utils.ts +43 -0
- package/src/validation/cte.ts +198 -0
- package/src/validation/dispatch.ts +312 -0
- package/src/validation/joins.ts +198 -0
- package/src/validation/return-derived.ts +253 -0
- package/src/validation/return-types.ts +271 -0
- package/src/validation/validate-columns.ts +489 -0
- package/src/validation.ts +8 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
// SELECT/RETURNING result inference + select-return assembly.
|
|
2
|
+
import type { AliasesInQuery, NullableRelations, TablesInQuery } from "../tables.js";
|
|
3
|
+
import type { AllTrue, Simplify } from "../utils.js";
|
|
4
|
+
import type { CleanIdent, ExtractAlias, ExtractReturningList, ExtractSelectList, SplitSelectList, StripSubqueries } from "../parsing.js";
|
|
5
|
+
import type { ColumnExists, DatabaseSchema } from "../schema.js";
|
|
6
|
+
import type { CteOuterQuery, CteReturn, MultiCteReturn, SingleCteMatch, WithDmlOuter } from "./cte.js";
|
|
7
|
+
import type { DerivedTableMatch, DerivedTableReturn, JoinedDerivedReturn } from "./return-derived.js";
|
|
8
|
+
import type { ExprToObject } from "../expressions.js";
|
|
9
|
+
import type { HasReturning, HasReturningQuoteAware, QueryKind } from "./dispatch.js";
|
|
10
|
+
export type GetReturnTypeNormalized<N extends string, S extends DatabaseSchema> =
|
|
11
|
+
TablesInQuery<N, S> extends infer Tables extends string
|
|
12
|
+
? AliasesInQuery<N, S> extends infer Aliases extends string
|
|
13
|
+
? [WithDmlOuter<N>] extends [never]
|
|
14
|
+
? HasReturning<N> extends true
|
|
15
|
+
? SelectReturnWith<ExtractReturningList<N>, Tables, Aliases, S>
|
|
16
|
+
: QueryKind<N> extends "select"
|
|
17
|
+
? [SingleCteMatch<N>] extends [never]
|
|
18
|
+
? [DerivedTableMatch<N>] extends [never]
|
|
19
|
+
? OuterSelectReturn<N, Tables, Aliases, S>
|
|
20
|
+
: DerivedTableReturn<N, S>
|
|
21
|
+
: CteReturn<N, S>
|
|
22
|
+
: number
|
|
23
|
+
: WithDmlReturn<N, Tables, Aliases, S>
|
|
24
|
+
: number
|
|
25
|
+
: number;
|
|
26
|
+
|
|
27
|
+
// Outer-projection row for a plain (non-CTE, non-derived) SELECT. The outer
|
|
28
|
+
// SELECT list — `*` included — can only reference outer-scope relations, never a
|
|
29
|
+
// table that exists solely inside a `WHERE ... (NOT) EXISTS (SELECT ... FROM
|
|
30
|
+
// other)` / scalar subquery. So the relations the projection resolves against are
|
|
31
|
+
// collected from a subquery-stripped view: `select * from t where exists (select
|
|
32
|
+
// 1 from u)` expands `*` to `t`'s columns only, not `t`'s AND `u`'s.
|
|
33
|
+
//
|
|
34
|
+
// EXCEPTION: a `WITH ... SELECT` that reaches this branch is the multi-CTE
|
|
35
|
+
// fallback (a single CTE is handled by `CteReturn`); that path deliberately
|
|
36
|
+
// resolves the projected CTE columns against the relations *inside* the CTE
|
|
37
|
+
// bodies, so it must keep the unstripped table set.
|
|
38
|
+
export type OuterSelectReturn<
|
|
39
|
+
N extends string,
|
|
40
|
+
Tables extends string,
|
|
41
|
+
Aliases extends string,
|
|
42
|
+
S extends DatabaseSchema
|
|
43
|
+
> =
|
|
44
|
+
N extends `with ${string}`
|
|
45
|
+
? CteOuterQuery<N> extends infer Outer extends string
|
|
46
|
+
? Outer extends `${string} join ${string}`
|
|
47
|
+
// CTE outer that JOINs (CTE↔CTE or CTE↔base): outer cols are
|
|
48
|
+
// CTE-qualified (`a.id`) and the CTE rows aren't modeled, so the
|
|
49
|
+
// derived-table path can't resolve them. Keep the prior lenient
|
|
50
|
+
// behavior (resolve the first inner select list against the base
|
|
51
|
+
// table set) — unchanged, to avoid regressing those queries.
|
|
52
|
+
? SelectReturnWith<ExtractSelectList<N>, Tables, Aliases, S, NullableRelations<N, S>>
|
|
53
|
+
// Outer reads from a single CTE (no join): resolve as a derived
|
|
54
|
+
// table so casts over CTE columns type precisely (via OuterCastTs)
|
|
55
|
+
// instead of poisoning to `never`.
|
|
56
|
+
: MultiCteReturn<Outer>
|
|
57
|
+
: SelectReturnWith<ExtractSelectList<N>, Tables, Aliases, S, NullableRelations<N, S>>
|
|
58
|
+
// A derived subquery JOINed under an alias (`... JOIN [LATERAL] (...) d`)
|
|
59
|
+
// is invisible to the plain table/alias resolution, so its projected
|
|
60
|
+
// `d.col` refs would be dropped. Merge their resolved (nullability-aware)
|
|
61
|
+
// contribution on top of the normal row; `JoinedDerivedReturn` is `{}`
|
|
62
|
+
// (a no-op merge) for any query without such a source.
|
|
63
|
+
: StripSubqueries<N> extends infer Outer extends string
|
|
64
|
+
? TablesInQuery<Outer, S> extends infer OT extends string
|
|
65
|
+
? AliasesInQuery<Outer, S> extends infer OA extends string
|
|
66
|
+
? WithJoinedDerived<N, S, SelectReturnWith<ExtractSelectList<N>, OT, OA, S, NullableRelations<N, S>>>
|
|
67
|
+
: WithJoinedDerived<N, S, SelectReturnWith<ExtractSelectList<N>, Tables, Aliases, S, NullableRelations<N, S>>>
|
|
68
|
+
: WithJoinedDerived<N, S, SelectReturnWith<ExtractSelectList<N>, Tables, Aliases, S, NullableRelations<N, S>>>
|
|
69
|
+
: WithJoinedDerived<N, S, SelectReturnWith<ExtractSelectList<N>, Tables, Aliases, S, NullableRelations<N, S>>>;
|
|
70
|
+
|
|
71
|
+
export type WithJoinedDerived<N extends string, S extends DatabaseSchema, Row> =
|
|
72
|
+
Simplify<MergeRow<Row, JoinedDerivedReturn<N, S, NullableRelations<N, S>>>>;
|
|
73
|
+
|
|
74
|
+
// Result inference for a `WITH <cte> AS (...) <DML> ... RETURNING ...` statement:
|
|
75
|
+
// resolve the inner DML's RETURNING list against the query's tables. Only invoked
|
|
76
|
+
// when `WithDmlOuter<N>` is non-`never`, so the inner statement is a real DML.
|
|
77
|
+
export type WithDmlReturn<
|
|
78
|
+
N extends string,
|
|
79
|
+
Tables extends string,
|
|
80
|
+
Aliases extends string,
|
|
81
|
+
S extends DatabaseSchema
|
|
82
|
+
> =
|
|
83
|
+
WithDmlOuter<N> extends infer Outer extends string
|
|
84
|
+
? HasReturningQuoteAware<Outer> extends true
|
|
85
|
+
? SelectReturnWith<ExtractReturningList<Outer>, Tables, Aliases, S>
|
|
86
|
+
: number
|
|
87
|
+
: number;
|
|
88
|
+
|
|
89
|
+
// Derived table (subquery in FROM): `SELECT ... FROM (<subquery>) alias`.
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
// Select / returning return type
|
|
93
|
+
|
|
94
|
+
export type SelectReturn<SelectList extends string, N extends string, S extends DatabaseSchema> =
|
|
95
|
+
TablesInQuery<N, S> extends infer Tables extends string
|
|
96
|
+
? AliasesInQuery<N, S> extends infer Aliases extends string
|
|
97
|
+
? SelectReturnWith<SelectList, Tables, Aliases, S>
|
|
98
|
+
: unknown
|
|
99
|
+
: unknown;
|
|
100
|
+
|
|
101
|
+
export type SelectReturnWith<
|
|
102
|
+
SelectList extends string,
|
|
103
|
+
Tables extends string,
|
|
104
|
+
Aliases extends string,
|
|
105
|
+
S extends DatabaseSchema,
|
|
106
|
+
Nullable extends string = never
|
|
107
|
+
> = BuildSelectReturn<SplitSelectList<SelectList>, Tables, Aliases, S, Nullable>;
|
|
108
|
+
|
|
109
|
+
export type BuildSelectReturn<
|
|
110
|
+
Exprs extends string[],
|
|
111
|
+
Tables extends string,
|
|
112
|
+
Aliases extends string,
|
|
113
|
+
S extends DatabaseSchema,
|
|
114
|
+
Nullable extends string = never
|
|
115
|
+
> = MergeExprs<Exprs, Tables, Aliases, S, Nullable>;
|
|
116
|
+
|
|
117
|
+
// Project each expression to its column object INDEPENDENTLY into a tuple, then
|
|
118
|
+
// merge with a balanced pairwise reduction. A naive left fold nests one
|
|
119
|
+
// `Omit<Acc, …> &` per column, so resolving the final row needs a `keyof Acc`
|
|
120
|
+
// chain O(N) deep — on a wide (50+ column) SELECT that alone, plus the structural
|
|
121
|
+
// comparison a `RequireTrue<AssertExtends<…>>` test forces, crosses TS's depth-100
|
|
122
|
+
// guard (TS2589). The balanced merge keeps the merge tree O(log N) deep.
|
|
123
|
+
export type MergeExprs<
|
|
124
|
+
Exprs extends string[],
|
|
125
|
+
Tables extends string,
|
|
126
|
+
Aliases extends string,
|
|
127
|
+
S extends DatabaseSchema,
|
|
128
|
+
Nullable extends string = never
|
|
129
|
+
> = Simplify<MergeAll<ColObjects<Exprs, Tables, Aliases, S, Nullable>>>;
|
|
130
|
+
|
|
131
|
+
// Per-expression column objects, in source order (capped at 100 columns).
|
|
132
|
+
type ColObjects<
|
|
133
|
+
Exprs extends string[],
|
|
134
|
+
Tables extends string,
|
|
135
|
+
Aliases extends string,
|
|
136
|
+
S extends DatabaseSchema,
|
|
137
|
+
Nullable extends string,
|
|
138
|
+
Acc extends any[] = []
|
|
139
|
+
> = Acc["length"] extends 100
|
|
140
|
+
? Acc
|
|
141
|
+
: Exprs extends [infer H extends string, ...infer Rest extends string[]]
|
|
142
|
+
? ColObjects<Rest, Tables, Aliases, S, Nullable, [...Acc, ExprToObject<H, Tables, Aliases, S, Nullable>]>
|
|
143
|
+
: Acc;
|
|
144
|
+
|
|
145
|
+
// Merge adjacent pairs, halving the tuple each round, until a single object
|
|
146
|
+
// remains. Resolution depth is O(log N), not O(N). The projection path uses an
|
|
147
|
+
// INFORMATIVENESS-preferring merge (`MergeRowProj`) for duplicate output
|
|
148
|
+
// aliases: when the same alias is projected by more than one SELECT expression
|
|
149
|
+
// — e.g. two mutually-exclusive `selectIf` branches both rendered into the
|
|
150
|
+
// maximal query — the MORE INFORMATIVE of the two column types is kept (see
|
|
151
|
+
// `PreferInformative`) instead of blindly taking the last. PairMerge is
|
|
152
|
+
// left-associative, so the merge folds in source order.
|
|
153
|
+
type PairMerge<T extends any[]> =
|
|
154
|
+
T extends [infer A, infer B, ...infer Rest extends any[]]
|
|
155
|
+
? [MergeRowProj<A, B>, ...PairMerge<Rest>]
|
|
156
|
+
: T;
|
|
157
|
+
|
|
158
|
+
type MergeAll<T extends any[]> =
|
|
159
|
+
T extends []
|
|
160
|
+
? {}
|
|
161
|
+
: T extends [infer Only]
|
|
162
|
+
? MergeRowProj<{}, Only>
|
|
163
|
+
: MergeAll<PairMerge<T>>;
|
|
164
|
+
|
|
165
|
+
// Merge a "later" column object into an "earlier" one, last write wins: a
|
|
166
|
+
// duplicate output alias keeps the later column's type instead of intersecting
|
|
167
|
+
// (which would collapse two differing same-named outputs to never). Either side
|
|
168
|
+
// may be `never` (an expression that projects nothing) — guard both.
|
|
169
|
+
//
|
|
170
|
+
// Used for JOIN/derived OVERLAYS, where a later contribution (e.g. an outer-join
|
|
171
|
+
// re-projection that adds `| null`) is meant to override an earlier same-named
|
|
172
|
+
// column — there, last-write-wins is correct.
|
|
173
|
+
export type MergeRow<Acc, Next> =
|
|
174
|
+
[Next] extends [never] ? Acc
|
|
175
|
+
: [Acc] extends [never] ? Next
|
|
176
|
+
: Omit<Acc, keyof Next> & Next;
|
|
177
|
+
|
|
178
|
+
// `true` for the `unknown` top type only (a column whose type we couldn't infer).
|
|
179
|
+
// `[unknown] extends [T]` holds only when T is `unknown` (or `any`, which never
|
|
180
|
+
// reaches here from inference). Guard `never` first so `[never]` doesn't qualify.
|
|
181
|
+
type IsUnknown<T> = [T] extends [never] ? false : [unknown] extends [T] ? true : false;
|
|
182
|
+
|
|
183
|
+
// Of two types for the SAME duplicate output alias, pick the more informative:
|
|
184
|
+
// - drop `unknown` in favour of any concrete type;
|
|
185
|
+
// - otherwise prefer the one whose non-null BASE is strictly narrower
|
|
186
|
+
// (e.g. a branded `User_id` over a plain `string`, ignoring `| null` on
|
|
187
|
+
// either side so a nullable branded column still beats a non-null `string`);
|
|
188
|
+
// - equal bases or incomparable types fall back to LAST-write-wins (`B`),
|
|
189
|
+
// preserving the historical behaviour for genuinely distinct same-named
|
|
190
|
+
// outputs (two different columns aliased identically).
|
|
191
|
+
type PreferInformative<A, B> =
|
|
192
|
+
IsUnknown<A> extends true ? B
|
|
193
|
+
: IsUnknown<B> extends true ? A
|
|
194
|
+
: [NonNullable<A>] extends [NonNullable<B>]
|
|
195
|
+
? ([NonNullable<B>] extends [NonNullable<A>] ? B : A)
|
|
196
|
+
: B;
|
|
197
|
+
|
|
198
|
+
// Projection-path merge: like `MergeRow` for non-overlapping keys, but a key
|
|
199
|
+
// present on BOTH sides is resolved by `PreferInformative` rather than last-wins.
|
|
200
|
+
export type MergeRowProj<Acc, Next> =
|
|
201
|
+
[Next] extends [never] ? Acc
|
|
202
|
+
: [Acc] extends [never] ? Next
|
|
203
|
+
: {
|
|
204
|
+
[K in keyof Acc | keyof Next]:
|
|
205
|
+
K extends keyof Acc
|
|
206
|
+
? K extends keyof Next ? PreferInformative<Acc[K], Next[K]> : Acc[K]
|
|
207
|
+
: K extends keyof Next ? Next[K] : never;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
// Select aliases (for ORDER BY / HAVING alias references)
|
|
211
|
+
|
|
212
|
+
export type SelectAliasesInQuery<N extends string> =
|
|
213
|
+
QueryKind<N> extends "select"
|
|
214
|
+
? HasReturning<N> extends true
|
|
215
|
+
? SelectAliases<SplitSelectList<ExtractReturningList<N>>>
|
|
216
|
+
: SelectAliases<SplitSelectList<ExtractSelectList<N>>>
|
|
217
|
+
: never;
|
|
218
|
+
|
|
219
|
+
export type SelectAliasSet<N extends string> =
|
|
220
|
+
NeedsSelectAliasResolution<N> extends true ? SelectAliasesInQuery<N> : never;
|
|
221
|
+
|
|
222
|
+
export type NeedsSelectAliasResolution<N extends string> =
|
|
223
|
+
N extends `${string} order by ${infer OrderExpr}`
|
|
224
|
+
? OrderExpr extends `${string}.${string}`
|
|
225
|
+
? false
|
|
226
|
+
: true
|
|
227
|
+
: false;
|
|
228
|
+
|
|
229
|
+
export type RefScanSegment<N extends string> =
|
|
230
|
+
QueryKind<N> extends "select"
|
|
231
|
+
? N extends `${string} from ${infer Rest}`
|
|
232
|
+
? `from ${Rest}`
|
|
233
|
+
: N
|
|
234
|
+
: N;
|
|
235
|
+
|
|
236
|
+
// The ref-scan segment up to (but not including) the LAST top-level ` order by `.
|
|
237
|
+
// This is the part where SELECT-list aliases are NOT resolvable.
|
|
238
|
+
export type RefScanBeforeOrderBy<N extends string> =
|
|
239
|
+
RefScanSegment<N> extends infer Seg extends string
|
|
240
|
+
? Seg extends `${infer Before} order by ${string}`
|
|
241
|
+
? Before
|
|
242
|
+
: Seg
|
|
243
|
+
: N;
|
|
244
|
+
|
|
245
|
+
// The ` order by ...` slice of the ref-scan segment, where SELECT-list aliases
|
|
246
|
+
// ARE resolvable. Empty when there is no ORDER BY.
|
|
247
|
+
export type RefScanOrderBy<N extends string> =
|
|
248
|
+
RefScanSegment<N> extends infer Seg extends string
|
|
249
|
+
? Seg extends `${string} order by ${infer After}`
|
|
250
|
+
? `order by ${After}`
|
|
251
|
+
: ""
|
|
252
|
+
: "";
|
|
253
|
+
|
|
254
|
+
export type SelectAliases<
|
|
255
|
+
Exprs extends string[],
|
|
256
|
+
Acc extends string = never,
|
|
257
|
+
Steps extends any[] = []
|
|
258
|
+
> = Steps["length"] extends 140
|
|
259
|
+
? Acc
|
|
260
|
+
: Exprs extends [infer H extends string, ...infer Rest extends string[]]
|
|
261
|
+
? ExtractAlias<H> extends { alias: infer Alias }
|
|
262
|
+
? Alias extends string
|
|
263
|
+
? SelectAliases<Rest, Acc | Alias, [any, ...Steps]>
|
|
264
|
+
: SelectAliases<Rest, Acc, [any, ...Steps]>
|
|
265
|
+
: SelectAliases<Rest, Acc, [any, ...Steps]>
|
|
266
|
+
: Acc;
|
|
267
|
+
|
|
268
|
+
// Column lists
|
|
269
|
+
|
|
270
|
+
export type ColumnsExistInTable<Cols extends string[], TableKey extends string, S extends DatabaseSchema> =
|
|
271
|
+
AllTrue<Cols[number] extends infer C ? (C extends string ? ColumnExists<TableKey, CleanIdent<C>, S> : true) : true>;
|