prisma-sql 1.75.4 → 1.75.5
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/generator.cjs +119 -69
- package/dist/generator.cjs.map +1 -1
- package/dist/generator.js +119 -69
- package/dist/generator.js.map +1 -1
- package/dist/index.cjs +112 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +112 -62
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/dist/index.cjs
CHANGED
|
@@ -2374,6 +2374,12 @@ function maxDepthFromTree(nodes) {
|
|
|
2374
2374
|
}
|
|
2375
2375
|
return max;
|
|
2376
2376
|
}
|
|
2377
|
+
function anyChildHasWhere(nodes) {
|
|
2378
|
+
for (const n of nodes) {
|
|
2379
|
+
if (n.hasChildWhere) return true;
|
|
2380
|
+
}
|
|
2381
|
+
return false;
|
|
2382
|
+
}
|
|
2377
2383
|
function computeWhereInCost(nodes, parentCount) {
|
|
2378
2384
|
const R = globalRoundtripRowEquivalent;
|
|
2379
2385
|
let totalRows = 0;
|
|
@@ -2477,13 +2483,18 @@ function pickIncludeStrategy(params) {
|
|
|
2477
2483
|
}
|
|
2478
2484
|
}
|
|
2479
2485
|
const costTree = buildCostTree(includeSpec, model, schemas);
|
|
2486
|
+
const treeDepth = maxDepthFromTree(costTree);
|
|
2487
|
+
if (treeDepth === 1 && anyChildHasWhere(costTree)) {
|
|
2488
|
+
if (debug)
|
|
2489
|
+
console.log(` [strategy] ${model.name}: depth-1 + childWhere \u2192 where-in`);
|
|
2490
|
+
return "where-in";
|
|
2491
|
+
}
|
|
2480
2492
|
const P = isSingleParent ? 1 : takeValue != null ? takeValue : DEFAULT_PARENT_COUNT;
|
|
2481
2493
|
const costW = computeWhereInCost(costTree, P);
|
|
2482
2494
|
const costC = computeCorrelatedCost(costTree, P);
|
|
2483
2495
|
if (debug) {
|
|
2484
|
-
const depth = maxDepthFromTree(costTree);
|
|
2485
2496
|
console.log(
|
|
2486
|
-
` [strategy] ${model.name}: P=${P} D=${
|
|
2497
|
+
` [strategy] ${model.name}: P=${P} D=${treeDepth} costW=${costW.toFixed(0)} costC=${costC.toFixed(0)}`
|
|
2487
2498
|
);
|
|
2488
2499
|
}
|
|
2489
2500
|
if (costC < costW) {
|
|
@@ -5608,6 +5619,7 @@ function buildIncludeSql(args, model, schemas, parentAlias, params, dialect, out
|
|
|
5608
5619
|
}
|
|
5609
5620
|
|
|
5610
5621
|
// src/builder/shared/order-by-relation.ts
|
|
5622
|
+
var MAX_RELATION_ORDER_BY_DEPTH = 10;
|
|
5611
5623
|
function resolveTableRef(model, dialect) {
|
|
5612
5624
|
const tableName = model.tableName || model.dbName || model.name;
|
|
5613
5625
|
if (dialect === "sqlite") {
|
|
@@ -5619,6 +5631,90 @@ function resolveTableRef(model, dialect) {
|
|
|
5619
5631
|
function findRelationField(model, fieldName) {
|
|
5620
5632
|
return model.fields.find((f) => f.name === fieldName && f.isRelation);
|
|
5621
5633
|
}
|
|
5634
|
+
function nextJoinAlias(ctx) {
|
|
5635
|
+
let alias;
|
|
5636
|
+
do {
|
|
5637
|
+
alias = `ob_${ctx.aliasCounter.value++}`;
|
|
5638
|
+
} while (ctx.usedAliases.has(alias));
|
|
5639
|
+
ctx.usedAliases.add(alias);
|
|
5640
|
+
return alias;
|
|
5641
|
+
}
|
|
5642
|
+
function resolveRelationOrderByChain(relationFieldName, value, currentModel, currentAlias, ctx, depth) {
|
|
5643
|
+
if (depth > MAX_RELATION_ORDER_BY_DEPTH) {
|
|
5644
|
+
throw new Error(
|
|
5645
|
+
`Relation orderBy nesting too deep (max ${MAX_RELATION_ORDER_BY_DEPTH} levels)`
|
|
5646
|
+
);
|
|
5647
|
+
}
|
|
5648
|
+
if ("_count" in value) {
|
|
5649
|
+
throw new Error(
|
|
5650
|
+
`Relation orderBy with _count on '${relationFieldName}' is not yet supported by prisma-sql`
|
|
5651
|
+
);
|
|
5652
|
+
}
|
|
5653
|
+
const field = findRelationField(currentModel, relationFieldName);
|
|
5654
|
+
if (!field) {
|
|
5655
|
+
throw new Error(
|
|
5656
|
+
`Relation field '${relationFieldName}' not found on model ${currentModel.name}`
|
|
5657
|
+
);
|
|
5658
|
+
}
|
|
5659
|
+
const relatedModel = getModelByName(ctx.schemas, field.relatedModel);
|
|
5660
|
+
if (!relatedModel) {
|
|
5661
|
+
throw new Error(
|
|
5662
|
+
`Related model '${field.relatedModel}' not found for relation '${relationFieldName}'`
|
|
5663
|
+
);
|
|
5664
|
+
}
|
|
5665
|
+
const joinAlias = nextJoinAlias(ctx);
|
|
5666
|
+
const tableRef = resolveTableRef(relatedModel, ctx.dialect);
|
|
5667
|
+
const cond = joinCondition(
|
|
5668
|
+
field,
|
|
5669
|
+
currentModel,
|
|
5670
|
+
relatedModel,
|
|
5671
|
+
currentAlias,
|
|
5672
|
+
joinAlias
|
|
5673
|
+
);
|
|
5674
|
+
ctx.joins.push(`LEFT JOIN ${tableRef} ${joinAlias} ON ${cond}`);
|
|
5675
|
+
const relScalarSet = getScalarFieldSet(relatedModel);
|
|
5676
|
+
const relRelationSet = getRelationFieldSet(relatedModel);
|
|
5677
|
+
const nestedEntries = Object.entries(value);
|
|
5678
|
+
const orderFragments = [];
|
|
5679
|
+
for (const [nestedField, nestedValue] of nestedEntries) {
|
|
5680
|
+
if (relScalarSet.has(nestedField)) {
|
|
5681
|
+
const entries = normalizeAndValidateOrderBy(
|
|
5682
|
+
[{ [nestedField]: nestedValue }],
|
|
5683
|
+
relatedModel,
|
|
5684
|
+
parseOrderByValue
|
|
5685
|
+
);
|
|
5686
|
+
const sql = buildOrderByFragment(
|
|
5687
|
+
entries,
|
|
5688
|
+
joinAlias,
|
|
5689
|
+
ctx.dialect,
|
|
5690
|
+
relatedModel
|
|
5691
|
+
);
|
|
5692
|
+
if (sql) orderFragments.push(sql);
|
|
5693
|
+
continue;
|
|
5694
|
+
}
|
|
5695
|
+
if (relRelationSet.has(nestedField)) {
|
|
5696
|
+
if (!isPlainObject(nestedValue)) {
|
|
5697
|
+
throw new Error(
|
|
5698
|
+
`Relation orderBy for '${nestedField}' must be an object`
|
|
5699
|
+
);
|
|
5700
|
+
}
|
|
5701
|
+
const nested = resolveRelationOrderByChain(
|
|
5702
|
+
nestedField,
|
|
5703
|
+
nestedValue,
|
|
5704
|
+
relatedModel,
|
|
5705
|
+
joinAlias,
|
|
5706
|
+
ctx,
|
|
5707
|
+
depth + 1
|
|
5708
|
+
);
|
|
5709
|
+
orderFragments.push(...nested);
|
|
5710
|
+
continue;
|
|
5711
|
+
}
|
|
5712
|
+
throw new Error(
|
|
5713
|
+
`orderBy field '${nestedField}' does not exist on related model '${relatedModel.name}'`
|
|
5714
|
+
);
|
|
5715
|
+
}
|
|
5716
|
+
return orderFragments;
|
|
5717
|
+
}
|
|
5622
5718
|
function buildOrderByWithRelations(orderBy, alias, dialect, model, schemas) {
|
|
5623
5719
|
if (!isNotNullish(orderBy)) return { sql: "", joins: [] };
|
|
5624
5720
|
const expanded = expandOrderByInput(orderBy);
|
|
@@ -5626,9 +5722,13 @@ function buildOrderByWithRelations(orderBy, alias, dialect, model, schemas) {
|
|
|
5626
5722
|
const relationSet = getRelationFieldSet(model);
|
|
5627
5723
|
const scalarSet = getScalarFieldSet(model);
|
|
5628
5724
|
const orderFragments = [];
|
|
5629
|
-
const
|
|
5630
|
-
|
|
5631
|
-
|
|
5725
|
+
const ctx = {
|
|
5726
|
+
schemas,
|
|
5727
|
+
dialect,
|
|
5728
|
+
joins: [],
|
|
5729
|
+
usedAliases: /* @__PURE__ */ new Set(),
|
|
5730
|
+
aliasCounter: { value: 0 }
|
|
5731
|
+
};
|
|
5632
5732
|
for (const [fieldName, value] of expanded) {
|
|
5633
5733
|
if (scalarSet.has(fieldName)) {
|
|
5634
5734
|
const entries = normalizeAndValidateOrderBy(
|
|
@@ -5644,65 +5744,15 @@ function buildOrderByWithRelations(orderBy, alias, dialect, model, schemas) {
|
|
|
5644
5744
|
if (!isPlainObject(value)) {
|
|
5645
5745
|
throw new Error(`Relation orderBy for '${fieldName}' must be an object`);
|
|
5646
5746
|
}
|
|
5647
|
-
const
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
throw new Error(
|
|
5651
|
-
`Relation orderBy with _count on '${fieldName}' is not yet supported by prisma-sql`
|
|
5652
|
-
);
|
|
5653
|
-
}
|
|
5654
|
-
const field = findRelationField(model, fieldName);
|
|
5655
|
-
if (!field) {
|
|
5656
|
-
throw new Error(
|
|
5657
|
-
`Relation field '${fieldName}' not found on model ${model.name}`
|
|
5658
|
-
);
|
|
5659
|
-
}
|
|
5660
|
-
const relatedModel = getModelByName(schemas, field.relatedModel);
|
|
5661
|
-
if (!relatedModel) {
|
|
5662
|
-
throw new Error(
|
|
5663
|
-
`Related model '${field.relatedModel}' not found for relation '${fieldName}'`
|
|
5664
|
-
);
|
|
5665
|
-
}
|
|
5666
|
-
const relScalarSet = getScalarFieldSet(relatedModel);
|
|
5667
|
-
const relRelationSet = getRelationFieldSet(relatedModel);
|
|
5668
|
-
for (const [nestedField] of nestedEntries) {
|
|
5669
|
-
if (relRelationSet.has(nestedField)) {
|
|
5670
|
-
throw new Error(
|
|
5671
|
-
`Nested relation orderBy (${fieldName}.${nestedField}) is not yet supported by prisma-sql`
|
|
5672
|
-
);
|
|
5673
|
-
}
|
|
5674
|
-
if (!relScalarSet.has(nestedField)) {
|
|
5675
|
-
throw new Error(
|
|
5676
|
-
`orderBy field '${nestedField}' does not exist on related model '${relatedModel.name}'`
|
|
5677
|
-
);
|
|
5678
|
-
}
|
|
5679
|
-
}
|
|
5680
|
-
let joinAlias;
|
|
5681
|
-
do {
|
|
5682
|
-
joinAlias = `ob_${relAliasCounter++}`;
|
|
5683
|
-
} while (usedAliases.has(joinAlias));
|
|
5684
|
-
usedAliases.add(joinAlias);
|
|
5685
|
-
const tableRef = resolveTableRef(relatedModel, dialect);
|
|
5686
|
-
const cond = joinCondition(
|
|
5687
|
-
field,
|
|
5747
|
+
const fragments = resolveRelationOrderByChain(
|
|
5748
|
+
fieldName,
|
|
5749
|
+
value,
|
|
5688
5750
|
model,
|
|
5689
|
-
relatedModel,
|
|
5690
5751
|
alias,
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
joins.push(`LEFT JOIN ${tableRef} ${joinAlias} ON ${cond}`);
|
|
5694
|
-
const entries = normalizeAndValidateOrderBy(
|
|
5695
|
-
[value],
|
|
5696
|
-
relatedModel,
|
|
5697
|
-
parseOrderByValue
|
|
5698
|
-
);
|
|
5699
|
-
const sql = buildOrderByFragment(
|
|
5700
|
-
entries,
|
|
5701
|
-
joinAlias,
|
|
5702
|
-
dialect,
|
|
5703
|
-
relatedModel
|
|
5752
|
+
ctx,
|
|
5753
|
+
0
|
|
5704
5754
|
);
|
|
5705
|
-
|
|
5755
|
+
orderFragments.push(...fragments);
|
|
5706
5756
|
continue;
|
|
5707
5757
|
}
|
|
5708
5758
|
throw new Error(
|
|
@@ -5711,7 +5761,7 @@ function buildOrderByWithRelations(orderBy, alias, dialect, model, schemas) {
|
|
|
5711
5761
|
}
|
|
5712
5762
|
return {
|
|
5713
5763
|
sql: orderFragments.join(SQL_SEPARATORS.ORDER_BY),
|
|
5714
|
-
joins
|
|
5764
|
+
joins: ctx.joins
|
|
5715
5765
|
};
|
|
5716
5766
|
}
|
|
5717
5767
|
|