effect-qb 0.16.0 → 0.19.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 +4 -0
- package/dist/index.js +8065 -0
- package/dist/mysql.js +4036 -2418
- package/dist/postgres/metadata.js +2536 -625
- package/dist/postgres.js +8248 -7857
- package/dist/sqlite.js +8854 -0
- package/dist/standard.js +8019 -0
- package/package.json +15 -3
- package/src/casing.ts +71 -0
- package/src/index.ts +2 -0
- package/src/internal/casing.ts +89 -0
- package/src/internal/column-state.ts +11 -6
- package/src/internal/column.ts +44 -7
- package/src/internal/datatypes/define.ts +2 -1
- package/src/internal/datatypes/enrich.ts +23 -0
- package/src/internal/datatypes/lookup.ts +14 -7
- package/src/internal/derived-table.ts +7 -13
- package/src/internal/dialect-renderers/mysql.ts +2046 -0
- package/src/{postgres/internal/sql-expression-renderer.ts → internal/dialect-renderers/postgres.ts} +867 -283
- package/src/{mysql/internal/sql-expression-renderer.ts → internal/dialect-renderers/sqlite.ts} +834 -358
- package/src/internal/dialect.ts +37 -0
- package/src/internal/dsl-mutation-runtime.ts +29 -10
- package/src/internal/dsl-plan-runtime.ts +41 -24
- package/src/internal/dsl-query-runtime.ts +11 -31
- package/src/internal/dsl-transaction-ddl-runtime.ts +61 -15
- package/src/internal/executor.ts +57 -15
- package/src/internal/expression-ast.ts +3 -2
- package/src/internal/grouping-key.ts +216 -9
- package/src/internal/implication-runtime.ts +3 -2
- package/src/internal/json/types.ts +155 -40
- package/src/internal/predicate/context.ts +14 -1
- package/src/internal/predicate/key.ts +19 -2
- package/src/internal/predicate/runtime.ts +30 -3
- package/src/internal/query.d.ts +38 -11
- package/src/internal/query.ts +315 -54
- package/src/internal/renderer.ts +51 -6
- package/src/internal/runtime/driver-value-mapping.ts +58 -0
- package/src/internal/runtime/normalize.ts +74 -43
- package/src/internal/runtime/schema.ts +5 -3
- package/src/internal/runtime/value.ts +153 -30
- package/src/internal/scalar.ts +6 -1
- package/src/internal/schema-derivation.d.ts +12 -61
- package/src/internal/schema-derivation.ts +90 -38
- package/src/internal/schema-expression.ts +2 -2
- package/src/internal/sql-expression-renderer.ts +19 -0
- package/src/internal/standard-dsl.ts +6885 -0
- package/src/internal/table-options.ts +229 -62
- package/src/internal/table.d.ts +33 -32
- package/src/internal/table.ts +469 -160
- package/src/mysql/column-extension.ts +3 -0
- package/src/mysql/column.ts +27 -12
- package/src/mysql/datatypes/index.ts +24 -2
- package/src/mysql/errors/catalog.ts +5 -5
- package/src/mysql/errors/normalize.ts +2 -2
- package/src/mysql/executor.ts +7 -5
- package/src/mysql/internal/dialect.ts +9 -4
- package/src/mysql/internal/dsl.ts +906 -324
- package/src/mysql/internal/renderer.ts +7 -2
- package/src/mysql/json.ts +37 -0
- package/src/mysql/query-extension.ts +16 -0
- package/src/mysql/query.ts +9 -2
- package/src/mysql/renderer.ts +31 -4
- package/src/mysql.ts +4 -12
- package/src/postgres/column-extension.ts +28 -0
- package/src/postgres/column.ts +9 -13
- package/src/postgres/datatypes/index.d.ts +2 -1
- package/src/postgres/datatypes/index.ts +3 -2
- package/src/postgres/errors/normalize.ts +2 -2
- package/src/postgres/executor.ts +55 -10
- package/src/postgres/function/core.ts +20 -4
- package/src/postgres/function/index.ts +1 -17
- package/src/postgres/internal/dialect.ts +9 -4
- package/src/postgres/internal/dsl.ts +850 -359
- package/src/postgres/internal/renderer.ts +7 -2
- package/src/postgres/internal/schema-ddl.ts +22 -9
- package/src/postgres/internal/schema-model.ts +244 -10
- package/src/postgres/json.ts +100 -24
- package/src/postgres/jsonb.ts +38 -0
- package/src/postgres/query-extension.ts +2 -0
- package/src/postgres/query.ts +9 -2
- package/src/postgres/renderer.ts +31 -4
- package/src/postgres/schema-management.ts +108 -16
- package/src/postgres/schema.ts +98 -15
- package/src/postgres/table.ts +203 -398
- package/src/postgres/type.ts +8 -7
- package/src/postgres.ts +9 -11
- package/src/sqlite/column-extension.ts +3 -0
- package/src/sqlite/column.ts +127 -0
- package/src/sqlite/datatypes/index.ts +80 -0
- package/src/sqlite/datatypes/spec.ts +98 -0
- package/src/sqlite/errors/catalog.ts +103 -0
- package/src/sqlite/errors/fields.ts +19 -0
- package/src/sqlite/errors/index.ts +19 -0
- package/src/sqlite/errors/normalize.ts +229 -0
- package/src/sqlite/errors/requirements.ts +71 -0
- package/src/sqlite/errors/types.ts +29 -0
- package/src/sqlite/executor.ts +229 -0
- package/src/sqlite/function/aggregate.ts +2 -0
- package/src/sqlite/function/core.ts +2 -0
- package/src/sqlite/function/index.ts +19 -0
- package/src/sqlite/function/string.ts +2 -0
- package/src/sqlite/function/temporal.ts +100 -0
- package/src/sqlite/function/window.ts +2 -0
- package/src/sqlite/internal/dialect.ts +42 -0
- package/src/sqlite/internal/dsl.ts +6979 -0
- package/src/sqlite/internal/renderer.ts +51 -0
- package/src/sqlite/json.ts +39 -0
- package/src/sqlite/query-extension.ts +2 -0
- package/src/sqlite/query.ts +196 -0
- package/src/sqlite/renderer.ts +51 -0
- package/src/sqlite.ts +14 -0
- package/src/standard/column.ts +163 -0
- package/src/standard/datatypes/index.ts +83 -0
- package/src/standard/datatypes/spec.ts +98 -0
- package/src/standard/dialect.ts +40 -0
- package/src/standard/function/aggregate.ts +2 -0
- package/src/standard/function/core.ts +2 -0
- package/src/standard/function/index.ts +18 -0
- package/src/standard/function/string.ts +2 -0
- package/src/standard/function/temporal.ts +78 -0
- package/src/standard/function/window.ts +2 -0
- package/src/standard/internal/renderer.ts +45 -0
- package/src/standard/query.ts +152 -0
- package/src/standard/renderer.ts +21 -0
- package/src/standard/table.ts +147 -0
- package/src/standard.ts +18 -0
- package/src/internal/aggregation-validation.ts +0 -57
- package/src/mysql/table.ts +0 -157
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effect-qb",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
"README.md"
|
|
22
22
|
],
|
|
23
23
|
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./src/index.ts",
|
|
26
|
+
"import": "./dist/index.js"
|
|
27
|
+
},
|
|
24
28
|
"./postgres": {
|
|
25
29
|
"types": "./src/postgres.ts",
|
|
26
30
|
"import": "./dist/postgres.js"
|
|
@@ -33,11 +37,17 @@
|
|
|
33
37
|
"types": "./src/mysql.ts",
|
|
34
38
|
"import": "./dist/mysql.js"
|
|
35
39
|
},
|
|
40
|
+
"./sqlite": {
|
|
41
|
+
"types": "./src/sqlite.ts",
|
|
42
|
+
"import": "./dist/sqlite.js"
|
|
43
|
+
},
|
|
36
44
|
"./package.json": "./package.json"
|
|
37
45
|
},
|
|
38
46
|
"imports": {
|
|
47
|
+
"#standard": "./src/standard.ts",
|
|
39
48
|
"#postgres": "./src/postgres.ts",
|
|
40
49
|
"#mysql": "./src/mysql.ts",
|
|
50
|
+
"#sqlite": "./src/sqlite.ts",
|
|
41
51
|
"#internal/*": "./src/internal/*"
|
|
42
52
|
},
|
|
43
53
|
"publishConfig": {
|
|
@@ -52,9 +62,11 @@
|
|
|
52
62
|
"@typescript/native-preview": "beta"
|
|
53
63
|
},
|
|
54
64
|
"dependencies": {
|
|
65
|
+
"pgsql-ast-parser": "^12.0.2"
|
|
66
|
+
},
|
|
67
|
+
"peerDependencies": {
|
|
55
68
|
"@effect/experimental": "^0.57.0",
|
|
56
69
|
"@effect/sql": "^0.48.0",
|
|
57
|
-
"effect": "^3.19.3"
|
|
58
|
-
"pgsql-ast-parser": "^12.0.2"
|
|
70
|
+
"effect": "^3.19.3"
|
|
59
71
|
}
|
|
60
72
|
}
|
package/src/casing.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as InternalCasing from "./internal/casing.js"
|
|
2
|
+
import * as BaseTable from "./internal/table.js"
|
|
3
|
+
import * as Table from "./standard/table.js"
|
|
4
|
+
|
|
5
|
+
export type Style = InternalCasing.Style
|
|
6
|
+
export type Options = InternalCasing.Options
|
|
7
|
+
export type Input = Options | Style
|
|
8
|
+
|
|
9
|
+
export interface TableFactory {
|
|
10
|
+
readonly table: typeof Table.make
|
|
11
|
+
readonly [InternalCasing.TypeId]: InternalCasing.State
|
|
12
|
+
readonly withCasing: (options: Input) => TableFactory
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type CasingTarget =
|
|
16
|
+
| BaseTable.TableDefinition<any, any, any, any, any>
|
|
17
|
+
| {
|
|
18
|
+
readonly [InternalCasing.TypeId]: InternalCasing.State
|
|
19
|
+
readonly withCasing: (options: Options) => CasingTarget
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const isTable = (value: unknown): value is BaseTable.TableDefinition<any, any, any, any, any> =>
|
|
23
|
+
typeof value === "object" && value !== null && BaseTable.TypeId in value
|
|
24
|
+
|
|
25
|
+
const allCategories = (style: Style): Options => ({
|
|
26
|
+
tables: style,
|
|
27
|
+
columns: style,
|
|
28
|
+
schemas: style,
|
|
29
|
+
indexes: style,
|
|
30
|
+
constraints: style,
|
|
31
|
+
types: style,
|
|
32
|
+
sequences: style
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const normalize = (input: Input): Options =>
|
|
36
|
+
typeof input === "string" || typeof input === "function" ? allCategories(input) : input
|
|
37
|
+
|
|
38
|
+
export function withCasing(options: Style): <Value extends CasingTarget>(value: Value) => Value
|
|
39
|
+
export function withCasing(options: Options): <Value extends CasingTarget>(value: Value) => Value
|
|
40
|
+
export function withCasing(options: Input) {
|
|
41
|
+
return <Value extends CasingTarget>(value: Value): Value => {
|
|
42
|
+
const normalized = normalize(options)
|
|
43
|
+
if (isTable(value)) {
|
|
44
|
+
return BaseTable.withCasing(value, normalized) as Value
|
|
45
|
+
}
|
|
46
|
+
return (value as Exclude<CasingTarget, BaseTable.TableDefinition<any, any, any, any, any>>).withCasing(normalized) as Value
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function make(options: Style): TableFactory
|
|
51
|
+
export function make(options: Options): TableFactory
|
|
52
|
+
export function make(options: Input): TableFactory {
|
|
53
|
+
const normalized = normalize(options)
|
|
54
|
+
const withFactoryCasing = withCasing(normalized)
|
|
55
|
+
const table = ((name: string, fields: any, schemaName?: string) =>
|
|
56
|
+
schemaName === undefined
|
|
57
|
+
? Table.make(name, fields).pipe(withFactoryCasing)
|
|
58
|
+
: Table.make(name, fields, schemaName).pipe(withFactoryCasing)) as typeof Table.make
|
|
59
|
+
const factory = {
|
|
60
|
+
table,
|
|
61
|
+
[InternalCasing.TypeId]: {
|
|
62
|
+
casing: normalized
|
|
63
|
+
},
|
|
64
|
+
withCasing: (override: Input) => make(InternalCasing.merge(normalized, normalize(override)) ?? {})
|
|
65
|
+
}
|
|
66
|
+
return factory
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const apply = InternalCasing.apply
|
|
70
|
+
export const applyCategory = InternalCasing.applyCategory
|
|
71
|
+
export const merge = InternalCasing.merge
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export const TypeId: unique symbol = Symbol.for("effect-qb/Casing")
|
|
2
|
+
|
|
3
|
+
export type Style =
|
|
4
|
+
| "preserve"
|
|
5
|
+
| "snake_case"
|
|
6
|
+
| "camelCase"
|
|
7
|
+
| "PascalCase"
|
|
8
|
+
| "kebab-case"
|
|
9
|
+
| "SCREAMING_SNAKE_CASE"
|
|
10
|
+
| ((name: string) => string)
|
|
11
|
+
|
|
12
|
+
export interface Options {
|
|
13
|
+
readonly tables?: Style
|
|
14
|
+
readonly columns?: Style
|
|
15
|
+
readonly schemas?: Style
|
|
16
|
+
readonly indexes?: Style
|
|
17
|
+
readonly constraints?: Style
|
|
18
|
+
readonly types?: Style
|
|
19
|
+
readonly sequences?: Style
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type Category = keyof Options
|
|
23
|
+
|
|
24
|
+
export interface State {
|
|
25
|
+
readonly casing?: Options
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const merge = (
|
|
29
|
+
base: Options | undefined,
|
|
30
|
+
override: Options | undefined
|
|
31
|
+
): Options | undefined => {
|
|
32
|
+
if (base === undefined) {
|
|
33
|
+
return override
|
|
34
|
+
}
|
|
35
|
+
if (override === undefined) {
|
|
36
|
+
return base
|
|
37
|
+
}
|
|
38
|
+
return { ...base, ...override }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const words = (name: string): readonly string[] =>
|
|
42
|
+
name
|
|
43
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
44
|
+
.replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2")
|
|
45
|
+
.split(/[^A-Za-z0-9]+/)
|
|
46
|
+
.filter((part) => part.length > 0)
|
|
47
|
+
|
|
48
|
+
const capitalize = (value: string): string =>
|
|
49
|
+
value.length === 0 ? value : `${value[0]!.toUpperCase()}${value.slice(1)}`
|
|
50
|
+
|
|
51
|
+
const lowerWords = (name: string): readonly string[] =>
|
|
52
|
+
words(name).map((part) => part.toLowerCase())
|
|
53
|
+
|
|
54
|
+
const applyNamedStyle = (style: Exclude<Style, (name: string) => string>, name: string): string => {
|
|
55
|
+
switch (style) {
|
|
56
|
+
case "preserve":
|
|
57
|
+
return name
|
|
58
|
+
case "snake_case":
|
|
59
|
+
return lowerWords(name).join("_")
|
|
60
|
+
case "camelCase": {
|
|
61
|
+
const parts = lowerWords(name)
|
|
62
|
+
const [head, ...tail] = parts
|
|
63
|
+
return head === undefined ? "" : `${head}${tail.map(capitalize).join("")}`
|
|
64
|
+
}
|
|
65
|
+
case "PascalCase":
|
|
66
|
+
return lowerWords(name).map(capitalize).join("")
|
|
67
|
+
case "kebab-case":
|
|
68
|
+
return lowerWords(name).join("-")
|
|
69
|
+
case "SCREAMING_SNAKE_CASE":
|
|
70
|
+
return lowerWords(name).join("_").toUpperCase()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export const apply = (
|
|
75
|
+
style: Style | undefined,
|
|
76
|
+
name: string
|
|
77
|
+
): string => {
|
|
78
|
+
if (style === undefined) {
|
|
79
|
+
return name
|
|
80
|
+
}
|
|
81
|
+
return typeof style === "function" ? style(name) : applyNamedStyle(style, name)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export const applyCategory = (
|
|
85
|
+
options: Options | undefined,
|
|
86
|
+
category: Category,
|
|
87
|
+
name: string
|
|
88
|
+
): string => apply(options?.[category], name)
|
|
89
|
+
|
|
@@ -4,6 +4,7 @@ import * as Schema from "effect/Schema"
|
|
|
4
4
|
|
|
5
5
|
import * as Expression from "./scalar.js"
|
|
6
6
|
import * as ExpressionAst from "./expression-ast.js"
|
|
7
|
+
import type * as Casing from "./casing.js"
|
|
7
8
|
import type * as SchemaExpression from "./schema-expression.js"
|
|
8
9
|
|
|
9
10
|
/** Symbol used to attach column-definition metadata. */
|
|
@@ -183,6 +184,7 @@ export interface BoundColumn<
|
|
|
183
184
|
readonly columnName: ColumnName
|
|
184
185
|
readonly baseTableName: BaseTableName
|
|
185
186
|
readonly schemaName?: string
|
|
187
|
+
readonly casing?: Casing.Options
|
|
186
188
|
}
|
|
187
189
|
readonly [Expression.TypeId]: Expression.State<
|
|
188
190
|
Select,
|
|
@@ -227,7 +229,7 @@ export type AnyBoundColumn = BoundColumn<
|
|
|
227
229
|
>
|
|
228
230
|
|
|
229
231
|
const ColumnProto = {
|
|
230
|
-
pipe(this:
|
|
232
|
+
pipe(this: Pipeable) {
|
|
231
233
|
return pipeArguments(this, arguments)
|
|
232
234
|
}
|
|
233
235
|
}
|
|
@@ -236,7 +238,7 @@ const attachPipe = <Value extends object>(value: Value): Value => {
|
|
|
236
238
|
Object.defineProperty(value, "pipe", {
|
|
237
239
|
configurable: true,
|
|
238
240
|
writable: true,
|
|
239
|
-
value: function(this:
|
|
241
|
+
value: function(this: Value) {
|
|
240
242
|
return pipeArguments(value, arguments)
|
|
241
243
|
}
|
|
242
244
|
})
|
|
@@ -407,17 +409,18 @@ export const remapColumnDefinition = <
|
|
|
407
409
|
enum: metadata.enum
|
|
408
410
|
}
|
|
409
411
|
if (ExpressionAst.TypeId in column) {
|
|
410
|
-
next[ExpressionAst.TypeId] = (column as
|
|
412
|
+
next[ExpressionAst.TypeId] = (column as {
|
|
411
413
|
readonly [ExpressionAst.TypeId]: ExpressionAst.Any
|
|
412
414
|
})[ExpressionAst.TypeId]
|
|
413
415
|
}
|
|
414
416
|
if (BoundColumnTypeId in column) {
|
|
415
|
-
next[BoundColumnTypeId] = (column as
|
|
417
|
+
next[BoundColumnTypeId] = (column as {
|
|
416
418
|
readonly [BoundColumnTypeId]: {
|
|
417
419
|
readonly tableName: string
|
|
418
420
|
readonly columnName: string
|
|
419
421
|
readonly baseTableName: string
|
|
420
422
|
readonly schemaName?: string
|
|
423
|
+
readonly casing?: Casing.Options
|
|
421
424
|
}
|
|
422
425
|
})[BoundColumnTypeId]
|
|
423
426
|
}
|
|
@@ -436,7 +439,8 @@ export const bindColumn = <
|
|
|
436
439
|
columnName: ColumnName,
|
|
437
440
|
column: Column,
|
|
438
441
|
baseTableName: BaseTableName,
|
|
439
|
-
schemaName?: SchemaName
|
|
442
|
+
schemaName?: SchemaName,
|
|
443
|
+
casing?: Casing.Options
|
|
440
444
|
): BoundColumnFrom<Column, TableName, ColumnName, BaseTableName> => {
|
|
441
445
|
const brandName = `${tableName}.${columnName}`
|
|
442
446
|
const schema = column.metadata.brand === true
|
|
@@ -467,7 +471,8 @@ export const bindColumn = <
|
|
|
467
471
|
tableName,
|
|
468
472
|
columnName,
|
|
469
473
|
baseTableName,
|
|
470
|
-
schemaName
|
|
474
|
+
schemaName,
|
|
475
|
+
casing
|
|
471
476
|
}
|
|
472
477
|
return bound
|
|
473
478
|
}
|
package/src/internal/column.ts
CHANGED
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
type SelectType,
|
|
43
43
|
type UpdateType
|
|
44
44
|
} from "./column-state.js"
|
|
45
|
+
import type { NonEmptyStringInput } from "./table-options.js"
|
|
45
46
|
|
|
46
47
|
type ReferentialAction = "noAction" | "restrict" | "cascade" | "setNull" | "setDefault"
|
|
47
48
|
|
|
@@ -223,6 +224,36 @@ type ForeignKeyOptions<Target extends AnyBoundColumn> = {
|
|
|
223
224
|
readonly initiallyDeferred?: boolean
|
|
224
225
|
}
|
|
225
226
|
|
|
227
|
+
type NonEmptyOptionNameInput<Options> = Options extends { readonly name: infer Name extends string }
|
|
228
|
+
? NonEmptyStringInput<Name> extends never ? never : unknown
|
|
229
|
+
: unknown
|
|
230
|
+
|
|
231
|
+
type NonEmptyStringArrayInput<Values extends readonly string[]> =
|
|
232
|
+
[Extract<Values[number], "">] extends [never] ? unknown : never
|
|
233
|
+
|
|
234
|
+
type NonEmptyIndexMethodInput<Options> = Options extends { readonly method: infer Method extends string }
|
|
235
|
+
? NonEmptyStringInput<Method> extends never ? never : unknown
|
|
236
|
+
: unknown
|
|
237
|
+
|
|
238
|
+
type NonEmptyIndexIncludeInput<Options> = Options extends { readonly include: infer Include extends readonly string[] }
|
|
239
|
+
? NonEmptyStringArrayInput<Include>
|
|
240
|
+
: unknown
|
|
241
|
+
|
|
242
|
+
type NonEmptyIndexOperatorClassInput<Options> = Options extends { readonly operatorClass: infer OperatorClass extends string }
|
|
243
|
+
? NonEmptyStringInput<OperatorClass> extends never ? never : unknown
|
|
244
|
+
: unknown
|
|
245
|
+
|
|
246
|
+
type NonEmptyIndexCollationInput<Options> = Options extends { readonly collation: infer Collation extends string }
|
|
247
|
+
? NonEmptyStringInput<Collation> extends never ? never : unknown
|
|
248
|
+
: unknown
|
|
249
|
+
|
|
250
|
+
type NonEmptyIndexMetadataInput<Options> =
|
|
251
|
+
& NonEmptyOptionNameInput<Options>
|
|
252
|
+
& NonEmptyIndexMethodInput<Options>
|
|
253
|
+
& NonEmptyIndexIncludeInput<Options>
|
|
254
|
+
& NonEmptyIndexOperatorClassInput<Options>
|
|
255
|
+
& NonEmptyIndexCollationInput<Options>
|
|
256
|
+
|
|
226
257
|
type SchemaCompatibleColumn<
|
|
227
258
|
Column extends AnyColumnDefinition,
|
|
228
259
|
SchemaType extends Schema.Schema.Any
|
|
@@ -500,7 +531,7 @@ export const primaryKey = <Column extends AnyColumnDefinition>(
|
|
|
500
531
|
type UniqueModifier = {
|
|
501
532
|
<Column extends AnyColumnDefinition>(column: Column): UniqueColumn<Column>
|
|
502
533
|
readonly options: <const Options extends ColumnUniqueOptions>(
|
|
503
|
-
options: Options
|
|
534
|
+
options: Options & NonEmptyOptionNameInput<Options>
|
|
504
535
|
) => <Column extends AnyColumnDefinition>(column: Column) => UniqueColumn<Column>
|
|
505
536
|
}
|
|
506
537
|
|
|
@@ -550,11 +581,11 @@ export const generated = <Value extends DdlExpression>(value: Value) =>
|
|
|
550
581
|
}) as GeneratedColumn<Column>
|
|
551
582
|
|
|
552
583
|
/** Preserves the exact SQL type used for DDL rendering. */
|
|
553
|
-
export const ddlType = <SqlType extends string>(sqlType: SqlType) =>
|
|
584
|
+
export const ddlType = <SqlType extends string>(sqlType: NonEmptyStringInput<SqlType>) =>
|
|
554
585
|
<Column extends AnyColumnDefinition>(column: Column): DdlTypedColumn<Column> =>
|
|
555
586
|
mapColumn(column, {
|
|
556
587
|
...column.metadata,
|
|
557
|
-
ddlType: sqlType
|
|
588
|
+
ddlType: sqlType as SqlType
|
|
558
589
|
}) as DdlTypedColumn<Column>
|
|
559
590
|
|
|
560
591
|
/** Overrides how a column crosses the SQL driver boundary. */
|
|
@@ -590,13 +621,15 @@ export const array = <Options extends ArrayOptions | undefined = undefined>(
|
|
|
590
621
|
}) as ArrayColumn<Column, Options>
|
|
591
622
|
|
|
592
623
|
/** Marks a column as indexed. */
|
|
624
|
+
type IndexPipe = <Column extends AnyColumnDefinition>(column: Column) => IndexedColumn<Column>
|
|
625
|
+
|
|
593
626
|
export function index<Column extends AnyColumnDefinition>(
|
|
594
627
|
column: Column
|
|
595
628
|
): IndexedColumn<Column>
|
|
596
629
|
export function index<const Options extends ColumnIndexOptions>(
|
|
597
|
-
options: Options
|
|
630
|
+
options: Options & NonEmptyIndexMetadataInput<Options>
|
|
598
631
|
): <Column extends AnyColumnDefinition>(column: Column) => IndexedColumn<Column>
|
|
599
|
-
export function index(arg:
|
|
632
|
+
export function index(arg: AnyColumnDefinition | ColumnIndexOptions): IndexedColumn<AnyColumnDefinition> | IndexPipe {
|
|
600
633
|
if (isColumnDefinitionValue(arg)) {
|
|
601
634
|
return mapColumn(arg, {
|
|
602
635
|
...arg.metadata,
|
|
@@ -648,17 +681,21 @@ export const identityAlways = <Column extends AnyColumnDefinition>(
|
|
|
648
681
|
*
|
|
649
682
|
* The base, non-null select types must match.
|
|
650
683
|
*/
|
|
684
|
+
type ForeignKeyPipe<Target extends AnyBoundColumn = AnyBoundColumn> = <Column extends AnyColumnDefinition>(
|
|
685
|
+
column: CompatibleReference<Column, Target>
|
|
686
|
+
) => ReferencingColumn<Column, Target>
|
|
687
|
+
|
|
651
688
|
export function foreignKey<Target extends AnyBoundColumn>(
|
|
652
689
|
target: () => Target
|
|
653
690
|
): <Column extends AnyColumnDefinition>(
|
|
654
691
|
column: CompatibleReference<Column, Target>
|
|
655
692
|
) => ReferencingColumn<Column, Target>
|
|
656
693
|
export function foreignKey<const Options extends ForeignKeyOptions<AnyBoundColumn>>(
|
|
657
|
-
options: Options
|
|
694
|
+
options: Options & NonEmptyOptionNameInput<Options>
|
|
658
695
|
): <Column extends AnyColumnDefinition>(
|
|
659
696
|
column: CompatibleReference<Column, ReturnType<Options["target"]>>
|
|
660
697
|
) => ReferencingColumn<Column, ReturnType<Options["target"]>>
|
|
661
|
-
export function foreignKey(arg:
|
|
698
|
+
export function foreignKey(arg: (() => AnyBoundColumn) | ForeignKeyOptions<AnyBoundColumn>): ForeignKeyPipe {
|
|
662
699
|
if (typeof arg === "function") {
|
|
663
700
|
const target = arg as () => AnyBoundColumn
|
|
664
701
|
return <Column extends AnyColumnDefinition>(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type * as Expression from "../scalar.js"
|
|
2
|
+
import type { NonEmptyStringInput } from "../table-options.js"
|
|
2
3
|
import type { DatatypeFamilySpec, DatatypeKindSpec } from "./shape.js"
|
|
3
4
|
|
|
4
5
|
type DatatypeWitness<
|
|
@@ -20,7 +21,7 @@ export type DatatypeModule<
|
|
|
20
21
|
Families extends Record<string, DatatypeFamilySpec>,
|
|
21
22
|
Aliases extends Record<string, string> = Record<never, never>
|
|
22
23
|
> = {
|
|
23
|
-
readonly custom: <Kind extends string>(kind: Kind) => Expression.DbType.Base<Dialect, Kind>
|
|
24
|
+
readonly custom: <Kind extends string>(kind: NonEmptyStringInput<Kind>) => Expression.DbType.Base<Dialect, Kind>
|
|
24
25
|
} & {
|
|
25
26
|
readonly [Kind in keyof Kinds]: () => DatatypeWitness<Dialect, Kinds, Families, Kind & string>
|
|
26
27
|
} & {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type * as Expression from "../scalar.js"
|
|
2
|
+
|
|
3
|
+
type DatatypeLookup = Readonly<Record<string, (() => Expression.DbType.Any) | undefined>>
|
|
4
|
+
|
|
5
|
+
export const enrichDbType = <
|
|
6
|
+
Module extends object,
|
|
7
|
+
Db extends Expression.DbType.Any
|
|
8
|
+
>(
|
|
9
|
+
datatypes: Module,
|
|
10
|
+
dbType: Db
|
|
11
|
+
): Db => {
|
|
12
|
+
if (dbType.kind === "custom") {
|
|
13
|
+
return dbType
|
|
14
|
+
}
|
|
15
|
+
const lookup = datatypes as DatatypeLookup
|
|
16
|
+
if (!(dbType.kind in lookup)) {
|
|
17
|
+
return dbType
|
|
18
|
+
}
|
|
19
|
+
const candidate = lookup[dbType.kind]
|
|
20
|
+
return typeof candidate === "function"
|
|
21
|
+
? { ...candidate(), ...dbType } as Db
|
|
22
|
+
: dbType
|
|
23
|
+
}
|
|
@@ -31,6 +31,13 @@ type BaseCastTargetsOf<Db extends Expression.DbType.Base<any, any>> =
|
|
|
31
31
|
? Target
|
|
32
32
|
: never
|
|
33
33
|
|
|
34
|
+
type DbTypeCompatibleWithDialect<
|
|
35
|
+
Db extends Expression.DbType.Any,
|
|
36
|
+
Dialect extends string
|
|
37
|
+
> = Dialect extends "standard"
|
|
38
|
+
? Db extends { readonly dialect: string } ? true : false
|
|
39
|
+
: Db extends { readonly dialect: Dialect | "standard" } ? true : false
|
|
40
|
+
|
|
34
41
|
type BaseHasTextualTrait<Db extends Expression.DbType.Base<any, any>> =
|
|
35
42
|
Db extends { readonly traits?: infer Traits }
|
|
36
43
|
? Traits extends { readonly textual: true }
|
|
@@ -103,8 +110,8 @@ export type CanCompareDbTypes<
|
|
|
103
110
|
Left extends Expression.DbType.Any,
|
|
104
111
|
Right extends Expression.DbType.Any,
|
|
105
112
|
Dialect extends string
|
|
106
|
-
> = Left extends
|
|
107
|
-
? Right extends
|
|
113
|
+
> = DbTypeCompatibleWithDialect<Left, Dialect> extends true
|
|
114
|
+
? DbTypeCompatibleWithDialect<Right, Dialect> extends true
|
|
108
115
|
? CompareGroupOfDbType<Left> extends never
|
|
109
116
|
? false
|
|
110
117
|
: CompareGroupOfDbType<Right> extends never
|
|
@@ -125,8 +132,8 @@ export type CanContainDbTypes<
|
|
|
125
132
|
Left extends Expression.DbType.Any,
|
|
126
133
|
Right extends Expression.DbType.Any,
|
|
127
134
|
Dialect extends string
|
|
128
|
-
> = Left extends
|
|
129
|
-
? Right extends
|
|
135
|
+
> = DbTypeCompatibleWithDialect<Left, Dialect> extends true
|
|
136
|
+
? DbTypeCompatibleWithDialect<Right, Dialect> extends true
|
|
130
137
|
? FamilyOfDbType<Left> extends "array" | "range" | "multirange"
|
|
131
138
|
? FamilyOfDbType<Right> extends "array" | "range" | "multirange"
|
|
132
139
|
? [CompareGroupOfDbType<Left>] extends [CompareGroupOfDbType<Right>]
|
|
@@ -142,7 +149,7 @@ export type CanContainDbTypes<
|
|
|
142
149
|
export type CanTextuallyCoerceDbType<
|
|
143
150
|
Db extends Expression.DbType.Any,
|
|
144
151
|
Dialect extends string
|
|
145
|
-
> = Db extends
|
|
152
|
+
> = DbTypeCompatibleWithDialect<Db, Dialect> extends true
|
|
146
153
|
? Db extends Expression.DbType.Domain<any, infer Base extends Expression.DbType.Any, any>
|
|
147
154
|
? CanTextuallyCoerceDbType<Base, Dialect>
|
|
148
155
|
: Db extends Expression.DbType.Enum<any, any> | Expression.DbType.Set<any, any>
|
|
@@ -158,8 +165,8 @@ export type CanCastDbType<
|
|
|
158
165
|
Source extends Expression.DbType.Any,
|
|
159
166
|
Target extends Expression.DbType.Any,
|
|
160
167
|
Dialect extends string
|
|
161
|
-
> = Source extends
|
|
162
|
-
? Target extends
|
|
168
|
+
> = DbTypeCompatibleWithDialect<Source, Dialect> extends true
|
|
169
|
+
? DbTypeCompatibleWithDialect<Target, Dialect> extends true
|
|
163
170
|
? Source extends Expression.DbType.Domain<any, infer Base extends Expression.DbType.Any, any>
|
|
164
171
|
? CanCastDbType<Base, Target, Dialect>
|
|
165
172
|
: Target extends Expression.DbType.Domain<any, infer TargetBase extends Expression.DbType.Any, any>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { pipeArguments } from "effect/Pipeable"
|
|
1
|
+
import { pipeArguments, type Pipeable } from "effect/Pipeable"
|
|
2
2
|
|
|
3
3
|
import * as Expression from "./scalar.js"
|
|
4
4
|
import * as Plan from "./row-set.js"
|
|
@@ -11,13 +11,14 @@ import {
|
|
|
11
11
|
type QueryPlan,
|
|
12
12
|
getAst,
|
|
13
13
|
makeExpression,
|
|
14
|
+
currentRequiredList,
|
|
14
15
|
type SelectionOfPlan
|
|
15
16
|
} from "./query.js"
|
|
16
17
|
import * as ExpressionAst from "./expression-ast.js"
|
|
17
18
|
import { flattenSelection } from "./projections.js"
|
|
18
19
|
|
|
19
20
|
const DerivedProto = {
|
|
20
|
-
pipe(this:
|
|
21
|
+
pipe(this: Pipeable) {
|
|
21
22
|
return pipeArguments(this, arguments)
|
|
22
23
|
}
|
|
23
24
|
}
|
|
@@ -26,7 +27,7 @@ const attachPipe = <Value extends object>(value: Value): Value => {
|
|
|
26
27
|
Object.defineProperty(value, "pipe", {
|
|
27
28
|
configurable: true,
|
|
28
29
|
writable: true,
|
|
29
|
-
value: function(this:
|
|
30
|
+
value: function(this: Value) {
|
|
30
31
|
return pipeArguments(value, arguments)
|
|
31
32
|
}
|
|
32
33
|
})
|
|
@@ -53,8 +54,6 @@ const setPath = (
|
|
|
53
54
|
current[path[path.length - 1]!] = value
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
const pathAlias = (path: readonly string[]): string => path.join("__")
|
|
57
|
-
|
|
58
57
|
const reboundedColumns = <
|
|
59
58
|
PlanValue extends QueryPlan<any, any, any, any, any, any, any, any, any, any>,
|
|
60
59
|
Alias extends string
|
|
@@ -64,13 +63,8 @@ const reboundedColumns = <
|
|
|
64
63
|
): DerivedSelectionOf<SelectionOfPlan<PlanValue>, Alias> => {
|
|
65
64
|
const ast = getAst(plan)
|
|
66
65
|
const selection = {} as Record<string, unknown>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (projection.alias !== expectedAlias) {
|
|
70
|
-
throw new Error(
|
|
71
|
-
`Derived subqueries currently require path-based output aliases; expected '${expectedAlias}' for path '${projection.path.join(".")}'`
|
|
72
|
-
)
|
|
73
|
-
}
|
|
66
|
+
const projections = flattenSelection(ast.select as Record<string, unknown>)
|
|
67
|
+
for (const projection of projections) {
|
|
74
68
|
const expression = projection.expression
|
|
75
69
|
setPath(selection, projection.path, makeExpression({
|
|
76
70
|
runtime: undefined as never,
|
|
@@ -148,7 +142,7 @@ export const makeLateralSource = <
|
|
|
148
142
|
lateral.baseName = alias
|
|
149
143
|
lateral.dialect = plan[Plan.TypeId].dialect
|
|
150
144
|
lateral.plan = plan
|
|
151
|
-
lateral.required =
|
|
145
|
+
lateral.required = currentRequiredList(plan[Plan.TypeId].required) as never
|
|
152
146
|
lateral.columns = columns
|
|
153
147
|
return lateral as unknown as LateralSource<PlanValue, Alias>
|
|
154
148
|
}
|