effect-qb 0.16.0 → 4.0.0-beta.66
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 +7 -0
- package/dist/mysql.js +1858 -715
- package/dist/postgres/metadata.js +2036 -172
- package/dist/postgres.js +8011 -6849
- package/dist/sqlite.js +8433 -0
- package/package.json +7 -4
- package/src/internal/column-state.d.ts +3 -3
- package/src/internal/column-state.ts +3 -3
- package/src/internal/column.ts +8 -8
- package/src/internal/derived-table.ts +29 -3
- package/src/internal/dialect.ts +3 -1
- package/src/internal/dsl-mutation-runtime.ts +173 -4
- package/src/internal/dsl-plan-runtime.ts +165 -20
- package/src/internal/dsl-query-runtime.ts +60 -6
- package/src/internal/dsl-transaction-ddl-runtime.ts +72 -2
- package/src/internal/executor.ts +100 -43
- package/src/internal/expression-ast.ts +3 -2
- package/src/internal/grouping-key.ts +141 -1
- package/src/internal/implication-runtime.ts +2 -1
- 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 +27 -3
- package/src/internal/query.d.ts +1 -1
- package/src/internal/query.ts +253 -31
- package/src/internal/renderer.ts +35 -2
- package/src/internal/runtime/driver-value-mapping.ts +60 -2
- package/src/internal/runtime/normalize.ts +62 -38
- package/src/internal/runtime/schema.ts +32 -40
- package/src/internal/runtime/value.ts +159 -39
- package/src/internal/scalar.d.ts +1 -1
- package/src/internal/scalar.ts +1 -1
- package/src/internal/schema-derivation.d.ts +12 -61
- package/src/internal/schema-derivation.ts +95 -43
- package/src/internal/table-options.ts +108 -1
- package/src/internal/table.d.ts +29 -22
- package/src/internal/table.ts +260 -53
- package/src/mysql/column.ts +24 -8
- package/src/mysql/datatypes/index.ts +21 -0
- package/src/mysql/errors/catalog.ts +5 -5
- package/src/mysql/errors/normalize.ts +2 -2
- package/src/mysql/executor.ts +4 -4
- package/src/mysql/function/temporal.ts +1 -1
- package/src/mysql/internal/dsl.ts +759 -235
- package/src/mysql/internal/renderer.ts +2 -1
- package/src/mysql/internal/sql-expression-renderer.ts +486 -130
- package/src/mysql/query.ts +9 -2
- package/src/mysql/table.ts +64 -35
- package/src/postgres/column.ts +14 -12
- package/src/postgres/errors/normalize.ts +2 -2
- package/src/postgres/executor.ts +52 -9
- package/src/postgres/function/core.ts +19 -1
- package/src/postgres/function/temporal.ts +1 -1
- package/src/postgres/internal/dsl.ts +705 -256
- package/src/postgres/internal/renderer.ts +2 -1
- package/src/postgres/internal/schema-ddl.ts +2 -1
- package/src/postgres/internal/schema-model.ts +6 -3
- package/src/postgres/internal/sql-expression-renderer.ts +420 -91
- package/src/postgres/json.ts +57 -17
- package/src/postgres/query.ts +9 -2
- package/src/postgres/schema-management.ts +92 -6
- package/src/postgres/schema.ts +1 -1
- package/src/postgres/table.ts +203 -75
- package/src/sqlite/column.ts +128 -0
- package/src/sqlite/datatypes/index.ts +79 -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 +227 -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 +37 -0
- package/src/sqlite/internal/dsl.ts +6927 -0
- package/src/sqlite/internal/renderer.ts +47 -0
- package/src/sqlite/internal/sql-expression-renderer.ts +1821 -0
- package/src/sqlite/json.ts +2 -0
- package/src/sqlite/query.ts +196 -0
- package/src/sqlite/renderer.ts +24 -0
- package/src/sqlite/table.ts +175 -0
- package/src/sqlite.ts +22 -0
|
@@ -176,6 +176,27 @@ var bindColumn = (tableName, columnName, column, baseTableName, schemaName) => {
|
|
|
176
176
|
};
|
|
177
177
|
|
|
178
178
|
// src/internal/table-options.ts
|
|
179
|
+
var referentialActionError = "Foreign key action must be noAction, restrict, cascade, setNull, or setDefault";
|
|
180
|
+
var renderReferentialAction = (action) => {
|
|
181
|
+
switch (action) {
|
|
182
|
+
case "noAction":
|
|
183
|
+
return "no action";
|
|
184
|
+
case "restrict":
|
|
185
|
+
return "restrict";
|
|
186
|
+
case "cascade":
|
|
187
|
+
return "cascade";
|
|
188
|
+
case "setNull":
|
|
189
|
+
return "set null";
|
|
190
|
+
case "setDefault":
|
|
191
|
+
return "set default";
|
|
192
|
+
}
|
|
193
|
+
throw new Error(referentialActionError);
|
|
194
|
+
};
|
|
195
|
+
var validateReferentialAction = (action) => {
|
|
196
|
+
if (action !== undefined) {
|
|
197
|
+
renderReferentialAction(action);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
179
200
|
var normalizeColumnList = (columns) => {
|
|
180
201
|
const normalized = Array.isArray(columns) ? [...columns] : [columns];
|
|
181
202
|
if (normalized.length === 0) {
|
|
@@ -203,6 +224,8 @@ var collectInlineOptions = (fields) => {
|
|
|
203
224
|
});
|
|
204
225
|
}
|
|
205
226
|
if (column.metadata.references) {
|
|
227
|
+
validateReferentialAction(column.metadata.references.onUpdate);
|
|
228
|
+
validateReferentialAction(column.metadata.references.onDelete);
|
|
206
229
|
const local = [columnName];
|
|
207
230
|
options.push({
|
|
208
231
|
kind: "foreignKey",
|
|
@@ -279,6 +302,8 @@ var validateOptions = (tableName, fields, options) => {
|
|
|
279
302
|
}
|
|
280
303
|
}
|
|
281
304
|
if (option.kind === "foreignKey") {
|
|
305
|
+
validateReferentialAction(option.onUpdate);
|
|
306
|
+
validateReferentialAction(option.onDelete);
|
|
282
307
|
const reference = option.references();
|
|
283
308
|
if (reference.columns.length !== columns.length) {
|
|
284
309
|
throw new Error(`Foreign key on table '${tableName}' must reference the same number of columns`);
|
|
@@ -303,7 +328,7 @@ var validateOptions = (tableName, fields, options) => {
|
|
|
303
328
|
throw new Error(`Unknown index key column '${key.column}' on table '${tableName}'`);
|
|
304
329
|
}
|
|
305
330
|
}
|
|
306
|
-
if (
|
|
331
|
+
if (columns.length === 0 && (option.keys === undefined || option.keys.length === 0)) {
|
|
307
332
|
throw new Error(`Index on table '${tableName}' requires at least one column or key`);
|
|
308
333
|
}
|
|
309
334
|
}
|
|
@@ -322,12 +347,7 @@ var validateOptions = (tableName, fields, options) => {
|
|
|
322
347
|
};
|
|
323
348
|
|
|
324
349
|
// src/internal/schema-derivation.ts
|
|
325
|
-
import * as VariantSchema from "@effect/experimental/VariantSchema";
|
|
326
350
|
import * as Schema2 from "effect/Schema";
|
|
327
|
-
var TableSchema = VariantSchema.make({
|
|
328
|
-
variants: ["select", "insert", "update"],
|
|
329
|
-
defaultVariant: "select"
|
|
330
|
-
});
|
|
331
351
|
var maybeBrandSchema = (column, tableName, columnName) => column.metadata.brand === true ? Schema2.brand(`${tableName}.${columnName}`)(column.schema) : column.schema;
|
|
332
352
|
var selectSchema = (column, tableName, columnName) => column.metadata.nullable ? Schema2.NullOr(maybeBrandSchema(column, tableName, columnName)) : maybeBrandSchema(column, tableName, columnName);
|
|
333
353
|
var insertSchema = (column, tableName, columnName) => {
|
|
@@ -344,42 +364,37 @@ var updateSchema = (column, tableName, columnName, isPrimaryKey) => {
|
|
|
344
364
|
const base = column.metadata.nullable ? Schema2.NullOr(maybeBrandSchema(column, tableName, columnName)) : maybeBrandSchema(column, tableName, columnName);
|
|
345
365
|
return Schema2.optional(base);
|
|
346
366
|
};
|
|
347
|
-
var
|
|
367
|
+
var fieldSchemaForVariant = (variant, column, tableName, columnName, primaryKeySet) => {
|
|
368
|
+
switch (variant) {
|
|
369
|
+
case "select":
|
|
370
|
+
return selectSchema(column, tableName, columnName);
|
|
371
|
+
case "insert":
|
|
372
|
+
return insertSchema(column, tableName, columnName);
|
|
373
|
+
case "update":
|
|
374
|
+
return updateSchema(column, tableName, columnName, primaryKeySet.has(columnName));
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
var deriveSchema = (variant, tableName, fields, primaryKeyColumns) => {
|
|
348
378
|
const primaryKeySet = new Set(primaryKeyColumns);
|
|
349
|
-
const
|
|
379
|
+
const structFields = {};
|
|
350
380
|
for (const [key, column] of Object.entries(fields)) {
|
|
351
|
-
const
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
update: undefined
|
|
355
|
-
};
|
|
356
|
-
const insert = insertSchema(column, tableName, key);
|
|
357
|
-
const update = updateSchema(column, tableName, key, primaryKeySet.has(key));
|
|
358
|
-
if (insert !== undefined) {
|
|
359
|
-
config.insert = insert;
|
|
360
|
-
} else {
|
|
361
|
-
delete config.insert;
|
|
362
|
-
}
|
|
363
|
-
if (update !== undefined) {
|
|
364
|
-
config.update = update;
|
|
365
|
-
} else {
|
|
366
|
-
delete config.update;
|
|
381
|
+
const schema = fieldSchemaForVariant(variant, column, tableName, key, primaryKeySet);
|
|
382
|
+
if (schema !== undefined) {
|
|
383
|
+
structFields[key] = schema;
|
|
367
384
|
}
|
|
368
|
-
variants[key] = TableSchema.Field(config);
|
|
369
385
|
}
|
|
370
|
-
|
|
371
|
-
return {
|
|
372
|
-
select: TableSchema.extract(struct, "select"),
|
|
373
|
-
insert: TableSchema.extract(struct, "insert"),
|
|
374
|
-
update: TableSchema.extract(struct, "update")
|
|
375
|
-
};
|
|
386
|
+
return Schema2.Struct(structFields);
|
|
376
387
|
};
|
|
388
|
+
var deriveSelectSchema = (tableName, fields, primaryKeyColumns) => deriveSchema("select", tableName, fields, primaryKeyColumns);
|
|
389
|
+
var deriveInsertSchema = (tableName, fields, primaryKeyColumns) => deriveSchema("insert", tableName, fields, primaryKeyColumns);
|
|
390
|
+
var deriveUpdateSchema = (tableName, fields, primaryKeyColumns) => deriveSchema("update", tableName, fields, primaryKeyColumns);
|
|
377
391
|
|
|
378
392
|
// src/internal/table.ts
|
|
379
393
|
var TypeId4 = Symbol.for("effect-qb/Table");
|
|
380
394
|
var OptionsSymbol = Symbol.for("effect-qb/Table/normalizedOptions");
|
|
381
395
|
var options = Symbol.for("effect-qb/Table/declaredOptions");
|
|
382
396
|
var CacheSymbol = Symbol.for("effect-qb/Table/cache");
|
|
397
|
+
var SchemaCacheSymbol = Symbol.for("effect-qb/Table/schemaCache");
|
|
383
398
|
var DeclaredOptionsSymbol = Symbol.for("effect-qb/Table/factoryDeclaredOptions");
|
|
384
399
|
var TableProto = {
|
|
385
400
|
pipe() {
|
|
@@ -402,14 +417,86 @@ var buildArtifacts = (name, fields, declaredOptions, schemaName) => {
|
|
|
402
417
|
validateOptions(name, fields, declaredOptions);
|
|
403
418
|
const primaryKey = resolvePrimaryKeyColumns(fields, declaredOptions);
|
|
404
419
|
const columns = Object.fromEntries(Object.entries(fields).map(([key, column]) => [key, bindColumn(name, key, column, name, schemaName)]));
|
|
405
|
-
const schemas = deriveSchemas(name, fields, primaryKey);
|
|
406
420
|
return {
|
|
407
421
|
columns,
|
|
408
|
-
schemas,
|
|
409
422
|
normalizedOptions,
|
|
410
423
|
primaryKey
|
|
411
424
|
};
|
|
412
425
|
};
|
|
426
|
+
var getSchemaCache = (table) => {
|
|
427
|
+
const target = table;
|
|
428
|
+
if (target[SchemaCacheSymbol] !== undefined) {
|
|
429
|
+
return target[SchemaCacheSymbol];
|
|
430
|
+
}
|
|
431
|
+
const cache = {};
|
|
432
|
+
Object.defineProperty(table, SchemaCacheSymbol, {
|
|
433
|
+
configurable: true,
|
|
434
|
+
value: cache
|
|
435
|
+
});
|
|
436
|
+
return cache;
|
|
437
|
+
};
|
|
438
|
+
var deriveTableSchema = (table, variant) => {
|
|
439
|
+
const state = table[TypeId4];
|
|
440
|
+
switch (variant) {
|
|
441
|
+
case "select":
|
|
442
|
+
return deriveSelectSchema(state.name, state.fields, state.primaryKey);
|
|
443
|
+
case "insert":
|
|
444
|
+
return deriveInsertSchema(state.name, state.fields, state.primaryKey);
|
|
445
|
+
case "update":
|
|
446
|
+
return deriveUpdateSchema(state.name, state.fields, state.primaryKey);
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
var schemaFor = (table, variant) => {
|
|
450
|
+
const cache = getSchemaCache(table);
|
|
451
|
+
const cached = cache[variant];
|
|
452
|
+
if (cached !== undefined) {
|
|
453
|
+
return cached;
|
|
454
|
+
}
|
|
455
|
+
const schema = deriveTableSchema(table, variant);
|
|
456
|
+
cache[variant] = schema;
|
|
457
|
+
return schema;
|
|
458
|
+
};
|
|
459
|
+
function selectSchema2(table) {
|
|
460
|
+
return schemaFor(table, "select");
|
|
461
|
+
}
|
|
462
|
+
function insertSchema2(table) {
|
|
463
|
+
return schemaFor(table, "insert");
|
|
464
|
+
}
|
|
465
|
+
function updateSchema2(table) {
|
|
466
|
+
return schemaFor(table, "update");
|
|
467
|
+
}
|
|
468
|
+
var schemasFor = (table) => {
|
|
469
|
+
const cache = getSchemaCache(table);
|
|
470
|
+
if (cache.schemas !== undefined) {
|
|
471
|
+
return cache.schemas;
|
|
472
|
+
}
|
|
473
|
+
const schemas = {};
|
|
474
|
+
Object.defineProperties(schemas, {
|
|
475
|
+
select: {
|
|
476
|
+
enumerable: true,
|
|
477
|
+
get: () => selectSchema2(table)
|
|
478
|
+
},
|
|
479
|
+
insert: {
|
|
480
|
+
enumerable: true,
|
|
481
|
+
get: () => insertSchema2(table)
|
|
482
|
+
},
|
|
483
|
+
update: {
|
|
484
|
+
enumerable: true,
|
|
485
|
+
get: () => updateSchema2(table)
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
cache.schemas = schemas;
|
|
489
|
+
return schemas;
|
|
490
|
+
};
|
|
491
|
+
var defineSchemasGetter = (table) => {
|
|
492
|
+
Object.defineProperty(table, "schemas", {
|
|
493
|
+
configurable: true,
|
|
494
|
+
enumerable: true,
|
|
495
|
+
get() {
|
|
496
|
+
return schemasFor(table);
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
};
|
|
413
500
|
var makeTable = (name, fields, declaredOptions, baseName = name, kind = "schema", schemaName, schemaMode = "default") => {
|
|
414
501
|
const resolvedSchemaName = schemaMode === "explicit" ? schemaName : "public";
|
|
415
502
|
const artifacts = buildArtifacts(name, fields, declaredOptions, resolvedSchemaName);
|
|
@@ -417,7 +504,7 @@ var makeTable = (name, fields, declaredOptions, baseName = name, kind = "schema"
|
|
|
417
504
|
const table = attachPipe2(Object.create(TableProto));
|
|
418
505
|
table.name = name;
|
|
419
506
|
table.columns = artifacts.columns;
|
|
420
|
-
table
|
|
507
|
+
defineSchemasGetter(table);
|
|
421
508
|
table[TypeId4] = {
|
|
422
509
|
name,
|
|
423
510
|
baseName,
|
|
@@ -490,7 +577,6 @@ var ensureClassArtifacts = (self) => {
|
|
|
490
577
|
const table = applyDeclaredOptions(makeTable(state.name, state.fields, [], state.name, "schema", state.schemaName, state.schemaName === undefined || state.schemaName === "public" ? "default" : "explicit"), classOptions);
|
|
491
578
|
const artifacts = {
|
|
492
579
|
columns: table.columns,
|
|
493
|
-
schemas: table.schemas,
|
|
494
580
|
normalizedOptions: table[OptionsSymbol],
|
|
495
581
|
primaryKey: table[TypeId4].primaryKey
|
|
496
582
|
};
|
|
@@ -513,21 +599,24 @@ var makeOption = (option) => {
|
|
|
513
599
|
return builder;
|
|
514
600
|
};
|
|
515
601
|
var option = (spec) => makeOption(spec);
|
|
516
|
-
function
|
|
602
|
+
function make(name, fields, schemaName) {
|
|
517
603
|
const resolvedSchemaName = arguments.length >= 3 ? schemaName : "public";
|
|
518
604
|
return makeTable(name, fields, [], name, "schema", resolvedSchemaName, arguments.length >= 3 ? "explicit" : "default");
|
|
519
605
|
}
|
|
520
|
-
var schema = (schemaName) =>
|
|
521
|
-
schemaName,
|
|
522
|
-
|
|
523
|
-
|
|
606
|
+
var schema = (schemaName) => {
|
|
607
|
+
const table = (name, fields, ...options2) => applyDeclaredOptions(makeTable(name, fields, [], name, "schema", schemaName, "explicit"), options2);
|
|
608
|
+
return {
|
|
609
|
+
schemaName,
|
|
610
|
+
table
|
|
611
|
+
};
|
|
612
|
+
};
|
|
524
613
|
var alias = (table, aliasName) => {
|
|
525
614
|
const state = table[TypeId4];
|
|
526
615
|
const columns = Object.fromEntries(Object.entries(state.fields).map(([key, column]) => [key, bindColumn(aliasName, key, column, state.baseName, state.schemaName)]));
|
|
527
616
|
const aliased = attachPipe2(Object.create(TableProto));
|
|
528
617
|
aliased.name = aliasName;
|
|
529
618
|
aliased.columns = columns;
|
|
530
|
-
aliased
|
|
619
|
+
defineSchemasGetter(aliased);
|
|
531
620
|
aliased[TypeId4] = {
|
|
532
621
|
name: aliasName,
|
|
533
622
|
baseName: state.baseName,
|
|
@@ -568,7 +657,7 @@ function Class(name, schemaName) {
|
|
|
568
657
|
return ensureClassArtifacts(this).columns;
|
|
569
658
|
}
|
|
570
659
|
static get schemas() {
|
|
571
|
-
return
|
|
660
|
+
return schemasFor(this);
|
|
572
661
|
}
|
|
573
662
|
static get [TypeId4]() {
|
|
574
663
|
const declaredOptions = extractDeclaredOptions(this[options]);
|
|
@@ -696,6 +785,9 @@ var normalize = (expression) => (() => {
|
|
|
696
785
|
}
|
|
697
786
|
})();
|
|
698
787
|
|
|
788
|
+
// src/postgres/internal/sql-expression-renderer.ts
|
|
789
|
+
import * as Schema5 from "effect/Schema";
|
|
790
|
+
|
|
699
791
|
// src/internal/query.ts
|
|
700
792
|
import { pipeArguments as pipeArguments4 } from "effect/Pipeable";
|
|
701
793
|
|
|
@@ -732,7 +824,18 @@ var cloneContext = (context) => ({
|
|
|
732
824
|
unknown: context.unknown
|
|
733
825
|
});
|
|
734
826
|
var freezeContext = (context) => context;
|
|
735
|
-
var
|
|
827
|
+
var columnPredicateKey = (tableName, columnName) => JSON.stringify([tableName, columnName]);
|
|
828
|
+
var columnPredicateKeyParts = (key) => {
|
|
829
|
+
const jsonSeparator = key.indexOf("#json:");
|
|
830
|
+
const columnKey = jsonSeparator === -1 ? key : key.slice(0, jsonSeparator);
|
|
831
|
+
try {
|
|
832
|
+
const parsed = JSON.parse(columnKey);
|
|
833
|
+
return Array.isArray(parsed) && parsed.length === 2 && typeof parsed[0] === "string" && typeof parsed[1] === "string" ? [parsed[0], parsed[1]] : undefined;
|
|
834
|
+
} catch {
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
var sourceNameOfKey = (key) => columnPredicateKeyParts(key)?.[0] ?? key.split(".", 1)[0] ?? key;
|
|
736
839
|
var addSourceName = (context, key) => {
|
|
737
840
|
context.sourceNames.add(sourceNameOfKey(key));
|
|
738
841
|
};
|
|
@@ -982,9 +1085,10 @@ var analyzeFormula = (formula) => freezeContext(analyzeStack(emptyContext(), [{
|
|
|
982
1085
|
var astOf = (value) => value[TypeId3];
|
|
983
1086
|
var columnKeyOfExpression = (value) => {
|
|
984
1087
|
const ast = astOf(value);
|
|
985
|
-
return ast.kind === "column" ?
|
|
1088
|
+
return ast.kind === "column" ? columnPredicateKey(ast.tableName, ast.columnName) : undefined;
|
|
986
1089
|
};
|
|
987
1090
|
var sameDbType = (left, right) => left.dialect === right.dialect && left.kind === right.kind;
|
|
1091
|
+
var escapeJsonPathPredicateKeySegment = (value) => value.replaceAll("\\", "\\\\").replaceAll(".", "\\.");
|
|
988
1092
|
var jsonPathPredicateKeyOfExpression = (value) => {
|
|
989
1093
|
const ast = astOf(value);
|
|
990
1094
|
switch (ast.kind) {
|
|
@@ -1008,7 +1112,7 @@ var jsonPathPredicateKeyOfExpression = (value) => {
|
|
|
1008
1112
|
return;
|
|
1009
1113
|
}
|
|
1010
1114
|
const baseKey = columnKeyOfExpression(jsonAst.base);
|
|
1011
|
-
return baseKey === undefined ? undefined : `${baseKey}#json:${path.join(".")}`;
|
|
1115
|
+
return baseKey === undefined ? undefined : `${baseKey}#json:${path.map(escapeJsonPathPredicateKeySegment).join(".")}`;
|
|
1012
1116
|
}
|
|
1013
1117
|
default:
|
|
1014
1118
|
return;
|
|
@@ -1463,13 +1567,1309 @@ var path = (...segments) => ({
|
|
|
1463
1567
|
segments
|
|
1464
1568
|
});
|
|
1465
1569
|
|
|
1570
|
+
// src/internal/dsl-plan-runtime.ts
|
|
1571
|
+
var renderSelectLockMode = (mode) => {
|
|
1572
|
+
switch (mode) {
|
|
1573
|
+
case "update":
|
|
1574
|
+
return "for update";
|
|
1575
|
+
case "share":
|
|
1576
|
+
return "for share";
|
|
1577
|
+
}
|
|
1578
|
+
throw new Error("lock(...) mode must be update or share for select statements");
|
|
1579
|
+
};
|
|
1580
|
+
var renderMysqlMutationLockMode = (mode, statement) => {
|
|
1581
|
+
switch (mode) {
|
|
1582
|
+
case "lowPriority":
|
|
1583
|
+
return " low_priority";
|
|
1584
|
+
case "ignore":
|
|
1585
|
+
return " ignore";
|
|
1586
|
+
case "quick":
|
|
1587
|
+
if (statement === "delete") {
|
|
1588
|
+
return " quick";
|
|
1589
|
+
}
|
|
1590
|
+
break;
|
|
1591
|
+
}
|
|
1592
|
+
throw new Error(statement === "update" ? "lock(...) mode must be lowPriority or ignore for update statements" : "lock(...) mode must be lowPriority, quick, or ignore for delete statements");
|
|
1593
|
+
};
|
|
1594
|
+
var makeDslPlanRuntime = (ctx) => {
|
|
1595
|
+
const aliasedSourceKinds = new Set(["derived", "cte", "lateral", "values", "unnest", "tableFunction"]);
|
|
1596
|
+
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
1597
|
+
const isPlan = (value) => isRecord(value) && (TypeId in value);
|
|
1598
|
+
const hasColumnRecord = (value) => isRecord(value.columns);
|
|
1599
|
+
const sourceRequiredList = (source) => typeof source === "object" && source !== null && ("required" in source) ? ctx.currentRequiredList(source.required) : [];
|
|
1600
|
+
const isAliasedSource = (source) => {
|
|
1601
|
+
if (!isRecord(source)) {
|
|
1602
|
+
return false;
|
|
1603
|
+
}
|
|
1604
|
+
if (TypeId4 in source) {
|
|
1605
|
+
return true;
|
|
1606
|
+
}
|
|
1607
|
+
if (!("kind" in source) || !("name" in source) || !("baseName" in source)) {
|
|
1608
|
+
return false;
|
|
1609
|
+
}
|
|
1610
|
+
if (typeof source.kind !== "string" || !aliasedSourceKinds.has(source.kind)) {
|
|
1611
|
+
return false;
|
|
1612
|
+
}
|
|
1613
|
+
if (typeof source.name !== "string" || typeof source.baseName !== "string") {
|
|
1614
|
+
return false;
|
|
1615
|
+
}
|
|
1616
|
+
switch (source.kind) {
|
|
1617
|
+
case "derived":
|
|
1618
|
+
case "cte":
|
|
1619
|
+
case "lateral":
|
|
1620
|
+
return isPlan(source.plan) && hasColumnRecord(source);
|
|
1621
|
+
case "values":
|
|
1622
|
+
return Array.isArray(source.rows) && hasColumnRecord(source);
|
|
1623
|
+
case "unnest":
|
|
1624
|
+
return isRecord(source.arrays) && hasColumnRecord(source);
|
|
1625
|
+
case "tableFunction":
|
|
1626
|
+
return typeof source.functionName === "string" && Array.isArray(source.args) && hasColumnRecord(source);
|
|
1627
|
+
}
|
|
1628
|
+
return false;
|
|
1629
|
+
};
|
|
1630
|
+
const assertAliasedSource = (source, message) => {
|
|
1631
|
+
if (!isAliasedSource(source)) {
|
|
1632
|
+
throw new Error(message);
|
|
1633
|
+
}
|
|
1634
|
+
};
|
|
1635
|
+
const assertPlanComplete = (plan) => {
|
|
1636
|
+
const required = ctx.currentRequiredList(plan[TypeId].required);
|
|
1637
|
+
if (required.length > 0) {
|
|
1638
|
+
throw new Error(`query references sources that are not yet in scope: ${required.join(", ")}`);
|
|
1639
|
+
}
|
|
1640
|
+
};
|
|
1641
|
+
const assertSourceNameAvailable = (available, sourceName) => {
|
|
1642
|
+
if (sourceName in available) {
|
|
1643
|
+
throw new Error(`query source name is already in scope: ${sourceName}`);
|
|
1644
|
+
}
|
|
1645
|
+
};
|
|
1646
|
+
const assertSelectHasBaseSourceForJoin = (statement, available) => {
|
|
1647
|
+
if (statement === "select" && Object.keys(available).length === 0) {
|
|
1648
|
+
throw new Error("select joins require a from(...) source before joining");
|
|
1649
|
+
}
|
|
1650
|
+
};
|
|
1651
|
+
const supportsJoinSources = (statement) => statement === "select" || statement === "update" || statement === "delete";
|
|
1652
|
+
const assertSetOperandStatement = (plan) => {
|
|
1653
|
+
const statement = ctx.getQueryState(plan).statement;
|
|
1654
|
+
if (statement !== "select" && statement !== "set") {
|
|
1655
|
+
throw new Error("set operator operands only accept select-like query plans");
|
|
1656
|
+
}
|
|
1657
|
+
};
|
|
1658
|
+
const buildSetOperation = (kind, all, left, right) => {
|
|
1659
|
+
assertSetOperandStatement(left);
|
|
1660
|
+
assertSetOperandStatement(right);
|
|
1661
|
+
assertPlanComplete(left);
|
|
1662
|
+
assertPlanComplete(right);
|
|
1663
|
+
const leftState = left[TypeId];
|
|
1664
|
+
const leftAst = ctx.getAst(left);
|
|
1665
|
+
const basePlan = leftAst.kind === "set" ? leftAst.setBase ?? left : left;
|
|
1666
|
+
const leftOperations = leftAst.kind === "set" ? [...leftAst.setOperations ?? []] : [];
|
|
1667
|
+
return ctx.makePlan({
|
|
1668
|
+
selection: leftState.selection,
|
|
1669
|
+
required: undefined,
|
|
1670
|
+
available: {},
|
|
1671
|
+
dialect: leftState.dialect ?? right[TypeId].dialect
|
|
1672
|
+
}, {
|
|
1673
|
+
kind: "set",
|
|
1674
|
+
select: leftState.selection,
|
|
1675
|
+
where: [],
|
|
1676
|
+
having: [],
|
|
1677
|
+
joins: [],
|
|
1678
|
+
groupBy: [],
|
|
1679
|
+
orderBy: [],
|
|
1680
|
+
setBase: basePlan,
|
|
1681
|
+
setOperations: [
|
|
1682
|
+
...leftOperations,
|
|
1683
|
+
{
|
|
1684
|
+
kind,
|
|
1685
|
+
all,
|
|
1686
|
+
query: right
|
|
1687
|
+
}
|
|
1688
|
+
]
|
|
1689
|
+
}, undefined, undefined, "set");
|
|
1690
|
+
};
|
|
1691
|
+
const where = (predicate) => (plan) => {
|
|
1692
|
+
const current = plan[TypeId];
|
|
1693
|
+
const currentAst = ctx.getAst(plan);
|
|
1694
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1695
|
+
const predicateExpression = ctx.toDialectExpression(predicate);
|
|
1696
|
+
const predicateRequired = ctx.extractRequiredFromDialectInputRuntime(predicate);
|
|
1697
|
+
return ctx.makePlan({
|
|
1698
|
+
selection: current.selection,
|
|
1699
|
+
required: [...ctx.currentRequiredList(current.required), ...predicateRequired].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
|
|
1700
|
+
available: current.available,
|
|
1701
|
+
dialect: current.dialect ?? predicateExpression[TypeId2].dialect
|
|
1702
|
+
}, {
|
|
1703
|
+
...currentAst,
|
|
1704
|
+
where: [...currentAst.where, {
|
|
1705
|
+
kind: "where",
|
|
1706
|
+
predicate: predicateExpression
|
|
1707
|
+
}]
|
|
1708
|
+
}, ctx.assumeFormulaTrue(currentQuery.assumptions, ctx.formulaOfExpressionRuntime(predicateExpression)), currentQuery.capabilities, currentQuery.statement);
|
|
1709
|
+
};
|
|
1710
|
+
const from = (source) => (plan) => {
|
|
1711
|
+
const current = plan[TypeId];
|
|
1712
|
+
const currentAst = ctx.getAst(plan);
|
|
1713
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1714
|
+
if (currentQuery.statement === "insert") {
|
|
1715
|
+
return ctx.attachInsertSource(plan, source);
|
|
1716
|
+
}
|
|
1717
|
+
assertAliasedSource(source, "from(...) requires an aliased source in select/update statements");
|
|
1718
|
+
if (currentQuery.statement === "select" && currentAst.from !== undefined) {
|
|
1719
|
+
throw new Error("select statements accept only one from(...) source; use joins for additional sources");
|
|
1720
|
+
}
|
|
1721
|
+
const sourceLike = source;
|
|
1722
|
+
const { sourceName, sourceBaseName } = ctx.sourceDetails(sourceLike);
|
|
1723
|
+
const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(sourceLike);
|
|
1724
|
+
const sourceRequired = sourceRequiredList(sourceLike);
|
|
1725
|
+
assertSourceNameAvailable(current.available, sourceName);
|
|
1726
|
+
if (currentQuery.statement === "select") {
|
|
1727
|
+
const nextAvailable = {
|
|
1728
|
+
[sourceName]: {
|
|
1729
|
+
name: sourceName,
|
|
1730
|
+
mode: "required",
|
|
1731
|
+
baseName: sourceBaseName,
|
|
1732
|
+
_presentFormula: ctx.trueFormula(),
|
|
1733
|
+
_presenceWitnesses: presenceWitnesses
|
|
1734
|
+
}
|
|
1735
|
+
};
|
|
1736
|
+
return ctx.makePlan({
|
|
1737
|
+
selection: current.selection,
|
|
1738
|
+
required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
|
|
1739
|
+
available: nextAvailable,
|
|
1740
|
+
dialect: current.dialect
|
|
1741
|
+
}, {
|
|
1742
|
+
...currentAst,
|
|
1743
|
+
from: {
|
|
1744
|
+
kind: "from",
|
|
1745
|
+
tableName: sourceName,
|
|
1746
|
+
baseTableName: sourceBaseName,
|
|
1747
|
+
source: sourceLike
|
|
1748
|
+
}
|
|
1749
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1750
|
+
}
|
|
1751
|
+
if (currentQuery.statement === "update") {
|
|
1752
|
+
const nextAvailable = {
|
|
1753
|
+
...current.available,
|
|
1754
|
+
[sourceName]: {
|
|
1755
|
+
name: sourceName,
|
|
1756
|
+
mode: "required",
|
|
1757
|
+
baseName: sourceBaseName,
|
|
1758
|
+
_presentFormula: ctx.trueFormula(),
|
|
1759
|
+
_presenceWitnesses: presenceWitnesses
|
|
1760
|
+
}
|
|
1761
|
+
};
|
|
1762
|
+
return ctx.makePlan({
|
|
1763
|
+
selection: current.selection,
|
|
1764
|
+
required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
|
|
1765
|
+
available: nextAvailable,
|
|
1766
|
+
dialect: current.dialect
|
|
1767
|
+
}, {
|
|
1768
|
+
...currentAst,
|
|
1769
|
+
fromSources: [
|
|
1770
|
+
...currentAst.fromSources ?? [],
|
|
1771
|
+
{
|
|
1772
|
+
kind: "from",
|
|
1773
|
+
tableName: sourceName,
|
|
1774
|
+
baseTableName: sourceBaseName,
|
|
1775
|
+
source: sourceLike
|
|
1776
|
+
}
|
|
1777
|
+
]
|
|
1778
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1779
|
+
}
|
|
1780
|
+
throw new Error(`from(...) is not supported for ${currentQuery.statement} statements`);
|
|
1781
|
+
};
|
|
1782
|
+
const having = (predicate) => (plan) => {
|
|
1783
|
+
const current = plan[TypeId];
|
|
1784
|
+
const currentAst = ctx.getAst(plan);
|
|
1785
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1786
|
+
const predicateExpression = ctx.toDialectExpression(predicate);
|
|
1787
|
+
const predicateRequired = ctx.extractRequiredFromDialectInputRuntime(predicate);
|
|
1788
|
+
return ctx.makePlan({
|
|
1789
|
+
selection: current.selection,
|
|
1790
|
+
required: [...ctx.currentRequiredList(current.required), ...predicateRequired].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
|
|
1791
|
+
available: current.available,
|
|
1792
|
+
dialect: current.dialect ?? predicateExpression[TypeId2].dialect
|
|
1793
|
+
}, {
|
|
1794
|
+
...currentAst,
|
|
1795
|
+
having: [...currentAst.having, {
|
|
1796
|
+
kind: "having",
|
|
1797
|
+
predicate: predicateExpression
|
|
1798
|
+
}]
|
|
1799
|
+
}, ctx.assumeFormulaTrue(currentQuery.assumptions, ctx.formulaOfExpressionRuntime(predicateExpression)), currentQuery.capabilities, currentQuery.statement);
|
|
1800
|
+
};
|
|
1801
|
+
const crossJoin = (table) => (plan) => {
|
|
1802
|
+
const current = plan[TypeId];
|
|
1803
|
+
const currentAst = ctx.getAst(plan);
|
|
1804
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1805
|
+
if (supportsJoinSources(currentQuery.statement)) {
|
|
1806
|
+
assertAliasedSource(table, "join(...) requires an aliased source in select/update/delete statements");
|
|
1807
|
+
assertSelectHasBaseSourceForJoin(currentQuery.statement, current.available);
|
|
1808
|
+
}
|
|
1809
|
+
const { sourceName, sourceBaseName } = ctx.sourceDetails(table);
|
|
1810
|
+
const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table);
|
|
1811
|
+
const sourceRequired = sourceRequiredList(table);
|
|
1812
|
+
if (supportsJoinSources(currentQuery.statement)) {
|
|
1813
|
+
assertSourceNameAvailable(current.available, sourceName);
|
|
1814
|
+
}
|
|
1815
|
+
const nextAvailable = {
|
|
1816
|
+
...current.available,
|
|
1817
|
+
[sourceName]: {
|
|
1818
|
+
name: sourceName,
|
|
1819
|
+
mode: "required",
|
|
1820
|
+
baseName: sourceBaseName,
|
|
1821
|
+
_presentFormula: ctx.trueFormula(),
|
|
1822
|
+
_presenceWitnesses: presenceWitnesses
|
|
1823
|
+
}
|
|
1824
|
+
};
|
|
1825
|
+
return ctx.makePlan({
|
|
1826
|
+
selection: current.selection,
|
|
1827
|
+
required: [...ctx.currentRequiredList(current.required), ...sourceRequired].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
|
|
1828
|
+
available: nextAvailable,
|
|
1829
|
+
dialect: current.dialect ?? table[TypeId]?.dialect ?? table.dialect
|
|
1830
|
+
}, {
|
|
1831
|
+
...currentAst,
|
|
1832
|
+
joins: [...currentAst.joins, {
|
|
1833
|
+
kind: "cross",
|
|
1834
|
+
tableName: sourceName,
|
|
1835
|
+
baseTableName: sourceBaseName,
|
|
1836
|
+
source: table
|
|
1837
|
+
}]
|
|
1838
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1839
|
+
};
|
|
1840
|
+
const join = (kind, table, on) => (plan) => {
|
|
1841
|
+
const current = plan[TypeId];
|
|
1842
|
+
const currentAst = ctx.getAst(plan);
|
|
1843
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1844
|
+
const onExpression = ctx.toDialectExpression(on);
|
|
1845
|
+
const onFormula = ctx.formulaOfExpressionRuntime(onExpression);
|
|
1846
|
+
if (supportsJoinSources(currentQuery.statement)) {
|
|
1847
|
+
assertAliasedSource(table, "join(...) requires an aliased source in select/update/delete statements");
|
|
1848
|
+
assertSelectHasBaseSourceForJoin(currentQuery.statement, current.available);
|
|
1849
|
+
}
|
|
1850
|
+
const { sourceName, sourceBaseName } = ctx.sourceDetails(table);
|
|
1851
|
+
const presenceWitnesses = ctx.presenceWitnessesOfSourceLike(table);
|
|
1852
|
+
const sourceRequired = sourceRequiredList(table);
|
|
1853
|
+
if (supportsJoinSources(currentQuery.statement)) {
|
|
1854
|
+
assertSourceNameAvailable(current.available, sourceName);
|
|
1855
|
+
}
|
|
1856
|
+
const baseAvailable = kind === "right" || kind === "full" ? Object.fromEntries(Object.entries(current.available).map(([name, source]) => [name, {
|
|
1857
|
+
name: source.name,
|
|
1858
|
+
mode: "optional",
|
|
1859
|
+
baseName: source.baseName,
|
|
1860
|
+
_presentFormula: source._presentFormula,
|
|
1861
|
+
_presenceWitnesses: source._presenceWitnesses
|
|
1862
|
+
}])) : current.available;
|
|
1863
|
+
const nextAvailable = {
|
|
1864
|
+
...baseAvailable,
|
|
1865
|
+
[sourceName]: {
|
|
1866
|
+
name: sourceName,
|
|
1867
|
+
mode: kind === "left" || kind === "full" ? "optional" : "required",
|
|
1868
|
+
baseName: sourceBaseName,
|
|
1869
|
+
_presentFormula: kind === "inner" || kind === "left" ? onFormula : ctx.trueFormula(),
|
|
1870
|
+
_presenceWitnesses: presenceWitnesses
|
|
1871
|
+
}
|
|
1872
|
+
};
|
|
1873
|
+
return ctx.makePlan({
|
|
1874
|
+
selection: current.selection,
|
|
1875
|
+
required: [...ctx.currentRequiredList(current.required), ...sourceRequired, ...ctx.extractRequiredFromDialectInputRuntime(on)].filter((name, index3, values) => !(name in nextAvailable) && values.indexOf(name) === index3),
|
|
1876
|
+
available: nextAvailable,
|
|
1877
|
+
dialect: current.dialect ?? table.dialect ?? onExpression[TypeId2].dialect
|
|
1878
|
+
}, {
|
|
1879
|
+
...currentAst,
|
|
1880
|
+
joins: [...currentAst.joins, {
|
|
1881
|
+
kind,
|
|
1882
|
+
tableName: sourceName,
|
|
1883
|
+
baseTableName: sourceBaseName,
|
|
1884
|
+
source: table,
|
|
1885
|
+
on: onExpression
|
|
1886
|
+
}]
|
|
1887
|
+
}, kind === "inner" ? ctx.assumeFormulaTrue(currentQuery.assumptions, onFormula) : currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1888
|
+
};
|
|
1889
|
+
const orderBy = (value, direction = "asc") => (plan) => {
|
|
1890
|
+
if (direction !== "asc" && direction !== "desc") {
|
|
1891
|
+
throw new Error("orderBy(...) direction must be asc or desc");
|
|
1892
|
+
}
|
|
1893
|
+
const current = plan[TypeId];
|
|
1894
|
+
const currentAst = ctx.getAst(plan);
|
|
1895
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1896
|
+
const expression = ctx.toDialectExpression(value);
|
|
1897
|
+
const required = ctx.extractRequiredFromDialectInputRuntime(value);
|
|
1898
|
+
return ctx.makePlan({
|
|
1899
|
+
selection: current.selection,
|
|
1900
|
+
required: [...ctx.currentRequiredList(current.required), ...required].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
|
|
1901
|
+
available: current.available,
|
|
1902
|
+
dialect: current.dialect ?? expression[TypeId2].dialect
|
|
1903
|
+
}, {
|
|
1904
|
+
...currentAst,
|
|
1905
|
+
orderBy: [...currentAst.orderBy, {
|
|
1906
|
+
kind: "orderBy",
|
|
1907
|
+
value: expression,
|
|
1908
|
+
direction
|
|
1909
|
+
}]
|
|
1910
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1911
|
+
};
|
|
1912
|
+
const lock = (mode, options2 = {}) => (plan) => {
|
|
1913
|
+
const current = plan[TypeId];
|
|
1914
|
+
const currentAst = ctx.getAst(plan);
|
|
1915
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1916
|
+
if (currentQuery.statement === "select") {
|
|
1917
|
+
renderSelectLockMode(mode);
|
|
1918
|
+
}
|
|
1919
|
+
if (ctx.profile.dialect === "mysql" && currentQuery.statement === "update") {
|
|
1920
|
+
renderMysqlMutationLockMode(mode, "update");
|
|
1921
|
+
}
|
|
1922
|
+
if (ctx.profile.dialect === "mysql" && currentQuery.statement === "delete") {
|
|
1923
|
+
renderMysqlMutationLockMode(mode, "delete");
|
|
1924
|
+
}
|
|
1925
|
+
return ctx.makePlan({
|
|
1926
|
+
selection: current.selection,
|
|
1927
|
+
required: current.required,
|
|
1928
|
+
available: current.available,
|
|
1929
|
+
dialect: current.dialect
|
|
1930
|
+
}, {
|
|
1931
|
+
...currentAst,
|
|
1932
|
+
lock: {
|
|
1933
|
+
kind: "lock",
|
|
1934
|
+
mode,
|
|
1935
|
+
nowait: options2.nowait ?? false,
|
|
1936
|
+
skipLocked: options2.skipLocked ?? false
|
|
1937
|
+
}
|
|
1938
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1939
|
+
};
|
|
1940
|
+
const distinct = () => (plan) => {
|
|
1941
|
+
const current = plan[TypeId];
|
|
1942
|
+
const currentAst = ctx.getAst(plan);
|
|
1943
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1944
|
+
return ctx.makePlan({
|
|
1945
|
+
selection: current.selection,
|
|
1946
|
+
required: current.required,
|
|
1947
|
+
available: current.available,
|
|
1948
|
+
dialect: current.dialect
|
|
1949
|
+
}, {
|
|
1950
|
+
...currentAst,
|
|
1951
|
+
distinct: true
|
|
1952
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1953
|
+
};
|
|
1954
|
+
const limit = (value) => (plan) => {
|
|
1955
|
+
const current = plan[TypeId];
|
|
1956
|
+
const currentAst = ctx.getAst(plan);
|
|
1957
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1958
|
+
const expression = ctx.toDialectNumericExpression(value);
|
|
1959
|
+
const required = ctx.extractRequiredFromDialectNumericInputRuntime(value);
|
|
1960
|
+
return ctx.makePlan({
|
|
1961
|
+
selection: current.selection,
|
|
1962
|
+
required: [...ctx.currentRequiredList(current.required), ...required].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
|
|
1963
|
+
available: current.available,
|
|
1964
|
+
dialect: current.dialect ?? expression[TypeId2].dialect
|
|
1965
|
+
}, {
|
|
1966
|
+
...currentAst,
|
|
1967
|
+
limit: expression
|
|
1968
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1969
|
+
};
|
|
1970
|
+
const offset = (value) => (plan) => {
|
|
1971
|
+
const current = plan[TypeId];
|
|
1972
|
+
const currentAst = ctx.getAst(plan);
|
|
1973
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
1974
|
+
const expression = ctx.toDialectNumericExpression(value);
|
|
1975
|
+
const required = ctx.extractRequiredFromDialectNumericInputRuntime(value);
|
|
1976
|
+
return ctx.makePlan({
|
|
1977
|
+
selection: current.selection,
|
|
1978
|
+
required: [...ctx.currentRequiredList(current.required), ...required].filter((name, index3, values) => !(name in current.available) && values.indexOf(name) === index3),
|
|
1979
|
+
available: current.available,
|
|
1980
|
+
dialect: current.dialect ?? expression[TypeId2].dialect
|
|
1981
|
+
}, {
|
|
1982
|
+
...currentAst,
|
|
1983
|
+
offset: expression
|
|
1984
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement);
|
|
1985
|
+
};
|
|
1986
|
+
return {
|
|
1987
|
+
buildSetOperation,
|
|
1988
|
+
where,
|
|
1989
|
+
from,
|
|
1990
|
+
having,
|
|
1991
|
+
crossJoin,
|
|
1992
|
+
join,
|
|
1993
|
+
orderBy,
|
|
1994
|
+
lock,
|
|
1995
|
+
distinct,
|
|
1996
|
+
limit,
|
|
1997
|
+
offset
|
|
1998
|
+
};
|
|
1999
|
+
};
|
|
2000
|
+
|
|
2001
|
+
// src/internal/dsl-mutation-runtime.ts
|
|
2002
|
+
var expectInsertSourceKind = (source) => {
|
|
2003
|
+
if (source !== undefined && source.kind !== "values" && source.kind !== "query" && source.kind !== "unnest") {
|
|
2004
|
+
throw new Error("Unsupported insert source kind");
|
|
2005
|
+
}
|
|
2006
|
+
return source;
|
|
2007
|
+
};
|
|
2008
|
+
var expectConflictClause = (conflict) => {
|
|
2009
|
+
if (conflict === undefined) {
|
|
2010
|
+
return conflict;
|
|
2011
|
+
}
|
|
2012
|
+
if (conflict.kind !== "conflict") {
|
|
2013
|
+
throw new Error("Unsupported conflict clause kind");
|
|
2014
|
+
}
|
|
2015
|
+
if (conflict.action !== "doNothing" && conflict.action !== "doUpdate") {
|
|
2016
|
+
throw new Error("Unsupported conflict action");
|
|
2017
|
+
}
|
|
2018
|
+
if (conflict.target !== undefined && conflict.target.kind !== "columns" && conflict.target.kind !== "constraint") {
|
|
2019
|
+
throw new Error("Unsupported conflict target kind");
|
|
2020
|
+
}
|
|
2021
|
+
return conflict;
|
|
2022
|
+
};
|
|
2023
|
+
var makeDslMutationRuntime = (ctx) => {
|
|
2024
|
+
const aliasedSourceKinds = new Set(["derived", "cte", "lateral", "values", "unnest", "tableFunction"]);
|
|
2025
|
+
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
2026
|
+
const isTableTarget = (target) => typeof target === "object" && target !== null && (TypeId4 in target) && (TypeId in target);
|
|
2027
|
+
const hasColumnRecord = (value) => isRecord(value.columns);
|
|
2028
|
+
const isAliasedSource = (source) => {
|
|
2029
|
+
if (!isRecord(source)) {
|
|
2030
|
+
return false;
|
|
2031
|
+
}
|
|
2032
|
+
if (isTableTarget(source)) {
|
|
2033
|
+
return true;
|
|
2034
|
+
}
|
|
2035
|
+
if (!("kind" in source) || !("name" in source) || !("baseName" in source)) {
|
|
2036
|
+
return false;
|
|
2037
|
+
}
|
|
2038
|
+
if (typeof source.kind !== "string" || !aliasedSourceKinds.has(source.kind)) {
|
|
2039
|
+
return false;
|
|
2040
|
+
}
|
|
2041
|
+
if (typeof source.name !== "string" || typeof source.baseName !== "string") {
|
|
2042
|
+
return false;
|
|
2043
|
+
}
|
|
2044
|
+
switch (source.kind) {
|
|
2045
|
+
case "derived":
|
|
2046
|
+
case "cte":
|
|
2047
|
+
case "lateral":
|
|
2048
|
+
return isRecord(source.plan) && TypeId in source.plan && hasColumnRecord(source);
|
|
2049
|
+
case "values":
|
|
2050
|
+
return Array.isArray(source.rows) && hasColumnRecord(source);
|
|
2051
|
+
case "unnest":
|
|
2052
|
+
return isRecord(source.arrays) && hasColumnRecord(source);
|
|
2053
|
+
case "tableFunction":
|
|
2054
|
+
return typeof source.functionName === "string" && Array.isArray(source.args) && hasColumnRecord(source);
|
|
2055
|
+
}
|
|
2056
|
+
return false;
|
|
2057
|
+
};
|
|
2058
|
+
const assertMutationTarget = (target, apiName) => {
|
|
2059
|
+
if (!isTableTarget(target)) {
|
|
2060
|
+
throw new Error(`${apiName}(...) requires table targets`);
|
|
2061
|
+
}
|
|
2062
|
+
};
|
|
2063
|
+
const assertAliasedSource = (source, apiName) => {
|
|
2064
|
+
if (!isAliasedSource(source)) {
|
|
2065
|
+
throw new Error(`${apiName}(...) requires an aliased source`);
|
|
2066
|
+
}
|
|
2067
|
+
};
|
|
2068
|
+
const assertMutationTargets = (target, apiName, options2 = {}) => {
|
|
2069
|
+
const targets = Array.isArray(target) ? target : [target];
|
|
2070
|
+
if (targets.length === 0) {
|
|
2071
|
+
throw new Error(`${apiName}(...) requires at least one table target`);
|
|
2072
|
+
}
|
|
2073
|
+
if (Array.isArray(target) && targets.length === 1) {
|
|
2074
|
+
throw new Error(`${apiName}(...) requires a table target, not a single-element target tuple`);
|
|
2075
|
+
}
|
|
2076
|
+
for (const entry of targets) {
|
|
2077
|
+
assertMutationTarget(entry, apiName);
|
|
2078
|
+
}
|
|
2079
|
+
if (targets.length > 1 && options2.allowMultiple !== true) {
|
|
2080
|
+
throw new Error(`${apiName}(...) requires a single table target`);
|
|
2081
|
+
}
|
|
2082
|
+
if (targets.length > 1 && ctx.profile.dialect !== "mysql" && ctx.profile.dialect !== "sqlite") {
|
|
2083
|
+
throw new Error(`${apiName}(...) only supports multiple mutation targets for mysql`);
|
|
2084
|
+
}
|
|
2085
|
+
};
|
|
2086
|
+
const assertUniqueTargetNames = (targets) => {
|
|
2087
|
+
const seen = new Set;
|
|
2088
|
+
for (const target of targets) {
|
|
2089
|
+
if (seen.has(target.tableName)) {
|
|
2090
|
+
throw new Error(`mutation target source names must be unique: ${target.tableName}`);
|
|
2091
|
+
}
|
|
2092
|
+
seen.add(target.tableName);
|
|
2093
|
+
}
|
|
2094
|
+
};
|
|
2095
|
+
const assertInsertSelectSource = (sourcePlan, selection) => {
|
|
2096
|
+
const statement = ctx.getQueryState(sourcePlan).statement;
|
|
2097
|
+
if (statement !== "select" && statement !== "set") {
|
|
2098
|
+
throw new Error("insert sources only accept select-like query plans");
|
|
2099
|
+
}
|
|
2100
|
+
for (const value of Object.values(selection)) {
|
|
2101
|
+
if (value === null || typeof value !== "object" || !(TypeId2 in value)) {
|
|
2102
|
+
throw new Error("insert sources require a flat selection object");
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
};
|
|
2106
|
+
const insert = (target, values) => {
|
|
2107
|
+
assertMutationTargets(target, "insert");
|
|
2108
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2109
|
+
const assignments = values === undefined ? [] : ctx.buildMutationAssignments(target, values);
|
|
2110
|
+
const required = assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies));
|
|
2111
|
+
const insertState = values === undefined ? "missing" : "ready";
|
|
2112
|
+
return ctx.makePlan({
|
|
2113
|
+
selection: {},
|
|
2114
|
+
required: required.filter((name, index3, list) => name !== sourceName && list.indexOf(name) === index3),
|
|
2115
|
+
available: {
|
|
2116
|
+
[sourceName]: {
|
|
2117
|
+
name: sourceName,
|
|
2118
|
+
mode: "required",
|
|
2119
|
+
baseName: sourceBaseName
|
|
2120
|
+
}
|
|
2121
|
+
},
|
|
2122
|
+
dialect: target[TypeId].dialect
|
|
2123
|
+
}, {
|
|
2124
|
+
kind: "insert",
|
|
2125
|
+
select: {},
|
|
2126
|
+
into: {
|
|
2127
|
+
kind: "from",
|
|
2128
|
+
tableName: sourceName,
|
|
2129
|
+
baseTableName: sourceBaseName,
|
|
2130
|
+
source: target
|
|
2131
|
+
},
|
|
2132
|
+
values: assignments,
|
|
2133
|
+
conflict: undefined,
|
|
2134
|
+
where: [],
|
|
2135
|
+
having: [],
|
|
2136
|
+
joins: [],
|
|
2137
|
+
groupBy: [],
|
|
2138
|
+
orderBy: []
|
|
2139
|
+
}, undefined, "write", "insert", target, insertState);
|
|
2140
|
+
};
|
|
2141
|
+
const attachInsertSource = (plan, source) => {
|
|
2142
|
+
const current = plan[TypeId];
|
|
2143
|
+
const currentAst = ctx.getAst(plan);
|
|
2144
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
2145
|
+
const target = currentQuery.target;
|
|
2146
|
+
const sourceName = currentAst.into.tableName;
|
|
2147
|
+
if (typeof source === "object" && source !== null && "kind" in source && source.kind === "values") {
|
|
2148
|
+
const normalized = ctx.buildInsertValuesRows(target, source.rows);
|
|
2149
|
+
return ctx.makePlan({
|
|
2150
|
+
selection: current.selection,
|
|
2151
|
+
required: normalized.required.filter((name) => name !== sourceName),
|
|
2152
|
+
available: current.available,
|
|
2153
|
+
dialect: current.dialect
|
|
2154
|
+
}, {
|
|
2155
|
+
...currentAst,
|
|
2156
|
+
values: [],
|
|
2157
|
+
insertSource: {
|
|
2158
|
+
kind: "values",
|
|
2159
|
+
columns: normalized.columns,
|
|
2160
|
+
rows: normalized.rows
|
|
2161
|
+
}
|
|
2162
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, "ready");
|
|
2163
|
+
}
|
|
2164
|
+
if (typeof source === "object" && source !== null && "kind" in source && source.kind === "unnest") {
|
|
2165
|
+
const normalized = ctx.normalizeInsertUnnestValues(target, source.values);
|
|
2166
|
+
return ctx.makePlan({
|
|
2167
|
+
selection: current.selection,
|
|
2168
|
+
required: [],
|
|
2169
|
+
available: current.available,
|
|
2170
|
+
dialect: current.dialect
|
|
2171
|
+
}, {
|
|
2172
|
+
...currentAst,
|
|
2173
|
+
values: [],
|
|
2174
|
+
insertSource: {
|
|
2175
|
+
kind: "unnest",
|
|
2176
|
+
columns: normalized.columns,
|
|
2177
|
+
values: normalized.values
|
|
2178
|
+
}
|
|
2179
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, "ready");
|
|
2180
|
+
}
|
|
2181
|
+
const sourcePlan = source;
|
|
2182
|
+
const selection = sourcePlan[TypeId].selection;
|
|
2183
|
+
assertInsertSelectSource(sourcePlan, selection);
|
|
2184
|
+
const columns = ctx.normalizeInsertSelectColumns(selection);
|
|
2185
|
+
return ctx.makePlan({
|
|
2186
|
+
selection: current.selection,
|
|
2187
|
+
required: ctx.currentRequiredList(sourcePlan[TypeId].required),
|
|
2188
|
+
available: current.available,
|
|
2189
|
+
dialect: current.dialect
|
|
2190
|
+
}, {
|
|
2191
|
+
...currentAst,
|
|
2192
|
+
values: [],
|
|
2193
|
+
insertSource: {
|
|
2194
|
+
kind: "query",
|
|
2195
|
+
columns,
|
|
2196
|
+
query: sourcePlan
|
|
2197
|
+
}
|
|
2198
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, "ready");
|
|
2199
|
+
};
|
|
2200
|
+
const onConflict = (target, options2 = {}) => (plan) => {
|
|
2201
|
+
const current = plan[TypeId];
|
|
2202
|
+
const currentAst = ctx.getAst(plan);
|
|
2203
|
+
const currentQuery = ctx.getQueryState(plan);
|
|
2204
|
+
if (currentQuery.statement !== "insert") {
|
|
2205
|
+
throw new Error(`onConflict(...) is not supported for ${currentQuery.statement} statements`);
|
|
2206
|
+
}
|
|
2207
|
+
const insertTarget = currentAst.into.source;
|
|
2208
|
+
const conflictTarget = ctx.buildConflictTarget(insertTarget, target);
|
|
2209
|
+
const updateAssignments = options2.update ? ctx.buildMutationAssignments(insertTarget, options2.update) : [];
|
|
2210
|
+
if (options2.update !== undefined && updateAssignments.length === 0) {
|
|
2211
|
+
throw new Error("conflict update assignments require at least one assignment");
|
|
2212
|
+
}
|
|
2213
|
+
const updateWhere = options2.where === undefined ? undefined : ctx.toDialectExpression(options2.where);
|
|
2214
|
+
const targetWhere = conflictTarget.kind === "columns" ? conflictTarget.where : undefined;
|
|
2215
|
+
const required = [
|
|
2216
|
+
...ctx.currentRequiredList(current.required),
|
|
2217
|
+
...updateAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
|
|
2218
|
+
...updateWhere ? Object.keys(updateWhere[TypeId2].dependencies) : [],
|
|
2219
|
+
...targetWhere ? Object.keys(targetWhere[TypeId2].dependencies) : []
|
|
2220
|
+
].filter((name, index3, list) => !(name in current.available) && list.indexOf(name) === index3);
|
|
2221
|
+
return ctx.makePlan({
|
|
2222
|
+
selection: current.selection,
|
|
2223
|
+
required,
|
|
2224
|
+
available: current.available,
|
|
2225
|
+
dialect: current.dialect
|
|
2226
|
+
}, {
|
|
2227
|
+
...currentAst,
|
|
2228
|
+
conflict: {
|
|
2229
|
+
kind: "conflict",
|
|
2230
|
+
target: conflictTarget,
|
|
2231
|
+
action: updateAssignments.length === 0 ? "doNothing" : "doUpdate",
|
|
2232
|
+
values: updateAssignments.length === 0 ? undefined : updateAssignments,
|
|
2233
|
+
where: updateWhere
|
|
2234
|
+
}
|
|
2235
|
+
}, currentQuery.assumptions, currentQuery.capabilities, currentQuery.statement, currentQuery.target, currentQuery.insertSource);
|
|
2236
|
+
};
|
|
2237
|
+
const update = (target, values) => {
|
|
2238
|
+
assertMutationTargets(target, "update", { allowMultiple: true });
|
|
2239
|
+
const targets = ctx.mutationTargetClauses(target);
|
|
2240
|
+
assertUniqueTargetNames(targets);
|
|
2241
|
+
const primaryTarget = targets[0];
|
|
2242
|
+
const assignments = ctx.buildMutationAssignments(target, values);
|
|
2243
|
+
const targetNames = new Set(targets.map((entry) => entry.tableName));
|
|
2244
|
+
const required = assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)).filter((name, index3, list) => !targetNames.has(name) && list.indexOf(name) === index3);
|
|
2245
|
+
return ctx.makePlan({
|
|
2246
|
+
selection: {},
|
|
2247
|
+
required,
|
|
2248
|
+
available: ctx.mutationAvailableSources(target),
|
|
2249
|
+
dialect: primaryTarget.source[TypeId].dialect
|
|
2250
|
+
}, {
|
|
2251
|
+
kind: "update",
|
|
2252
|
+
select: {},
|
|
2253
|
+
target: primaryTarget,
|
|
2254
|
+
targets,
|
|
2255
|
+
set: assignments,
|
|
2256
|
+
where: [],
|
|
2257
|
+
having: [],
|
|
2258
|
+
joins: [],
|
|
2259
|
+
groupBy: [],
|
|
2260
|
+
orderBy: []
|
|
2261
|
+
}, undefined, "write", "update");
|
|
2262
|
+
};
|
|
2263
|
+
const upsert = (target, values, conflictColumns, updateValues) => {
|
|
2264
|
+
assertMutationTargets(target, "upsert");
|
|
2265
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2266
|
+
const assignments = ctx.buildMutationAssignments(target, values);
|
|
2267
|
+
const updateAssignments = updateValues ? ctx.buildMutationAssignments(target, updateValues) : [];
|
|
2268
|
+
if (updateValues !== undefined && updateAssignments.length === 0) {
|
|
2269
|
+
throw new Error("upsert update assignments require at least one assignment");
|
|
2270
|
+
}
|
|
2271
|
+
const required = [
|
|
2272
|
+
...assignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
|
|
2273
|
+
...updateAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies))
|
|
2274
|
+
];
|
|
2275
|
+
return ctx.makePlan({
|
|
2276
|
+
selection: {},
|
|
2277
|
+
required: required.filter((name, index3, list) => name !== sourceName && list.indexOf(name) === index3),
|
|
2278
|
+
available: {
|
|
2279
|
+
[sourceName]: {
|
|
2280
|
+
name: sourceName,
|
|
2281
|
+
mode: "required",
|
|
2282
|
+
baseName: sourceBaseName
|
|
2283
|
+
}
|
|
2284
|
+
},
|
|
2285
|
+
dialect: target[TypeId].dialect
|
|
2286
|
+
}, {
|
|
2287
|
+
kind: "insert",
|
|
2288
|
+
select: {},
|
|
2289
|
+
into: {
|
|
2290
|
+
kind: "from",
|
|
2291
|
+
tableName: sourceName,
|
|
2292
|
+
baseTableName: sourceBaseName,
|
|
2293
|
+
source: target
|
|
2294
|
+
},
|
|
2295
|
+
values: assignments,
|
|
2296
|
+
conflict: {
|
|
2297
|
+
kind: "conflict",
|
|
2298
|
+
target: {
|
|
2299
|
+
kind: "columns",
|
|
2300
|
+
columns: ctx.normalizeConflictColumns(target, conflictColumns)
|
|
2301
|
+
},
|
|
2302
|
+
action: updateAssignments.length > 0 ? "doUpdate" : "doNothing",
|
|
2303
|
+
values: updateAssignments.length > 0 ? updateAssignments : undefined
|
|
2304
|
+
},
|
|
2305
|
+
where: [],
|
|
2306
|
+
having: [],
|
|
2307
|
+
joins: [],
|
|
2308
|
+
groupBy: [],
|
|
2309
|
+
orderBy: []
|
|
2310
|
+
}, undefined, "write", "insert", target, "ready");
|
|
2311
|
+
};
|
|
2312
|
+
const delete_ = (target) => {
|
|
2313
|
+
assertMutationTargets(target, "delete", { allowMultiple: true });
|
|
2314
|
+
const targets = ctx.mutationTargetClauses(target);
|
|
2315
|
+
assertUniqueTargetNames(targets);
|
|
2316
|
+
const primaryTarget = targets[0];
|
|
2317
|
+
return ctx.makePlan({
|
|
2318
|
+
selection: {},
|
|
2319
|
+
required: [],
|
|
2320
|
+
available: ctx.mutationAvailableSources(target),
|
|
2321
|
+
dialect: primaryTarget.source[TypeId].dialect
|
|
2322
|
+
}, {
|
|
2323
|
+
kind: "delete",
|
|
2324
|
+
select: {},
|
|
2325
|
+
target: primaryTarget,
|
|
2326
|
+
targets,
|
|
2327
|
+
where: [],
|
|
2328
|
+
having: [],
|
|
2329
|
+
joins: [],
|
|
2330
|
+
groupBy: [],
|
|
2331
|
+
orderBy: []
|
|
2332
|
+
}, undefined, "write", "delete");
|
|
2333
|
+
};
|
|
2334
|
+
const truncate = (target, options2 = {}) => {
|
|
2335
|
+
assertMutationTargets(target, "truncate");
|
|
2336
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2337
|
+
return ctx.makePlan({
|
|
2338
|
+
selection: {},
|
|
2339
|
+
required: [],
|
|
2340
|
+
available: {},
|
|
2341
|
+
dialect: target[TypeId].dialect
|
|
2342
|
+
}, {
|
|
2343
|
+
kind: "truncate",
|
|
2344
|
+
select: {},
|
|
2345
|
+
target: {
|
|
2346
|
+
kind: "from",
|
|
2347
|
+
tableName: sourceName,
|
|
2348
|
+
baseTableName: sourceBaseName,
|
|
2349
|
+
source: target
|
|
2350
|
+
},
|
|
2351
|
+
truncate: {
|
|
2352
|
+
kind: "truncate",
|
|
2353
|
+
restartIdentity: options2.restartIdentity ?? false,
|
|
2354
|
+
cascade: options2.cascade ?? false
|
|
2355
|
+
},
|
|
2356
|
+
where: [],
|
|
2357
|
+
having: [],
|
|
2358
|
+
joins: [],
|
|
2359
|
+
groupBy: [],
|
|
2360
|
+
orderBy: []
|
|
2361
|
+
}, undefined, "write", "truncate");
|
|
2362
|
+
};
|
|
2363
|
+
const merge = (target, source, on, options2 = {}) => {
|
|
2364
|
+
assertMutationTargets(target, "merge");
|
|
2365
|
+
assertAliasedSource(source, "merge");
|
|
2366
|
+
const { sourceName: targetName, sourceBaseName: targetBaseName } = ctx.targetSourceDetails(target);
|
|
2367
|
+
const { sourceName: usingName, sourceBaseName: usingBaseName } = ctx.sourceDetails(source);
|
|
2368
|
+
if (targetName === usingName) {
|
|
2369
|
+
throw new Error(`merge(...) source name must differ from target source name: ${targetName}`);
|
|
2370
|
+
}
|
|
2371
|
+
const onExpression = ctx.toDialectExpression(on);
|
|
2372
|
+
const matched = options2.whenMatched;
|
|
2373
|
+
const notMatched = options2.whenNotMatched;
|
|
2374
|
+
if (matched && "delete" in matched && "update" in matched) {
|
|
2375
|
+
throw new Error("merge whenMatched cannot specify both update and delete");
|
|
2376
|
+
}
|
|
2377
|
+
const matchedPredicate = matched?.predicate ? ctx.toDialectExpression(matched.predicate) : undefined;
|
|
2378
|
+
const matchedAssignments = matched && "update" in matched && matched.update ? ctx.buildMutationAssignments(target, matched.update) : [];
|
|
2379
|
+
const notMatchedPredicate = notMatched?.predicate ? ctx.toDialectExpression(notMatched.predicate) : undefined;
|
|
2380
|
+
const notMatchedAssignments = notMatched ? ctx.buildMutationAssignments(target, notMatched.values) : [];
|
|
2381
|
+
const required = [
|
|
2382
|
+
...Object.keys(onExpression[TypeId2].dependencies),
|
|
2383
|
+
...matchedAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
|
|
2384
|
+
...notMatchedAssignments.flatMap((entry) => Object.keys(entry.value[TypeId2].dependencies)),
|
|
2385
|
+
...matchedPredicate ? Object.keys(matchedPredicate[TypeId2].dependencies) : [],
|
|
2386
|
+
...notMatchedPredicate ? Object.keys(notMatchedPredicate[TypeId2].dependencies) : []
|
|
2387
|
+
].filter((name, index3, values) => name !== targetName && name !== usingName && values.indexOf(name) === index3);
|
|
2388
|
+
return ctx.makePlan({
|
|
2389
|
+
selection: {},
|
|
2390
|
+
required,
|
|
2391
|
+
available: {
|
|
2392
|
+
[targetName]: {
|
|
2393
|
+
name: targetName,
|
|
2394
|
+
mode: "required",
|
|
2395
|
+
baseName: targetBaseName
|
|
2396
|
+
},
|
|
2397
|
+
[usingName]: {
|
|
2398
|
+
name: usingName,
|
|
2399
|
+
mode: "required",
|
|
2400
|
+
baseName: usingBaseName
|
|
2401
|
+
}
|
|
2402
|
+
},
|
|
2403
|
+
dialect: target[TypeId].dialect
|
|
2404
|
+
}, {
|
|
2405
|
+
kind: "merge",
|
|
2406
|
+
select: {},
|
|
2407
|
+
target: {
|
|
2408
|
+
kind: "from",
|
|
2409
|
+
tableName: targetName,
|
|
2410
|
+
baseTableName: targetBaseName,
|
|
2411
|
+
source: target
|
|
2412
|
+
},
|
|
2413
|
+
using: {
|
|
2414
|
+
kind: "from",
|
|
2415
|
+
tableName: usingName,
|
|
2416
|
+
baseTableName: usingBaseName,
|
|
2417
|
+
source
|
|
2418
|
+
},
|
|
2419
|
+
merge: {
|
|
2420
|
+
kind: "merge",
|
|
2421
|
+
on: onExpression,
|
|
2422
|
+
whenMatched: matched ? "delete" in matched && matched.delete ? {
|
|
2423
|
+
kind: "delete",
|
|
2424
|
+
predicate: matchedPredicate
|
|
2425
|
+
} : {
|
|
2426
|
+
kind: "update",
|
|
2427
|
+
values: matchedAssignments,
|
|
2428
|
+
predicate: matchedPredicate
|
|
2429
|
+
} : undefined,
|
|
2430
|
+
whenNotMatched: notMatched ? {
|
|
2431
|
+
kind: "insert",
|
|
2432
|
+
values: notMatchedAssignments,
|
|
2433
|
+
predicate: notMatchedPredicate
|
|
2434
|
+
} : undefined
|
|
2435
|
+
},
|
|
2436
|
+
where: [],
|
|
2437
|
+
having: [],
|
|
2438
|
+
joins: [],
|
|
2439
|
+
groupBy: [],
|
|
2440
|
+
orderBy: []
|
|
2441
|
+
}, undefined, "write", "merge");
|
|
2442
|
+
};
|
|
2443
|
+
return {
|
|
2444
|
+
insert,
|
|
2445
|
+
attachInsertSource,
|
|
2446
|
+
onConflict,
|
|
2447
|
+
update,
|
|
2448
|
+
upsert,
|
|
2449
|
+
delete_,
|
|
2450
|
+
truncate,
|
|
2451
|
+
merge
|
|
2452
|
+
};
|
|
2453
|
+
};
|
|
2454
|
+
|
|
2455
|
+
// src/internal/dsl-transaction-ddl-runtime.ts
|
|
2456
|
+
var allowedIsolationLevels = new Set(["read committed", "repeatable read", "serializable"]);
|
|
2457
|
+
var renderTransactionIsolationLevel = (isolationLevel) => {
|
|
2458
|
+
if (isolationLevel === undefined) {
|
|
2459
|
+
return "";
|
|
2460
|
+
}
|
|
2461
|
+
if (typeof isolationLevel !== "string" || !allowedIsolationLevels.has(isolationLevel)) {
|
|
2462
|
+
throw new Error("Unsupported transaction isolation level");
|
|
2463
|
+
}
|
|
2464
|
+
return `isolation level ${isolationLevel}`;
|
|
2465
|
+
};
|
|
2466
|
+
var expectDdlClauseKind = (ddl, kind) => {
|
|
2467
|
+
if (ddl === undefined || ddl.kind !== kind) {
|
|
2468
|
+
throw new Error("Unsupported DDL statement kind");
|
|
2469
|
+
}
|
|
2470
|
+
return ddl;
|
|
2471
|
+
};
|
|
2472
|
+
var expectTruncateClause = (truncate) => {
|
|
2473
|
+
if (truncate === undefined || truncate.kind !== "truncate") {
|
|
2474
|
+
throw new Error("Unsupported truncate statement kind");
|
|
2475
|
+
}
|
|
2476
|
+
return truncate;
|
|
2477
|
+
};
|
|
2478
|
+
var validateIsolationLevel = (isolationLevel) => {
|
|
2479
|
+
renderTransactionIsolationLevel(isolationLevel);
|
|
2480
|
+
};
|
|
2481
|
+
var makeDslTransactionDdlRuntime = (ctx) => {
|
|
2482
|
+
const isRecord = (value) => typeof value === "object" && value !== null;
|
|
2483
|
+
const assertTableTarget = (target, apiName) => {
|
|
2484
|
+
if (!isRecord(target) || !(TypeId4 in target) || !(TypeId in target)) {
|
|
2485
|
+
throw new Error(`${apiName}(...) requires a table target`);
|
|
2486
|
+
}
|
|
2487
|
+
};
|
|
2488
|
+
const validateIndexColumns = (target, columns) => {
|
|
2489
|
+
const fields = target[TypeId4]?.fields;
|
|
2490
|
+
if (fields === undefined) {
|
|
2491
|
+
return;
|
|
2492
|
+
}
|
|
2493
|
+
for (const columnName of columns) {
|
|
2494
|
+
if (!(columnName in fields)) {
|
|
2495
|
+
throw new Error(`effect-qb: unknown index column '${columnName}'`);
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
};
|
|
2499
|
+
const transaction = (options2 = {}) => {
|
|
2500
|
+
validateIsolationLevel(options2.isolationLevel);
|
|
2501
|
+
return ctx.makePlan({
|
|
2502
|
+
selection: {},
|
|
2503
|
+
required: [],
|
|
2504
|
+
available: {},
|
|
2505
|
+
dialect: ctx.profile.dialect
|
|
2506
|
+
}, {
|
|
2507
|
+
kind: "transaction",
|
|
2508
|
+
select: {},
|
|
2509
|
+
transaction: {
|
|
2510
|
+
kind: "transaction",
|
|
2511
|
+
isolationLevel: options2.isolationLevel,
|
|
2512
|
+
readOnly: options2.readOnly
|
|
2513
|
+
},
|
|
2514
|
+
where: [],
|
|
2515
|
+
having: [],
|
|
2516
|
+
joins: [],
|
|
2517
|
+
groupBy: [],
|
|
2518
|
+
orderBy: []
|
|
2519
|
+
}, undefined, "transaction", "transaction");
|
|
2520
|
+
};
|
|
2521
|
+
const commit = () => ctx.makePlan({
|
|
2522
|
+
selection: {},
|
|
2523
|
+
required: [],
|
|
2524
|
+
available: {},
|
|
2525
|
+
dialect: ctx.profile.dialect
|
|
2526
|
+
}, {
|
|
2527
|
+
kind: "commit",
|
|
2528
|
+
select: {},
|
|
2529
|
+
transaction: {
|
|
2530
|
+
kind: "commit"
|
|
2531
|
+
},
|
|
2532
|
+
where: [],
|
|
2533
|
+
having: [],
|
|
2534
|
+
joins: [],
|
|
2535
|
+
groupBy: [],
|
|
2536
|
+
orderBy: []
|
|
2537
|
+
}, undefined, "transaction", "commit");
|
|
2538
|
+
const rollback = () => ctx.makePlan({
|
|
2539
|
+
selection: {},
|
|
2540
|
+
required: [],
|
|
2541
|
+
available: {},
|
|
2542
|
+
dialect: ctx.profile.dialect
|
|
2543
|
+
}, {
|
|
2544
|
+
kind: "rollback",
|
|
2545
|
+
select: {},
|
|
2546
|
+
transaction: {
|
|
2547
|
+
kind: "rollback"
|
|
2548
|
+
},
|
|
2549
|
+
where: [],
|
|
2550
|
+
having: [],
|
|
2551
|
+
joins: [],
|
|
2552
|
+
groupBy: [],
|
|
2553
|
+
orderBy: []
|
|
2554
|
+
}, undefined, "transaction", "rollback");
|
|
2555
|
+
const savepoint = (name) => ctx.makePlan({
|
|
2556
|
+
selection: {},
|
|
2557
|
+
required: [],
|
|
2558
|
+
available: {},
|
|
2559
|
+
dialect: ctx.profile.dialect
|
|
2560
|
+
}, {
|
|
2561
|
+
kind: "savepoint",
|
|
2562
|
+
select: {},
|
|
2563
|
+
transaction: {
|
|
2564
|
+
kind: "savepoint",
|
|
2565
|
+
name
|
|
2566
|
+
},
|
|
2567
|
+
where: [],
|
|
2568
|
+
having: [],
|
|
2569
|
+
joins: [],
|
|
2570
|
+
groupBy: [],
|
|
2571
|
+
orderBy: []
|
|
2572
|
+
}, undefined, "transaction", "savepoint");
|
|
2573
|
+
const rollbackTo = (name) => ctx.makePlan({
|
|
2574
|
+
selection: {},
|
|
2575
|
+
required: [],
|
|
2576
|
+
available: {},
|
|
2577
|
+
dialect: ctx.profile.dialect
|
|
2578
|
+
}, {
|
|
2579
|
+
kind: "rollbackTo",
|
|
2580
|
+
select: {},
|
|
2581
|
+
transaction: {
|
|
2582
|
+
kind: "rollbackTo",
|
|
2583
|
+
name
|
|
2584
|
+
},
|
|
2585
|
+
where: [],
|
|
2586
|
+
having: [],
|
|
2587
|
+
joins: [],
|
|
2588
|
+
groupBy: [],
|
|
2589
|
+
orderBy: []
|
|
2590
|
+
}, undefined, "transaction", "rollbackTo");
|
|
2591
|
+
const releaseSavepoint = (name) => ctx.makePlan({
|
|
2592
|
+
selection: {},
|
|
2593
|
+
required: [],
|
|
2594
|
+
available: {},
|
|
2595
|
+
dialect: ctx.profile.dialect
|
|
2596
|
+
}, {
|
|
2597
|
+
kind: "releaseSavepoint",
|
|
2598
|
+
select: {},
|
|
2599
|
+
transaction: {
|
|
2600
|
+
kind: "releaseSavepoint",
|
|
2601
|
+
name
|
|
2602
|
+
},
|
|
2603
|
+
where: [],
|
|
2604
|
+
having: [],
|
|
2605
|
+
joins: [],
|
|
2606
|
+
groupBy: [],
|
|
2607
|
+
orderBy: []
|
|
2608
|
+
}, undefined, "transaction", "releaseSavepoint");
|
|
2609
|
+
const createTable = (target, options2 = {}) => {
|
|
2610
|
+
assertTableTarget(target, "createTable");
|
|
2611
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2612
|
+
return ctx.makePlan({
|
|
2613
|
+
selection: {},
|
|
2614
|
+
required: [],
|
|
2615
|
+
available: {},
|
|
2616
|
+
dialect: target[TypeId].dialect
|
|
2617
|
+
}, {
|
|
2618
|
+
kind: "createTable",
|
|
2619
|
+
select: {},
|
|
2620
|
+
target: {
|
|
2621
|
+
kind: "from",
|
|
2622
|
+
tableName: sourceName,
|
|
2623
|
+
baseTableName: sourceBaseName,
|
|
2624
|
+
source: target
|
|
2625
|
+
},
|
|
2626
|
+
ddl: {
|
|
2627
|
+
kind: "createTable",
|
|
2628
|
+
ifNotExists: options2.ifNotExists ?? false
|
|
2629
|
+
},
|
|
2630
|
+
where: [],
|
|
2631
|
+
having: [],
|
|
2632
|
+
joins: [],
|
|
2633
|
+
groupBy: [],
|
|
2634
|
+
orderBy: []
|
|
2635
|
+
}, undefined, "ddl", "createTable");
|
|
2636
|
+
};
|
|
2637
|
+
const dropTable = (target, options2 = {}) => {
|
|
2638
|
+
assertTableTarget(target, "dropTable");
|
|
2639
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2640
|
+
return ctx.makePlan({
|
|
2641
|
+
selection: {},
|
|
2642
|
+
required: [],
|
|
2643
|
+
available: {},
|
|
2644
|
+
dialect: target[TypeId].dialect
|
|
2645
|
+
}, {
|
|
2646
|
+
kind: "dropTable",
|
|
2647
|
+
select: {},
|
|
2648
|
+
target: {
|
|
2649
|
+
kind: "from",
|
|
2650
|
+
tableName: sourceName,
|
|
2651
|
+
baseTableName: sourceBaseName,
|
|
2652
|
+
source: target
|
|
2653
|
+
},
|
|
2654
|
+
ddl: {
|
|
2655
|
+
kind: "dropTable",
|
|
2656
|
+
ifExists: options2.ifExists ?? false
|
|
2657
|
+
},
|
|
2658
|
+
where: [],
|
|
2659
|
+
having: [],
|
|
2660
|
+
joins: [],
|
|
2661
|
+
groupBy: [],
|
|
2662
|
+
orderBy: []
|
|
2663
|
+
}, undefined, "ddl", "dropTable");
|
|
2664
|
+
};
|
|
2665
|
+
const createIndex = (target, columns, options2 = {}) => {
|
|
2666
|
+
assertTableTarget(target, "createIndex");
|
|
2667
|
+
const normalizedColumns = ctx.normalizeColumnList(columns);
|
|
2668
|
+
validateIndexColumns(target, normalizedColumns);
|
|
2669
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2670
|
+
return ctx.makePlan({
|
|
2671
|
+
selection: {},
|
|
2672
|
+
required: [],
|
|
2673
|
+
available: {},
|
|
2674
|
+
dialect: target[TypeId].dialect
|
|
2675
|
+
}, {
|
|
2676
|
+
kind: "createIndex",
|
|
2677
|
+
select: {},
|
|
2678
|
+
target: {
|
|
2679
|
+
kind: "from",
|
|
2680
|
+
tableName: sourceName,
|
|
2681
|
+
baseTableName: sourceBaseName,
|
|
2682
|
+
source: target
|
|
2683
|
+
},
|
|
2684
|
+
ddl: {
|
|
2685
|
+
kind: "createIndex",
|
|
2686
|
+
name: options2.name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, options2.unique ?? false),
|
|
2687
|
+
columns: normalizedColumns,
|
|
2688
|
+
unique: options2.unique ?? false,
|
|
2689
|
+
ifNotExists: options2.ifNotExists ?? false
|
|
2690
|
+
},
|
|
2691
|
+
where: [],
|
|
2692
|
+
having: [],
|
|
2693
|
+
joins: [],
|
|
2694
|
+
groupBy: [],
|
|
2695
|
+
orderBy: []
|
|
2696
|
+
}, undefined, "ddl", "createIndex");
|
|
2697
|
+
};
|
|
2698
|
+
const dropIndex = (target, columns, options2 = {}) => {
|
|
2699
|
+
assertTableTarget(target, "dropIndex");
|
|
2700
|
+
const normalizedColumns = ctx.normalizeColumnList(columns);
|
|
2701
|
+
validateIndexColumns(target, normalizedColumns);
|
|
2702
|
+
const { sourceName, sourceBaseName } = ctx.targetSourceDetails(target);
|
|
2703
|
+
return ctx.makePlan({
|
|
2704
|
+
selection: {},
|
|
2705
|
+
required: [],
|
|
2706
|
+
available: {},
|
|
2707
|
+
dialect: target[TypeId].dialect
|
|
2708
|
+
}, {
|
|
2709
|
+
kind: "dropIndex",
|
|
2710
|
+
select: {},
|
|
2711
|
+
target: {
|
|
2712
|
+
kind: "from",
|
|
2713
|
+
tableName: sourceName,
|
|
2714
|
+
baseTableName: sourceBaseName,
|
|
2715
|
+
source: target
|
|
2716
|
+
},
|
|
2717
|
+
ddl: {
|
|
2718
|
+
kind: "dropIndex",
|
|
2719
|
+
name: options2.name ?? ctx.defaultIndexName(sourceBaseName, normalizedColumns, false),
|
|
2720
|
+
ifExists: options2.ifExists ?? false
|
|
2721
|
+
},
|
|
2722
|
+
where: [],
|
|
2723
|
+
having: [],
|
|
2724
|
+
joins: [],
|
|
2725
|
+
groupBy: [],
|
|
2726
|
+
orderBy: []
|
|
2727
|
+
}, undefined, "ddl", "dropIndex");
|
|
2728
|
+
};
|
|
2729
|
+
return {
|
|
2730
|
+
transaction,
|
|
2731
|
+
commit,
|
|
2732
|
+
rollback,
|
|
2733
|
+
savepoint,
|
|
2734
|
+
rollbackTo,
|
|
2735
|
+
releaseSavepoint,
|
|
2736
|
+
createTable,
|
|
2737
|
+
dropTable,
|
|
2738
|
+
createIndex,
|
|
2739
|
+
dropIndex
|
|
2740
|
+
};
|
|
2741
|
+
};
|
|
2742
|
+
|
|
1466
2743
|
// src/internal/runtime/driver-value-mapping.ts
|
|
2744
|
+
import * as Schema4 from "effect/Schema";
|
|
2745
|
+
|
|
2746
|
+
// src/internal/runtime/value.ts
|
|
1467
2747
|
import * as Schema3 from "effect/Schema";
|
|
2748
|
+
var brandString = (pattern, brand4) => Schema3.String.pipe(Schema3.check(Schema3.isPattern(pattern)), Schema3.brand(brand4));
|
|
2749
|
+
var localDatePattern = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
2750
|
+
var isValidLocalDateString = (value) => {
|
|
2751
|
+
const match = localDatePattern.exec(value);
|
|
2752
|
+
if (match === null) {
|
|
2753
|
+
return false;
|
|
2754
|
+
}
|
|
2755
|
+
const year = Number(match[1]);
|
|
2756
|
+
const month = Number(match[2]);
|
|
2757
|
+
const day = Number(match[3]);
|
|
2758
|
+
const parsed = new Date(Date.UTC(year, month - 1, day));
|
|
2759
|
+
parsed.setUTCFullYear(year);
|
|
2760
|
+
return parsed.getUTCFullYear() === year && parsed.getUTCMonth() === month - 1 && parsed.getUTCDate() === day;
|
|
2761
|
+
};
|
|
2762
|
+
var localTimePattern = /^(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?$/;
|
|
2763
|
+
var isValidLocalTimeString = (value) => {
|
|
2764
|
+
const match = localTimePattern.exec(value);
|
|
2765
|
+
if (match === null) {
|
|
2766
|
+
return false;
|
|
2767
|
+
}
|
|
2768
|
+
const hour = Number(match[1]);
|
|
2769
|
+
const minute = Number(match[2]);
|
|
2770
|
+
const second = Number(match[3]);
|
|
2771
|
+
return hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59 && second >= 0 && second <= 59;
|
|
2772
|
+
};
|
|
2773
|
+
var offsetPattern = /^(?:Z|[+-](\d{2}):(\d{2}))$/;
|
|
2774
|
+
var isValidOffset = (value) => {
|
|
2775
|
+
const match = offsetPattern.exec(value);
|
|
2776
|
+
if (match === null) {
|
|
2777
|
+
return false;
|
|
2778
|
+
}
|
|
2779
|
+
if (value === "Z") {
|
|
2780
|
+
return true;
|
|
2781
|
+
}
|
|
2782
|
+
const hour = Number(match[1]);
|
|
2783
|
+
const minute = Number(match[2]);
|
|
2784
|
+
return hour >= 0 && hour <= 23 && minute >= 0 && minute <= 59;
|
|
2785
|
+
};
|
|
2786
|
+
var offsetTimePattern = /^(\d{2}:\d{2}:\d{2}(?:\.\d+)?)(Z|[+-]\d{2}:\d{2})$/;
|
|
2787
|
+
var isValidOffsetTimeString = (value) => {
|
|
2788
|
+
const match = offsetTimePattern.exec(value);
|
|
2789
|
+
return match !== null && isValidLocalTimeString(match[1]) && isValidOffset(match[2]);
|
|
2790
|
+
};
|
|
2791
|
+
var localDateTimePattern = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?)$/;
|
|
2792
|
+
var isValidLocalDateTimeString = (value) => {
|
|
2793
|
+
const match = localDateTimePattern.exec(value);
|
|
2794
|
+
return match !== null && isValidLocalDateString(match[1]) && isValidLocalTimeString(match[2]);
|
|
2795
|
+
};
|
|
2796
|
+
var instantPattern = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2}(?:\.\d+)?)(Z|[+-]\d{2}:\d{2})$/;
|
|
2797
|
+
var isValidInstantString = (value) => {
|
|
2798
|
+
const match = instantPattern.exec(value);
|
|
2799
|
+
return match !== null && isValidLocalDateString(match[1]) && isValidLocalTimeString(match[2]) && isValidOffset(match[3]);
|
|
2800
|
+
};
|
|
2801
|
+
var LocalDateStringSchema = Schema3.String.pipe(Schema3.check(Schema3.isPattern(localDatePattern)), Schema3.check(Schema3.makeFilter((value) => isValidLocalDateString(value))), Schema3.brand("LocalDateString"));
|
|
2802
|
+
var LocalTimeStringSchema = Schema3.String.pipe(Schema3.check(Schema3.isPattern(localTimePattern)), Schema3.check(Schema3.makeFilter((value) => isValidLocalTimeString(value))), Schema3.brand("LocalTimeString"));
|
|
2803
|
+
var OffsetTimeStringSchema = Schema3.String.pipe(Schema3.check(Schema3.isPattern(offsetTimePattern)), Schema3.check(Schema3.makeFilter((value) => isValidOffsetTimeString(value))), Schema3.brand("OffsetTimeString"));
|
|
2804
|
+
var LocalDateTimeStringSchema = Schema3.String.pipe(Schema3.check(Schema3.isPattern(localDateTimePattern)), Schema3.check(Schema3.makeFilter((value) => isValidLocalDateTimeString(value))), Schema3.brand("LocalDateTimeString"));
|
|
2805
|
+
var InstantStringSchema = Schema3.String.pipe(Schema3.check(Schema3.isPattern(instantPattern)), Schema3.check(Schema3.makeFilter((value) => isValidInstantString(value))), Schema3.brand("InstantString"));
|
|
2806
|
+
var YearStringSchema = brandString(/^\d{4}$/, "YearString");
|
|
2807
|
+
var canonicalizeBigIntString = (input) => {
|
|
2808
|
+
const trimmed = input.trim();
|
|
2809
|
+
if (!/^-?\d+$/.test(trimmed)) {
|
|
2810
|
+
throw new Error("Expected an integer-like bigint value");
|
|
2811
|
+
}
|
|
2812
|
+
return BigInt(trimmed).toString();
|
|
2813
|
+
};
|
|
2814
|
+
var isCanonicalBigIntString = (value) => {
|
|
2815
|
+
try {
|
|
2816
|
+
return canonicalizeBigIntString(value) === value;
|
|
2817
|
+
} catch {
|
|
2818
|
+
return false;
|
|
2819
|
+
}
|
|
2820
|
+
};
|
|
2821
|
+
var canonicalizeDecimalString = (input) => {
|
|
2822
|
+
const trimmed = input.trim();
|
|
2823
|
+
const match = /^([+-]?)(\d+)(?:\.(\d+))?$/.exec(trimmed);
|
|
2824
|
+
if (match === null) {
|
|
2825
|
+
throw new Error("Expected a decimal string");
|
|
2826
|
+
}
|
|
2827
|
+
const sign = match[1] === "-" ? "-" : "";
|
|
2828
|
+
const integer = match[2].replace(/^0+(?=\d)/, "") || "0";
|
|
2829
|
+
const fraction = (match[3] ?? "").replace(/0+$/, "");
|
|
2830
|
+
if (fraction.length === 0) {
|
|
2831
|
+
if (integer === "0") {
|
|
2832
|
+
return "0";
|
|
2833
|
+
}
|
|
2834
|
+
return `${sign}${integer}`;
|
|
2835
|
+
}
|
|
2836
|
+
return `${sign}${integer}.${fraction}`;
|
|
2837
|
+
};
|
|
2838
|
+
var isCanonicalDecimalString = (value) => {
|
|
2839
|
+
try {
|
|
2840
|
+
return canonicalizeDecimalString(value) === value;
|
|
2841
|
+
} catch {
|
|
2842
|
+
return false;
|
|
2843
|
+
}
|
|
2844
|
+
};
|
|
2845
|
+
var BigIntStringSchema = Schema3.String.pipe(Schema3.check(Schema3.makeFilter((value) => isCanonicalBigIntString(value))), Schema3.brand("BigIntString"));
|
|
2846
|
+
var DecimalStringSchema = Schema3.String.pipe(Schema3.check(Schema3.makeFilter((value) => isCanonicalDecimalString(value))), Schema3.brand("DecimalString"));
|
|
2847
|
+
var JsonValueSchema = Schema3.suspend(() => Schema3.Union([
|
|
2848
|
+
Schema3.String,
|
|
2849
|
+
Schema3.Number.check(Schema3.isFinite()),
|
|
2850
|
+
Schema3.Boolean,
|
|
2851
|
+
Schema3.Null,
|
|
2852
|
+
Schema3.Array(JsonValueSchema),
|
|
2853
|
+
Schema3.Record(Schema3.String, JsonValueSchema)
|
|
2854
|
+
]));
|
|
2855
|
+
var JsonPrimitiveSchema = Schema3.Union([
|
|
2856
|
+
Schema3.String,
|
|
2857
|
+
Schema3.Number.check(Schema3.isFinite()),
|
|
2858
|
+
Schema3.Boolean,
|
|
2859
|
+
Schema3.Null
|
|
2860
|
+
]);
|
|
1468
2861
|
|
|
1469
2862
|
// src/internal/runtime/normalize.ts
|
|
1470
2863
|
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2864
|
+
var isPlainRecord = (value) => {
|
|
2865
|
+
if (!isRecord(value)) {
|
|
2866
|
+
return false;
|
|
2867
|
+
}
|
|
2868
|
+
const prototype = Object.getPrototypeOf(value);
|
|
2869
|
+
return prototype === Object.prototype || prototype === null;
|
|
2870
|
+
};
|
|
1471
2871
|
var pad = (value, width = 2) => value.toString().padStart(width, "0");
|
|
1472
|
-
var formatLocalDate = (value) => `${value.getUTCFullYear()}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())}`;
|
|
2872
|
+
var formatLocalDate = (value) => `${pad(value.getUTCFullYear(), 4)}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())}`;
|
|
1473
2873
|
var formatLocalTime = (value) => {
|
|
1474
2874
|
const milliseconds = value.getUTCMilliseconds();
|
|
1475
2875
|
const base = `${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}`;
|
|
@@ -1489,12 +2889,14 @@ var expectString = (value, label) => {
|
|
|
1489
2889
|
}
|
|
1490
2890
|
throw new Error(`Expected ${label} as string`);
|
|
1491
2891
|
};
|
|
2892
|
+
var finiteNumberStringPattern = /^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[eE][+-]?\d+)?$/;
|
|
1492
2893
|
var normalizeNumber = (value) => {
|
|
1493
2894
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1494
2895
|
return value;
|
|
1495
2896
|
}
|
|
1496
|
-
if (typeof value === "string"
|
|
1497
|
-
const
|
|
2897
|
+
if (typeof value === "string") {
|
|
2898
|
+
const trimmed = value.trim();
|
|
2899
|
+
const parsed = finiteNumberStringPattern.test(trimmed) ? Number(trimmed) : Number.NaN;
|
|
1498
2900
|
if (Number.isFinite(parsed)) {
|
|
1499
2901
|
return parsed;
|
|
1500
2902
|
}
|
|
@@ -1534,25 +2936,11 @@ var normalizeBigIntString = (value) => {
|
|
|
1534
2936
|
if (typeof value === "number" && Number.isSafeInteger(value)) {
|
|
1535
2937
|
return BigInt(value).toString();
|
|
1536
2938
|
}
|
|
1537
|
-
if (typeof value === "string"
|
|
1538
|
-
return
|
|
2939
|
+
if (typeof value === "string") {
|
|
2940
|
+
return canonicalizeBigIntString(value);
|
|
1539
2941
|
}
|
|
1540
2942
|
throw new Error("Expected an integer-like bigint value");
|
|
1541
2943
|
};
|
|
1542
|
-
var canonicalizeDecimalString = (input) => {
|
|
1543
|
-
const trimmed = input.trim();
|
|
1544
|
-
const match = /^([+-]?)(\d+)(?:\.(\d+))?$/.exec(trimmed);
|
|
1545
|
-
if (match === null) {
|
|
1546
|
-
throw new Error("Expected a decimal string");
|
|
1547
|
-
}
|
|
1548
|
-
const sign = match[1] === "-" ? "-" : "";
|
|
1549
|
-
const integer = match[2].replace(/^0+(?=\d)/, "") || "0";
|
|
1550
|
-
const fraction = (match[3] ?? "").replace(/0+$/, "");
|
|
1551
|
-
if (fraction.length === 0) {
|
|
1552
|
-
return `${sign}${integer}`;
|
|
1553
|
-
}
|
|
1554
|
-
return `${sign}${integer}.${fraction}`;
|
|
1555
|
-
};
|
|
1556
2944
|
var normalizeDecimalString = (value) => {
|
|
1557
2945
|
if (typeof value === "string") {
|
|
1558
2946
|
return canonicalizeDecimalString(value);
|
|
@@ -1571,12 +2959,15 @@ var normalizeLocalDate = (value) => {
|
|
|
1571
2959
|
return formatLocalDate(value);
|
|
1572
2960
|
}
|
|
1573
2961
|
const raw = expectString(value, "local date").trim();
|
|
1574
|
-
if (
|
|
2962
|
+
if (isValidLocalDateString(raw)) {
|
|
1575
2963
|
return raw;
|
|
1576
2964
|
}
|
|
1577
|
-
const
|
|
1578
|
-
if (
|
|
1579
|
-
|
|
2965
|
+
const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
|
|
2966
|
+
if (isValidInstantString(canonicalInstant)) {
|
|
2967
|
+
const parsed = new Date(canonicalInstant);
|
|
2968
|
+
if (!Number.isNaN(parsed.getTime())) {
|
|
2969
|
+
return formatLocalDate(parsed);
|
|
2970
|
+
}
|
|
1580
2971
|
}
|
|
1581
2972
|
throw new Error("Expected a local-date value");
|
|
1582
2973
|
};
|
|
@@ -1585,7 +2976,7 @@ var normalizeLocalTime = (value) => {
|
|
|
1585
2976
|
return formatLocalTime(value);
|
|
1586
2977
|
}
|
|
1587
2978
|
const raw = expectString(value, "local time").trim();
|
|
1588
|
-
if (
|
|
2979
|
+
if (isValidLocalTimeString(raw)) {
|
|
1589
2980
|
return raw;
|
|
1590
2981
|
}
|
|
1591
2982
|
throw new Error("Expected a local-time value");
|
|
@@ -1595,7 +2986,7 @@ var normalizeOffsetTime = (value) => {
|
|
|
1595
2986
|
return `${formatLocalTime(value)}Z`;
|
|
1596
2987
|
}
|
|
1597
2988
|
const raw = expectString(value, "offset time").trim();
|
|
1598
|
-
if (
|
|
2989
|
+
if (isValidOffsetTimeString(raw)) {
|
|
1599
2990
|
return raw;
|
|
1600
2991
|
}
|
|
1601
2992
|
throw new Error("Expected an offset-time value");
|
|
@@ -1605,11 +2996,13 @@ var normalizeLocalDateTime = (value) => {
|
|
|
1605
2996
|
return formatLocalDateTime(value);
|
|
1606
2997
|
}
|
|
1607
2998
|
const raw = expectString(value, "local datetime").trim();
|
|
1608
|
-
|
|
1609
|
-
|
|
2999
|
+
const canonicalLocalDateTime = raw.replace(" ", "T");
|
|
3000
|
+
if (isValidLocalDateTimeString(canonicalLocalDateTime)) {
|
|
3001
|
+
return canonicalLocalDateTime;
|
|
1610
3002
|
}
|
|
1611
|
-
|
|
1612
|
-
|
|
3003
|
+
const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
|
|
3004
|
+
if (isValidInstantString(canonicalInstant)) {
|
|
3005
|
+
const parsed = new Date(canonicalInstant);
|
|
1613
3006
|
if (!Number.isNaN(parsed.getTime())) {
|
|
1614
3007
|
return formatLocalDateTime(parsed);
|
|
1615
3008
|
}
|
|
@@ -1624,7 +3017,11 @@ var normalizeInstant = (value) => {
|
|
|
1624
3017
|
if (!/[zZ]|[+-]\d{2}:\d{2}$/.test(raw)) {
|
|
1625
3018
|
throw new Error("Instant values require a timezone offset");
|
|
1626
3019
|
}
|
|
1627
|
-
const
|
|
3020
|
+
const canonicalInstant = raw.replace(" ", "T").replace(/z$/, "Z");
|
|
3021
|
+
if (!isValidInstantString(canonicalInstant)) {
|
|
3022
|
+
throw new Error("Expected an ISO instant value");
|
|
3023
|
+
}
|
|
3024
|
+
const parsed = new Date(canonicalInstant);
|
|
1628
3025
|
if (Number.isNaN(parsed.getTime())) {
|
|
1629
3026
|
throw new Error("Expected an ISO instant value");
|
|
1630
3027
|
}
|
|
@@ -1656,25 +3053,33 @@ var isJsonValue = (value) => {
|
|
|
1656
3053
|
}
|
|
1657
3054
|
switch (typeof value) {
|
|
1658
3055
|
case "string":
|
|
1659
|
-
case "number":
|
|
1660
3056
|
case "boolean":
|
|
1661
3057
|
return true;
|
|
3058
|
+
case "number":
|
|
3059
|
+
return Number.isFinite(value);
|
|
1662
3060
|
case "object":
|
|
1663
3061
|
if (Array.isArray(value)) {
|
|
1664
3062
|
return value.every(isJsonValue);
|
|
1665
3063
|
}
|
|
1666
|
-
return
|
|
3064
|
+
return isPlainRecord(value) && Object.values(value).every(isJsonValue);
|
|
1667
3065
|
default:
|
|
1668
3066
|
return false;
|
|
1669
3067
|
}
|
|
1670
3068
|
};
|
|
1671
3069
|
var normalizeJson = (value) => {
|
|
1672
3070
|
if (typeof value === "string") {
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
3071
|
+
try {
|
|
3072
|
+
const parsed = JSON.parse(value);
|
|
3073
|
+
if (isJsonValue(parsed)) {
|
|
3074
|
+
return parsed;
|
|
3075
|
+
}
|
|
3076
|
+
throw new Error("Parsed JSON value is not a valid JSON runtime");
|
|
3077
|
+
} catch (error) {
|
|
3078
|
+
if (error instanceof SyntaxError) {
|
|
3079
|
+
return value;
|
|
3080
|
+
}
|
|
3081
|
+
throw error;
|
|
1676
3082
|
}
|
|
1677
|
-
throw new Error("Parsed JSON value is not a valid JSON runtime");
|
|
1678
3083
|
}
|
|
1679
3084
|
if (isJsonValue(value)) {
|
|
1680
3085
|
return value;
|
|
@@ -1809,22 +3214,61 @@ var findMapping = (context, key2) => {
|
|
|
1809
3214
|
}
|
|
1810
3215
|
return;
|
|
1811
3216
|
};
|
|
3217
|
+
var isJsonDbType = (dbType) => {
|
|
3218
|
+
if (dbType === undefined) {
|
|
3219
|
+
return false;
|
|
3220
|
+
}
|
|
3221
|
+
if ("base" in dbType) {
|
|
3222
|
+
return isJsonDbType(dbType.base);
|
|
3223
|
+
}
|
|
3224
|
+
if (!("variant" in dbType)) {
|
|
3225
|
+
return false;
|
|
3226
|
+
}
|
|
3227
|
+
const variant = dbType.variant;
|
|
3228
|
+
return variant === "json" || variant === "jsonb";
|
|
3229
|
+
};
|
|
3230
|
+
var schemaAccepts = (schema2, value) => schema2 !== undefined && Schema4.is(schema2)(value);
|
|
1812
3231
|
var encodeWithSchema = (schema2, value) => {
|
|
1813
3232
|
if (schema2 === undefined) {
|
|
1814
3233
|
return { value, encoded: false };
|
|
1815
3234
|
}
|
|
1816
|
-
if (!
|
|
3235
|
+
if (!Schema4.is(schema2)(value)) {
|
|
1817
3236
|
return { value, encoded: false };
|
|
1818
3237
|
}
|
|
1819
3238
|
return {
|
|
1820
|
-
value:
|
|
3239
|
+
value: Schema4.encodeUnknownSync(schema2)(value),
|
|
1821
3240
|
encoded: true
|
|
1822
3241
|
};
|
|
1823
3242
|
};
|
|
3243
|
+
var normalizeJsonDriverString = (value, context) => {
|
|
3244
|
+
if (!isJsonDbType(context.dbType) || context.runtimeSchema === undefined) {
|
|
3245
|
+
return;
|
|
3246
|
+
}
|
|
3247
|
+
try {
|
|
3248
|
+
const parsed = JSON.parse(value);
|
|
3249
|
+
if (value.trimStart().startsWith('"') && schemaAccepts(context.runtimeSchema, parsed)) {
|
|
3250
|
+
return parsed;
|
|
3251
|
+
}
|
|
3252
|
+
if (schemaAccepts(context.runtimeSchema, value) && !schemaAccepts(context.runtimeSchema, parsed)) {
|
|
3253
|
+
return value;
|
|
3254
|
+
}
|
|
3255
|
+
} catch (error) {
|
|
3256
|
+
if (error instanceof SyntaxError && schemaAccepts(context.runtimeSchema, value)) {
|
|
3257
|
+
return value;
|
|
3258
|
+
}
|
|
3259
|
+
if (!(error instanceof SyntaxError)) {
|
|
3260
|
+
throw error;
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
return;
|
|
3264
|
+
};
|
|
1824
3265
|
var toDriverValue = (value, context) => {
|
|
1825
3266
|
if (value === null) {
|
|
1826
3267
|
return null;
|
|
1827
3268
|
}
|
|
3269
|
+
if (value instanceof Date && Number.isNaN(value.getTime())) {
|
|
3270
|
+
throw new Error("Expected a valid Date value");
|
|
3271
|
+
}
|
|
1828
3272
|
const dbType = context.dbType;
|
|
1829
3273
|
const encoded = encodeWithSchema(context.runtimeSchema, value);
|
|
1830
3274
|
let current = encoded.value;
|
|
@@ -1832,6 +3276,9 @@ var toDriverValue = (value, context) => {
|
|
|
1832
3276
|
if (custom !== undefined && dbType !== undefined) {
|
|
1833
3277
|
return custom(current, dbType);
|
|
1834
3278
|
}
|
|
3279
|
+
if (encoded.encoded && typeof current === "string" && isJsonDbType(dbType)) {
|
|
3280
|
+
return current;
|
|
3281
|
+
}
|
|
1835
3282
|
return dbType === undefined || !encoded.encoded ? current : normalizeDbValue(dbType, current);
|
|
1836
3283
|
};
|
|
1837
3284
|
var fromDriverValue = (value, context) => {
|
|
@@ -1843,6 +3290,12 @@ var fromDriverValue = (value, context) => {
|
|
|
1843
3290
|
if (custom !== undefined && dbType !== undefined) {
|
|
1844
3291
|
return custom(value, dbType);
|
|
1845
3292
|
}
|
|
3293
|
+
if (typeof value === "string") {
|
|
3294
|
+
const normalizedJsonString = normalizeJsonDriverString(value, context);
|
|
3295
|
+
if (normalizedJsonString !== undefined) {
|
|
3296
|
+
return normalizedJsonString;
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
1846
3299
|
return dbType === undefined ? value : normalizeDbValue(dbType, value);
|
|
1847
3300
|
};
|
|
1848
3301
|
var textCast = (sql) => `(${sql})::text`;
|
|
@@ -1930,6 +3383,20 @@ var validateProjections = (projections) => {
|
|
|
1930
3383
|
};
|
|
1931
3384
|
|
|
1932
3385
|
// src/internal/grouping-key.ts
|
|
3386
|
+
var subqueryPlanIds = new WeakMap;
|
|
3387
|
+
var nextSubqueryPlanId = 0;
|
|
3388
|
+
var subqueryPlanGroupingKey = (plan) => {
|
|
3389
|
+
if (plan === null || typeof plan !== "object") {
|
|
3390
|
+
return "unknown";
|
|
3391
|
+
}
|
|
3392
|
+
const existing = subqueryPlanIds.get(plan);
|
|
3393
|
+
if (existing !== undefined) {
|
|
3394
|
+
return existing;
|
|
3395
|
+
}
|
|
3396
|
+
const next = `${nextSubqueryPlanId++}`;
|
|
3397
|
+
subqueryPlanIds.set(plan, next);
|
|
3398
|
+
return next;
|
|
3399
|
+
};
|
|
1933
3400
|
var literalGroupingKey = (value) => {
|
|
1934
3401
|
if (value instanceof Date) {
|
|
1935
3402
|
return `date:${value.toISOString()}`;
|
|
@@ -1948,15 +3415,62 @@ var literalGroupingKey = (value) => {
|
|
|
1948
3415
|
return `literal:${JSON.stringify(value)}`;
|
|
1949
3416
|
}
|
|
1950
3417
|
};
|
|
3418
|
+
var isExpression2 = (value) => value !== null && typeof value === "object" && (TypeId2 in value);
|
|
3419
|
+
var expressionGroupingKey = (value) => isExpression2(value) ? groupingKeyOfExpression(value) : "missing";
|
|
3420
|
+
var escapeGroupingText = (value) => value.replace(/\\/g, "\\\\").replace(/,/g, "\\,").replace(/\|/g, "\\|").replace(/=/g, "\\=").replace(/>/g, "\\>");
|
|
3421
|
+
var jsonSegmentGroupingKey = (segment) => {
|
|
3422
|
+
if (segment !== null && typeof segment === "object" && "kind" in segment) {
|
|
3423
|
+
switch (segment.kind) {
|
|
3424
|
+
case "key":
|
|
3425
|
+
return `key:${escapeGroupingText(segment.key)}`;
|
|
3426
|
+
case "index":
|
|
3427
|
+
return `index:${segment.index}`;
|
|
3428
|
+
case "wildcard":
|
|
3429
|
+
return "wildcard";
|
|
3430
|
+
case "slice": {
|
|
3431
|
+
const slice2 = segment;
|
|
3432
|
+
return `slice:${slice2.start ?? ""}:${slice2.end ?? ""}`;
|
|
3433
|
+
}
|
|
3434
|
+
case "descend":
|
|
3435
|
+
return "descend";
|
|
3436
|
+
}
|
|
3437
|
+
}
|
|
3438
|
+
if (typeof segment === "string") {
|
|
3439
|
+
return `key:${escapeGroupingText(segment)}`;
|
|
3440
|
+
}
|
|
3441
|
+
if (typeof segment === "number") {
|
|
3442
|
+
return `index:${segment}`;
|
|
3443
|
+
}
|
|
3444
|
+
return "unknown";
|
|
3445
|
+
};
|
|
3446
|
+
var jsonPathGroupingKey = (segments) => (segments ?? []).map(jsonSegmentGroupingKey).join(",");
|
|
3447
|
+
var isJsonPath = (value) => value !== null && typeof value === "object" && (TypeId7 in value);
|
|
3448
|
+
var jsonOpaquePathGroupingKey = (value) => {
|
|
3449
|
+
if (isJsonPath(value)) {
|
|
3450
|
+
return `jsonpath:${jsonPathGroupingKey(value.segments)}`;
|
|
3451
|
+
}
|
|
3452
|
+
if (typeof value === "string") {
|
|
3453
|
+
return `jsonpath:${escapeGroupingText(value)}`;
|
|
3454
|
+
}
|
|
3455
|
+
if (isExpression2(value)) {
|
|
3456
|
+
return `jsonpath:${groupingKeyOfExpression(value)}`;
|
|
3457
|
+
}
|
|
3458
|
+
return "jsonpath:unknown";
|
|
3459
|
+
};
|
|
3460
|
+
var jsonEntryGroupingKey = (entry) => `${escapeGroupingText(entry.key)}=>${groupingKeyOfExpression(entry.value)}`;
|
|
1951
3461
|
var groupingKeyOfExpression = (expression) => {
|
|
1952
3462
|
const ast = expression[TypeId3];
|
|
1953
3463
|
switch (ast.kind) {
|
|
1954
3464
|
case "column":
|
|
1955
|
-
return `column:${ast.tableName
|
|
3465
|
+
return `column:${columnPredicateKey(ast.tableName, ast.columnName)}`;
|
|
1956
3466
|
case "literal":
|
|
1957
3467
|
return `literal:${literalGroupingKey(ast.value)}`;
|
|
1958
3468
|
case "cast":
|
|
1959
3469
|
return `cast(${groupingKeyOfExpression(ast.value)} as ${ast.target.dialect}:${ast.target.kind})`;
|
|
3470
|
+
case "collate":
|
|
3471
|
+
return `collate(${groupingKeyOfExpression(ast.value)},${ast.collation.map(escapeGroupingText).join(",")})`;
|
|
3472
|
+
case "function":
|
|
3473
|
+
return `function(${escapeGroupingText(ast.name)},${ast.args.map(groupingKeyOfExpression).join(",")})`;
|
|
1960
3474
|
case "isNull":
|
|
1961
3475
|
case "isNotNull":
|
|
1962
3476
|
case "not":
|
|
@@ -1974,8 +3488,15 @@ var groupingKeyOfExpression = (expression) => {
|
|
|
1974
3488
|
case "gte":
|
|
1975
3489
|
case "like":
|
|
1976
3490
|
case "ilike":
|
|
3491
|
+
case "regexMatch":
|
|
3492
|
+
case "regexIMatch":
|
|
3493
|
+
case "regexNotMatch":
|
|
3494
|
+
case "regexNotIMatch":
|
|
1977
3495
|
case "isDistinctFrom":
|
|
1978
3496
|
case "isNotDistinctFrom":
|
|
3497
|
+
case "contains":
|
|
3498
|
+
case "containedBy":
|
|
3499
|
+
case "overlaps":
|
|
1979
3500
|
return `${ast.kind}(${groupingKeyOfExpression(ast.left)},${groupingKeyOfExpression(ast.right)})`;
|
|
1980
3501
|
case "and":
|
|
1981
3502
|
case "or":
|
|
@@ -1987,6 +3508,54 @@ var groupingKeyOfExpression = (expression) => {
|
|
|
1987
3508
|
return `${ast.kind}(${ast.values.map(groupingKeyOfExpression).join(",")})`;
|
|
1988
3509
|
case "case":
|
|
1989
3510
|
return `case(${ast.branches.map((branch) => `when:${groupingKeyOfExpression(branch.when)}=>${groupingKeyOfExpression(branch.then)}`).join("|")};else:${groupingKeyOfExpression(ast.else)})`;
|
|
3511
|
+
case "exists":
|
|
3512
|
+
return `exists(${subqueryPlanGroupingKey(ast.plan)})`;
|
|
3513
|
+
case "scalarSubquery":
|
|
3514
|
+
return `scalarSubquery(${subqueryPlanGroupingKey(ast.plan)})`;
|
|
3515
|
+
case "inSubquery":
|
|
3516
|
+
return `inSubquery(${groupingKeyOfExpression(ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
|
|
3517
|
+
case "comparisonAny":
|
|
3518
|
+
case "comparisonAll":
|
|
3519
|
+
return `${ast.kind}(${ast.operator},${groupingKeyOfExpression(ast.left)},${subqueryPlanGroupingKey(ast.plan)})`;
|
|
3520
|
+
case "jsonGet":
|
|
3521
|
+
case "jsonPath":
|
|
3522
|
+
case "jsonAccess":
|
|
3523
|
+
case "jsonTraverse":
|
|
3524
|
+
case "jsonGetText":
|
|
3525
|
+
case "jsonPathText":
|
|
3526
|
+
case "jsonAccessText":
|
|
3527
|
+
case "jsonTraverseText":
|
|
3528
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.base)},${jsonPathGroupingKey(ast.segments)})`;
|
|
3529
|
+
case "jsonHasKey":
|
|
3530
|
+
case "jsonKeyExists":
|
|
3531
|
+
case "jsonHasAnyKeys":
|
|
3532
|
+
case "jsonHasAllKeys":
|
|
3533
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.base)},${(ast.keys ?? []).map(escapeGroupingText).join(",")})`;
|
|
3534
|
+
case "jsonConcat":
|
|
3535
|
+
case "jsonMerge":
|
|
3536
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.left)},${expressionGroupingKey(ast.right)},)`;
|
|
3537
|
+
case "jsonDelete":
|
|
3538
|
+
case "jsonDeletePath":
|
|
3539
|
+
case "jsonRemove":
|
|
3540
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(undefined)},${jsonPathGroupingKey(ast.segments)})`;
|
|
3541
|
+
case "jsonSet":
|
|
3542
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(ast.newValue)},${jsonPathGroupingKey(ast.segments)})`;
|
|
3543
|
+
case "jsonInsert":
|
|
3544
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.base)},${expressionGroupingKey(ast.insert)},${jsonPathGroupingKey(ast.segments)})`;
|
|
3545
|
+
case "jsonPathExists":
|
|
3546
|
+
case "jsonPathMatch":
|
|
3547
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.base)},${jsonOpaquePathGroupingKey(ast.query)})`;
|
|
3548
|
+
case "jsonBuildObject":
|
|
3549
|
+
return `json(${ast.kind},${(ast.entries ?? []).map(jsonEntryGroupingKey).join("|")})`;
|
|
3550
|
+
case "jsonBuildArray":
|
|
3551
|
+
return `json(${ast.kind},${(ast.values ?? []).map(groupingKeyOfExpression).join(",")})`;
|
|
3552
|
+
case "jsonToJson":
|
|
3553
|
+
case "jsonToJsonb":
|
|
3554
|
+
case "jsonTypeOf":
|
|
3555
|
+
case "jsonLength":
|
|
3556
|
+
case "jsonKeys":
|
|
3557
|
+
case "jsonStripNulls":
|
|
3558
|
+
return `json(${ast.kind},${expressionGroupingKey(ast.value)})`;
|
|
1990
3559
|
default:
|
|
1991
3560
|
throw new Error("Unsupported expression for grouping key generation");
|
|
1992
3561
|
}
|
|
@@ -2004,15 +3573,15 @@ var dedupeGroupedExpressions = (values) => {
|
|
|
2004
3573
|
};
|
|
2005
3574
|
|
|
2006
3575
|
// src/internal/aggregation-validation.ts
|
|
2007
|
-
var
|
|
3576
|
+
var isExpression3 = (value) => typeof value === "object" && value !== null && (TypeId2 in value);
|
|
2008
3577
|
var selectionHasAggregate = (selection) => {
|
|
2009
|
-
if (
|
|
3578
|
+
if (isExpression3(selection)) {
|
|
2010
3579
|
return selection[TypeId2].kind === "aggregate";
|
|
2011
3580
|
}
|
|
2012
3581
|
return Object.values(selection).some((value) => selectionHasAggregate(value));
|
|
2013
3582
|
};
|
|
2014
3583
|
var isGroupedSelectionValid = (selection, groupedExpressions) => {
|
|
2015
|
-
if (
|
|
3584
|
+
if (isExpression3(selection)) {
|
|
2016
3585
|
const aggregation = selection[TypeId2].kind;
|
|
2017
3586
|
if (aggregation === "aggregate") {
|
|
2018
3587
|
return true;
|
|
@@ -2065,7 +3634,46 @@ var renderCastType = (dialect, dbType) => {
|
|
|
2065
3634
|
return dbType.kind;
|
|
2066
3635
|
}
|
|
2067
3636
|
};
|
|
2068
|
-
var
|
|
3637
|
+
var renderPostgresDdlString = (value) => `'${value.replaceAll("'", "''")}'`;
|
|
3638
|
+
var renderPostgresDdlBytes = (value) => `decode('${Array.from(value, (byte) => byte.toString(16).padStart(2, "0")).join("")}', 'hex')`;
|
|
3639
|
+
var renderPostgresDdlLiteral = (value, state, context = {}) => {
|
|
3640
|
+
const driverValue = toDriverValue(value, {
|
|
3641
|
+
dialect: "postgres",
|
|
3642
|
+
valueMappings: state.valueMappings,
|
|
3643
|
+
...context
|
|
3644
|
+
});
|
|
3645
|
+
if (driverValue === null) {
|
|
3646
|
+
return "null";
|
|
3647
|
+
}
|
|
3648
|
+
switch (typeof driverValue) {
|
|
3649
|
+
case "boolean":
|
|
3650
|
+
return driverValue ? "true" : "false";
|
|
3651
|
+
case "number":
|
|
3652
|
+
if (!Number.isFinite(driverValue)) {
|
|
3653
|
+
throw new Error("Expected a finite numeric value");
|
|
3654
|
+
}
|
|
3655
|
+
return String(driverValue);
|
|
3656
|
+
case "bigint":
|
|
3657
|
+
return driverValue.toString();
|
|
3658
|
+
case "string":
|
|
3659
|
+
return renderPostgresDdlString(driverValue);
|
|
3660
|
+
case "object":
|
|
3661
|
+
if (driverValue instanceof Uint8Array) {
|
|
3662
|
+
return renderPostgresDdlBytes(driverValue);
|
|
3663
|
+
}
|
|
3664
|
+
break;
|
|
3665
|
+
}
|
|
3666
|
+
throw new Error("Unsupported postgres DDL literal value");
|
|
3667
|
+
};
|
|
3668
|
+
var renderDdlExpression = (expression, state, dialect) => {
|
|
3669
|
+
if (isSchemaExpression(expression)) {
|
|
3670
|
+
return render(expression);
|
|
3671
|
+
}
|
|
3672
|
+
return renderExpression(expression, state, {
|
|
3673
|
+
...dialect,
|
|
3674
|
+
renderLiteral: renderPostgresDdlLiteral
|
|
3675
|
+
});
|
|
3676
|
+
};
|
|
2069
3677
|
var renderColumnDefinition = (dialect, state, columnName, column) => {
|
|
2070
3678
|
const clauses = [
|
|
2071
3679
|
dialect.quoteIdentifier(columnName),
|
|
@@ -2097,14 +3705,16 @@ var renderCreateTableSql = (targetSource, state, dialect, ifNotExists) => {
|
|
|
2097
3705
|
break;
|
|
2098
3706
|
case "foreignKey": {
|
|
2099
3707
|
const reference = option2.references();
|
|
2100
|
-
definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(option2.name)} ` : ""}foreign key (${option2.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")}) references ${dialect.renderTableReference(reference.tableName, reference.tableName, reference.schemaName)} (${reference.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${option2.onDelete ? ` on delete ${option2.onDelete
|
|
3708
|
+
definitions.push(`${option2.name ? `constraint ${dialect.quoteIdentifier(option2.name)} ` : ""}foreign key (${option2.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")}) references ${dialect.renderTableReference(reference.tableName, reference.tableName, reference.schemaName)} (${reference.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${option2.onDelete !== undefined ? ` on delete ${renderReferentialAction(option2.onDelete)}` : ""}${option2.onUpdate !== undefined ? ` on update ${renderReferentialAction(option2.onUpdate)}` : ""}${option2.deferrable ? ` deferrable${option2.initiallyDeferred ? " initially deferred" : ""}` : ""}`);
|
|
2101
3709
|
break;
|
|
2102
3710
|
}
|
|
2103
3711
|
case "check":
|
|
2104
|
-
definitions.push(`constraint ${dialect.quoteIdentifier(option2.name)} check (${renderDdlExpression(option2.predicate, state, dialect)})${option2.noInherit ? " no inherit" : ""}`);
|
|
3712
|
+
definitions.push(`constraint ${dialect.quoteIdentifier(option2.name)} check (${renderDdlExpression(option2.predicate, { ...state, rowLocalColumns: true }, dialect)})${option2.noInherit ? " no inherit" : ""}`);
|
|
2105
3713
|
break;
|
|
2106
3714
|
case "index":
|
|
2107
3715
|
break;
|
|
3716
|
+
default:
|
|
3717
|
+
throw new Error("Unsupported table option kind");
|
|
2108
3718
|
}
|
|
2109
3719
|
}
|
|
2110
3720
|
return `create table${ifNotExists ? " if not exists" : ""} ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${definitions.join(", ")})`;
|
|
@@ -2113,10 +3723,56 @@ var renderCreateIndexSql = (targetSource, ddl, state, dialect) => {
|
|
|
2113
3723
|
const maybeIfNotExists = dialect.name === "postgres" && ddl.ifNotExists ? " if not exists" : "";
|
|
2114
3724
|
return `create${ddl.unique ? " unique" : ""} index${maybeIfNotExists} ${dialect.quoteIdentifier(ddl.name)} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} (${ddl.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})`;
|
|
2115
3725
|
};
|
|
2116
|
-
var renderDropIndexSql = (targetSource, ddl, state, dialect) =>
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
3726
|
+
var renderDropIndexSql = (targetSource, ddl, state, dialect) => {
|
|
3727
|
+
if (dialect.name === "postgres") {
|
|
3728
|
+
const schemaName = typeof targetSource.source === "object" && targetSource.source !== null && TypeId4 in targetSource.source ? targetSource.source[TypeId4].schemaName : undefined;
|
|
3729
|
+
const indexName = schemaName === undefined || schemaName === "public" ? dialect.quoteIdentifier(ddl.name) : `${dialect.quoteIdentifier(schemaName)}.${dialect.quoteIdentifier(ddl.name)}`;
|
|
3730
|
+
return `drop index${ddl.ifExists ? " if exists" : ""} ${indexName}`;
|
|
3731
|
+
}
|
|
3732
|
+
return `drop index ${dialect.quoteIdentifier(ddl.name)} on ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
|
|
3733
|
+
};
|
|
3734
|
+
var isExpression4 = (value) => value !== null && typeof value === "object" && (TypeId2 in value);
|
|
3735
|
+
var isJsonDbType2 = (dbType) => {
|
|
3736
|
+
if (dbType.kind === "jsonb" || dbType.kind === "json") {
|
|
3737
|
+
return true;
|
|
3738
|
+
}
|
|
3739
|
+
if (!("variant" in dbType)) {
|
|
3740
|
+
return false;
|
|
3741
|
+
}
|
|
3742
|
+
const variant = dbType.variant;
|
|
3743
|
+
return variant === "json" || variant === "jsonb";
|
|
3744
|
+
};
|
|
3745
|
+
var isJsonExpression = (value) => isExpression4(value) && isJsonDbType2(value[TypeId2].dbType);
|
|
3746
|
+
var postgresRangeSubtypeByKind = {
|
|
3747
|
+
int4range: "int4",
|
|
3748
|
+
int8range: "int8",
|
|
3749
|
+
numrange: "numeric",
|
|
3750
|
+
tsrange: "timestamp",
|
|
3751
|
+
tstzrange: "timestamptz",
|
|
3752
|
+
daterange: "date",
|
|
3753
|
+
int4multirange: "int4",
|
|
3754
|
+
int8multirange: "int8",
|
|
3755
|
+
nummultirange: "numeric",
|
|
3756
|
+
tsmultirange: "timestamp",
|
|
3757
|
+
tstzmultirange: "timestamptz",
|
|
3758
|
+
datemultirange: "date"
|
|
3759
|
+
};
|
|
3760
|
+
var postgresRangeSubtypeKey = (dbType) => {
|
|
3761
|
+
if ("base" in dbType) {
|
|
3762
|
+
return postgresRangeSubtypeKey(dbType.base);
|
|
3763
|
+
}
|
|
3764
|
+
if ("subtype" in dbType) {
|
|
3765
|
+
return postgresRangeSubtypeKey(dbType.subtype) ?? dbType.subtype.kind;
|
|
3766
|
+
}
|
|
3767
|
+
return postgresRangeSubtypeByKind[dbType.kind];
|
|
3768
|
+
};
|
|
3769
|
+
var assertCompatiblePostgresRangeOperands = (left, right) => {
|
|
3770
|
+
const leftKey = postgresRangeSubtypeKey(left[TypeId2].dbType);
|
|
3771
|
+
const rightKey = postgresRangeSubtypeKey(right[TypeId2].dbType);
|
|
3772
|
+
if (leftKey !== undefined && rightKey !== undefined && leftKey !== rightKey) {
|
|
3773
|
+
throw new Error("Incompatible postgres range operands");
|
|
3774
|
+
}
|
|
3775
|
+
};
|
|
2120
3776
|
var unsupportedJsonFeature = (dialect, feature) => {
|
|
2121
3777
|
const error = new Error(`Unsupported JSON feature for ${dialect.name}: ${feature}`);
|
|
2122
3778
|
Object.assign(error, {
|
|
@@ -2159,15 +3815,16 @@ var extractJsonPathSegments = (node) => {
|
|
|
2159
3815
|
};
|
|
2160
3816
|
var extractJsonValue = (node) => node.newValue ?? node.insert ?? node.right;
|
|
2161
3817
|
var renderJsonPathSegment = (segment) => {
|
|
3818
|
+
const renderKey = (value) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(value) ? `.${value}` : `.${JSON.stringify(value)}`;
|
|
2162
3819
|
if (typeof segment === "string") {
|
|
2163
|
-
return
|
|
3820
|
+
return renderKey(segment);
|
|
2164
3821
|
}
|
|
2165
3822
|
if (typeof segment === "number") {
|
|
2166
3823
|
return `[${segment}]`;
|
|
2167
3824
|
}
|
|
2168
3825
|
switch (segment.kind) {
|
|
2169
3826
|
case "key":
|
|
2170
|
-
return
|
|
3827
|
+
return renderKey(segment.key);
|
|
2171
3828
|
case "index":
|
|
2172
3829
|
return `[${segment.index}]`;
|
|
2173
3830
|
case "wildcard":
|
|
@@ -2210,13 +3867,13 @@ var renderPostgresJsonAccessStep = (segment, textMode, state, dialect) => {
|
|
|
2210
3867
|
case "key":
|
|
2211
3868
|
return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(segment.key, state)}`;
|
|
2212
3869
|
case "index":
|
|
2213
|
-
return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(
|
|
3870
|
+
return `${textMode ? "->>" : "->"} ${dialect.renderLiteral(segment.index, state)}`;
|
|
2214
3871
|
default:
|
|
2215
3872
|
throw new Error("Postgres exact JSON access requires key/index segments");
|
|
2216
3873
|
}
|
|
2217
3874
|
};
|
|
2218
3875
|
var renderPostgresJsonValue = (value, state, dialect) => {
|
|
2219
|
-
if (!
|
|
3876
|
+
if (!isExpression4(value)) {
|
|
2220
3877
|
throw new Error("Expected a JSON expression");
|
|
2221
3878
|
}
|
|
2222
3879
|
const rendered = renderExpression(value, state, dialect);
|
|
@@ -2234,13 +3891,21 @@ var expressionDriverContext = (expression, state, dialect) => ({
|
|
|
2234
3891
|
driverValueMapping: expression[TypeId2].driverValueMapping
|
|
2235
3892
|
});
|
|
2236
3893
|
var renderJsonInputExpression = (expression, state, dialect) => renderJsonSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect));
|
|
2237
|
-
var encodeArrayValues = (values, column, state, dialect) => values.map((value) =>
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
3894
|
+
var encodeArrayValues = (values, column, state, dialect) => values.map((value) => {
|
|
3895
|
+
if (value === null && column.metadata.nullable) {
|
|
3896
|
+
return null;
|
|
3897
|
+
}
|
|
3898
|
+
const runtimeSchemaAccepts = column.schema !== undefined && Schema5.is(column.schema)(value);
|
|
3899
|
+
const normalizedValue = runtimeSchemaAccepts ? value : normalizeDbValue(column.metadata.dbType, value);
|
|
3900
|
+
const encodedValue = column.schema === undefined || runtimeSchemaAccepts ? normalizedValue : Schema5.decodeUnknownSync(column.schema)(normalizedValue);
|
|
3901
|
+
return toDriverValue(encodedValue, {
|
|
3902
|
+
dialect: dialect.name,
|
|
3903
|
+
valueMappings: state.valueMappings,
|
|
3904
|
+
dbType: column.metadata.dbType,
|
|
3905
|
+
runtimeSchema: column.schema,
|
|
3906
|
+
driverValueMapping: column.metadata.driverValueMapping
|
|
3907
|
+
});
|
|
3908
|
+
});
|
|
2244
3909
|
var renderPostgresJsonKind = (value) => value[TypeId2].dbType.kind === "jsonb" ? "jsonb" : "json";
|
|
2245
3910
|
var renderJsonOpaquePath = (value, state, dialect) => {
|
|
2246
3911
|
if (isJsonPathValue(value)) {
|
|
@@ -2249,7 +3914,7 @@ var renderJsonOpaquePath = (value, state, dialect) => {
|
|
|
2249
3914
|
if (typeof value === "string") {
|
|
2250
3915
|
return dialect.renderLiteral(value, state);
|
|
2251
3916
|
}
|
|
2252
|
-
if (
|
|
3917
|
+
if (isExpression4(value)) {
|
|
2253
3918
|
return renderExpression(value, state, dialect);
|
|
2254
3919
|
}
|
|
2255
3920
|
throw new Error("Unsupported SQL/JSON path input");
|
|
@@ -2267,7 +3932,7 @@ var renderFunctionCall = (name, args, state, dialect) => {
|
|
|
2267
3932
|
if (source === undefined) {
|
|
2268
3933
|
throw new Error("Unsupported SQL extract expression");
|
|
2269
3934
|
}
|
|
2270
|
-
const fieldRuntime =
|
|
3935
|
+
const fieldRuntime = isExpression4(field) && field[TypeId2].dbType.kind === "text" && typeof field[TypeId2].runtime === "string" ? field[TypeId2].runtime : undefined;
|
|
2271
3936
|
const renderedField = fieldRuntime ?? renderExpression(field, state, dialect);
|
|
2272
3937
|
return `extract(${renderedField} from ${renderExpression(source, state, dialect)})`;
|
|
2273
3938
|
}
|
|
@@ -2305,7 +3970,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
2305
3970
|
case "jsonPathText":
|
|
2306
3971
|
case "jsonAccessText":
|
|
2307
3972
|
case "jsonTraverseText": {
|
|
2308
|
-
if (!
|
|
3973
|
+
if (!isExpression4(base) || segments.length === 0) {
|
|
2309
3974
|
return;
|
|
2310
3975
|
}
|
|
2311
3976
|
const baseSql = renderExpression(base, state, dialect);
|
|
@@ -2328,7 +3993,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
2328
3993
|
case "jsonKeyExists":
|
|
2329
3994
|
case "jsonHasAnyKeys":
|
|
2330
3995
|
case "jsonHasAllKeys": {
|
|
2331
|
-
if (!
|
|
3996
|
+
if (!isExpression4(base)) {
|
|
2332
3997
|
return;
|
|
2333
3998
|
}
|
|
2334
3999
|
const baseSql = dialect.name === "postgres" ? renderPostgresJsonValue(base, state, dialect) : renderExpression(base, state, dialect);
|
|
@@ -2354,7 +4019,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
2354
4019
|
}
|
|
2355
4020
|
case "jsonConcat":
|
|
2356
4021
|
case "jsonMerge": {
|
|
2357
|
-
if (!
|
|
4022
|
+
if (!isExpression4(ast.left) || !isExpression4(ast.right)) {
|
|
2358
4023
|
return;
|
|
2359
4024
|
}
|
|
2360
4025
|
if (dialect.name === "postgres") {
|
|
@@ -2391,7 +4056,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
2391
4056
|
return;
|
|
2392
4057
|
}
|
|
2393
4058
|
case "jsonToJson":
|
|
2394
|
-
if (!
|
|
4059
|
+
if (!isExpression4(base)) {
|
|
2395
4060
|
return;
|
|
2396
4061
|
}
|
|
2397
4062
|
if (dialect.name === "postgres") {
|
|
@@ -2402,7 +4067,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
2402
4067
|
}
|
|
2403
4068
|
return;
|
|
2404
4069
|
case "jsonToJsonb":
|
|
2405
|
-
if (!
|
|
4070
|
+
if (!isExpression4(base)) {
|
|
2406
4071
|
return;
|
|
2407
4072
|
}
|
|
2408
4073
|
if (dialect.name === "postgres") {
|
|
@@ -2413,7 +4078,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
2413
4078
|
}
|
|
2414
4079
|
return;
|
|
2415
4080
|
case "jsonTypeOf":
|
|
2416
|
-
if (!
|
|
4081
|
+
if (!isExpression4(base)) {
|
|
2417
4082
|
return;
|
|
2418
4083
|
}
|
|
2419
4084
|
if (dialect.name === "postgres") {
|
|
@@ -2425,7 +4090,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
2425
4090
|
}
|
|
2426
4091
|
return;
|
|
2427
4092
|
case "jsonLength":
|
|
2428
|
-
if (!
|
|
4093
|
+
if (!isExpression4(base)) {
|
|
2429
4094
|
return;
|
|
2430
4095
|
}
|
|
2431
4096
|
if (dialect.name === "postgres") {
|
|
@@ -2440,21 +4105,21 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
2440
4105
|
}
|
|
2441
4106
|
return;
|
|
2442
4107
|
case "jsonKeys":
|
|
2443
|
-
if (!
|
|
4108
|
+
if (!isExpression4(base)) {
|
|
2444
4109
|
return;
|
|
2445
4110
|
}
|
|
2446
4111
|
if (dialect.name === "postgres") {
|
|
2447
4112
|
const baseSql = renderExpression(base, state, dialect);
|
|
2448
4113
|
const typeOf = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_typeof`;
|
|
2449
4114
|
const objectKeys = `${postgresBaseKind === "jsonb" ? "jsonb" : "json"}_object_keys`;
|
|
2450
|
-
return `(case when ${typeOf}(${baseSql}) = 'object' then array(select ${objectKeys}(${baseSql})) else null end)`;
|
|
4115
|
+
return `(case when ${typeOf}(${baseSql}) = 'object' then to_json(array(select ${objectKeys}(${baseSql}))) else null end)`;
|
|
2451
4116
|
}
|
|
2452
4117
|
if (dialect.name === "mysql") {
|
|
2453
4118
|
return `json_keys(${renderExpression(base, state, dialect)})`;
|
|
2454
4119
|
}
|
|
2455
4120
|
return;
|
|
2456
4121
|
case "jsonStripNulls":
|
|
2457
|
-
if (!
|
|
4122
|
+
if (!isExpression4(base)) {
|
|
2458
4123
|
return;
|
|
2459
4124
|
}
|
|
2460
4125
|
if (dialect.name === "postgres") {
|
|
@@ -2465,14 +4130,14 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
2465
4130
|
case "jsonDelete":
|
|
2466
4131
|
case "jsonDeletePath":
|
|
2467
4132
|
case "jsonRemove": {
|
|
2468
|
-
if (!
|
|
4133
|
+
if (!isExpression4(base) || segments.length === 0) {
|
|
2469
4134
|
return;
|
|
2470
4135
|
}
|
|
2471
4136
|
if (dialect.name === "postgres") {
|
|
2472
4137
|
const baseSql = renderPostgresJsonValue(base, state, dialect);
|
|
2473
4138
|
if (segments.length === 1 && (segments[0].kind === "key" || segments[0].kind === "index")) {
|
|
2474
4139
|
const segment = segments[0];
|
|
2475
|
-
return `(${baseSql} - ${segment.kind === "key" ? dialect.renderLiteral(segment.key, state) : dialect.renderLiteral(
|
|
4140
|
+
return `(${baseSql} - ${segment.kind === "key" ? dialect.renderLiteral(segment.key, state) : dialect.renderLiteral(segment.index, state)})`;
|
|
2476
4141
|
}
|
|
2477
4142
|
return `(${baseSql} #- ${renderPostgresJsonPathArray(segments, state, dialect)})`;
|
|
2478
4143
|
}
|
|
@@ -2483,11 +4148,11 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
2483
4148
|
}
|
|
2484
4149
|
case "jsonSet":
|
|
2485
4150
|
case "jsonInsert": {
|
|
2486
|
-
if (!
|
|
4151
|
+
if (!isExpression4(base) || segments.length === 0) {
|
|
2487
4152
|
return;
|
|
2488
4153
|
}
|
|
2489
4154
|
const nextValue = extractJsonValue(ast);
|
|
2490
|
-
if (!
|
|
4155
|
+
if (!isExpression4(nextValue)) {
|
|
2491
4156
|
return;
|
|
2492
4157
|
}
|
|
2493
4158
|
const createMissing = ast.createMissing === true;
|
|
@@ -2504,7 +4169,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
2504
4169
|
return;
|
|
2505
4170
|
}
|
|
2506
4171
|
case "jsonPathExists": {
|
|
2507
|
-
if (!
|
|
4172
|
+
if (!isExpression4(base)) {
|
|
2508
4173
|
return;
|
|
2509
4174
|
}
|
|
2510
4175
|
const path2 = ast.path ?? ast.query ?? ast.right;
|
|
@@ -2520,7 +4185,7 @@ var renderJsonExpression = (expression, ast, state, dialect) => {
|
|
|
2520
4185
|
return;
|
|
2521
4186
|
}
|
|
2522
4187
|
case "jsonPathMatch": {
|
|
2523
|
-
if (!
|
|
4188
|
+
if (!isExpression4(base)) {
|
|
2524
4189
|
return;
|
|
2525
4190
|
}
|
|
2526
4191
|
const path2 = ast.path ?? ast.query ?? ast.right;
|
|
@@ -2547,6 +4212,11 @@ var renderJoinSourcesForMutation = (joins, state, dialect) => joins.map((join) =
|
|
|
2547
4212
|
var renderFromSources = (sources, state, dialect) => sources.map((source) => renderSourceReference(source.source, source.tableName, source.baseTableName, state, dialect)).join(", ");
|
|
2548
4213
|
var renderJoinPredicatesForMutation = (joins, state, dialect) => joins.flatMap((join) => join.kind === "cross" || !join.on ? [] : [renderExpression(join.on, state, dialect)]);
|
|
2549
4214
|
var renderDeleteTargets = (targets, dialect) => targets.map((target) => dialect.quoteIdentifier(target.tableName)).join(", ");
|
|
4215
|
+
var assertMergeActionKind = (kind, allowed) => {
|
|
4216
|
+
if (typeof kind !== "string" || !allowed.includes(kind)) {
|
|
4217
|
+
throw new Error("Unsupported merge action kind");
|
|
4218
|
+
}
|
|
4219
|
+
};
|
|
2550
4220
|
var renderMysqlMutationLock = (lock, statement) => {
|
|
2551
4221
|
if (!lock) {
|
|
2552
4222
|
return "";
|
|
@@ -2566,8 +4236,9 @@ var renderTransactionClause = (clause, dialect) => {
|
|
|
2566
4236
|
switch (clause.kind) {
|
|
2567
4237
|
case "transaction": {
|
|
2568
4238
|
const modes = [];
|
|
2569
|
-
|
|
2570
|
-
|
|
4239
|
+
const isolationLevel = renderTransactionIsolationLevel(clause.isolationLevel);
|
|
4240
|
+
if (isolationLevel) {
|
|
4241
|
+
modes.push(isolationLevel);
|
|
2571
4242
|
}
|
|
2572
4243
|
if (clause.readOnly === true) {
|
|
2573
4244
|
modes.push("read only");
|
|
@@ -2585,13 +4256,16 @@ var renderTransactionClause = (clause, dialect) => {
|
|
|
2585
4256
|
case "releaseSavepoint":
|
|
2586
4257
|
return `release savepoint ${dialect.quoteIdentifier(clause.name)}`;
|
|
2587
4258
|
}
|
|
2588
|
-
|
|
4259
|
+
throw new Error("Unsupported transaction statement kind");
|
|
2589
4260
|
};
|
|
2590
4261
|
var renderSelectionList = (selection, state, dialect, validateAggregation) => {
|
|
2591
4262
|
if (validateAggregation) {
|
|
2592
4263
|
validateAggregationSelection(selection, []);
|
|
2593
4264
|
}
|
|
2594
4265
|
const flattened = flattenSelection(selection);
|
|
4266
|
+
if (dialect.name === "mysql" && flattened.length === 0) {
|
|
4267
|
+
throw new Error("mysql select statements require at least one selected expression");
|
|
4268
|
+
}
|
|
2595
4269
|
const projections = selectionProjections(selection);
|
|
2596
4270
|
const sql = flattened.map(({ expression, alias: alias2 }) => `${renderSelectSql(renderExpression(expression, state, dialect), expressionDriverContext(expression, state, dialect))} as ${dialect.quoteIdentifier(alias2)}`).join(", ");
|
|
2597
4271
|
return {
|
|
@@ -2599,7 +4273,84 @@ var renderSelectionList = (selection, state, dialect, validateAggregation) => {
|
|
|
2599
4273
|
projections
|
|
2600
4274
|
};
|
|
2601
4275
|
};
|
|
2602
|
-
var
|
|
4276
|
+
var nestedRenderState = (state) => ({
|
|
4277
|
+
params: state.params,
|
|
4278
|
+
valueMappings: state.valueMappings,
|
|
4279
|
+
ctes: [],
|
|
4280
|
+
cteNames: new Set(state.cteNames),
|
|
4281
|
+
cteSources: new Map(state.cteSources)
|
|
4282
|
+
});
|
|
4283
|
+
var assertMatchingSetProjections = (left, right) => {
|
|
4284
|
+
const leftKeys = left.map((projection) => JSON.stringify(projection.path));
|
|
4285
|
+
const rightKeys = right.map((projection) => JSON.stringify(projection.path));
|
|
4286
|
+
if (leftKeys.length !== rightKeys.length || leftKeys.some((key2, index3) => key2 !== rightKeys[index3])) {
|
|
4287
|
+
throw new Error("set operator operands must have matching result rows");
|
|
4288
|
+
}
|
|
4289
|
+
};
|
|
4290
|
+
var assertNoGroupedMutationClauses = (ast, statement) => {
|
|
4291
|
+
if (ast.groupBy.length > 0) {
|
|
4292
|
+
throw new Error(`groupBy(...) is not supported for ${statement} statements`);
|
|
4293
|
+
}
|
|
4294
|
+
if (ast.having.length > 0) {
|
|
4295
|
+
throw new Error(`having(...) is not supported for ${statement} statements`);
|
|
4296
|
+
}
|
|
4297
|
+
};
|
|
4298
|
+
var assertNoInsertQueryClauses = (ast) => {
|
|
4299
|
+
if (ast.where.length > 0) {
|
|
4300
|
+
throw new Error("where(...) is not supported for insert statements");
|
|
4301
|
+
}
|
|
4302
|
+
if (ast.joins.length > 0) {
|
|
4303
|
+
throw new Error("join(...) is not supported for insert statements");
|
|
4304
|
+
}
|
|
4305
|
+
if (ast.orderBy.length > 0) {
|
|
4306
|
+
throw new Error("orderBy(...) is not supported for insert statements");
|
|
4307
|
+
}
|
|
4308
|
+
if (ast.limit) {
|
|
4309
|
+
throw new Error("limit(...) is not supported for insert statements");
|
|
4310
|
+
}
|
|
4311
|
+
if (ast.offset) {
|
|
4312
|
+
throw new Error("offset(...) is not supported for insert statements");
|
|
4313
|
+
}
|
|
4314
|
+
if (ast.lock) {
|
|
4315
|
+
throw new Error("lock(...) is not supported for insert statements");
|
|
4316
|
+
}
|
|
4317
|
+
};
|
|
4318
|
+
var assertNoStatementQueryClauses = (ast, statement, options2 = {}) => {
|
|
4319
|
+
if (ast.distinct) {
|
|
4320
|
+
throw new Error(`distinct(...) is not supported for ${statement} statements`);
|
|
4321
|
+
}
|
|
4322
|
+
if (ast.where.length > 0) {
|
|
4323
|
+
throw new Error(`where(...) is not supported for ${statement} statements`);
|
|
4324
|
+
}
|
|
4325
|
+
if ((ast.fromSources?.length ?? 0) > 0 || ast.from) {
|
|
4326
|
+
throw new Error(`from(...) is not supported for ${statement} statements`);
|
|
4327
|
+
}
|
|
4328
|
+
if (ast.joins.length > 0) {
|
|
4329
|
+
throw new Error(`join(...) is not supported for ${statement} statements`);
|
|
4330
|
+
}
|
|
4331
|
+
if (ast.groupBy.length > 0) {
|
|
4332
|
+
throw new Error(`groupBy(...) is not supported for ${statement} statements`);
|
|
4333
|
+
}
|
|
4334
|
+
if (ast.having.length > 0) {
|
|
4335
|
+
throw new Error(`having(...) is not supported for ${statement} statements`);
|
|
4336
|
+
}
|
|
4337
|
+
if (ast.orderBy.length > 0) {
|
|
4338
|
+
throw new Error(`orderBy(...) is not supported for ${statement} statements`);
|
|
4339
|
+
}
|
|
4340
|
+
if (ast.limit) {
|
|
4341
|
+
throw new Error(`limit(...) is not supported for ${statement} statements`);
|
|
4342
|
+
}
|
|
4343
|
+
if (ast.offset) {
|
|
4344
|
+
throw new Error(`offset(...) is not supported for ${statement} statements`);
|
|
4345
|
+
}
|
|
4346
|
+
if (ast.lock) {
|
|
4347
|
+
throw new Error(`lock(...) is not supported for ${statement} statements`);
|
|
4348
|
+
}
|
|
4349
|
+
if (options2.allowSelection !== true && Object.keys(ast.select).length > 0) {
|
|
4350
|
+
throw new Error(`returning(...) is not supported for ${statement} statements`);
|
|
4351
|
+
}
|
|
4352
|
+
};
|
|
4353
|
+
var renderQueryAst = (ast, state, dialect, options2 = {}) => {
|
|
2603
4354
|
let sql = "";
|
|
2604
4355
|
let projections = [];
|
|
2605
4356
|
switch (ast.kind) {
|
|
@@ -2607,8 +4358,9 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2607
4358
|
validateAggregationSelection(ast.select, ast.groupBy);
|
|
2608
4359
|
const rendered = renderSelectionList(ast.select, state, dialect, false);
|
|
2609
4360
|
projections = rendered.projections;
|
|
4361
|
+
const selectList = rendered.sql.length > 0 ? ` ${rendered.sql}` : "";
|
|
2610
4362
|
const clauses = [
|
|
2611
|
-
ast.distinctOn && ast.distinctOn.length > 0 ? `select distinct on (${ast.distinctOn.map((value) => renderExpression(value, state, dialect)).join(", ")})
|
|
4363
|
+
ast.distinctOn && ast.distinctOn.length > 0 ? `select distinct on (${ast.distinctOn.map((value) => renderExpression(value, state, dialect)).join(", ")})${selectList}` : `select${ast.distinct ? " distinct" : ""}${selectList}`
|
|
2612
4364
|
];
|
|
2613
4365
|
if (ast.from) {
|
|
2614
4366
|
clauses.push(`from ${renderSourceReference(ast.from.source, ast.from.tableName, ast.from.baseTableName, state, dialect)}`);
|
|
@@ -2636,19 +4388,25 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2636
4388
|
clauses.push(`offset ${renderExpression(ast.offset, state, dialect)}`);
|
|
2637
4389
|
}
|
|
2638
4390
|
if (ast.lock) {
|
|
2639
|
-
|
|
4391
|
+
if (ast.lock.nowait && ast.lock.skipLocked) {
|
|
4392
|
+
throw new Error("lock(...) cannot specify both nowait and skipLocked");
|
|
4393
|
+
}
|
|
4394
|
+
clauses.push(`${renderSelectLockMode(ast.lock.mode)}${ast.lock.nowait ? " nowait" : ""}${ast.lock.skipLocked ? " skip locked" : ""}`);
|
|
2640
4395
|
}
|
|
2641
4396
|
sql = clauses.join(" ");
|
|
2642
4397
|
break;
|
|
2643
4398
|
}
|
|
2644
4399
|
case "set": {
|
|
2645
4400
|
const setAst = ast;
|
|
4401
|
+
assertNoStatementQueryClauses(setAst, "set", { allowSelection: true });
|
|
2646
4402
|
const base = renderQueryAst(getAst(setAst.setBase), state, dialect);
|
|
2647
4403
|
projections = selectionProjections(setAst.select);
|
|
4404
|
+
assertMatchingSetProjections(projections, base.projections);
|
|
2648
4405
|
sql = [
|
|
2649
4406
|
`(${base.sql})`,
|
|
2650
4407
|
...(setAst.setOperations ?? []).map((entry) => {
|
|
2651
4408
|
const rendered = renderQueryAst(getAst(entry.query), state, dialect);
|
|
4409
|
+
assertMatchingSetProjections(projections, rendered.projections);
|
|
2652
4410
|
return `${entry.kind}${entry.all ? " all" : ""} (${rendered.sql})`;
|
|
2653
4411
|
})
|
|
2654
4412
|
].join(" ");
|
|
@@ -2656,28 +4414,34 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2656
4414
|
}
|
|
2657
4415
|
case "insert": {
|
|
2658
4416
|
const insertAst = ast;
|
|
4417
|
+
if (insertAst.distinct) {
|
|
4418
|
+
throw new Error("distinct(...) is not supported for insert statements");
|
|
4419
|
+
}
|
|
4420
|
+
assertNoGroupedMutationClauses(insertAst, "insert");
|
|
4421
|
+
assertNoInsertQueryClauses(insertAst);
|
|
2659
4422
|
const targetSource = insertAst.into;
|
|
2660
4423
|
const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
|
|
4424
|
+
const insertSource = expectInsertSourceKind(insertAst.insertSource);
|
|
4425
|
+
const conflict = expectConflictClause(insertAst.conflict);
|
|
2661
4426
|
sql = `insert into ${target}`;
|
|
2662
|
-
if (
|
|
2663
|
-
const columns =
|
|
2664
|
-
const rows =
|
|
4427
|
+
if (insertSource?.kind === "values") {
|
|
4428
|
+
const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
|
|
4429
|
+
const rows = insertSource.rows.map((row) => `(${row.values.map((entry) => renderExpression(entry.value, state, dialect)).join(", ")})`).join(", ");
|
|
2665
4430
|
sql += ` (${columns}) values ${rows}`;
|
|
2666
|
-
} else if (
|
|
2667
|
-
const columns =
|
|
2668
|
-
const renderedQuery = renderQueryAst(getAst(
|
|
4431
|
+
} else if (insertSource?.kind === "query") {
|
|
4432
|
+
const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
|
|
4433
|
+
const renderedQuery = renderQueryAst(getAst(insertSource.query), state, dialect);
|
|
2669
4434
|
sql += ` (${columns}) ${renderedQuery.sql}`;
|
|
2670
|
-
} else if (
|
|
2671
|
-
const
|
|
2672
|
-
const columns = unnestSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
|
|
4435
|
+
} else if (insertSource?.kind === "unnest") {
|
|
4436
|
+
const columns = insertSource.columns.map((column) => dialect.quoteIdentifier(column)).join(", ");
|
|
2673
4437
|
if (dialect.name === "postgres") {
|
|
2674
4438
|
const table = targetSource.source;
|
|
2675
4439
|
const fields = table[TypeId4].fields;
|
|
2676
|
-
const rendered =
|
|
4440
|
+
const rendered = insertSource.values.map((entry) => `cast(${dialect.renderLiteral(encodeArrayValues(entry.values, fields[entry.columnName], state, dialect), state)} as ${renderCastType(dialect, fields[entry.columnName].metadata.dbType)}[])`).join(", ");
|
|
2677
4441
|
sql += ` (${columns}) select * from unnest(${rendered})`;
|
|
2678
4442
|
} else {
|
|
2679
|
-
const rowCount =
|
|
2680
|
-
const rows = Array.from({ length: rowCount }, (_, index3) => `(${
|
|
4443
|
+
const rowCount = insertSource.values[0]?.values.length ?? 0;
|
|
4444
|
+
const rows = Array.from({ length: rowCount }, (_, index3) => `(${insertSource.values.map((entry) => dialect.renderLiteral(entry.values[index3], state, targetSource.source[TypeId4].fields[entry.columnName][TypeId2])).join(", ")})`).join(", ");
|
|
2681
4445
|
sql += ` (${columns}) values ${rows}`;
|
|
2682
4446
|
}
|
|
2683
4447
|
} else {
|
|
@@ -2689,13 +4453,16 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2689
4453
|
sql += " default values";
|
|
2690
4454
|
}
|
|
2691
4455
|
}
|
|
2692
|
-
if (
|
|
2693
|
-
|
|
4456
|
+
if (conflict) {
|
|
4457
|
+
if (conflict.action === "doNothing" && conflict.where) {
|
|
4458
|
+
throw new Error("conflict action predicates require update assignments");
|
|
4459
|
+
}
|
|
4460
|
+
const updateValues = (conflict.values ?? []).map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ");
|
|
2694
4461
|
if (dialect.name === "postgres") {
|
|
2695
|
-
const targetSql =
|
|
4462
|
+
const targetSql = conflict.target?.kind === "constraint" ? ` on conflict on constraint ${dialect.quoteIdentifier(conflict.target.name)}` : conflict.target?.kind === "columns" ? ` on conflict (${conflict.target.columns.map((column) => dialect.quoteIdentifier(column)).join(", ")})${conflict.target.where ? ` where ${renderExpression(conflict.target.where, state, dialect)}` : ""}` : " on conflict";
|
|
2696
4463
|
sql += targetSql;
|
|
2697
|
-
sql +=
|
|
2698
|
-
} else if (
|
|
4464
|
+
sql += conflict.action === "doNothing" ? " do nothing" : ` do update set ${updateValues}${conflict.where ? ` where ${renderExpression(conflict.where, state, dialect)}` : ""}`;
|
|
4465
|
+
} else if (conflict.action === "doNothing") {
|
|
2699
4466
|
sql = sql.replace(/^insert/, "insert ignore");
|
|
2700
4467
|
} else {
|
|
2701
4468
|
sql += ` on duplicate key update ${updateValues}`;
|
|
@@ -2710,10 +4477,29 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2710
4477
|
}
|
|
2711
4478
|
case "update": {
|
|
2712
4479
|
const updateAst = ast;
|
|
4480
|
+
if (updateAst.distinct) {
|
|
4481
|
+
throw new Error("distinct(...) is not supported for update statements");
|
|
4482
|
+
}
|
|
4483
|
+
assertNoGroupedMutationClauses(updateAst, "update");
|
|
4484
|
+
if (updateAst.orderBy.length > 0) {
|
|
4485
|
+
throw new Error("orderBy(...) is not supported for update statements");
|
|
4486
|
+
}
|
|
4487
|
+
if (updateAst.limit) {
|
|
4488
|
+
throw new Error("limit(...) is not supported for update statements");
|
|
4489
|
+
}
|
|
4490
|
+
if (updateAst.offset) {
|
|
4491
|
+
throw new Error("offset(...) is not supported for update statements");
|
|
4492
|
+
}
|
|
4493
|
+
if (updateAst.lock) {
|
|
4494
|
+
throw new Error("lock(...) is not supported for update statements");
|
|
4495
|
+
}
|
|
2713
4496
|
const targetSource = updateAst.target;
|
|
2714
4497
|
const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
|
|
2715
4498
|
const targets = updateAst.targets ?? [targetSource];
|
|
2716
4499
|
const fromSources = updateAst.fromSources ?? [];
|
|
4500
|
+
if ((updateAst.set ?? []).length === 0) {
|
|
4501
|
+
throw new Error("update statements require at least one assignment");
|
|
4502
|
+
}
|
|
2717
4503
|
const assignments = updateAst.set.map((entry) => renderMutationAssignment(entry, state, dialect)).join(", ");
|
|
2718
4504
|
if (dialect.name === "mysql") {
|
|
2719
4505
|
const modifiers = renderMysqlMutationLock(updateAst.lock, "update");
|
|
@@ -2756,6 +4542,22 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2756
4542
|
}
|
|
2757
4543
|
case "delete": {
|
|
2758
4544
|
const deleteAst = ast;
|
|
4545
|
+
if (deleteAst.distinct) {
|
|
4546
|
+
throw new Error("distinct(...) is not supported for delete statements");
|
|
4547
|
+
}
|
|
4548
|
+
assertNoGroupedMutationClauses(deleteAst, "delete");
|
|
4549
|
+
if (deleteAst.orderBy.length > 0 && dialect.name === "postgres") {
|
|
4550
|
+
throw new Error("orderBy(...) is not supported for delete statements");
|
|
4551
|
+
}
|
|
4552
|
+
if (deleteAst.limit && dialect.name === "postgres") {
|
|
4553
|
+
throw new Error("limit(...) is not supported for delete statements");
|
|
4554
|
+
}
|
|
4555
|
+
if (deleteAst.offset) {
|
|
4556
|
+
throw new Error("offset(...) is not supported for delete statements");
|
|
4557
|
+
}
|
|
4558
|
+
if (deleteAst.lock) {
|
|
4559
|
+
throw new Error("lock(...) is not supported for delete statements");
|
|
4560
|
+
}
|
|
2759
4561
|
const targetSource = deleteAst.target;
|
|
2760
4562
|
const target = renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect);
|
|
2761
4563
|
const targets = deleteAst.targets ?? [targetSource];
|
|
@@ -2794,12 +4596,14 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2794
4596
|
}
|
|
2795
4597
|
case "truncate": {
|
|
2796
4598
|
const truncateAst = ast;
|
|
4599
|
+
assertNoStatementQueryClauses(truncateAst, "truncate");
|
|
4600
|
+
const truncate = expectTruncateClause(truncateAst.truncate);
|
|
2797
4601
|
const targetSource = truncateAst.target;
|
|
2798
4602
|
sql = `truncate table ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)}`;
|
|
2799
|
-
if (
|
|
4603
|
+
if (truncate.restartIdentity) {
|
|
2800
4604
|
sql += " restart identity";
|
|
2801
4605
|
}
|
|
2802
|
-
if (
|
|
4606
|
+
if (truncate.cascade) {
|
|
2803
4607
|
sql += " cascade";
|
|
2804
4608
|
}
|
|
2805
4609
|
break;
|
|
@@ -2812,8 +4616,18 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2812
4616
|
const targetSource = mergeAst.target;
|
|
2813
4617
|
const usingSource = mergeAst.using;
|
|
2814
4618
|
const merge = mergeAst.merge;
|
|
4619
|
+
if (merge.kind !== "merge") {
|
|
4620
|
+
throw new Error("Unsupported merge statement kind");
|
|
4621
|
+
}
|
|
4622
|
+
if (Object.keys(mergeAst.select).length > 0) {
|
|
4623
|
+
throw new Error("returning(...) is not supported for merge statements");
|
|
4624
|
+
}
|
|
4625
|
+
if (!merge.whenMatched && !merge.whenNotMatched) {
|
|
4626
|
+
throw new Error("merge statements require at least one action");
|
|
4627
|
+
}
|
|
2815
4628
|
sql = `merge into ${renderSourceReference(targetSource.source, targetSource.tableName, targetSource.baseTableName, state, dialect)} using ${renderSourceReference(usingSource.source, usingSource.tableName, usingSource.baseTableName, state, dialect)} on ${renderExpression(merge.on, state, dialect)}`;
|
|
2816
4629
|
if (merge.whenMatched) {
|
|
4630
|
+
assertMergeActionKind(merge.whenMatched.kind, ["update", "delete"]);
|
|
2817
4631
|
sql += " when matched";
|
|
2818
4632
|
if (merge.whenMatched.predicate) {
|
|
2819
4633
|
sql += ` and ${renderExpression(merge.whenMatched.predicate, state, dialect)}`;
|
|
@@ -2821,14 +4635,21 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2821
4635
|
if (merge.whenMatched.kind === "delete") {
|
|
2822
4636
|
sql += " then delete";
|
|
2823
4637
|
} else {
|
|
4638
|
+
if (merge.whenMatched.values.length === 0) {
|
|
4639
|
+
throw new Error("merge update actions require at least one assignment");
|
|
4640
|
+
}
|
|
2824
4641
|
sql += ` then update set ${merge.whenMatched.values.map((entry) => `${dialect.quoteIdentifier(entry.columnName)} = ${renderExpression(entry.value, state, dialect)}`).join(", ")}`;
|
|
2825
4642
|
}
|
|
2826
4643
|
}
|
|
2827
4644
|
if (merge.whenNotMatched) {
|
|
4645
|
+
assertMergeActionKind(merge.whenNotMatched.kind, ["insert"]);
|
|
2828
4646
|
sql += " when not matched";
|
|
2829
4647
|
if (merge.whenNotMatched.predicate) {
|
|
2830
4648
|
sql += ` and ${renderExpression(merge.whenNotMatched.predicate, state, dialect)}`;
|
|
2831
4649
|
}
|
|
4650
|
+
if (merge.whenNotMatched.values.length === 0) {
|
|
4651
|
+
throw new Error("merge insert actions require at least one value");
|
|
4652
|
+
}
|
|
2832
4653
|
sql += ` then insert (${merge.whenNotMatched.values.map((entry) => dialect.quoteIdentifier(entry.columnName)).join(", ")}) values (${merge.whenNotMatched.values.map((entry) => renderExpression(entry.value, state, dialect)).join(", ")})`;
|
|
2833
4654
|
}
|
|
2834
4655
|
break;
|
|
@@ -2839,32 +4660,40 @@ var renderQueryAst = (ast, state, dialect) => {
|
|
|
2839
4660
|
case "savepoint":
|
|
2840
4661
|
case "rollbackTo":
|
|
2841
4662
|
case "releaseSavepoint": {
|
|
4663
|
+
assertNoStatementQueryClauses(ast, ast.kind);
|
|
2842
4664
|
sql = renderTransactionClause(ast.transaction, dialect);
|
|
2843
4665
|
break;
|
|
2844
4666
|
}
|
|
2845
4667
|
case "createTable": {
|
|
2846
4668
|
const createTableAst = ast;
|
|
2847
|
-
|
|
4669
|
+
assertNoStatementQueryClauses(createTableAst, "createTable");
|
|
4670
|
+
const ddl = expectDdlClauseKind(createTableAst.ddl, "createTable");
|
|
4671
|
+
sql = renderCreateTableSql(createTableAst.target, state, dialect, ddl.ifNotExists);
|
|
2848
4672
|
break;
|
|
2849
4673
|
}
|
|
2850
4674
|
case "dropTable": {
|
|
2851
4675
|
const dropTableAst = ast;
|
|
2852
|
-
|
|
2853
|
-
|
|
4676
|
+
assertNoStatementQueryClauses(dropTableAst, "dropTable");
|
|
4677
|
+
const ddl = expectDdlClauseKind(dropTableAst.ddl, "dropTable");
|
|
4678
|
+
sql = `drop table${ddl.ifExists ? " if exists" : ""} ${renderSourceReference(dropTableAst.target.source, dropTableAst.target.tableName, dropTableAst.target.baseTableName, state, dialect)}`;
|
|
2854
4679
|
break;
|
|
2855
4680
|
}
|
|
2856
4681
|
case "createIndex": {
|
|
2857
4682
|
const createIndexAst = ast;
|
|
2858
|
-
|
|
4683
|
+
assertNoStatementQueryClauses(createIndexAst, "createIndex");
|
|
4684
|
+
sql = renderCreateIndexSql(createIndexAst.target, expectDdlClauseKind(createIndexAst.ddl, "createIndex"), state, dialect);
|
|
2859
4685
|
break;
|
|
2860
4686
|
}
|
|
2861
4687
|
case "dropIndex": {
|
|
2862
4688
|
const dropIndexAst = ast;
|
|
2863
|
-
|
|
4689
|
+
assertNoStatementQueryClauses(dropIndexAst, "dropIndex");
|
|
4690
|
+
sql = renderDropIndexSql(dropIndexAst.target, expectDdlClauseKind(dropIndexAst.ddl, "dropIndex"), state, dialect);
|
|
2864
4691
|
break;
|
|
2865
4692
|
}
|
|
4693
|
+
default:
|
|
4694
|
+
throw new Error("Unsupported query statement kind");
|
|
2866
4695
|
}
|
|
2867
|
-
if (state.ctes.length === 0) {
|
|
4696
|
+
if (state.ctes.length === 0 || options2.emitCtes === false) {
|
|
2868
4697
|
return {
|
|
2869
4698
|
sql,
|
|
2870
4699
|
projections
|
|
@@ -2887,9 +4716,14 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
|
|
|
2887
4716
|
};
|
|
2888
4717
|
if (typeof source === "object" && source !== null && "kind" in source && source.kind === "cte") {
|
|
2889
4718
|
const cte = source;
|
|
4719
|
+
const registeredCteSource = state.cteSources.get(cte.name);
|
|
4720
|
+
if (registeredCteSource !== undefined && registeredCteSource !== cte.plan) {
|
|
4721
|
+
throw new Error(`common table expression name is already registered with a different plan: ${cte.name}`);
|
|
4722
|
+
}
|
|
2890
4723
|
if (!state.cteNames.has(cte.name)) {
|
|
2891
4724
|
state.cteNames.add(cte.name);
|
|
2892
|
-
|
|
4725
|
+
state.cteSources.set(cte.name, cte.plan);
|
|
4726
|
+
const rendered = renderQueryAst(getAst(cte.plan), state, dialect, { emitCtes: false });
|
|
2893
4727
|
state.ctes.push({
|
|
2894
4728
|
name: cte.name,
|
|
2895
4729
|
sql: rendered.sql,
|
|
@@ -2901,11 +4735,11 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
|
|
|
2901
4735
|
if (typeof source === "object" && source !== null && "kind" in source && source.kind === "derived") {
|
|
2902
4736
|
const derived = source;
|
|
2903
4737
|
if (!state.cteNames.has(derived.name)) {}
|
|
2904
|
-
return `(${renderQueryAst(getAst(derived.plan), state, dialect).sql}) as ${dialect.quoteIdentifier(derived.name)}`;
|
|
4738
|
+
return `(${renderQueryAst(getAst(derived.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(derived.name)}`;
|
|
2905
4739
|
}
|
|
2906
4740
|
if (typeof source === "object" && source !== null && "kind" in source && source.kind === "lateral") {
|
|
2907
4741
|
const lateral = source;
|
|
2908
|
-
return `lateral (${renderQueryAst(getAst(lateral.plan), state, dialect).sql}) as ${dialect.quoteIdentifier(lateral.name)}`;
|
|
4742
|
+
return `lateral (${renderQueryAst(getAst(lateral.plan), nestedRenderState(state), dialect).sql}) as ${dialect.quoteIdentifier(lateral.name)}`;
|
|
2909
4743
|
}
|
|
2910
4744
|
if (typeof source === "object" && source !== null && source.kind === "values") {
|
|
2911
4745
|
const values = source;
|
|
@@ -2926,6 +4760,13 @@ var renderSourceReference = (source, tableName, baseTableName, state, dialect) =
|
|
|
2926
4760
|
const schemaName = typeof source === "object" && source !== null && TypeId4 in source ? source[TypeId4].schemaName : undefined;
|
|
2927
4761
|
return dialect.renderTableReference(tableName, baseTableName, schemaName);
|
|
2928
4762
|
};
|
|
4763
|
+
var renderSubqueryExpressionPlan = (plan, state, dialect) => {
|
|
4764
|
+
const statement = getQueryState(plan).statement;
|
|
4765
|
+
if (statement !== "select" && statement !== "set") {
|
|
4766
|
+
throw new Error("subquery expressions only accept select-like query plans");
|
|
4767
|
+
}
|
|
4768
|
+
return renderQueryAst(getAst(plan), state, dialect).sql;
|
|
4769
|
+
};
|
|
2929
4770
|
var renderExpression = (expression, state, dialect) => {
|
|
2930
4771
|
const rawAst = expression[TypeId3];
|
|
2931
4772
|
const jsonSql = renderJsonExpression(expression, rawAst, state, dialect);
|
|
@@ -2936,8 +4777,11 @@ var renderExpression = (expression, state, dialect) => {
|
|
|
2936
4777
|
const renderComparisonOperator = (operator) => operator === "eq" ? "=" : operator === "neq" ? "<>" : operator === "lt" ? "<" : operator === "lte" ? "<=" : operator === "gt" ? ">" : ">=";
|
|
2937
4778
|
switch (ast.kind) {
|
|
2938
4779
|
case "column":
|
|
2939
|
-
return ast.tableName.length === 0 ? dialect.quoteIdentifier(ast.columnName) : `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`;
|
|
4780
|
+
return state.rowLocalColumns || ast.tableName.length === 0 ? dialect.quoteIdentifier(ast.columnName) : `${dialect.quoteIdentifier(ast.tableName)}.${dialect.quoteIdentifier(ast.columnName)}`;
|
|
2940
4781
|
case "literal":
|
|
4782
|
+
if (typeof ast.value === "number" && !Number.isFinite(ast.value)) {
|
|
4783
|
+
throw new Error("Expected a finite numeric value");
|
|
4784
|
+
}
|
|
2941
4785
|
return dialect.renderLiteral(ast.value, state, expression[TypeId2]);
|
|
2942
4786
|
case "excluded":
|
|
2943
4787
|
return dialect.name === "mysql" ? `values(${dialect.quoteIdentifier(ast.columnName)})` : `excluded.${dialect.quoteIdentifier(ast.columnName)}`;
|
|
@@ -2977,6 +4821,7 @@ var renderExpression = (expression, state, dialect) => {
|
|
|
2977
4821
|
return dialect.name === "mysql" ? `(${renderExpression(ast.left, state, dialect)} <=> ${renderExpression(ast.right, state, dialect)})` : `(${renderExpression(ast.left, state, dialect)} is not distinct from ${renderExpression(ast.right, state, dialect)})`;
|
|
2978
4822
|
case "contains":
|
|
2979
4823
|
if (dialect.name === "postgres") {
|
|
4824
|
+
assertCompatiblePostgresRangeOperands(ast.left, ast.right);
|
|
2980
4825
|
const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
|
|
2981
4826
|
const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
|
|
2982
4827
|
return `(${left} @> ${right})`;
|
|
@@ -2987,6 +4832,7 @@ var renderExpression = (expression, state, dialect) => {
|
|
|
2987
4832
|
throw new Error("Unsupported container operator for SQL rendering");
|
|
2988
4833
|
case "containedBy":
|
|
2989
4834
|
if (dialect.name === "postgres") {
|
|
4835
|
+
assertCompatiblePostgresRangeOperands(ast.left, ast.right);
|
|
2990
4836
|
const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
|
|
2991
4837
|
const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
|
|
2992
4838
|
return `(${left} <@ ${right})`;
|
|
@@ -2997,6 +4843,7 @@ var renderExpression = (expression, state, dialect) => {
|
|
|
2997
4843
|
throw new Error("Unsupported container operator for SQL rendering");
|
|
2998
4844
|
case "overlaps":
|
|
2999
4845
|
if (dialect.name === "postgres") {
|
|
4846
|
+
assertCompatiblePostgresRangeOperands(ast.left, ast.right);
|
|
3000
4847
|
const left = isJsonExpression(ast.left) ? renderPostgresJsonValue(ast.left, state, dialect) : renderExpression(ast.left, state, dialect);
|
|
3001
4848
|
const right = isJsonExpression(ast.right) ? renderPostgresJsonValue(ast.right, state, dialect) : renderExpression(ast.right, state, dialect);
|
|
3002
4849
|
return `(${left} && ${right})`;
|
|
@@ -3022,14 +4869,26 @@ var renderExpression = (expression, state, dialect) => {
|
|
|
3022
4869
|
case "min":
|
|
3023
4870
|
return `min(${renderExpression(ast.value, state, dialect)})`;
|
|
3024
4871
|
case "and":
|
|
4872
|
+
if (ast.values.length === 0) {
|
|
4873
|
+
throw new Error("and(...) requires at least one predicate");
|
|
4874
|
+
}
|
|
3025
4875
|
return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" and ")})`;
|
|
3026
4876
|
case "or":
|
|
4877
|
+
if (ast.values.length === 0) {
|
|
4878
|
+
throw new Error("or(...) requires at least one predicate");
|
|
4879
|
+
}
|
|
3027
4880
|
return `(${ast.values.map((value) => renderExpression(value, state, dialect)).join(" or ")})`;
|
|
3028
4881
|
case "coalesce":
|
|
3029
4882
|
return `coalesce(${ast.values.map((value) => renderExpression(value, state, dialect)).join(", ")})`;
|
|
3030
4883
|
case "in":
|
|
4884
|
+
if (ast.values.length < 2) {
|
|
4885
|
+
throw new Error("in(...) requires at least one candidate value");
|
|
4886
|
+
}
|
|
3031
4887
|
return `(${renderExpression(ast.values[0], state, dialect)} in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
|
|
3032
4888
|
case "notIn":
|
|
4889
|
+
if (ast.values.length < 2) {
|
|
4890
|
+
throw new Error("notIn(...) requires at least one candidate value");
|
|
4891
|
+
}
|
|
3033
4892
|
return `(${renderExpression(ast.values[0], state, dialect)} not in (${ast.values.slice(1).map((value) => renderExpression(value, state, dialect)).join(", ")}))`;
|
|
3034
4893
|
case "between":
|
|
3035
4894
|
return `(${renderExpression(ast.values[0], state, dialect)} between ${renderExpression(ast.values[1], state, dialect)} and ${renderExpression(ast.values[2], state, dialect)})`;
|
|
@@ -3038,15 +4897,15 @@ var renderExpression = (expression, state, dialect) => {
|
|
|
3038
4897
|
case "case":
|
|
3039
4898
|
return `case ${ast.branches.map((branch) => `when ${renderExpression(branch.when, state, dialect)} then ${renderExpression(branch.then, state, dialect)}`).join(" ")} else ${renderExpression(ast.else, state, dialect)} end`;
|
|
3040
4899
|
case "exists":
|
|
3041
|
-
return `exists (${
|
|
4900
|
+
return `exists (${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
|
|
3042
4901
|
case "scalarSubquery":
|
|
3043
|
-
return `(${
|
|
4902
|
+
return `(${renderSubqueryExpressionPlan(ast.plan, state, dialect)})`;
|
|
3044
4903
|
case "inSubquery":
|
|
3045
|
-
return `(${renderExpression(ast.left, state, dialect)} in (${
|
|
4904
|
+
return `(${renderExpression(ast.left, state, dialect)} in (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
|
|
3046
4905
|
case "comparisonAny":
|
|
3047
|
-
return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} any (${
|
|
4906
|
+
return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} any (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
|
|
3048
4907
|
case "comparisonAll":
|
|
3049
|
-
return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} all (${
|
|
4908
|
+
return `(${renderExpression(ast.left, state, dialect)} ${renderComparisonOperator(ast.operator)} all (${renderSubqueryExpressionPlan(ast.plan, state, dialect)}))`;
|
|
3050
4909
|
case "window": {
|
|
3051
4910
|
if (!Array.isArray(ast.partitionBy) || !Array.isArray(ast.orderBy) || typeof ast.function !== "string") {
|
|
3052
4911
|
break;
|
|
@@ -3131,7 +4990,8 @@ var inlineLiteralDialect = {
|
|
|
3131
4990
|
var renderDdlExpressionSql = (expression) => isSchemaExpression(expression) ? render(expression) : renderExpression(expression, {
|
|
3132
4991
|
params: [],
|
|
3133
4992
|
ctes: [],
|
|
3134
|
-
cteNames: new Set
|
|
4993
|
+
cteNames: new Set,
|
|
4994
|
+
cteSources: new Map
|
|
3135
4995
|
}, inlineLiteralDialect);
|
|
3136
4996
|
var stripRedundantOuterParens = (value) => {
|
|
3137
4997
|
let current = value.trim();
|
|
@@ -3182,10 +5042,14 @@ var normalizeDdlExpressionSql = (expression) => {
|
|
|
3182
5042
|
};
|
|
3183
5043
|
|
|
3184
5044
|
// src/postgres/schema-management.ts
|
|
3185
|
-
import * as
|
|
5045
|
+
import * as Schema6 from "effect/Schema";
|
|
3186
5046
|
import { pipeArguments as pipeArguments5 } from "effect/Pipeable";
|
|
3187
5047
|
var EnumTypeId = Symbol.for("effect-qb/SchemaManagement/Enum");
|
|
3188
5048
|
var SequenceTypeId = Symbol.for("effect-qb/SchemaManagement/Sequence");
|
|
5049
|
+
var safeUnquotedIdentifier = /^[a-z_][a-z0-9_$]*$/;
|
|
5050
|
+
var quoteIdentifier2 = (value) => `"${value.replaceAll('"', '""')}"`;
|
|
5051
|
+
var renderIdentifier = (value) => safeUnquotedIdentifier.test(value) ? value : quoteIdentifier2(value);
|
|
5052
|
+
var renderQualifiedTypeName = (name, schemaName) => schemaName === undefined || schemaName === "public" ? renderIdentifier(name) : `${renderIdentifier(schemaName)}.${renderIdentifier(name)}`;
|
|
3189
5053
|
var EnumProto = {
|
|
3190
5054
|
pipe() {
|
|
3191
5055
|
return pipeArguments5(this, arguments);
|
|
@@ -3196,13 +5060,12 @@ var EnumProto = {
|
|
|
3196
5060
|
type() {
|
|
3197
5061
|
return {
|
|
3198
5062
|
dialect: "postgres",
|
|
3199
|
-
kind: this.
|
|
5063
|
+
kind: renderQualifiedTypeName(this.name, this.schemaName),
|
|
3200
5064
|
variant: "enum"
|
|
3201
5065
|
};
|
|
3202
5066
|
},
|
|
3203
5067
|
column() {
|
|
3204
|
-
|
|
3205
|
-
return makeColumnDefinition(values.length === 1 ? values[0] : Schema4.Union(...values), {
|
|
5068
|
+
return makeColumnDefinition(Schema6.Literals(this.values), {
|
|
3206
5069
|
dbType: this.type(),
|
|
3207
5070
|
nullable: false,
|
|
3208
5071
|
hasDefault: false,
|
|
@@ -3210,7 +5073,7 @@ var EnumProto = {
|
|
|
3210
5073
|
primaryKey: false,
|
|
3211
5074
|
unique: false,
|
|
3212
5075
|
references: undefined,
|
|
3213
|
-
ddlType: this.
|
|
5076
|
+
ddlType: renderQualifiedTypeName(this.name, this.schemaName),
|
|
3214
5077
|
identity: undefined,
|
|
3215
5078
|
enum: {
|
|
3216
5079
|
name: this.name,
|
|
@@ -3311,17 +5174,17 @@ var fromDiscoveredValues = (values) => {
|
|
|
3311
5174
|
const enums = new Map;
|
|
3312
5175
|
for (const value of values) {
|
|
3313
5176
|
if (isEnumDefinition(value)) {
|
|
3314
|
-
enums.set(
|
|
5177
|
+
enums.set(modelIdentityKey(value.schemaName, value.name), toEnumModel(value));
|
|
3315
5178
|
} else if (isTableDefinition(value)) {
|
|
3316
5179
|
for (const enumModel of enumModelsOfTable(value)) {
|
|
3317
|
-
const key2 =
|
|
5180
|
+
const key2 = modelIdentityKey(enumModel.schemaName, enumModel.name);
|
|
3318
5181
|
const existing = enums.get(key2);
|
|
3319
5182
|
if (existing === undefined) {
|
|
3320
5183
|
enums.set(key2, enumModel);
|
|
3321
5184
|
continue;
|
|
3322
5185
|
}
|
|
3323
5186
|
if (JSON.stringify(existing.values) !== JSON.stringify(enumModel.values)) {
|
|
3324
|
-
throw new Error(`Conflicting enum definitions discovered for '${
|
|
5187
|
+
throw new Error(`Conflicting enum definitions discovered for '${enumKey(enumModel.schemaName, enumModel.name)}'`);
|
|
3325
5188
|
}
|
|
3326
5189
|
}
|
|
3327
5190
|
}
|
|
@@ -3334,6 +5197,7 @@ var fromDiscoveredValues = (values) => {
|
|
|
3334
5197
|
};
|
|
3335
5198
|
var tableKey = (schemaName, name) => `${schemaName ?? "public"}.${name}`;
|
|
3336
5199
|
var enumKey = (schemaName, name) => `${schemaName ?? "public"}.${name}`;
|
|
5200
|
+
var modelIdentityKey = (schemaName, name) => JSON.stringify([schemaName ?? "public", name]);
|
|
3337
5201
|
export {
|
|
3338
5202
|
toTableModel,
|
|
3339
5203
|
toEnumModel,
|