effect-qb 0.15.0 → 0.16.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/dist/mysql.js +362 -70
- package/dist/postgres/metadata.js +557 -27
- package/dist/postgres.js +5028 -4732
- package/package.json +2 -2
- package/src/internal/column-state.ts +7 -0
- package/src/internal/column.ts +22 -0
- package/src/internal/dialect.ts +12 -1
- package/src/internal/executor.ts +15 -4
- package/src/internal/predicate/analysis.ts +103 -1
- package/src/internal/predicate/atom.ts +7 -0
- package/src/internal/predicate/context.ts +156 -16
- package/src/internal/predicate/key.ts +46 -1
- package/src/internal/predicate/normalize.ts +115 -34
- package/src/internal/predicate/runtime.ts +118 -11
- package/src/internal/query.ts +328 -90
- package/src/internal/renderer.ts +4 -0
- package/src/internal/runtime/driver-value-mapping.ts +186 -0
- package/src/internal/scalar.ts +11 -0
- package/src/mysql/column.ts +1 -0
- package/src/mysql/executor.ts +20 -5
- package/src/mysql/internal/dialect.ts +12 -6
- package/src/mysql/internal/dsl.ts +268 -54
- package/src/mysql/internal/renderer.ts +11 -2
- package/src/mysql/internal/sql-expression-renderer.ts +54 -8
- package/src/mysql/renderer.ts +7 -2
- package/src/postgres/cast.ts +22 -7
- package/src/postgres/column.ts +1 -0
- package/src/postgres/executor.ts +20 -5
- package/src/postgres/internal/dialect.ts +12 -6
- package/src/postgres/internal/dsl.ts +285 -58
- package/src/postgres/internal/renderer.ts +11 -2
- package/src/postgres/internal/sql-expression-renderer.ts +60 -8
- package/src/postgres/renderer.ts +7 -2
- package/src/postgres/type.ts +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effect-qb",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/bun": "latest",
|
|
52
|
-
"@typescript/native-preview": "
|
|
52
|
+
"@typescript/native-preview": "beta"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@effect/experimental": "^0.57.0",
|
|
@@ -76,6 +76,7 @@ export interface ColumnState<
|
|
|
76
76
|
readonly defaultValue?: DdlExpression
|
|
77
77
|
readonly generatedValue?: DdlExpression
|
|
78
78
|
readonly ddlType?: string
|
|
79
|
+
readonly driverValueMapping?: Expression.DriverValueMapping
|
|
79
80
|
readonly identity?: {
|
|
80
81
|
readonly generation: "always" | "byDefault"
|
|
81
82
|
}
|
|
@@ -137,6 +138,7 @@ export interface ColumnDefinition<
|
|
|
137
138
|
readonly defaultValue?: DdlExpression
|
|
138
139
|
readonly generatedValue?: DdlExpression
|
|
139
140
|
readonly ddlType?: string
|
|
141
|
+
readonly driverValueMapping?: Expression.DriverValueMapping
|
|
140
142
|
readonly identity?: {
|
|
141
143
|
readonly generation: "always" | "byDefault"
|
|
142
144
|
}
|
|
@@ -289,6 +291,7 @@ export const makeColumnDefinition = <
|
|
|
289
291
|
runtime: undefined as Select,
|
|
290
292
|
dbType: metadata.dbType,
|
|
291
293
|
runtimeSchema: schema,
|
|
294
|
+
driverValueMapping: metadata.driverValueMapping,
|
|
292
295
|
nullability: (metadata.nullable ? "maybe" : "never") as Nullable extends true ? "maybe" : "never",
|
|
293
296
|
dialect: metadata.dbType.dialect,
|
|
294
297
|
kind: "scalar",
|
|
@@ -308,6 +311,7 @@ export const makeColumnDefinition = <
|
|
|
308
311
|
defaultValue: metadata.defaultValue,
|
|
309
312
|
generatedValue: metadata.generatedValue,
|
|
310
313
|
ddlType: metadata.ddlType,
|
|
314
|
+
driverValueMapping: metadata.driverValueMapping,
|
|
311
315
|
identity: metadata.identity,
|
|
312
316
|
enum: metadata.enum
|
|
313
317
|
}
|
|
@@ -379,6 +383,7 @@ export const remapColumnDefinition = <
|
|
|
379
383
|
runtime: undefined as Select,
|
|
380
384
|
dbType: metadata.dbType,
|
|
381
385
|
runtimeSchema: schema,
|
|
386
|
+
driverValueMapping: metadata.driverValueMapping,
|
|
382
387
|
nullability: (metadata.nullable ? "maybe" : "never") as Nullable extends true ? "maybe" : "never",
|
|
383
388
|
dialect: metadata.dbType.dialect
|
|
384
389
|
}
|
|
@@ -397,6 +402,7 @@ export const remapColumnDefinition = <
|
|
|
397
402
|
defaultValue: metadata.defaultValue,
|
|
398
403
|
generatedValue: metadata.generatedValue,
|
|
399
404
|
ddlType: metadata.ddlType,
|
|
405
|
+
driverValueMapping: metadata.driverValueMapping,
|
|
400
406
|
identity: metadata.identity,
|
|
401
407
|
enum: metadata.enum
|
|
402
408
|
}
|
|
@@ -443,6 +449,7 @@ export const bindColumn = <
|
|
|
443
449
|
runtime: undefined as SelectType<Column>,
|
|
444
450
|
dbType: column.metadata.dbType,
|
|
445
451
|
runtimeSchema: schema,
|
|
452
|
+
driverValueMapping: column.metadata.driverValueMapping,
|
|
446
453
|
nullability: (column.metadata.nullable ? "maybe" : "never") as IsNullable<Column> extends true ? "maybe" : "never",
|
|
447
454
|
dialect: column.metadata.dbType.dialect,
|
|
448
455
|
kind: "scalar",
|
package/src/internal/column.ts
CHANGED
|
@@ -123,6 +123,20 @@ type DdlTypedColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
|
|
|
123
123
|
ReferencesOf<Column>
|
|
124
124
|
> & PreserveBrand<Column>
|
|
125
125
|
|
|
126
|
+
type DriverValueMappedColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
|
|
127
|
+
SelectType<Column>,
|
|
128
|
+
InsertType<Column>,
|
|
129
|
+
UpdateType<Column>,
|
|
130
|
+
Column[typeof ColumnTypeId]["dbType"],
|
|
131
|
+
IsNullable<Column>,
|
|
132
|
+
HasDefault<Column>,
|
|
133
|
+
IsGenerated<Column>,
|
|
134
|
+
IsPrimaryKey<Column>,
|
|
135
|
+
Column[typeof ColumnTypeId]["unique"],
|
|
136
|
+
ReferencesOf<Column>,
|
|
137
|
+
Column[typeof ColumnTypeId]["dependencies"]
|
|
138
|
+
> & PreserveBrand<Column>
|
|
139
|
+
|
|
126
140
|
type GeneratedColumn<Column extends AnyColumnDefinition> = ColumnDefinition<
|
|
127
141
|
SelectType<Column>,
|
|
128
142
|
InsertType<Column>,
|
|
@@ -543,6 +557,14 @@ export const ddlType = <SqlType extends string>(sqlType: SqlType) =>
|
|
|
543
557
|
ddlType: sqlType
|
|
544
558
|
}) as DdlTypedColumn<Column>
|
|
545
559
|
|
|
560
|
+
/** Overrides how a column crosses the SQL driver boundary. */
|
|
561
|
+
export const driverValueMapping = (mapping: Expression.DriverValueMapping) =>
|
|
562
|
+
<Column extends AnyColumnDefinition>(column: Column): DriverValueMappedColumn<Column> =>
|
|
563
|
+
mapColumn(column, {
|
|
564
|
+
...column.metadata,
|
|
565
|
+
driverValueMapping: mapping
|
|
566
|
+
}) as DriverValueMappedColumn<Column>
|
|
567
|
+
|
|
546
568
|
/** Marks a column as a Postgres array type. */
|
|
547
569
|
export const array = <Options extends ArrayOptions | undefined = undefined>(
|
|
548
570
|
options?: Options
|
package/src/internal/dialect.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import type * as Schema from "effect/Schema"
|
|
2
|
+
|
|
3
|
+
import type * as Expression from "./scalar.js"
|
|
4
|
+
|
|
1
5
|
/**
|
|
2
6
|
* Mutable rendering state shared while serializing SQL for a concrete dialect.
|
|
3
7
|
*
|
|
@@ -6,6 +10,7 @@
|
|
|
6
10
|
*/
|
|
7
11
|
export interface RenderState {
|
|
8
12
|
readonly params: unknown[]
|
|
13
|
+
readonly valueMappings?: Expression.DriverValueMappings
|
|
9
14
|
readonly ctes: {
|
|
10
15
|
readonly name: string
|
|
11
16
|
readonly sql: string
|
|
@@ -14,6 +19,12 @@ export interface RenderState {
|
|
|
14
19
|
readonly cteNames: Set<string>
|
|
15
20
|
}
|
|
16
21
|
|
|
22
|
+
export interface RenderValueContext {
|
|
23
|
+
readonly dbType?: Expression.DbType.Any
|
|
24
|
+
readonly runtimeSchema?: Schema.Schema.Any
|
|
25
|
+
readonly driverValueMapping?: Expression.DriverValueMapping
|
|
26
|
+
}
|
|
27
|
+
|
|
17
28
|
/**
|
|
18
29
|
* Minimal runtime contract for a SQL dialect.
|
|
19
30
|
*
|
|
@@ -24,7 +35,7 @@ export interface RenderState {
|
|
|
24
35
|
export interface SqlDialect<Name extends string = string> {
|
|
25
36
|
readonly name: Name
|
|
26
37
|
quoteIdentifier(value: string): string
|
|
27
|
-
renderLiteral(value: unknown, state: RenderState): string
|
|
38
|
+
renderLiteral(value: unknown, state: RenderState, context?: RenderValueContext): string
|
|
28
39
|
renderTableReference(tableName: string, baseTableName: string, schemaName?: string): string
|
|
29
40
|
renderConcat(values: readonly string[]): string
|
|
30
41
|
}
|
package/src/internal/executor.ts
CHANGED
|
@@ -9,7 +9,7 @@ import * as Stream from "effect/Stream"
|
|
|
9
9
|
import * as Expression from "./scalar.js"
|
|
10
10
|
import * as ExpressionAst from "./expression-ast.js"
|
|
11
11
|
import { resolveImplicationScope, type ImplicationScope } from "./implication-runtime.js"
|
|
12
|
-
import {
|
|
12
|
+
import { fromDriverValue } from "./runtime/driver-value-mapping.js"
|
|
13
13
|
import { expressionRuntimeSchema } from "./runtime/schema.js"
|
|
14
14
|
import { flattenSelection } from "./projections.js"
|
|
15
15
|
import * as Query from "./query.js"
|
|
@@ -243,12 +243,19 @@ const decodeProjectionValue = (
|
|
|
243
243
|
expression: Expression.Any,
|
|
244
244
|
raw: unknown,
|
|
245
245
|
scope: ImplicationScope,
|
|
246
|
-
driverMode: DriverMode
|
|
246
|
+
driverMode: DriverMode,
|
|
247
|
+
valueMappings?: Expression.DriverValueMappings
|
|
247
248
|
): unknown => {
|
|
248
249
|
let normalized = raw
|
|
249
250
|
if (driverMode === "raw") {
|
|
250
251
|
try {
|
|
251
|
-
normalized =
|
|
252
|
+
normalized = fromDriverValue(raw, {
|
|
253
|
+
dialect: rendered.dialect,
|
|
254
|
+
dbType: expression[Expression.TypeId].dbType,
|
|
255
|
+
runtimeSchema: expression[Expression.TypeId].runtimeSchema,
|
|
256
|
+
driverValueMapping: expression[Expression.TypeId].driverValueMapping,
|
|
257
|
+
valueMappings
|
|
258
|
+
})
|
|
252
259
|
} catch (cause) {
|
|
253
260
|
throw makeRowDecodeError(rendered, projection, expression, raw, "normalize", cause)
|
|
254
261
|
}
|
|
@@ -303,6 +310,7 @@ export const makeRowDecoder = (
|
|
|
303
310
|
plan: Query.Plan.Any,
|
|
304
311
|
options: {
|
|
305
312
|
readonly driverMode?: DriverMode
|
|
313
|
+
readonly valueMappings?: Expression.DriverValueMappings
|
|
306
314
|
} = {}
|
|
307
315
|
): ((row: FlatRow) => any) => {
|
|
308
316
|
const projections = flattenSelection(
|
|
@@ -312,6 +320,7 @@ export const makeRowDecoder = (
|
|
|
312
320
|
projections.map((projection) => [projection.alias, projection.expression] as const)
|
|
313
321
|
)
|
|
314
322
|
const driverMode = options.driverMode ?? "raw"
|
|
323
|
+
const valueMappings = options.valueMappings ?? rendered.valueMappings
|
|
315
324
|
const scope = resolveImplicationScope(plan[Plan.TypeId].available, Query.getQueryState(plan).assumptions)
|
|
316
325
|
return (row) => {
|
|
317
326
|
const decoded: Record<string, unknown> = {}
|
|
@@ -326,7 +335,7 @@ export const makeRowDecoder = (
|
|
|
326
335
|
setPath(
|
|
327
336
|
decoded,
|
|
328
337
|
projection.path,
|
|
329
|
-
decodeProjectionValue(rendered, projection, expression, row[projection.alias], scope, driverMode)
|
|
338
|
+
decodeProjectionValue(rendered, projection, expression, row[projection.alias], scope, driverMode, valueMappings)
|
|
330
339
|
)
|
|
331
340
|
}
|
|
332
341
|
return decoded
|
|
@@ -339,6 +348,7 @@ export const decodeChunk = (
|
|
|
339
348
|
rows: Chunk.Chunk<FlatRow>,
|
|
340
349
|
options: {
|
|
341
350
|
readonly driverMode?: DriverMode
|
|
351
|
+
readonly valueMappings?: Expression.DriverValueMappings
|
|
342
352
|
} = {}
|
|
343
353
|
): Chunk.Chunk<any> => {
|
|
344
354
|
const decodeRow = makeRowDecoder(rendered, plan, options)
|
|
@@ -351,6 +361,7 @@ export const decodeRows = (
|
|
|
351
361
|
rows: ReadonlyArray<FlatRow>,
|
|
352
362
|
options: {
|
|
353
363
|
readonly driverMode?: DriverMode
|
|
364
|
+
readonly valueMappings?: Expression.DriverValueMappings
|
|
354
365
|
} = {}
|
|
355
366
|
): ReadonlyArray<any> => {
|
|
356
367
|
const decodeRow = makeRowDecoder(rendered, plan, options)
|
|
@@ -1,9 +1,74 @@
|
|
|
1
|
-
import type { AnalyzeFormula } from "./context.js"
|
|
1
|
+
import type { AnalyzeFormula, AssumeFactsFalse, AssumeFactsTrue, PredicateContext } from "./context.js"
|
|
2
2
|
import type { FormulaOfPredicate } from "./normalize.js"
|
|
3
3
|
import type { And, Not, PredicateFormula, TrueFormula } from "./formula.js"
|
|
4
4
|
|
|
5
5
|
type ContextOf<Formula extends PredicateFormula> = AnalyzeFormula<Formula>
|
|
6
6
|
|
|
7
|
+
export type EmptyFacts = AnalyzeFormula<TrueFormula>
|
|
8
|
+
|
|
9
|
+
export type FactsOfFormula<
|
|
10
|
+
Formula extends PredicateFormula
|
|
11
|
+
> = AnalyzeFormula<Formula>
|
|
12
|
+
|
|
13
|
+
export interface PredicateState<
|
|
14
|
+
Formula extends PredicateFormula = PredicateFormula,
|
|
15
|
+
Facts extends PredicateContext = PredicateContext
|
|
16
|
+
> {
|
|
17
|
+
readonly formula: Formula
|
|
18
|
+
readonly facts: Facts
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type EmptyPredicateState = PredicateState<TrueFormula, EmptyFacts>
|
|
22
|
+
|
|
23
|
+
export type PredicateStateFormula<
|
|
24
|
+
State extends PredicateState
|
|
25
|
+
> = State["formula"]
|
|
26
|
+
|
|
27
|
+
export type PredicateStateFacts<
|
|
28
|
+
State extends PredicateState
|
|
29
|
+
> = State["facts"]
|
|
30
|
+
|
|
31
|
+
export type GuaranteedNonNullKeysInFacts<
|
|
32
|
+
Facts extends PredicateContext
|
|
33
|
+
> = Facts["nonNullKeys"]
|
|
34
|
+
|
|
35
|
+
export type GuaranteedNullKeysInFacts<
|
|
36
|
+
Facts extends PredicateContext
|
|
37
|
+
> = Facts["nullKeys"]
|
|
38
|
+
|
|
39
|
+
export type GuaranteedSourceNamesInFacts<
|
|
40
|
+
Facts extends PredicateContext
|
|
41
|
+
> = Facts["sourceNames"]
|
|
42
|
+
|
|
43
|
+
export type GuaranteedLiteralSetInFacts<
|
|
44
|
+
Facts extends PredicateContext,
|
|
45
|
+
Key extends string
|
|
46
|
+
> = [Facts["literalSets"]] extends [{ readonly [K in Key]: infer Values }]
|
|
47
|
+
? Values
|
|
48
|
+
: never
|
|
49
|
+
|
|
50
|
+
export type GuaranteedEqLiteralInFacts<
|
|
51
|
+
Facts extends PredicateContext,
|
|
52
|
+
Key extends string
|
|
53
|
+
> = [Facts["eqLiterals"]] extends [{ readonly [K in Key]: infer Values }]
|
|
54
|
+
? Values
|
|
55
|
+
: never
|
|
56
|
+
|
|
57
|
+
export type GuaranteedNeqLiteralInFacts<
|
|
58
|
+
Facts extends PredicateContext,
|
|
59
|
+
Key extends string
|
|
60
|
+
> = [Facts["neqLiterals"]] extends [{ readonly [K in Key]: infer Values }]
|
|
61
|
+
? Values
|
|
62
|
+
: never
|
|
63
|
+
|
|
64
|
+
export type GuaranteedJsonLiteralSetInFacts<
|
|
65
|
+
Facts extends PredicateContext,
|
|
66
|
+
ColumnKey extends string,
|
|
67
|
+
Path extends string
|
|
68
|
+
> = [Facts["jsonLiteralSets"]] extends [{ readonly [C in ColumnKey]: { readonly [P in Path]: infer Values } }]
|
|
69
|
+
? Values
|
|
70
|
+
: never
|
|
71
|
+
|
|
7
72
|
export type GuaranteedNonNullKeys<
|
|
8
73
|
Assumptions extends PredicateFormula
|
|
9
74
|
> = ContextOf<Assumptions>["nonNullKeys"]
|
|
@@ -23,6 +88,17 @@ export type GuaranteedEqLiteral<
|
|
|
23
88
|
? ContextOf<Assumptions>["eqLiterals"][Key]
|
|
24
89
|
: never
|
|
25
90
|
|
|
91
|
+
export type GuaranteedLiteralSets<
|
|
92
|
+
Assumptions extends PredicateFormula
|
|
93
|
+
> = ContextOf<Assumptions>["literalSets"]
|
|
94
|
+
|
|
95
|
+
export type GuaranteedLiteralSet<
|
|
96
|
+
Assumptions extends PredicateFormula,
|
|
97
|
+
Key extends string
|
|
98
|
+
> = Key extends keyof ContextOf<Assumptions>["literalSets"]
|
|
99
|
+
? ContextOf<Assumptions>["literalSets"][Key]
|
|
100
|
+
: never
|
|
101
|
+
|
|
26
102
|
type IsContradiction<Formula extends PredicateFormula> =
|
|
27
103
|
ContextOf<Formula>["contradiction"] extends true ? true : false
|
|
28
104
|
|
|
@@ -70,6 +146,32 @@ export type AssumeFalse<
|
|
|
70
146
|
Predicate
|
|
71
147
|
> = AssumeFormulaFalse<Assumptions, FormulaOfPredicate<Predicate>>
|
|
72
148
|
|
|
149
|
+
export type AssumePredicateStateFormulaTrue<
|
|
150
|
+
State extends PredicateState,
|
|
151
|
+
Formula extends PredicateFormula
|
|
152
|
+
> = PredicateState<
|
|
153
|
+
AssumeFormulaTrue<PredicateStateFormula<State>, Formula>,
|
|
154
|
+
AssumeFactsTrue<PredicateStateFacts<State>, Formula>
|
|
155
|
+
>
|
|
156
|
+
|
|
157
|
+
export type AssumePredicateStateFormulaFalse<
|
|
158
|
+
State extends PredicateState,
|
|
159
|
+
Formula extends PredicateFormula
|
|
160
|
+
> = PredicateState<
|
|
161
|
+
AssumeFormulaFalse<PredicateStateFormula<State>, Formula>,
|
|
162
|
+
AssumeFactsFalse<PredicateStateFacts<State>, Formula>
|
|
163
|
+
>
|
|
164
|
+
|
|
165
|
+
export type AssumePredicateStateTrue<
|
|
166
|
+
State extends PredicateState,
|
|
167
|
+
Predicate
|
|
168
|
+
> = AssumePredicateStateFormulaTrue<State, FormulaOfPredicate<Predicate>>
|
|
169
|
+
|
|
170
|
+
export type AssumePredicateStateFalse<
|
|
171
|
+
State extends PredicateState,
|
|
172
|
+
Predicate
|
|
173
|
+
> = AssumePredicateStateFormulaFalse<State, FormulaOfPredicate<Predicate>>
|
|
174
|
+
|
|
73
175
|
export type Contradicts<
|
|
74
176
|
Assumptions extends PredicateFormula,
|
|
75
177
|
Predicate
|
|
@@ -20,6 +20,12 @@ export interface NeqLiteralAtom<Key extends string, Value extends string> {
|
|
|
20
20
|
readonly value: Value
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
export interface LiteralSetAtom<Key extends string, Values extends string> {
|
|
24
|
+
readonly kind: "literal-set"
|
|
25
|
+
readonly key: Key
|
|
26
|
+
readonly values: readonly Values[]
|
|
27
|
+
}
|
|
28
|
+
|
|
23
29
|
export interface EqColumnAtom<
|
|
24
30
|
LeftKey extends string,
|
|
25
31
|
RightKey extends string
|
|
@@ -39,5 +45,6 @@ export type PredicateAtom =
|
|
|
39
45
|
| NonNullAtom<string>
|
|
40
46
|
| EqLiteralAtom<string, string>
|
|
41
47
|
| NeqLiteralAtom<string, string>
|
|
48
|
+
| LiteralSetAtom<string, string>
|
|
42
49
|
| EqColumnAtom<string, string>
|
|
43
50
|
| UnknownAtom<string>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EqColumnAtom, EqLiteralAtom, NeqLiteralAtom, NonNullAtom, NullAtom, PredicateAtom, UnknownAtom } from "./atom.js"
|
|
1
|
+
import type { EqColumnAtom, EqLiteralAtom, LiteralSetAtom, NeqLiteralAtom, NonNullAtom, NullAtom, PredicateAtom, UnknownAtom } from "./atom.js"
|
|
2
2
|
import type { AllFormula, AnyFormula, AtomFormula, FalseFormula, NotFormula, PredicateFormula, TrueFormula } from "./formula.js"
|
|
3
3
|
|
|
4
4
|
type Polarity = "positive" | "negative"
|
|
@@ -8,6 +8,8 @@ export interface Context<
|
|
|
8
8
|
NullKeys extends string = never,
|
|
9
9
|
EqLiterals = {},
|
|
10
10
|
NeqLiterals = {},
|
|
11
|
+
LiteralSets = {},
|
|
12
|
+
JsonLiteralSets = {},
|
|
11
13
|
SourceNames extends string = never,
|
|
12
14
|
Contradiction extends boolean = false,
|
|
13
15
|
Unknown extends boolean = false
|
|
@@ -16,6 +18,8 @@ export interface Context<
|
|
|
16
18
|
readonly nullKeys: NullKeys
|
|
17
19
|
readonly eqLiterals: EqLiterals
|
|
18
20
|
readonly neqLiterals: NeqLiterals
|
|
21
|
+
readonly literalSets: LiteralSets
|
|
22
|
+
readonly jsonLiteralSets: JsonLiteralSets
|
|
19
23
|
readonly sourceNames: SourceNames
|
|
20
24
|
readonly contradiction: Contradiction
|
|
21
25
|
readonly unknown: Unknown
|
|
@@ -27,6 +31,8 @@ type AnyContext = Context<
|
|
|
27
31
|
string,
|
|
28
32
|
Record<string, string>,
|
|
29
33
|
Record<string, string>,
|
|
34
|
+
Record<string, string>,
|
|
35
|
+
Record<string, Record<string, string>>,
|
|
30
36
|
string,
|
|
31
37
|
boolean,
|
|
32
38
|
boolean
|
|
@@ -84,15 +90,75 @@ type MergeNeqLiteralMaps<Left, Right> = {
|
|
|
84
90
|
: never
|
|
85
91
|
}
|
|
86
92
|
|
|
93
|
+
type MergeLiteralSetMaps<Left, Right> = {
|
|
94
|
+
readonly [K in Extract<keyof Left | keyof Right, string>]:
|
|
95
|
+
K extends keyof Left
|
|
96
|
+
? K extends keyof Right
|
|
97
|
+
? Extract<Left[K], Right[K]>
|
|
98
|
+
: Left[K]
|
|
99
|
+
: K extends keyof Right
|
|
100
|
+
? Right[K]
|
|
101
|
+
: never
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
type MergeJsonLiteralSetPathMaps<Left, Right> = {
|
|
105
|
+
readonly [K in Extract<keyof Left | keyof Right, string>]:
|
|
106
|
+
K extends keyof Left
|
|
107
|
+
? K extends keyof Right
|
|
108
|
+
? Extract<Left[K], Right[K]>
|
|
109
|
+
: Left[K]
|
|
110
|
+
: K extends keyof Right
|
|
111
|
+
? Right[K]
|
|
112
|
+
: never
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
type MergeJsonLiteralSetMaps<Left, Right> = {
|
|
116
|
+
readonly [K in Extract<keyof Left | keyof Right, string>]:
|
|
117
|
+
K extends keyof Left
|
|
118
|
+
? K extends keyof Right
|
|
119
|
+
? MergeJsonLiteralSetPathMaps<Left[K], Right[K]>
|
|
120
|
+
: Left[K]
|
|
121
|
+
: K extends keyof Right
|
|
122
|
+
? Right[K]
|
|
123
|
+
: never
|
|
124
|
+
}
|
|
125
|
+
|
|
87
126
|
type FilterNeverValues<Map> = {
|
|
88
127
|
readonly [K in keyof Map as Map[K] extends never ? never : K]: Map[K]
|
|
89
128
|
}
|
|
90
129
|
|
|
130
|
+
type JsonKeyParts<Key extends string> = string extends Key
|
|
131
|
+
? never
|
|
132
|
+
: Key extends `${infer ColumnKey}#json:${infer Path}`
|
|
133
|
+
? readonly [ColumnKey, Path]
|
|
134
|
+
: never
|
|
135
|
+
|
|
136
|
+
type LiteralSetMapAfterAdd<
|
|
137
|
+
LiteralSets,
|
|
138
|
+
Key extends string,
|
|
139
|
+
Values extends string
|
|
140
|
+
> = [JsonKeyParts<Key>] extends [never]
|
|
141
|
+
? FilterNeverValues<MergeLiteralSetMaps<LiteralSets, { readonly [K in Key]: Values }>>
|
|
142
|
+
: LiteralSets
|
|
143
|
+
|
|
144
|
+
type JsonLiteralSetMapAfterAdd<
|
|
145
|
+
JsonLiteralSets,
|
|
146
|
+
Key extends string,
|
|
147
|
+
Values extends string
|
|
148
|
+
> = JsonKeyParts<Key> extends readonly [infer ColumnKey extends string, infer Path extends string]
|
|
149
|
+
? MergeJsonLiteralSetMaps<
|
|
150
|
+
JsonLiteralSets,
|
|
151
|
+
{ readonly [C in ColumnKey]: { readonly [P in Path]: Values } }
|
|
152
|
+
>
|
|
153
|
+
: JsonLiteralSets
|
|
154
|
+
|
|
91
155
|
type MarkContradiction<Ctx extends AnyContext> = Context<
|
|
92
156
|
Ctx["nonNullKeys"],
|
|
93
157
|
Ctx["nullKeys"],
|
|
94
158
|
Ctx["eqLiterals"],
|
|
95
159
|
Ctx["neqLiterals"],
|
|
160
|
+
Ctx["literalSets"],
|
|
161
|
+
Ctx["jsonLiteralSets"],
|
|
96
162
|
Ctx["sourceNames"],
|
|
97
163
|
true,
|
|
98
164
|
Ctx["unknown"]
|
|
@@ -103,6 +169,8 @@ type MarkUnknown<Ctx extends AnyContext> = Context<
|
|
|
103
169
|
Ctx["nullKeys"],
|
|
104
170
|
Ctx["eqLiterals"],
|
|
105
171
|
Ctx["neqLiterals"],
|
|
172
|
+
Ctx["literalSets"],
|
|
173
|
+
Ctx["jsonLiteralSets"],
|
|
106
174
|
Ctx["sourceNames"],
|
|
107
175
|
Ctx["contradiction"],
|
|
108
176
|
true
|
|
@@ -116,6 +184,8 @@ type AddNonNull<
|
|
|
116
184
|
Ctx["nullKeys"],
|
|
117
185
|
Ctx["eqLiterals"],
|
|
118
186
|
Ctx["neqLiterals"],
|
|
187
|
+
Ctx["literalSets"],
|
|
188
|
+
Ctx["jsonLiteralSets"],
|
|
119
189
|
Ctx["sourceNames"] | SourceNameOfKey<Key>,
|
|
120
190
|
Key extends Ctx["nullKeys"] ? true : Ctx["contradiction"],
|
|
121
191
|
Ctx["unknown"]
|
|
@@ -129,11 +199,35 @@ type AddNull<
|
|
|
129
199
|
Ctx["nullKeys"] | Key,
|
|
130
200
|
Ctx["eqLiterals"],
|
|
131
201
|
Ctx["neqLiterals"],
|
|
202
|
+
Ctx["literalSets"],
|
|
203
|
+
Ctx["jsonLiteralSets"],
|
|
132
204
|
Ctx["sourceNames"] | SourceNameOfKey<Key>,
|
|
133
205
|
Key extends Ctx["nonNullKeys"] ? true : Ctx["contradiction"],
|
|
134
206
|
Ctx["unknown"]
|
|
135
207
|
>
|
|
136
208
|
|
|
209
|
+
type AddLiteralSet<
|
|
210
|
+
Ctx extends AnyContext,
|
|
211
|
+
Key extends string,
|
|
212
|
+
Values extends string
|
|
213
|
+
> = Context<
|
|
214
|
+
Ctx["nonNullKeys"] | Key,
|
|
215
|
+
Ctx["nullKeys"],
|
|
216
|
+
Ctx["eqLiterals"],
|
|
217
|
+
Ctx["neqLiterals"],
|
|
218
|
+
LiteralSetMapAfterAdd<Ctx["literalSets"], Key, Values>,
|
|
219
|
+
JsonLiteralSetMapAfterAdd<Ctx["jsonLiteralSets"], Key, Values>,
|
|
220
|
+
Ctx["sourceNames"] | SourceNameOfKey<Key>,
|
|
221
|
+
EqLiteralValueOf<Ctx["eqLiterals"], Key> extends infer EqValue
|
|
222
|
+
? [EqValue] extends [never]
|
|
223
|
+
? Key extends Ctx["nullKeys"] ? true : Ctx["contradiction"]
|
|
224
|
+
: EqValue extends Values
|
|
225
|
+
? Key extends Ctx["nullKeys"] ? true : Ctx["contradiction"]
|
|
226
|
+
: true
|
|
227
|
+
: true,
|
|
228
|
+
Ctx["unknown"]
|
|
229
|
+
>
|
|
230
|
+
|
|
137
231
|
type AddEqLiteral<
|
|
138
232
|
Ctx extends AnyContext,
|
|
139
233
|
Key extends string,
|
|
@@ -143,6 +237,8 @@ type AddEqLiteral<
|
|
|
143
237
|
Ctx["nullKeys"],
|
|
144
238
|
FilterNeverValues<MergeEqLiteralMaps<Ctx["eqLiterals"], { readonly [K in Key]: Value }>>,
|
|
145
239
|
Ctx["neqLiterals"],
|
|
240
|
+
LiteralSetMapAfterAdd<Ctx["literalSets"], Key, Value>,
|
|
241
|
+
JsonLiteralSetMapAfterAdd<Ctx["jsonLiteralSets"], Key, Value>,
|
|
146
242
|
Ctx["sourceNames"] | SourceNameOfKey<Key>,
|
|
147
243
|
EqLiteralValueOf<Ctx["eqLiterals"], Key> extends never
|
|
148
244
|
? NeqLiteralValuesOf<Ctx["neqLiterals"], Key> extends infer NeqValues
|
|
@@ -169,6 +265,8 @@ type AddNeqLiteral<
|
|
|
169
265
|
Ctx["nullKeys"],
|
|
170
266
|
Ctx["eqLiterals"],
|
|
171
267
|
FilterNeverValues<MergeNeqLiteralMaps<Ctx["neqLiterals"], { readonly [K in Key]: Value }>>,
|
|
268
|
+
Ctx["literalSets"],
|
|
269
|
+
Ctx["jsonLiteralSets"],
|
|
172
270
|
Ctx["sourceNames"] | SourceNameOfKey<Key>,
|
|
173
271
|
EqLiteralValueOf<Ctx["eqLiterals"], Key> extends infer EqValue
|
|
174
272
|
? [EqValue] extends [never]
|
|
@@ -219,11 +317,13 @@ type ApplyAtom<
|
|
|
219
317
|
? AddEqLiteral<Ctx, Key, Value>
|
|
220
318
|
: Atom extends NeqLiteralAtom<infer Key extends string, infer Value extends string>
|
|
221
319
|
? AddNeqLiteral<Ctx, Key, Value>
|
|
222
|
-
: Atom extends
|
|
223
|
-
?
|
|
224
|
-
: Atom extends
|
|
225
|
-
?
|
|
226
|
-
:
|
|
320
|
+
: Atom extends LiteralSetAtom<infer Key extends string, infer Values extends string>
|
|
321
|
+
? AddLiteralSet<Ctx, Key, Values>
|
|
322
|
+
: Atom extends EqColumnAtom<infer Left extends string, infer Right extends string>
|
|
323
|
+
? ApplyEqColumn<Ctx, Left, Right>
|
|
324
|
+
: Atom extends UnknownAtom<any>
|
|
325
|
+
? MarkUnknown<Ctx>
|
|
326
|
+
: Ctx
|
|
227
327
|
|
|
228
328
|
type ApplyNegativeAtom<
|
|
229
329
|
Ctx extends AnyContext,
|
|
@@ -237,11 +337,13 @@ type ApplyNegativeAtom<
|
|
|
237
337
|
? AddNeqLiteral<Ctx, Key, Value>
|
|
238
338
|
: Atom extends NeqLiteralAtom<infer Key extends string, infer Value extends string>
|
|
239
339
|
? AddEqLiteral<Ctx, Key, Value>
|
|
240
|
-
: Atom extends
|
|
241
|
-
? AddNonNull<
|
|
242
|
-
: Atom extends
|
|
243
|
-
?
|
|
244
|
-
:
|
|
340
|
+
: Atom extends LiteralSetAtom<infer Key extends string, any>
|
|
341
|
+
? AddNonNull<Ctx, Key>
|
|
342
|
+
: Atom extends EqColumnAtom<infer Left extends string, infer Right extends string>
|
|
343
|
+
? AddNonNull<AddNonNull<Ctx, Left>, Right>
|
|
344
|
+
: Atom extends UnknownAtom<any>
|
|
345
|
+
? MarkUnknown<Ctx>
|
|
346
|
+
: Ctx
|
|
245
347
|
|
|
246
348
|
type FramesFromItems<
|
|
247
349
|
Items extends readonly PredicateFormula[],
|
|
@@ -268,6 +370,27 @@ type IntersectNeqLiteralMaps<
|
|
|
268
370
|
Extract<Left[K], Right[K]> extends never ? never : Extract<Left[K], Right[K]>
|
|
269
371
|
}>
|
|
270
372
|
|
|
373
|
+
type UnionLiteralSetMaps<
|
|
374
|
+
Left,
|
|
375
|
+
Right
|
|
376
|
+
> = FilterNeverValues<{
|
|
377
|
+
readonly [K in Extract<keyof Left, keyof Right>]: Left[K] | Right[K]
|
|
378
|
+
}>
|
|
379
|
+
|
|
380
|
+
type UnionJsonLiteralSetPathMaps<
|
|
381
|
+
Left,
|
|
382
|
+
Right
|
|
383
|
+
> = FilterNeverValues<{
|
|
384
|
+
readonly [K in Extract<keyof Left, keyof Right>]: Left[K] | Right[K]
|
|
385
|
+
}>
|
|
386
|
+
|
|
387
|
+
type UnionJsonLiteralSetMaps<
|
|
388
|
+
Left,
|
|
389
|
+
Right
|
|
390
|
+
> = {
|
|
391
|
+
readonly [K in Extract<keyof Left, keyof Right>]: UnionJsonLiteralSetPathMaps<Left[K], Right[K]>
|
|
392
|
+
}
|
|
393
|
+
|
|
271
394
|
type IntersectContexts<
|
|
272
395
|
Left extends AnyContext,
|
|
273
396
|
Right extends AnyContext
|
|
@@ -276,6 +399,8 @@ type IntersectContexts<
|
|
|
276
399
|
Extract<Left["nullKeys"], Right["nullKeys"]>,
|
|
277
400
|
IntersectEqLiteralMaps<Left["eqLiterals"], Right["eqLiterals"]>,
|
|
278
401
|
IntersectNeqLiteralMaps<Left["neqLiterals"], Right["neqLiterals"]>,
|
|
402
|
+
UnionLiteralSetMaps<Left["literalSets"], Right["literalSets"]>,
|
|
403
|
+
UnionJsonLiteralSetMaps<Left["jsonLiteralSets"], Right["jsonLiteralSets"]>,
|
|
279
404
|
Extract<Left["sourceNames"], Right["sourceNames"]>,
|
|
280
405
|
Left["contradiction"] extends true
|
|
281
406
|
? Right["contradiction"]
|
|
@@ -289,17 +414,20 @@ type AnalyzeAnyBranches<
|
|
|
289
414
|
Ctx extends AnyContext,
|
|
290
415
|
Items extends readonly PredicateFormula[],
|
|
291
416
|
Direction extends Polarity,
|
|
292
|
-
Current extends AnyContext | never = never
|
|
293
|
-
|
|
417
|
+
Current extends AnyContext | never = never,
|
|
418
|
+
Seen extends readonly unknown[] = []
|
|
419
|
+
> = Seen["length"] extends 20
|
|
420
|
+
? MarkUnknown<Ctx>
|
|
421
|
+
: Items extends readonly [
|
|
294
422
|
infer Head extends PredicateFormula,
|
|
295
423
|
...infer Tail extends readonly PredicateFormula[]
|
|
296
424
|
]
|
|
297
425
|
? AnalyzeBranch<Ctx, Head, Direction> extends infer Branch extends AnyContext
|
|
298
426
|
? Branch["contradiction"] extends true
|
|
299
|
-
? AnalyzeAnyBranches<Ctx, Tail, Direction, Current>
|
|
427
|
+
? AnalyzeAnyBranches<Ctx, Tail, Direction, Current, readonly [...Seen, unknown]>
|
|
300
428
|
: [Current] extends [never]
|
|
301
|
-
? AnalyzeAnyBranches<Ctx, Tail, Direction, Branch>
|
|
302
|
-
: AnalyzeAnyBranches<Ctx, Tail, Direction, IntersectContexts<Current, Branch
|
|
429
|
+
? AnalyzeAnyBranches<Ctx, Tail, Direction, Branch, readonly [...Seen, unknown]>
|
|
430
|
+
: AnalyzeAnyBranches<Ctx, Tail, Direction, IntersectContexts<Current, Branch>, readonly [...Seen, unknown]>
|
|
303
431
|
: never
|
|
304
432
|
: [Current] extends [never]
|
|
305
433
|
? MarkContradiction<Ctx>
|
|
@@ -356,3 +484,15 @@ export type AnalyzeStack<
|
|
|
356
484
|
|
|
357
485
|
export type AnalyzeFormula<Formula extends PredicateFormula> =
|
|
358
486
|
AnalyzeStack<EmptyContext, readonly [Frame<Formula, "positive">]>
|
|
487
|
+
|
|
488
|
+
export type PredicateContext = AnyContext
|
|
489
|
+
|
|
490
|
+
export type AssumeFactsTrue<
|
|
491
|
+
Ctx extends PredicateContext,
|
|
492
|
+
Formula extends PredicateFormula
|
|
493
|
+
> = AnalyzeStack<Ctx, readonly [Frame<Formula, "positive">]>
|
|
494
|
+
|
|
495
|
+
export type AssumeFactsFalse<
|
|
496
|
+
Ctx extends PredicateContext,
|
|
497
|
+
Formula extends PredicateFormula
|
|
498
|
+
> = AnalyzeStack<Ctx, readonly [Frame<Formula, "negative">]>
|