@kuindji/typed-sql 0.3.0 → 0.4.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/README.md +11 -3
- package/dist/columns.d.ts +11 -3
- package/dist/columns.d.ts.map +1 -1
- package/dist/expressions.d.ts +73 -8
- package/dist/expressions.d.ts.map +1 -1
- package/dist/parsing/extract.d.ts +13 -9
- package/dist/parsing/extract.d.ts.map +1 -1
- package/dist/parsing/normalize.d.ts +3 -1
- package/dist/parsing/normalize.d.ts.map +1 -1
- package/dist/parsing/pg-literals.d.ts +10 -2
- package/dist/parsing/pg-literals.d.ts.map +1 -1
- package/dist/parsing/split.d.ts +27 -3
- package/dist/parsing/split.d.ts.map +1 -1
- package/dist/parsing/string-utils.d.ts +2 -4
- package/dist/parsing/string-utils.d.ts.map +1 -1
- package/dist/parsing/tokenize.d.ts +27 -17
- package/dist/parsing/tokenize.d.ts.map +1 -1
- package/dist/partial.d.ts +6 -6
- package/dist/partial.d.ts.map +1 -1
- package/dist/tables.d.ts +58 -13
- package/dist/tables.d.ts.map +1 -1
- package/dist/validation/dispatch.d.ts +7 -5
- package/dist/validation/dispatch.d.ts.map +1 -1
- package/dist/validation/joins.d.ts +3 -3
- package/dist/validation/joins.d.ts.map +1 -1
- package/dist/validation/validate-columns.d.ts +14 -14
- package/dist/validation/validate-columns.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/columns.ts +168 -32
- package/src/expressions.ts +550 -57
- package/src/parsing/extract.ts +72 -32
- package/src/parsing/normalize.ts +54 -8
- package/src/parsing/pg-literals.ts +32 -10
- package/src/parsing/split.ts +236 -72
- package/src/parsing/string-utils.ts +15 -15
- package/src/parsing/tokenize.ts +224 -146
- package/src/partial.ts +9 -15
- package/src/tables.ts +546 -214
- package/src/validation/dispatch.ts +58 -52
- package/src/validation/joins.ts +15 -19
- package/src/validation/validate-columns.ts +54 -64
|
@@ -6,7 +6,7 @@ import type { CteNames, NonCteTables, SingleCteMatch } from "./cte.js";
|
|
|
6
6
|
import type { DatabaseSchema } from "../schema.js";
|
|
7
7
|
import type { DerivedAliasName, DerivedFirstWord, DerivedTableMatch } from "./return-derived.js";
|
|
8
8
|
import type { DistinctOnColsValid, JoinUsingColsValid, WindowFilterColsValid } from "./joins.js";
|
|
9
|
-
import type { ExceedsLengthBudget, ExtractBefore, ExtractLastWhere, HasLineBreaks,
|
|
9
|
+
import type { ExceedsLengthBudget, ExtractBefore, ExtractLastWhere, HasLineBreaks, Trim, ValidationScanView } from "../parsing.js";
|
|
10
10
|
import type { RefScanSegment } from "./return-types.js";
|
|
11
11
|
// Core validation / inference
|
|
12
12
|
|
|
@@ -126,16 +126,13 @@ export type WhereColsValidForUpdate<
|
|
|
126
126
|
TargetKey extends string,
|
|
127
127
|
AliasEntry extends string,
|
|
128
128
|
S extends DatabaseSchema
|
|
129
|
-
> =
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
true
|
|
137
|
-
>
|
|
138
|
-
: true;
|
|
129
|
+
> = And<
|
|
130
|
+
QualifiedColumnRefsValidFor<W, S, TargetKey, AliasEntry, W>,
|
|
131
|
+
UnqualifiedColumnRefsValidFor<W, S, TargetKey, AliasEntry, W, never>,
|
|
132
|
+
true,
|
|
133
|
+
true,
|
|
134
|
+
true
|
|
135
|
+
>;
|
|
139
136
|
|
|
140
137
|
// "Light" validator for high-complexity SELECTs: validate the cheap, bounded
|
|
141
138
|
// parts (every referenced table exists, and the select/returning list resolves)
|
|
@@ -217,21 +214,19 @@ export type LightSelectTablesAndList<N extends string, S extends DatabaseSchema>
|
|
|
217
214
|
export type ValidateSQLNormalizedCore<N extends string, S extends DatabaseSchema> =
|
|
218
215
|
TablesInQuery<N, S> extends infer Tables extends string
|
|
219
216
|
? AliasesInQuery<N, S> extends infer Aliases extends string
|
|
220
|
-
?
|
|
221
|
-
?
|
|
222
|
-
?
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
?
|
|
226
|
-
?
|
|
227
|
-
?
|
|
228
|
-
? true
|
|
229
|
-
: false
|
|
217
|
+
? AllTablesValidFor<NonCteTables<N, S, Tables>, S> extends true
|
|
218
|
+
? AllColumnsValidFor<N, S, Tables, Aliases, RefScanSegment<N>> extends true
|
|
219
|
+
? NoAliasShadowedQualifiers<N, S, Tables, Aliases> extends true
|
|
220
|
+
? OuterScopeUnqualifiedValid<N, S> extends true
|
|
221
|
+
? WindowFilterColsValid<N, S, Tables, Aliases> extends true
|
|
222
|
+
? JoinUsingColsValid<N, S, Tables> extends true
|
|
223
|
+
? DistinctOnColsValid<N, S, Tables, Aliases> extends true
|
|
224
|
+
? true
|
|
230
225
|
: false
|
|
231
226
|
: false
|
|
232
227
|
: false
|
|
233
|
-
: false
|
|
234
228
|
: false
|
|
229
|
+
: false
|
|
235
230
|
: false
|
|
236
231
|
: false
|
|
237
232
|
: false
|
|
@@ -290,41 +285,52 @@ export type HasReturning<N extends string> =
|
|
|
290
285
|
|
|
291
286
|
// Quote-free fast-path: a query with no `'` and no `"` has no place for a
|
|
292
287
|
// ` returning ` to hide, so every occurrence is top-level — a single pattern test
|
|
293
|
-
// is exact and skips the
|
|
294
|
-
//
|
|
295
|
-
//
|
|
296
|
-
export type HasReturningQuoteAware<
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
? HasReturningQuoteAwareWalk<S, InString, InDString, Steps>
|
|
305
|
-
: S extends `${string}"${string}`
|
|
306
|
-
? HasReturningQuoteAwareWalk<S, InString, InDString, Steps>
|
|
307
|
-
: S extends `${string} returning ${string}` ? true : false;
|
|
288
|
+
// is exact and skips the walk (these run on every DML). Only quote-bearing
|
|
289
|
+
// queries pay for the walk below. The fast-path pattern matches the step-cap
|
|
290
|
+
// fallback this walk already uses, so it is consistent with prior behavior.
|
|
291
|
+
export type HasReturningQuoteAware<S extends string> =
|
|
292
|
+
string extends S
|
|
293
|
+
? false
|
|
294
|
+
: S extends `${string}'${string}`
|
|
295
|
+
? HasReturningQuoteAwareWalk<S>
|
|
296
|
+
: S extends `${string}"${string}`
|
|
297
|
+
? HasReturningQuoteAwareWalk<S>
|
|
298
|
+
: S extends `${string} returning ${string}` ? true : false;
|
|
308
299
|
|
|
300
|
+
// Quote-jump, not per-char (the old walk minted the tail string PER CHARACTER on
|
|
301
|
+
// every quote-bearing DML). Find the leftmost ` returning `; if no quote opens
|
|
302
|
+
// before it, it is top-level — answer found. Otherwise jump the leftmost quote
|
|
303
|
+
// span whole (`'…'` or `"…"`, whichever opens first — a quote of the other kind
|
|
304
|
+
// inside the span is data, mirroring the old InString/InDString suppression) and
|
|
305
|
+
// re-test the remainder. O(quote spans) instead of O(chars); an unterminated
|
|
306
|
+
// quote swallows the rest, exactly like the old walk-to-EOF inside a literal.
|
|
309
307
|
type HasReturningQuoteAwareWalk<
|
|
310
308
|
S extends string,
|
|
311
|
-
InString extends boolean = false,
|
|
312
|
-
InDString extends boolean = false,
|
|
313
309
|
Steps extends any[] = []
|
|
314
310
|
> = string extends S
|
|
315
311
|
? false
|
|
316
|
-
: Steps["length"] extends
|
|
312
|
+
: Steps["length"] extends 400
|
|
317
313
|
? S extends `${string} returning ${string}` ? true : false
|
|
318
|
-
:
|
|
319
|
-
?
|
|
320
|
-
?
|
|
314
|
+
: S extends `${infer Before} returning ${string}`
|
|
315
|
+
? Before extends `${string}'${string}` | `${string}"${string}`
|
|
316
|
+
? HrqaQuoteJump<S, Steps>
|
|
317
|
+
: true
|
|
318
|
+
: false;
|
|
319
|
+
|
|
320
|
+
// Leftmost of `'` / `"` (the caller guarantees at least one occurs before the
|
|
321
|
+
// first ` returning `): skip its whole span, resume after the closing quote.
|
|
322
|
+
type HrqaQuoteJump<S extends string, Steps extends any[]> =
|
|
323
|
+
S extends `${infer P}'${infer R}`
|
|
324
|
+
? P extends `${string}"${string}`
|
|
325
|
+
? HrqaDQuoteJump<S, Steps>
|
|
326
|
+
: R extends `${string}'${infer R2}`
|
|
327
|
+
? HasReturningQuoteAwareWalk<R2, [any, ...Steps]>
|
|
321
328
|
: false
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
: false;
|
|
329
|
+
: HrqaDQuoteJump<S, Steps>;
|
|
330
|
+
|
|
331
|
+
type HrqaDQuoteJump<S extends string, Steps extends any[]> =
|
|
332
|
+
S extends `${string}"${infer R}`
|
|
333
|
+
? R extends `${string}"${infer R2}`
|
|
334
|
+
? HasReturningQuoteAwareWalk<R2, [any, ...Steps]>
|
|
335
|
+
: false
|
|
336
|
+
: false;
|
package/src/validation/joins.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// JOIN USING / window-filter / DISTINCT ON column validation.
|
|
2
2
|
import type { AllTrue, And, IsUnion } from "../utils.js";
|
|
3
|
-
import type { CleanIdent, ExtractCallParenBodies, SplitCommaSimple,
|
|
3
|
+
import type { CleanIdent, ExtractCallParenBodies, SplitCommaSimple, Trim } from "../parsing.js";
|
|
4
4
|
import type { ColumnExists, DatabaseSchema } from "../schema.js";
|
|
5
5
|
import type { QualifiedColumnRefsValidFor, UnqualifiedColumnRefsValidFor } from "./validate-columns.js";
|
|
6
6
|
import type { QueryKind } from "./dispatch.js";
|
|
@@ -151,15 +151,13 @@ export type WindowFilterColsValid<
|
|
|
151
151
|
? `${ExtractCallParenBodies<N, " over (">} ${ExtractCallParenBodies<N, " over(">} ${ExtractCallParenBodies<N, " filter (">} ${ExtractCallParenBodies<N, " filter(">} ${ExtractCallParenBodies<N, " within group (">} ${ExtractCallParenBodies<N, " within group(">}` extends infer Seg extends string
|
|
152
152
|
? Trim<Seg> extends ""
|
|
153
153
|
? true
|
|
154
|
-
:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
>
|
|
162
|
-
: true
|
|
154
|
+
: And<
|
|
155
|
+
QualifiedColumnRefsValidFor<N, S, Tables, Aliases, Seg>,
|
|
156
|
+
UnqualifiedColumnRefsValidFor<N, S, Tables, Aliases, Seg, never>,
|
|
157
|
+
true,
|
|
158
|
+
true,
|
|
159
|
+
true
|
|
160
|
+
>
|
|
163
161
|
: true
|
|
164
162
|
: true;
|
|
165
163
|
|
|
@@ -183,15 +181,13 @@ export type DistinctOnColsValid<
|
|
|
183
181
|
? `${ExtractCallParenBodies<N, " distinct on (">} ${ExtractCallParenBodies<N, " distinct on(">}` extends infer Seg extends string
|
|
184
182
|
? Trim<Seg> extends ""
|
|
185
183
|
? true
|
|
186
|
-
:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
>
|
|
194
|
-
: true
|
|
184
|
+
: And<
|
|
185
|
+
QualifiedColumnRefsValidFor<N, S, Tables, Aliases, Seg>,
|
|
186
|
+
UnqualifiedColumnRefsValidFor<N, S, Tables, Aliases, Seg, never>,
|
|
187
|
+
true,
|
|
188
|
+
true,
|
|
189
|
+
true
|
|
190
|
+
>
|
|
195
191
|
: true
|
|
196
192
|
: true
|
|
197
193
|
: true;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Table/column existence + qualified/unqualified ref + scope-shape validation.
|
|
2
2
|
import type { AliasesInQuery, InsertTargetTable, TableKeyValid, TablesInQuery, UpdateTargetTable } from "../tables.js";
|
|
3
3
|
import type { AllTrue, And, StartsWith } from "../utils.js";
|
|
4
|
-
import type { CleanIdent, DQuoteSpaceSentinel, ExceedsLengthBudget, ExtractAliasResult, ExtractBefore, ExtractConflictColumns, ExtractConflictUpdateExcludedCols, ExtractConflictUpdateSetColumns, ExtractInsertColumns, ExtractLastWhere, ExtractReturningList, ExtractSelectList, ExtractUpdateSetColumns, ReplaceAll, SplitSelectList, StripSubqueries,
|
|
5
|
-
import type { ColumnRefValidLooseWith, IsSimpleRefPart,
|
|
4
|
+
import type { CleanIdent, DQuoteSpaceSentinel, ExceedsLengthBudget, ExtractAliasResult, ExtractBefore, ExtractConflictColumns, ExtractConflictUpdateExcludedCols, ExtractConflictUpdateSetColumns, ExtractInsertColumns, ExtractLastWhere, ExtractReturningList, ExtractSelectList, ExtractUpdateSetColumns, ReplaceAll, SplitSelectList, StripSubqueries, Trim } from "../parsing.js";
|
|
5
|
+
import type { ColumnRefValidLooseWith, IsSimpleRefPart, QualifiedRefScan, ResolveAlias, TableKeysByName, UnqualifiedRefScan, UnqualifiedColumnValid } from "../columns.js";
|
|
6
6
|
import type { ColumnsExistInTable, RefScanBeforeOrderBy, RefScanOrderBy, RefScanSegment, SelectAliasesInQuery, SelectAliasSet } from "./return-types.js";
|
|
7
7
|
import type { CteNames, CteRow, SingleCteMatch } from "./cte.js";
|
|
8
8
|
import type { DatabaseSchema } from "../schema.js";
|
|
@@ -105,7 +105,7 @@ export type KeyInRow<K extends string, Row> = [K] extends [keyof Row] ? true : f
|
|
|
105
105
|
|
|
106
106
|
// Validate every column-reference candidate in an arbitrary text segment (an
|
|
107
107
|
// outer WHERE predicate, or a function call's argument list) against the
|
|
108
|
-
// CTE/derived relation's exposed `Row`. Reuses the same
|
|
108
|
+
// CTE/derived relation's exposed `Row`. Reuses the same ref-scan walkers the core
|
|
109
109
|
// validator uses to surface refs, then checks each via `ProjRefInRow` (qualifier
|
|
110
110
|
// must equal the relation `Name`, column must be a key of `Row`). `Tables`/
|
|
111
111
|
// `Aliases` are `never`: the walkers only consult them to EXCLUDE table/alias
|
|
@@ -115,22 +115,20 @@ export type KeyInRow<K extends string, Row> = [K] extends [keyof Row] ? true : f
|
|
|
115
115
|
export type SegRefsInRow<Seg extends string, Name extends string, Row, S extends DatabaseSchema> =
|
|
116
116
|
Trim<Seg> extends ""
|
|
117
117
|
? true
|
|
118
|
-
:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
>
|
|
133
|
-
: true;
|
|
118
|
+
: And<
|
|
119
|
+
AllTrue<
|
|
120
|
+
QualifiedRefScan<Seg> extends infer R
|
|
121
|
+
? R extends string ? ProjRefInRow<R, Name, Row, S> : true
|
|
122
|
+
: true
|
|
123
|
+
>,
|
|
124
|
+
AllTrue<
|
|
125
|
+
UnqualifiedRefScan<Seg, S, never, never> extends infer R
|
|
126
|
+
? R extends string ? ProjRefInRow<R, Name, Row, S> : true
|
|
127
|
+
: true
|
|
128
|
+
>,
|
|
129
|
+
true,
|
|
130
|
+
true
|
|
131
|
+
>;
|
|
134
132
|
|
|
135
133
|
// The outer query's WHERE predicate, scoped to the CTE/derived relation's exposed
|
|
136
134
|
// row. Strip subquery bodies FIRST so the derived/CTE body's own WHERE is never
|
|
@@ -191,22 +189,20 @@ type ExtractOrderByExpr<S extends string> =
|
|
|
191
189
|
export type SegRefsInRowWithAliases<Seg extends string, Name extends string, Row, S extends DatabaseSchema, SelAliases extends string> =
|
|
192
190
|
Trim<Seg> extends ""
|
|
193
191
|
? true
|
|
194
|
-
:
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
>
|
|
209
|
-
: true;
|
|
192
|
+
: And<
|
|
193
|
+
AllTrue<
|
|
194
|
+
QualifiedRefScan<Seg> extends infer R
|
|
195
|
+
? R extends string ? RefInRowOrAlias<R, Name, Row, S, SelAliases> : true
|
|
196
|
+
: true
|
|
197
|
+
>,
|
|
198
|
+
AllTrue<
|
|
199
|
+
UnqualifiedRefScan<Seg, S, never, never> extends infer R
|
|
200
|
+
? R extends string ? RefInRowOrAlias<R, Name, Row, S, SelAliases> : true
|
|
201
|
+
: true
|
|
202
|
+
>,
|
|
203
|
+
true,
|
|
204
|
+
true
|
|
205
|
+
>;
|
|
210
206
|
|
|
211
207
|
export type RefInRowOrAlias<R extends string, Name extends string, Row, S extends DatabaseSchema, SelAliases extends string> =
|
|
212
208
|
[SelAliases] extends [never]
|
|
@@ -231,9 +227,7 @@ export type AllTablesValidFor<Tables extends string, S extends DatabaseSchema> =
|
|
|
231
227
|
export type AllColumnsValid<N extends string, S extends DatabaseSchema> =
|
|
232
228
|
TablesInQuery<N, S> extends infer Tables extends string
|
|
233
229
|
? AliasesInQuery<N, S> extends infer Aliases extends string
|
|
234
|
-
?
|
|
235
|
-
? AllColumnsValidFor<N, S, Tables, Aliases, LooseTokens>
|
|
236
|
-
: false
|
|
230
|
+
? AllColumnsValidFor<N, S, Tables, Aliases, RefScanSegment<N>>
|
|
237
231
|
: false
|
|
238
232
|
: false;
|
|
239
233
|
|
|
@@ -242,7 +236,7 @@ export type AllColumnsValidFor<
|
|
|
242
236
|
S extends DatabaseSchema,
|
|
243
237
|
Tables extends string,
|
|
244
238
|
Aliases extends string,
|
|
245
|
-
|
|
239
|
+
RefSeg extends string
|
|
246
240
|
> = SelectAliasSet<N> extends infer SelectAliases extends string
|
|
247
241
|
? QueryKind<N> extends "update"
|
|
248
242
|
// A normal (non-high-complexity) UPDATE has no subquery/CASE SET, so its
|
|
@@ -254,14 +248,14 @@ export type AllColumnsValidFor<
|
|
|
254
248
|
ColumnsValidInUpdate<N, S>,
|
|
255
249
|
ColumnsValidInInsert<N, S>,
|
|
256
250
|
ColumnsValidInSelectOrReturningFor<N, S, Tables, Aliases>,
|
|
257
|
-
QualifiedColumnRefsValidFor<N, S, Tables, Aliases,
|
|
258
|
-
UnqualifiedColumnRefsValidFor<N, S, Tables, Aliases,
|
|
251
|
+
QualifiedColumnRefsValidFor<N, S, Tables, Aliases, RefSeg>,
|
|
252
|
+
UnqualifiedColumnRefsValidFor<N, S, Tables, Aliases, RefSeg, never>
|
|
259
253
|
>
|
|
260
254
|
: And<
|
|
261
255
|
ColumnsValidInSelectOrReturningFor<N, S, Tables, Aliases>,
|
|
262
256
|
ColumnsValidInInsert<N, S>,
|
|
263
257
|
ColumnsValidInUpdate<N, S>,
|
|
264
|
-
QualifiedColumnRefsValidFor<N, S, Tables, Aliases,
|
|
258
|
+
QualifiedColumnRefsValidFor<N, S, Tables, Aliases, RefSeg>,
|
|
265
259
|
// A SELECT-list alias is only resolvable in ORDER BY — NOT in
|
|
266
260
|
// WHERE/GROUP/HAVING. So the unqualified ref-scan blesses the alias
|
|
267
261
|
// set ONLY for the ORDER BY token slice; the FROM..(pre-order-by)
|
|
@@ -284,10 +278,10 @@ export type SelectUnqualifiedRefsScoped<
|
|
|
284
278
|
SelectAliases extends string
|
|
285
279
|
> =
|
|
286
280
|
[SelectAliases] extends [never]
|
|
287
|
-
? UnqualifiedColumnRefsValidFor<N, S, Tables, Aliases,
|
|
281
|
+
? UnqualifiedColumnRefsValidFor<N, S, Tables, Aliases, RefScanSegment<N>, never>
|
|
288
282
|
: And<
|
|
289
|
-
UnqualifiedColumnRefsValidFor<N, S, Tables, Aliases,
|
|
290
|
-
UnqualifiedColumnRefsValidFor<N, S, Tables, Aliases,
|
|
283
|
+
UnqualifiedColumnRefsValidFor<N, S, Tables, Aliases, RefScanBeforeOrderBy<N>, never>,
|
|
284
|
+
UnqualifiedColumnRefsValidFor<N, S, Tables, Aliases, RefScanOrderBy<N>, SelectAliases>,
|
|
291
285
|
true,
|
|
292
286
|
true,
|
|
293
287
|
true
|
|
@@ -365,9 +359,7 @@ export type ColumnsValidInUpdate<N extends string, S extends DatabaseSchema> =
|
|
|
365
359
|
export type QualifiedColumnRefsValid<N extends string, S extends DatabaseSchema> =
|
|
366
360
|
TablesInQuery<N, S> extends infer Tables extends string
|
|
367
361
|
? AliasesInQuery<N, S> extends infer Aliases extends string
|
|
368
|
-
?
|
|
369
|
-
? QualifiedColumnRefsValidFor<N, S, Tables, Aliases, LooseTokens>
|
|
370
|
-
: true
|
|
362
|
+
? QualifiedColumnRefsValidFor<N, S, Tables, Aliases, RefScanSegment<N>>
|
|
371
363
|
: true
|
|
372
364
|
: true;
|
|
373
365
|
|
|
@@ -376,14 +368,14 @@ export type QualifiedColumnRefsValidFor<
|
|
|
376
368
|
S extends DatabaseSchema,
|
|
377
369
|
Tables extends string,
|
|
378
370
|
Aliases extends string,
|
|
379
|
-
|
|
371
|
+
RefSeg extends string
|
|
380
372
|
> =
|
|
381
373
|
// Common path: with no CTE and no parenthesised FROM source there is no local
|
|
382
374
|
// relation that could qualify a ref, so skip the (per-ref) local-relation
|
|
383
375
|
// blessing entirely — exact prior behavior, zero added cost.
|
|
384
376
|
HasLocalRelations<N> extends true
|
|
385
|
-
? QualifiedRefsValidWithLocal<N, S, Tables, Aliases,
|
|
386
|
-
:
|
|
377
|
+
? QualifiedRefsValidWithLocal<N, S, Tables, Aliases, RefSeg, CteNames<N>>
|
|
378
|
+
: QualifiedRefScan<RefSeg> extends infer Cols
|
|
387
379
|
? AllTrue<Cols extends string ? ColumnRefValidLooseWith<Cols, Tables, Aliases, S> : true>
|
|
388
380
|
: true;
|
|
389
381
|
|
|
@@ -404,9 +396,9 @@ type QualifiedRefsValidWithLocal<
|
|
|
404
396
|
S extends DatabaseSchema,
|
|
405
397
|
Tables extends string,
|
|
406
398
|
Aliases extends string,
|
|
407
|
-
|
|
399
|
+
RefSeg extends string,
|
|
408
400
|
Ctes extends string
|
|
409
|
-
> =
|
|
401
|
+
> = QualifiedRefScan<RefSeg> extends infer Cols
|
|
410
402
|
? AllTrue<
|
|
411
403
|
Cols extends string
|
|
412
404
|
? IsLocalRelation<RefQualifierOf<Cols>, Ctes, N> extends true
|
|
@@ -468,12 +460,12 @@ export type NoAliasShadowedQualifiers<
|
|
|
468
460
|
[AliasedTableKeys<Aliases>] extends [never]
|
|
469
461
|
? true
|
|
470
462
|
// A shadowable qualifier is a `qualifier.column` token, which requires a
|
|
471
|
-
// `.`. With no `.` anywhere, `
|
|
472
|
-
// `AllTrue<never>` is `true` — so skip the whole-query
|
|
473
|
-
//
|
|
463
|
+
// `.`. With no `.` anywhere, `QualifiedRefScan` accumulates `never` and
|
|
464
|
+
// `AllTrue<never>` is `true` — so skip the whole-query re-scan (computed
|
|
465
|
+
// nowhere else) on dot-free queries. Exact-equivalent.
|
|
474
466
|
: N extends `${string}.${string}`
|
|
475
467
|
? AllTrue<
|
|
476
|
-
|
|
468
|
+
QualifiedRefScan<N> extends infer R
|
|
477
469
|
? R extends `${infer Q}.${string}`
|
|
478
470
|
? QualifierShadowedByAlias<Q, Tables, Aliases, S> extends true
|
|
479
471
|
? false
|
|
@@ -521,7 +513,7 @@ export type OuterScopeUnqualifiedValid<N extends string, S extends DatabaseSchem
|
|
|
521
513
|
S,
|
|
522
514
|
OT,
|
|
523
515
|
OA,
|
|
524
|
-
|
|
516
|
+
RefScanSegment<Stripped>,
|
|
525
517
|
SelectAliasesInQuery<Stripped>
|
|
526
518
|
>
|
|
527
519
|
: true
|
|
@@ -534,10 +526,8 @@ export type OuterScopeUnqualifiedValid<N extends string, S extends DatabaseSchem
|
|
|
534
526
|
export type UnqualifiedColumnRefsValid<N extends string, S extends DatabaseSchema> =
|
|
535
527
|
TablesInQuery<N, S> extends infer Tables extends string
|
|
536
528
|
? AliasesInQuery<N, S> extends infer Aliases extends string
|
|
537
|
-
?
|
|
538
|
-
?
|
|
539
|
-
? UnqualifiedColumnRefsValidFor<N, S, Tables, Aliases, LooseTokens, SelectAliases>
|
|
540
|
-
: true
|
|
529
|
+
? SelectAliasesInQuery<N> extends infer SelectAliases extends string
|
|
530
|
+
? UnqualifiedColumnRefsValidFor<N, S, Tables, Aliases, RefScanSegment<N>, SelectAliases>
|
|
541
531
|
: true
|
|
542
532
|
: true
|
|
543
533
|
: true;
|
|
@@ -547,9 +537,9 @@ export type UnqualifiedColumnRefsValidFor<
|
|
|
547
537
|
S extends DatabaseSchema,
|
|
548
538
|
Tables extends string,
|
|
549
539
|
Aliases extends string,
|
|
550
|
-
|
|
540
|
+
RefSeg extends string,
|
|
551
541
|
SelectAliases extends string
|
|
552
|
-
> =
|
|
542
|
+
> = UnqualifiedRefScan<RefSeg, S, Tables, Aliases> extends infer Cols
|
|
553
543
|
? AllTrue<
|
|
554
544
|
Cols extends string
|
|
555
545
|
? CleanIdent<Cols> extends SelectAliases
|