@dbsp/core 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +187 -50
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1665,7 +1665,7 @@ function isManyToMany(rel) {
|
|
|
1665
1665
|
}
|
|
1666
1666
|
|
|
1667
1667
|
// src/planner.ts
|
|
1668
|
-
import { toColumnList } from "@dbsp/types";
|
|
1668
|
+
import { resolveJsonAggOrderKey, toColumnList } from "@dbsp/types";
|
|
1669
1669
|
|
|
1670
1670
|
// src/dx/errors.ts
|
|
1671
1671
|
var ExecutionError = class _ExecutionError extends Error {
|
|
@@ -2410,12 +2410,6 @@ function isSubquerySelectedColumnNonNullable(existsIntent, sourceTable, model) {
|
|
|
2410
2410
|
if (!column) return false;
|
|
2411
2411
|
return !column.nullable;
|
|
2412
2412
|
}
|
|
2413
|
-
function resolveTargetJsonAggOrderKey(model, targetTable) {
|
|
2414
|
-
const table = model.getTable(targetTable);
|
|
2415
|
-
if (!table) return { columns: [], fallback: false };
|
|
2416
|
-
const pkColumns = toColumnList(table.primaryKey);
|
|
2417
|
-
return pkColumns.length > 0 ? { columns: pkColumns, fallback: false } : { columns: table.columns.map((col2) => col2.name), fallback: true };
|
|
2418
|
-
}
|
|
2419
2413
|
function optimizeInToExists(where, sourceTable, model, negated = false) {
|
|
2420
2414
|
switch (where.kind) {
|
|
2421
2415
|
case "in": {
|
|
@@ -2744,7 +2738,8 @@ function processInclude(include, sourceTable, model, state, opts, intentPath, de
|
|
|
2744
2738
|
const explicitJoinType = includeStrategy === "join" ? include.join ?? cascadedJoinType : void 0;
|
|
2745
2739
|
const includeDecisionId = generateDecisionId(state, "include-strategy");
|
|
2746
2740
|
const parentKey = relation.type === "belongsTo" ? relation.targetKey : relation.sourceKey;
|
|
2747
|
-
const
|
|
2741
|
+
const targetTable = model.getTable(relation.target);
|
|
2742
|
+
const targetOrder = targetTable ? resolveJsonAggOrderKey(targetTable) : void 0;
|
|
2748
2743
|
state.decisions.push({
|
|
2749
2744
|
id: includeDecisionId,
|
|
2750
2745
|
type: "include-strategy",
|
|
@@ -2760,10 +2755,10 @@ function processInclude(include, sourceTable, model, state, opts, intentPath, de
|
|
|
2760
2755
|
foreignKey: relation.foreignKey
|
|
2761
2756
|
},
|
|
2762
2757
|
...parentKey !== void 0 && { parentKey },
|
|
2763
|
-
...targetOrder.columns.length > 0 && {
|
|
2764
|
-
|
|
2758
|
+
...targetOrder && targetOrder.columns.length > 0 && {
|
|
2759
|
+
targetOrderKey: targetOrder.columns
|
|
2765
2760
|
},
|
|
2766
|
-
...targetOrder
|
|
2761
|
+
...targetOrder?.fallback && { orderByFallback: true }
|
|
2767
2762
|
},
|
|
2768
2763
|
choice: includeStrategy,
|
|
2769
2764
|
// Embed joinType so the adapter's join handler can use it directly
|
|
@@ -6257,7 +6252,7 @@ import {
|
|
|
6257
6252
|
NqlLexer,
|
|
6258
6253
|
compile as nqlCompile
|
|
6259
6254
|
} from "@dbsp/nql";
|
|
6260
|
-
import {
|
|
6255
|
+
import { resolveJsonAggOrderKey as resolveJsonAggOrderKey2 } from "@dbsp/types";
|
|
6261
6256
|
import {
|
|
6262
6257
|
explainUnsupportedNqlBindingIncludeHop,
|
|
6263
6258
|
getTrustedNqlRelationFilterFields,
|
|
@@ -6411,7 +6406,11 @@ function virtualRelationIncludeShape(relation) {
|
|
|
6411
6406
|
type: relationType,
|
|
6412
6407
|
foreignKey,
|
|
6413
6408
|
source: relation.sourceTable,
|
|
6414
|
-
target: relation.targetTable
|
|
6409
|
+
target: relation.targetTable,
|
|
6410
|
+
...relation.through !== void 0 && { through: relation.through },
|
|
6411
|
+
...relation.throughTargetColumn !== void 0 && {
|
|
6412
|
+
otherKey: relation.throughTargetColumn
|
|
6413
|
+
}
|
|
6415
6414
|
};
|
|
6416
6415
|
}
|
|
6417
6416
|
var BINDING_INCLUDE_NODE_ONLY_RELATION = {
|
|
@@ -6457,7 +6456,8 @@ function trustedBindingRelationColumnIsAdmitted(column) {
|
|
|
6457
6456
|
if (trusted.cardinality === "one") {
|
|
6458
6457
|
return !isDotted || trusted.hops.length > 0;
|
|
6459
6458
|
}
|
|
6460
|
-
|
|
6459
|
+
const hasCompleteManyToManyProof = (trusted.relationType === "manyToMany" || trusted.relationType === "belongsToMany") && trusted.through !== void 0 && trusted.throughSourceColumn !== void 0 && trusted.throughTargetColumn !== void 0;
|
|
6460
|
+
return trusted.cardinality === "many" && (trusted.relationType === "hasMany" || hasCompleteManyToManyProof) && !isDotted && trusted.hops.length === 0;
|
|
6461
6461
|
}
|
|
6462
6462
|
function assertProvenBindingInclude(bindingName, include, provenRelations) {
|
|
6463
6463
|
const proven = provenRelations.get(include.relation);
|
|
@@ -6519,7 +6519,8 @@ function createBindingIncludeDecision(intent, include, relation, index, model) {
|
|
|
6519
6519
|
const relationType = relation.relationType;
|
|
6520
6520
|
const foreignKey = relationType === "belongsTo" ? relation.sourceColumn : relation.targetColumn;
|
|
6521
6521
|
const parentKey = relationType === "belongsTo" ? relation.targetColumn : relation.sourceColumn;
|
|
6522
|
-
const
|
|
6522
|
+
const targetTable = model.getTable(relation.targetTable);
|
|
6523
|
+
const targetOrder = targetTable ? resolveJsonAggOrderKey2(targetTable) : void 0;
|
|
6523
6524
|
return {
|
|
6524
6525
|
id: `binding-include-${index}`,
|
|
6525
6526
|
type: "include-strategy",
|
|
@@ -6530,10 +6531,10 @@ function createBindingIncludeDecision(intent, include, relation, index, model) {
|
|
|
6530
6531
|
relationType,
|
|
6531
6532
|
foreignKey,
|
|
6532
6533
|
parentKey,
|
|
6533
|
-
...targetOrder.columns.length > 0 && {
|
|
6534
|
-
|
|
6534
|
+
...targetOrder && targetOrder.columns.length > 0 && {
|
|
6535
|
+
targetOrderKey: targetOrder.columns
|
|
6535
6536
|
},
|
|
6536
|
-
...targetOrder
|
|
6537
|
+
...targetOrder?.fallback && { orderByFallback: true },
|
|
6537
6538
|
includeAlias: include.relation,
|
|
6538
6539
|
intentPath: `include[${index}]`
|
|
6539
6540
|
},
|
|
@@ -6549,12 +6550,6 @@ function parentKeyForRelation(relation) {
|
|
|
6549
6550
|
if (relation.type === "belongsTo") return relation.targetKey;
|
|
6550
6551
|
return relation.sourceKey;
|
|
6551
6552
|
}
|
|
6552
|
-
function resolveTargetJsonAggOrderKey2(model, targetTable) {
|
|
6553
|
-
const table = model.getTable(targetTable);
|
|
6554
|
-
if (!table) return { columns: [], fallback: false };
|
|
6555
|
-
const pkColumns = toColumnList2(table.primaryKey);
|
|
6556
|
-
return pkColumns.length > 0 ? { columns: pkColumns, fallback: false } : { columns: table.columns.map((col2) => col2.name), fallback: true };
|
|
6557
|
-
}
|
|
6558
6553
|
function assertSupportedBindingIncludeHop(bindingName, rootIncludeRelation, relationName, relation, include, reasonPrefix = "") {
|
|
6559
6554
|
const unsupportedReason = explainUnsupportedNqlBindingIncludeHop(
|
|
6560
6555
|
relationName,
|
|
@@ -6653,10 +6648,11 @@ function createBindingTailIncludeDecisions(bindingName, include, firstHopRelatio
|
|
|
6653
6648
|
const baseContext = { ...decision.context };
|
|
6654
6649
|
delete baseContext.foreignKey;
|
|
6655
6650
|
delete baseContext.parentKey;
|
|
6656
|
-
delete baseContext.
|
|
6651
|
+
delete baseContext.targetOrderKey;
|
|
6657
6652
|
delete baseContext.orderByFallback;
|
|
6658
6653
|
const parentKey = parentKeyForRelation(relation);
|
|
6659
|
-
const
|
|
6654
|
+
const targetTable = model.getTable(relation.target);
|
|
6655
|
+
const targetOrder = targetTable ? resolveJsonAggOrderKey2(targetTable) : void 0;
|
|
6660
6656
|
return {
|
|
6661
6657
|
...decision,
|
|
6662
6658
|
id: `binding-include-${includeIndex}-tail-${tailIndex}`,
|
|
@@ -6674,10 +6670,10 @@ function createBindingTailIncludeDecisions(bindingName, include, firstHopRelatio
|
|
|
6674
6670
|
// Leave parentKey absent when RelationIR does not specify it so the
|
|
6675
6671
|
// adapter applies the same defaultPkColumnName fallback as real-table includes.
|
|
6676
6672
|
...parentKey !== void 0 && { parentKey },
|
|
6677
|
-
...targetOrder.columns.length > 0 && {
|
|
6678
|
-
|
|
6673
|
+
...targetOrder && targetOrder.columns.length > 0 && {
|
|
6674
|
+
targetOrderKey: targetOrder.columns
|
|
6679
6675
|
},
|
|
6680
|
-
...targetOrder
|
|
6676
|
+
...targetOrder?.fallback && { orderByFallback: true },
|
|
6681
6677
|
intentPath: rebaseBindingTailIntentPath(
|
|
6682
6678
|
decision.context.intentPath,
|
|
6683
6679
|
includeIndex
|
|
@@ -6698,6 +6694,13 @@ function createBindingFinalPlan(intent, bundle, model, dialectCapabilities) {
|
|
|
6698
6694
|
);
|
|
6699
6695
|
}
|
|
6700
6696
|
const proven = provenIncludes.get(include.relation);
|
|
6697
|
+
if (!proven) {
|
|
6698
|
+
throw bindingFinalIncludeError(
|
|
6699
|
+
intent.from,
|
|
6700
|
+
include.relation,
|
|
6701
|
+
"include relation proof was not emitted by the binding compiler"
|
|
6702
|
+
);
|
|
6703
|
+
}
|
|
6701
6704
|
const firstHopDecision = createBindingIncludeDecision(
|
|
6702
6705
|
intent,
|
|
6703
6706
|
include,
|
|
@@ -6848,6 +6851,14 @@ function assembleNqlTemplate(strings, values) {
|
|
|
6848
6851
|
function hasMutationBindingBodies(bundle) {
|
|
6849
6852
|
return (bundle.mutationBindings?.size ?? 0) > 0;
|
|
6850
6853
|
}
|
|
6854
|
+
function hasSnapshotReadBindingSteps(bundle) {
|
|
6855
|
+
return bundle.nqlProgramSequence?.some(
|
|
6856
|
+
(step) => step.kind === "query" && step.snapshot === true
|
|
6857
|
+
) ?? false;
|
|
6858
|
+
}
|
|
6859
|
+
function hasExecutableNqlProgramSequence(bundle) {
|
|
6860
|
+
return hasMutationBindingBodies(bundle) || hasSnapshotReadBindingSteps(bundle);
|
|
6861
|
+
}
|
|
6851
6862
|
function requireMutationBindingColumns(bundle, bindName) {
|
|
6852
6863
|
const columns = bundle.bindingOutputSchemas?.get(bindName)?.columns;
|
|
6853
6864
|
if (columns === void 0 || columns.length === 0) {
|
|
@@ -6911,6 +6922,7 @@ function orderedSequenceStepToProgramStep(step) {
|
|
|
6911
6922
|
intent: step.query,
|
|
6912
6923
|
...step.bindName !== void 0 && { bindName: step.bindName },
|
|
6913
6924
|
final: step.final,
|
|
6925
|
+
...step.snapshot === true && { snapshot: true },
|
|
6914
6926
|
...dependencyStep.bindingDependencies !== void 0 && {
|
|
6915
6927
|
bindingDependencies: dependencyStep.bindingDependencies
|
|
6916
6928
|
}
|
|
@@ -6926,15 +6938,32 @@ function orderedSequenceStepToProgramStep(step) {
|
|
|
6926
6938
|
}
|
|
6927
6939
|
};
|
|
6928
6940
|
}
|
|
6941
|
+
var structuredCloneFn = globalThis.structuredClone;
|
|
6942
|
+
function hasCustomSnapshotPrototype(value) {
|
|
6943
|
+
if (value === null || typeof value !== "object") return false;
|
|
6944
|
+
const prototype = Object.getPrototypeOf(value);
|
|
6945
|
+
return prototype !== Object.prototype && prototype !== null && prototype !== Array.prototype && prototype !== Date.prototype && prototype !== Map.prototype && prototype !== Set.prototype;
|
|
6946
|
+
}
|
|
6947
|
+
function cloneMutationSnapshotColumnValue(value) {
|
|
6948
|
+
if (hasCustomSnapshotPrototype(value) || structuredCloneFn === void 0) {
|
|
6949
|
+
return value;
|
|
6950
|
+
}
|
|
6951
|
+
try {
|
|
6952
|
+
return structuredCloneFn(value);
|
|
6953
|
+
} catch {
|
|
6954
|
+
return value;
|
|
6955
|
+
}
|
|
6956
|
+
}
|
|
6929
6957
|
function snapshotMutationRows(rows) {
|
|
6930
6958
|
return rows.map((row) => {
|
|
6931
|
-
if (
|
|
6932
|
-
return
|
|
6959
|
+
if (row === null || typeof row !== "object") {
|
|
6960
|
+
return cloneMutationSnapshotColumnValue(row);
|
|
6933
6961
|
}
|
|
6934
|
-
|
|
6935
|
-
|
|
6962
|
+
const snapshot = { ...row };
|
|
6963
|
+
for (const key of Reflect.ownKeys(snapshot)) {
|
|
6964
|
+
snapshot[key] = cloneMutationSnapshotColumnValue(snapshot[key]);
|
|
6936
6965
|
}
|
|
6937
|
-
return
|
|
6966
|
+
return snapshot;
|
|
6938
6967
|
});
|
|
6939
6968
|
}
|
|
6940
6969
|
function assertNqlProgramSteps(compiledIntent, steps) {
|
|
@@ -6958,6 +6987,13 @@ function assertNqlProgramSteps(compiledIntent, steps) {
|
|
|
6958
6987
|
}
|
|
6959
6988
|
const seenBindNames = /* @__PURE__ */ new Set();
|
|
6960
6989
|
for (const step of steps) {
|
|
6990
|
+
if (step.kind === "query" && step.snapshot === true) {
|
|
6991
|
+
if (step.bindName === void 0 || step.final) {
|
|
6992
|
+
throw new Error(
|
|
6993
|
+
"NQL program sequence query snapshots must be named non-final statements."
|
|
6994
|
+
);
|
|
6995
|
+
}
|
|
6996
|
+
}
|
|
6961
6997
|
if (step.bindName === void 0) continue;
|
|
6962
6998
|
if (seenBindNames.has(step.bindName)) {
|
|
6963
6999
|
throw new Error(
|
|
@@ -7063,6 +7099,18 @@ function filterOptionalMapByBindingDependencies(source, bindingDependencies) {
|
|
|
7063
7099
|
const filtered = filterMapByBindingDependencies(source, bindingDependencies);
|
|
7064
7100
|
return filtered.size > 0 ? filtered : void 0;
|
|
7065
7101
|
}
|
|
7102
|
+
function runtimeSourceBindingNames(sourceBundle) {
|
|
7103
|
+
const names = /* @__PURE__ */ new Set();
|
|
7104
|
+
for (const name of sourceBundle.mutationBindings?.keys() ?? []) {
|
|
7105
|
+
names.add(name);
|
|
7106
|
+
}
|
|
7107
|
+
for (const step of sourceBundle.nqlProgramSequence ?? []) {
|
|
7108
|
+
if (step.kind === "query" && step.snapshot === true && step.bindName !== void 0) {
|
|
7109
|
+
names.add(step.bindName);
|
|
7110
|
+
}
|
|
7111
|
+
}
|
|
7112
|
+
return names.size > 0 ? names : void 0;
|
|
7113
|
+
}
|
|
7066
7114
|
function filterMapByRuntimeBindingDependencies(source, runtimeSourceBindings, bindingDependencies) {
|
|
7067
7115
|
if (source === void 0) return /* @__PURE__ */ new Map();
|
|
7068
7116
|
if (bindingDependencies === void 0 || runtimeSourceBindings === void 0 || runtimeSourceBindings.size === 0) {
|
|
@@ -7202,7 +7250,7 @@ var NqlBuilderImpl = class {
|
|
|
7202
7250
|
}
|
|
7203
7251
|
dump(meta) {
|
|
7204
7252
|
const compiledIntent = this.compile();
|
|
7205
|
-
if (
|
|
7253
|
+
if (hasExecutableNqlProgramSequence(compiledIntent.bundle)) {
|
|
7206
7254
|
return this.dumpNqlProgramSequence(compiledIntent, meta);
|
|
7207
7255
|
}
|
|
7208
7256
|
if (compiledIntent.kind === "mutation") {
|
|
@@ -7285,7 +7333,7 @@ var NqlBuilderImpl = class {
|
|
|
7285
7333
|
createNqlStatementBundle(statement, bindings, runtimeBindings, sourceBundle, bindingDependencies, planReport) {
|
|
7286
7334
|
const statementBindings = filterMapByRuntimeBindingDependencies(
|
|
7287
7335
|
bindings,
|
|
7288
|
-
sourceBundle
|
|
7336
|
+
runtimeSourceBindingNames(sourceBundle),
|
|
7289
7337
|
bindingDependencies
|
|
7290
7338
|
);
|
|
7291
7339
|
const statementRuntimeBindings = filterMapByBindingDependencies(
|
|
@@ -7425,6 +7473,28 @@ var NqlBuilderImpl = class {
|
|
|
7425
7473
|
if (step.final) {
|
|
7426
7474
|
finalRows = rows.transformedRows;
|
|
7427
7475
|
}
|
|
7476
|
+
} else if (step.snapshot === true && step.bindName !== void 0) {
|
|
7477
|
+
const statementBundle = this.createNqlStatementBundle(
|
|
7478
|
+
{ query: step.intent },
|
|
7479
|
+
priorBindings,
|
|
7480
|
+
runtimeBindings,
|
|
7481
|
+
sourceBundle,
|
|
7482
|
+
step.bindingDependencies
|
|
7483
|
+
);
|
|
7484
|
+
const compiled = txAdapter.compile(
|
|
7485
|
+
statementBundle,
|
|
7486
|
+
this.nqlBundleCompileOptions()
|
|
7487
|
+
);
|
|
7488
|
+
const rows = await txAdapter.execute(compiled);
|
|
7489
|
+
runtimeBindings.set(
|
|
7490
|
+
step.bindName,
|
|
7491
|
+
createRuntimeBinding(
|
|
7492
|
+
sourceBundle,
|
|
7493
|
+
step.bindName,
|
|
7494
|
+
snapshotMutationRows(rows),
|
|
7495
|
+
txAdapter.dbCasing
|
|
7496
|
+
)
|
|
7497
|
+
);
|
|
7428
7498
|
} else if (step.final) {
|
|
7429
7499
|
const planReport = isBindingFinalQuery(compiledIntent.bundle) && compiledIntent.kind === "query" ? createBindingFinalPlan(
|
|
7430
7500
|
step.intent,
|
|
@@ -7516,6 +7586,12 @@ var NqlBuilderImpl = class {
|
|
|
7516
7586
|
sql: compiled.sql,
|
|
7517
7587
|
params: compiled.parameters
|
|
7518
7588
|
});
|
|
7589
|
+
if (step.snapshot === true && step.bindName !== void 0) {
|
|
7590
|
+
runtimeBindings.set(step.bindName, {
|
|
7591
|
+
columns: requireMutationBindingColumns(sourceBundle, step.bindName),
|
|
7592
|
+
rows: []
|
|
7593
|
+
});
|
|
7594
|
+
}
|
|
7519
7595
|
}
|
|
7520
7596
|
if (step.bindName !== void 0) {
|
|
7521
7597
|
const boundQuery = sourceBundle.bindings?.get(step.bindName);
|
|
@@ -7595,7 +7671,7 @@ var NqlBuilderImpl = class {
|
|
|
7595
7671
|
);
|
|
7596
7672
|
}
|
|
7597
7673
|
const compiledIntent = this.compile();
|
|
7598
|
-
if (
|
|
7674
|
+
if (hasExecutableNqlProgramSequence(compiledIntent.bundle)) {
|
|
7599
7675
|
return this.executeNqlProgramSequence(compiledIntent, adapter);
|
|
7600
7676
|
}
|
|
7601
7677
|
if (compiledIntent.kind === "mutation") {
|
|
@@ -7940,7 +8016,7 @@ async function cursorPaginate(builder, options) {
|
|
|
7940
8016
|
}
|
|
7941
8017
|
|
|
7942
8018
|
// src/dx/result-hydrator.ts
|
|
7943
|
-
import { toColumnList as
|
|
8019
|
+
import { toColumnList as toColumnList2 } from "@dbsp/types";
|
|
7944
8020
|
|
|
7945
8021
|
// src/dx/relation-paths.ts
|
|
7946
8022
|
function nonEmptyString(value) {
|
|
@@ -8317,7 +8393,7 @@ var ResultHydrator = class {
|
|
|
8317
8393
|
* Get the foreign key column name from relation metadata.
|
|
8318
8394
|
*/
|
|
8319
8395
|
getForeignKeyColumn(foreignKey) {
|
|
8320
|
-
const columns =
|
|
8396
|
+
const columns = toColumnList2(foreignKey);
|
|
8321
8397
|
if (columns.length === 0) {
|
|
8322
8398
|
return "parent_id";
|
|
8323
8399
|
}
|
|
@@ -8418,7 +8494,7 @@ var ResultHydrator = class {
|
|
|
8418
8494
|
* case (slower but collision-safe for any value content).
|
|
8419
8495
|
*/
|
|
8420
8496
|
extractKeyValue(obj, key) {
|
|
8421
|
-
const columns =
|
|
8497
|
+
const columns = toColumnList2(key);
|
|
8422
8498
|
if (columns.length === 0) {
|
|
8423
8499
|
return void 0;
|
|
8424
8500
|
}
|
|
@@ -8436,7 +8512,7 @@ var ResultHydrator = class {
|
|
|
8436
8512
|
return parts.join(COMPOSITE_KEY_SEP);
|
|
8437
8513
|
}
|
|
8438
8514
|
extractQueryKeyValue(obj, key) {
|
|
8439
|
-
const columns =
|
|
8515
|
+
const columns = toColumnList2(key);
|
|
8440
8516
|
if (columns.length === 0) {
|
|
8441
8517
|
return void 0;
|
|
8442
8518
|
}
|
|
@@ -10867,6 +10943,7 @@ function rangeContainedBy(fieldOrColumn, valueOrRange, rangeType = "daterange")
|
|
|
10867
10943
|
}
|
|
10868
10944
|
|
|
10869
10945
|
// src/dx/schema-bridge.ts
|
|
10946
|
+
import { buildRelationKeyFields, toColumnList as toColumnList3 } from "@dbsp/types";
|
|
10870
10947
|
import * as v from "valibot";
|
|
10871
10948
|
function generatedTypeToColumnType(genType) {
|
|
10872
10949
|
switch (genType) {
|
|
@@ -10919,6 +10996,37 @@ function mapRelationType2(kind) {
|
|
|
10919
10996
|
return "belongsToMany";
|
|
10920
10997
|
}
|
|
10921
10998
|
}
|
|
10999
|
+
function sourceTableFromQualifiedName(qualifiedName) {
|
|
11000
|
+
const dotIndex = qualifiedName.indexOf(".");
|
|
11001
|
+
return dotIndex > 0 ? qualifiedName.slice(0, dotIndex) : qualifiedName;
|
|
11002
|
+
}
|
|
11003
|
+
function relationNameFromQualifiedName(qualifiedName) {
|
|
11004
|
+
const dotIndex = qualifiedName.indexOf(".");
|
|
11005
|
+
return dotIndex > 0 ? qualifiedName.slice(dotIndex + 1) : qualifiedName;
|
|
11006
|
+
}
|
|
11007
|
+
function columnListsEqual(left, right) {
|
|
11008
|
+
const leftColumns = toColumnList3(left);
|
|
11009
|
+
const rightColumns = toColumnList3(right);
|
|
11010
|
+
return leftColumns.length === rightColumns.length && leftColumns.every((column, index) => column === rightColumns[index]);
|
|
11011
|
+
}
|
|
11012
|
+
function generatedReferencedColumns(key) {
|
|
11013
|
+
const columns = toColumnList3(key);
|
|
11014
|
+
return columns.length > 0 ? columns : ["id"];
|
|
11015
|
+
}
|
|
11016
|
+
function findRelationForeignKey(sourceTable, genRelation, tables) {
|
|
11017
|
+
switch (genRelation.kind) {
|
|
11018
|
+
case "belongsTo":
|
|
11019
|
+
return tables.get(sourceTable)?.foreignKeys.find(
|
|
11020
|
+
(fk) => fk.references.table === genRelation.target && columnListsEqual(fk.columns, genRelation.foreignKey)
|
|
11021
|
+
);
|
|
11022
|
+
case "hasMany":
|
|
11023
|
+
return tables.get(genRelation.target)?.foreignKeys.find(
|
|
11024
|
+
(fk) => fk.references.table === sourceTable && columnListsEqual(fk.columns, genRelation.foreignKey)
|
|
11025
|
+
);
|
|
11026
|
+
case "manyToMany":
|
|
11027
|
+
return void 0;
|
|
11028
|
+
}
|
|
11029
|
+
}
|
|
10922
11030
|
function isGeneratedTableWithConfig(table) {
|
|
10923
11031
|
const columns = table.columns;
|
|
10924
11032
|
return typeof columns === "object" && columns !== null && typeof columns.type !== "string";
|
|
@@ -11046,10 +11154,9 @@ function buildTableIRFromDefinition(tableName, genTable, fkAutoIndex) {
|
|
|
11046
11154
|
}
|
|
11047
11155
|
});
|
|
11048
11156
|
}
|
|
11049
|
-
function buildRelationIR(qualifiedName, genRelation, hints) {
|
|
11050
|
-
const
|
|
11051
|
-
const
|
|
11052
|
-
const relationName = dotIndex > 0 ? qualifiedName.slice(dotIndex + 1) : qualifiedName;
|
|
11157
|
+
function buildRelationIR(qualifiedName, genRelation, hints, relationFk) {
|
|
11158
|
+
const sourceTable = sourceTableFromQualifiedName(qualifiedName);
|
|
11159
|
+
const relationName = relationNameFromQualifiedName(qualifiedName);
|
|
11053
11160
|
const hint = hints[qualifiedName];
|
|
11054
11161
|
const relCardinality = genRelation.kind === "hasMany" ? genRelation.cardinality : void 0;
|
|
11055
11162
|
const cardinality = hint?.cardinality === "one" ? "one" : relCardinality === "one" ? "one" : genRelation.kind === "belongsTo" ? "one" : "many";
|
|
@@ -11073,14 +11180,38 @@ function buildRelationIR(qualifiedName, genRelation, hints) {
|
|
|
11073
11180
|
case "belongsTo":
|
|
11074
11181
|
return {
|
|
11075
11182
|
...baseRelation,
|
|
11076
|
-
|
|
11077
|
-
|
|
11183
|
+
...buildRelationKeyFields(
|
|
11184
|
+
relationFk ?? {
|
|
11185
|
+
columns: genRelation.foreignKey,
|
|
11186
|
+
references: {
|
|
11187
|
+
table: genRelation.target,
|
|
11188
|
+
columns: generatedReferencedColumns(genRelation.targetKey)
|
|
11189
|
+
}
|
|
11190
|
+
},
|
|
11191
|
+
"belongsTo",
|
|
11192
|
+
{
|
|
11193
|
+
foreignKeyShape: genRelation.foreignKey,
|
|
11194
|
+
...genRelation.targetKey !== void 0 ? { referencedKeyShape: genRelation.targetKey } : {}
|
|
11195
|
+
}
|
|
11196
|
+
)
|
|
11078
11197
|
};
|
|
11079
11198
|
case "hasMany":
|
|
11080
11199
|
return {
|
|
11081
11200
|
...baseRelation,
|
|
11082
|
-
|
|
11083
|
-
|
|
11201
|
+
...buildRelationKeyFields(
|
|
11202
|
+
relationFk ?? {
|
|
11203
|
+
columns: genRelation.foreignKey,
|
|
11204
|
+
references: {
|
|
11205
|
+
table: sourceTable,
|
|
11206
|
+
columns: generatedReferencedColumns(genRelation.sourceKey)
|
|
11207
|
+
}
|
|
11208
|
+
},
|
|
11209
|
+
"inverse",
|
|
11210
|
+
{
|
|
11211
|
+
foreignKeyShape: genRelation.foreignKey,
|
|
11212
|
+
...genRelation.sourceKey !== void 0 ? { referencedKeyShape: genRelation.sourceKey } : {}
|
|
11213
|
+
}
|
|
11214
|
+
)
|
|
11084
11215
|
};
|
|
11085
11216
|
case "manyToMany":
|
|
11086
11217
|
return {
|
|
@@ -11102,9 +11233,15 @@ function buildModelFromSchema(schema2) {
|
|
|
11102
11233
|
);
|
|
11103
11234
|
}
|
|
11104
11235
|
for (const [qualifiedName, genRelation] of Object.entries(schema2.relations)) {
|
|
11236
|
+
const sourceTable = sourceTableFromQualifiedName(qualifiedName);
|
|
11105
11237
|
relations.set(
|
|
11106
11238
|
qualifiedName,
|
|
11107
|
-
buildRelationIR(
|
|
11239
|
+
buildRelationIR(
|
|
11240
|
+
qualifiedName,
|
|
11241
|
+
genRelation,
|
|
11242
|
+
schema2.hints,
|
|
11243
|
+
findRelationForeignKey(sourceTable, genRelation, tables)
|
|
11244
|
+
)
|
|
11108
11245
|
);
|
|
11109
11246
|
}
|
|
11110
11247
|
return new ModelIRImpl(tables, relations);
|