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/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=${depth} costW=${costW.toFixed(0)} costC=${costC.toFixed(0)}`
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 joins = [];
5630
- const usedAliases = /* @__PURE__ */ new Set();
5631
- let relAliasCounter = 0;
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 nestedEntries = Object.entries(value);
5648
- if (nestedEntries.length === 0) continue;
5649
- if ("_count" in value) {
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
- joinAlias
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
- if (sql) orderFragments.push(sql);
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