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