prisma-sql 1.75.4 → 1.75.6

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 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=${depth} costW=${costW.toFixed(0)} costC=${costC.toFixed(0)}`
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 && value._count !== void 0) {
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).filter(([, v]) => v !== void 0);
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 joins = [];
5628
- const usedAliases = /* @__PURE__ */ new Set();
5629
- let relAliasCounter = 0;
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 nestedEntries = Object.entries(value);
5646
- if (nestedEntries.length === 0) continue;
5647
- if ("_count" in value) {
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
- joinAlias
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
- if (sql) orderFragments.push(sql);
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