@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
package/src/columns.ts
CHANGED
|
@@ -10,11 +10,14 @@ import type {
|
|
|
10
10
|
CanPrecedeColumn,
|
|
11
11
|
CleanExpr,
|
|
12
12
|
CleanIdent,
|
|
13
|
+
CleanLooseToken,
|
|
14
|
+
DQuoteSpaceSentinel,
|
|
13
15
|
HasSpecial,
|
|
14
16
|
IsParamPlaceholder,
|
|
15
17
|
IsQualifiedRefCandidate,
|
|
16
18
|
IsRuntimeStringFragment,
|
|
17
19
|
IsSqlConstant,
|
|
20
|
+
LooseScanView,
|
|
18
21
|
OperatorToken,
|
|
19
22
|
ReplaceAll,
|
|
20
23
|
SqlReserved,
|
|
@@ -206,49 +209,182 @@ export type ColumnRefValidNoTables<ColRef extends string, S extends DatabaseSche
|
|
|
206
209
|
: ColumnExistsInAnyTable<B, S>
|
|
207
210
|
: ColumnExistsInAnyTable<CleanIdent<ColRef>, S>;
|
|
208
211
|
|
|
209
|
-
//
|
|
212
|
+
// ---- Direct-string column ref-scans ----
|
|
213
|
+
//
|
|
214
|
+
// Best-effort qualified / unqualified column references across a query segment.
|
|
215
|
+
// These walk the padded `LooseScanView` string DIRECTLY, word by word — replacing
|
|
216
|
+
// the old `TokenizeLoose` token ARRAY plus two array-walks (round-9): every array
|
|
217
|
+
// build/destructure step minted a unique-content tuple and its apparent-`Array`
|
|
218
|
+
// types, while a word-jump string walk interns its substrings and `[any, ...Steps]`
|
|
219
|
+
// counter tuples. Token semantics are reproduced verbatim:
|
|
220
|
+
// - per word, the kept token is `CleanLooseToken<ReplaceAll<H, DQuoteSpaceSentinel, " ">>`
|
|
221
|
+
// (exactly the old `SrclPush`); a word cleaning to `""` never occupied an array
|
|
222
|
+
// position, so it updates NO register and consumes NO cap budget;
|
|
223
|
+
// - `IS [NOT] DISTINCT FROM` (old `DropDistinctFrom` pre-pass, fused in): a `from`
|
|
224
|
+
// token whose RAW-stream predecessor is `distinct` is operator text, not a
|
|
225
|
+
// FROM-clause boundary — it is dropped, so the filtered-stream `Prev` the next
|
|
226
|
+
// token sees stays `distinct` (which `CanPrecedeColumn` blesses) instead of
|
|
227
|
+
// `from` (which would mark it a table source and skip validation). `PrevRaw`
|
|
228
|
+
// tracks the UNFILTERED stream (a dropped `from` still sets it to `from`),
|
|
229
|
+
// mirroring the old pre-pass's own `Prev` chain exactly. The old pass only ran
|
|
230
|
+
// when the segment contained `distinct ` — per-token it's the same test, and
|
|
231
|
+
// its 400-token cap (remainder unfiltered) is gone: a >400-token `distinct`
|
|
232
|
+
// stream now validates its RHS like any other, never rejecting valid SQL.
|
|
233
|
+
//
|
|
234
|
+
// Cap parity: `Steps` caps total WORDS at 2000 (the old split cap — on cap the old
|
|
235
|
+
// pipeline blobbed the remainder into ONE token and the walkers processed it; the
|
|
236
|
+
// `*Last` arms apply the same one-token transform to the remainder). `Kept` caps
|
|
237
|
+
// kept TOKENS at 900 (the old ref-walk cap — return `Acc`, rest unscanned).
|
|
210
238
|
|
|
211
|
-
export type
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
239
|
+
export type QualifiedRefScan<Seg extends string> =
|
|
240
|
+
LooseScanView<Seg> extends infer V extends string
|
|
241
|
+
? QrsWalk<V>
|
|
242
|
+
: never;
|
|
243
|
+
|
|
244
|
+
type QrsWalk<
|
|
245
|
+
V extends string,
|
|
216
246
|
Acc extends string = never,
|
|
217
247
|
Prev extends string = "",
|
|
248
|
+
PrevRaw extends string = "",
|
|
249
|
+
Kept extends any[] = [],
|
|
218
250
|
Steps extends any[] = []
|
|
219
|
-
> = Steps["length"] extends
|
|
220
|
-
? Acc
|
|
221
|
-
:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
?
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
251
|
+
> = Steps["length"] extends 2000
|
|
252
|
+
? QrsLast<V, Acc, Prev>
|
|
253
|
+
: Kept["length"] extends 900
|
|
254
|
+
? Acc
|
|
255
|
+
: V extends `${infer H} ${infer R}`
|
|
256
|
+
? CleanLooseToken<ReplaceAll<H, DQuoteSpaceSentinel, " ">> extends infer M extends string
|
|
257
|
+
? M extends ""
|
|
258
|
+
? QrsWalk<R, Acc, Prev, PrevRaw, Kept, [any, ...Steps]>
|
|
259
|
+
: M extends "from"
|
|
260
|
+
? PrevRaw extends "distinct"
|
|
261
|
+
? QrsWalk<R, Acc, Prev, "from", Kept, [any, ...Steps]>
|
|
262
|
+
: QrsWalk<R, Acc, "from", "from", [any, ...Kept], [any, ...Steps]>
|
|
263
|
+
: M extends `${string}.${string}`
|
|
264
|
+
? Prev extends "from" | "join" | "update" | "into" | "delete"
|
|
265
|
+
? QrsWalk<R, Acc, M, M, [any, ...Kept], [any, ...Steps]>
|
|
266
|
+
: IsQualifiedRefCandidate<M> extends true
|
|
267
|
+
? QrsWalk<R, Acc | M, M, M, [any, ...Kept], [any, ...Steps]>
|
|
268
|
+
: QrsWalk<R, Acc, M, M, [any, ...Kept], [any, ...Steps]>
|
|
269
|
+
: QrsWalk<R, Acc, M, M, [any, ...Kept], [any, ...Steps]>
|
|
270
|
+
: never
|
|
271
|
+
: QrsLast<V, Acc, Prev>;
|
|
272
|
+
|
|
273
|
+
// Final word (or capped remainder) as one token. A trailing `from` is never a ref
|
|
274
|
+
// and there is no subsequent token for its `Prev` effect to matter — `Acc` either way.
|
|
275
|
+
type QrsLast<H extends string, Acc extends string, Prev extends string> =
|
|
276
|
+
CleanLooseToken<ReplaceAll<H, DQuoteSpaceSentinel, " ">> extends infer M extends string
|
|
277
|
+
? M extends `${string}.${string}`
|
|
278
|
+
? Prev extends "from" | "join" | "update" | "into" | "delete"
|
|
279
|
+
? Acc
|
|
280
|
+
: IsQualifiedRefCandidate<M> extends true
|
|
281
|
+
? Acc | M
|
|
282
|
+
: Acc
|
|
283
|
+
: Acc
|
|
284
|
+
: never;
|
|
230
285
|
|
|
231
|
-
|
|
286
|
+
export type UnqualifiedRefScan<
|
|
287
|
+
Seg extends string,
|
|
288
|
+
S extends DatabaseSchema,
|
|
289
|
+
Tables extends string,
|
|
290
|
+
Aliases extends string
|
|
291
|
+
> = LooseScanView<Seg> extends infer V extends string
|
|
292
|
+
? UrsWalk<V, S, Tables, Aliases>
|
|
293
|
+
: never;
|
|
232
294
|
|
|
233
|
-
|
|
234
|
-
|
|
295
|
+
// Deferred-decision walk: the old array walker judged token T with (Prev, Next) via
|
|
296
|
+
// one-token lookahead. Here the PENDING token `Pend` is judged only when the NEXT
|
|
297
|
+
// kept token `M` materializes — `IsUnqualifiedColumnCandidate<Pend, PrevPrev, M, …>`
|
|
298
|
+
// — then registers shift (`PrevPrev := Pend`, `Pend := M`). At end of stream `Pend`
|
|
299
|
+
// is judged with `Next = ""`, exactly the old `[T]` tail arm. `Pend = ""` means "no
|
|
300
|
+
// pending yet" — safe sentinel (kept tokens are never empty), and the candidate
|
|
301
|
+
// check is `false` for `""`, so the initial shift needs no special arm.
|
|
302
|
+
type UrsWalk<
|
|
303
|
+
V extends string,
|
|
235
304
|
S extends DatabaseSchema,
|
|
236
305
|
Tables extends string,
|
|
237
306
|
Aliases extends string,
|
|
238
307
|
Acc extends string = never,
|
|
239
|
-
|
|
308
|
+
PrevPrev extends string = "",
|
|
309
|
+
Pend extends string = "",
|
|
310
|
+
PrevRaw extends string = "",
|
|
311
|
+
Kept extends any[] = [],
|
|
240
312
|
Steps extends any[] = []
|
|
241
|
-
> = Steps["length"] extends
|
|
242
|
-
? Acc
|
|
243
|
-
:
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
313
|
+
> = Steps["length"] extends 2000
|
|
314
|
+
? UrsLast<V, S, Tables, Aliases, Acc, PrevPrev, Pend, PrevRaw>
|
|
315
|
+
: Kept["length"] extends 900
|
|
316
|
+
? Acc
|
|
317
|
+
: V extends `${infer H} ${infer R}`
|
|
318
|
+
? CleanLooseToken<ReplaceAll<H, DQuoteSpaceSentinel, " ">> extends infer M extends string
|
|
319
|
+
? M extends ""
|
|
320
|
+
? UrsWalk<R, S, Tables, Aliases, Acc, PrevPrev, Pend, PrevRaw, Kept, [any, ...Steps]>
|
|
321
|
+
: M extends "from"
|
|
322
|
+
? PrevRaw extends "distinct"
|
|
323
|
+
? UrsWalk<R, S, Tables, Aliases, Acc, PrevPrev, Pend, "from", Kept, [any, ...Steps]>
|
|
324
|
+
: UrsShift<R, S, Tables, Aliases, Acc, PrevPrev, Pend, M, Kept, Steps>
|
|
325
|
+
: UrsShift<R, S, Tables, Aliases, Acc, PrevPrev, Pend, M, Kept, Steps>
|
|
326
|
+
: never
|
|
327
|
+
: UrsLast<V, S, Tables, Aliases, Acc, PrevPrev, Pend, PrevRaw>;
|
|
328
|
+
|
|
329
|
+
type UrsShift<
|
|
330
|
+
R extends string,
|
|
331
|
+
S extends DatabaseSchema,
|
|
332
|
+
Tables extends string,
|
|
333
|
+
Aliases extends string,
|
|
334
|
+
Acc extends string,
|
|
335
|
+
PrevPrev extends string,
|
|
336
|
+
Pend extends string,
|
|
337
|
+
M extends string,
|
|
338
|
+
Kept extends any[],
|
|
339
|
+
Steps extends any[]
|
|
340
|
+
> = IsUnqualifiedColumnCandidate<Pend, PrevPrev, M, Tables, Aliases, S> extends true
|
|
341
|
+
? UrsWalk<R, S, Tables, Aliases, Acc | Pend, Pend, M, M, [any, ...Kept], [any, ...Steps]>
|
|
342
|
+
: UrsWalk<R, S, Tables, Aliases, Acc, Pend, M, M, [any, ...Kept], [any, ...Steps]>;
|
|
343
|
+
|
|
344
|
+
// Final word (or capped remainder) as one token: judge `Pend` with the final token
|
|
345
|
+
// as `Next`, then the final token itself with `Next = ""`. A final dropped
|
|
346
|
+
// `distinct`-`from` ends the stream, so only `Pend` (with `Next = ""`) is judged.
|
|
347
|
+
type UrsLast<
|
|
348
|
+
H extends string,
|
|
349
|
+
S extends DatabaseSchema,
|
|
350
|
+
Tables extends string,
|
|
351
|
+
Aliases extends string,
|
|
352
|
+
Acc extends string,
|
|
353
|
+
PrevPrev extends string,
|
|
354
|
+
Pend extends string,
|
|
355
|
+
PrevRaw extends string
|
|
356
|
+
> = CleanLooseToken<ReplaceAll<H, DQuoteSpaceSentinel, " ">> extends infer M extends string
|
|
357
|
+
? M extends ""
|
|
358
|
+
? UrsEnd<S, Tables, Aliases, Acc, PrevPrev, Pend>
|
|
359
|
+
: M extends "from"
|
|
360
|
+
? PrevRaw extends "distinct"
|
|
361
|
+
? UrsEnd<S, Tables, Aliases, Acc, PrevPrev, Pend>
|
|
362
|
+
: UrsLast2<S, Tables, Aliases, Acc, PrevPrev, Pend, M>
|
|
363
|
+
: UrsLast2<S, Tables, Aliases, Acc, PrevPrev, Pend, M>
|
|
364
|
+
: never;
|
|
365
|
+
|
|
366
|
+
type UrsLast2<
|
|
367
|
+
S extends DatabaseSchema,
|
|
368
|
+
Tables extends string,
|
|
369
|
+
Aliases extends string,
|
|
370
|
+
Acc extends string,
|
|
371
|
+
PrevPrev extends string,
|
|
372
|
+
Pend extends string,
|
|
373
|
+
M extends string
|
|
374
|
+
> = IsUnqualifiedColumnCandidate<Pend, PrevPrev, M, Tables, Aliases, S> extends true
|
|
375
|
+
? UrsEnd<S, Tables, Aliases, Acc | Pend, Pend, M>
|
|
376
|
+
: UrsEnd<S, Tables, Aliases, Acc, Pend, M>;
|
|
377
|
+
|
|
378
|
+
type UrsEnd<
|
|
379
|
+
S extends DatabaseSchema,
|
|
380
|
+
Tables extends string,
|
|
381
|
+
Aliases extends string,
|
|
382
|
+
Acc extends string,
|
|
383
|
+
PrevPrev extends string,
|
|
384
|
+
Pend extends string
|
|
385
|
+
> = IsUnqualifiedColumnCandidate<Pend, PrevPrev, "", Tables, Aliases, S> extends true
|
|
386
|
+
? Acc | Pend
|
|
387
|
+
: Acc;
|
|
252
388
|
|
|
253
389
|
export type UnqualifiedColumnValid<
|
|
254
390
|
Col extends string,
|