@prisma/orm-family-sql 0.17.0-dev.7 → 0.17.0-dev.9

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.
@@ -2459,7 +2459,91 @@ function isCollectionState(value) {
2459
2459
  function hasThrough$1(relation) {
2460
2460
  return relation.through !== void 0;
2461
2461
  }
2462
+ var SqlTableBinding = class SqlTableBinding {
2463
+ #storage;
2464
+ #reference;
2465
+ constructor(storage, reference) {
2466
+ this.#storage = Object.freeze({ ...storage });
2467
+ this.#reference = reference;
2468
+ Object.freeze(this);
2469
+ }
2470
+ static unaliased(storage) {
2471
+ return new SqlTableBinding(storage, storage.tableName);
2472
+ }
2473
+ static aliased(storage, alias) {
2474
+ return new SqlTableBinding(storage, alias);
2475
+ }
2476
+ column(columnName) {
2477
+ return ColumnRef.of(this.#reference, columnName);
2478
+ }
2479
+ tableSource(contract) {
2480
+ return tableSourceForContract(contract, this.#storage.namespaceId, this.#storage.tableName, this.#reference);
2481
+ }
2482
+ isReferencedAs(candidate) {
2483
+ return this.#reference === candidate;
2484
+ }
2485
+ isStoredAt(namespaceId, tableName) {
2486
+ return this.#storage.namespaceId === namespaceId && this.#storage.tableName === tableName;
2487
+ }
2488
+ };
2489
+ var ModelAccessorScope = class ModelAccessorScope {
2490
+ current;
2491
+ #visibleBindings;
2492
+ #aliasCounter;
2493
+ constructor(current, visibleBindings, aliasCounter) {
2494
+ this.current = current;
2495
+ this.#visibleBindings = Object.freeze([...visibleBindings]);
2496
+ this.#aliasCounter = aliasCounter;
2497
+ Object.freeze(this);
2498
+ }
2499
+ static root(namespaceId, tableName) {
2500
+ const binding = SqlTableBinding.unaliased({
2501
+ namespaceId,
2502
+ tableName
2503
+ });
2504
+ return new ModelAccessorScope(binding, [binding], { nextId: 1 });
2505
+ }
2506
+ forRelation(namespaceId, tableName) {
2507
+ const binding = this.#allocateBinding(namespaceId, tableName, "rel");
2508
+ return new ModelAccessorScope(binding, [...this.#visibleBindings, binding], this.#aliasCounter);
2509
+ }
2510
+ forManyToManyRelation(childNamespaceId, childTableName, junctionNamespaceId, junctionTableName) {
2511
+ const initialChildScope = this.forRelation(childNamespaceId, childTableName);
2512
+ const junctionBinding = initialChildScope.#allocateBinding(junctionNamespaceId, junctionTableName, "junction");
2513
+ return {
2514
+ childScope: new ModelAccessorScope(initialChildScope.current, [...initialChildScope.#visibleBindings, junctionBinding], this.#aliasCounter),
2515
+ junctionBinding
2516
+ };
2517
+ }
2518
+ forJoinedSource(namespaceId, tableName) {
2519
+ if (this.current.isStoredAt(namespaceId, tableName)) return this;
2520
+ const binding = SqlTableBinding.unaliased({
2521
+ namespaceId,
2522
+ tableName
2523
+ });
2524
+ return new ModelAccessorScope(binding, [...this.#visibleBindings, binding], this.#aliasCounter);
2525
+ }
2526
+ #allocateBinding(namespaceId, tableName, aliasKind) {
2527
+ const storage = {
2528
+ namespaceId,
2529
+ tableName
2530
+ };
2531
+ if (!this.#visibleBindings.some((binding) => binding.isReferencedAs(tableName))) return SqlTableBinding.unaliased(storage);
2532
+ return SqlTableBinding.aliased(storage, this.#allocateAlias(aliasKind));
2533
+ }
2534
+ #allocateAlias(kind) {
2535
+ while (true) {
2536
+ const alias = `__orm_${kind}_${this.#aliasCounter.nextId}`;
2537
+ this.#aliasCounter.nextId += 1;
2538
+ if (!this.#visibleBindings.some((binding) => binding.isReferencedAs(alias))) return alias;
2539
+ }
2540
+ }
2541
+ };
2462
2542
  function createModelAccessor(context, namespaceId, modelName, variantName) {
2543
+ const tableName = resolveModelTableName(context.contract, namespaceId, modelName);
2544
+ return createModelAccessorInScope(context, namespaceId, modelName, variantName, ModelAccessorScope.root(namespaceId, tableName));
2545
+ }
2546
+ function createModelAccessorInScope(context, namespaceId, modelName, variantName, scope) {
2463
2547
  const contract = context.contract;
2464
2548
  const fieldToColumn = getFieldToColumnMap(contract, namespaceId, modelName);
2465
2549
  const tableName = resolveModelTableName(contract, namespaceId, modelName);
@@ -2493,19 +2577,20 @@ function createModelAccessor(context, namespaceId, modelName, variantName) {
2493
2577
  if (typeof prop !== "string") return;
2494
2578
  if (variantCoordinates) {
2495
2579
  const variantRelation = variantCoordinates.relations[prop];
2496
- if (variantRelation) return createRelationFilterAccessor(context, namespaceId, variantCoordinates.name, variantCoordinates.tableName, prop, variantRelation);
2580
+ if (variantRelation) return createRelationFilterAccessor(context, namespaceId, variantCoordinates.name, scope.forJoinedSource(namespaceId, variantCoordinates.tableName), variantRelation);
2497
2581
  }
2498
2582
  const relation = modelRelations[prop];
2499
- if (relation) return createRelationFilterAccessor(context, namespaceId, modelName, tableName, prop, relation);
2583
+ if (relation) return createRelationFilterAccessor(context, namespaceId, modelName, scope, relation);
2500
2584
  const variantField = variantFieldColumns[prop];
2501
2585
  const resolvedTable = variantField?.table ?? tableName;
2586
+ const fieldBinding = scope.forJoinedSource(namespaceId, resolvedTable).current;
2502
2587
  const columnName = variantField?.column ?? fieldToColumn[prop] ?? prop;
2503
2588
  const column = resolveColumn(contract, namespaceId, resolvedTable, columnName);
2504
2589
  if (!column) return;
2505
2590
  const traits = context.codecDescriptors.descriptorFor(column.codecId)?.traits ?? [];
2506
2591
  const operations = opsByCodecId.get(column.codecId) ?? [];
2507
2592
  const codec = codecRefForStorageColumn(contract.storage, namespaceId, resolvedTable, columnName);
2508
- return createScalarFieldAccessor(resolvedTable, columnName, column.codecId, column.nullable, codec, traits, operations, context);
2593
+ return createScalarFieldAccessor(fieldBinding, columnName, column.codecId, column.nullable, codec, traits, operations, context);
2509
2594
  } }));
2510
2595
  }
2511
2596
  function resolveColumn(contract, namespaceId, tableName, columnName) {
@@ -2522,8 +2607,8 @@ function resolveColumn(contract, namespaceId, tableName, columnName) {
2522
2607
  nullable: column.nullable
2523
2608
  };
2524
2609
  }
2525
- function createScalarFieldAccessor(tableName, columnName, codecId, nullable, codec, traits, operations, context) {
2526
- const column = ColumnRef.of(tableName, columnName);
2610
+ function createScalarFieldAccessor(tableBinding, columnName, codecId, nullable, codec, traits, operations, context) {
2611
+ const column = tableBinding.column(columnName);
2527
2612
  const comparisonEntries = [];
2528
2613
  for (const [name, meta] of Object.entries(COMPARISON_METHODS_META)) {
2529
2614
  if (meta.traits.some((t) => !traits.includes(t))) continue;
@@ -2558,42 +2643,41 @@ function createExtensionMethodFactory(selfExpr, entry, context) {
2558
2643
  return methods;
2559
2644
  };
2560
2645
  }
2561
- function createRelationFilterAccessor(context, parentNamespaceId, parentModelName, parentTableName, relationName, relation) {
2646
+ function createRelationFilterAccessor(context, parentNamespaceId, parentModelName, parentScope, relation) {
2562
2647
  const relatedTableName = resolveModelTableName(context.contract, relation.toNamespace, relation.to);
2563
2648
  return {
2564
- some: (predicate) => buildExistsExpr(context, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relationName, relation, {
2649
+ some: (predicate) => buildExistsExpr(context, parentNamespaceId, parentModelName, parentScope, relatedTableName, relation, {
2565
2650
  mode: "some",
2566
2651
  predicate
2567
2652
  }),
2568
- every: (predicate) => buildExistsExpr(context, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relationName, relation, {
2653
+ every: (predicate) => buildExistsExpr(context, parentNamespaceId, parentModelName, parentScope, relatedTableName, relation, {
2569
2654
  mode: "every",
2570
2655
  predicate
2571
2656
  }),
2572
- none: (predicate) => buildExistsExpr(context, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relationName, relation, {
2657
+ none: (predicate) => buildExistsExpr(context, parentNamespaceId, parentModelName, parentScope, relatedTableName, relation, {
2573
2658
  mode: "none",
2574
2659
  predicate
2575
2660
  })
2576
2661
  };
2577
2662
  }
2578
- function buildExistsExpr(context, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relationName, relation, options) {
2579
- if (hasThrough$1(relation)) return buildManyToManyExistsExpr(context, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relationName, relation, options);
2580
- const filterPlan = planRelationFilterMode(buildJoinWhere(context.contract, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relation), toRelationWhereExpr(context, relation.toNamespace, relation.to, options.predicate), options.mode);
2663
+ function buildExistsExpr(context, parentNamespaceId, parentModelName, parentScope, relatedTableName, relation, options) {
2664
+ if (hasThrough$1(relation)) return buildManyToManyExistsExpr(context, parentNamespaceId, parentModelName, parentScope, relatedTableName, relation, options);
2665
+ const childScope = parentScope.forRelation(relation.toNamespace, relatedTableName);
2666
+ const filterPlan = planRelationFilterMode(buildJoinWhere(context.contract, parentNamespaceId, parentModelName, parentScope.current, childScope.current, relation), toRelationWhereExpr(context, relation.toNamespace, relation.to, options.predicate, childScope), options.mode);
2581
2667
  if (filterPlan.kind === "constantTrue") return AndExpr.true();
2582
2668
  const selectProjectionColumn = firstTargetColumn(context.contract, relation) ?? "id";
2583
- const subquery = SelectAst.from(tableSourceForContract(context.contract, relation.toNamespace, relatedTableName)).withProjection([ProjectionItem.of("_exists", ColumnRef.of(relatedTableName, selectProjectionColumn))]).withWhere(filterPlan.where);
2669
+ const subquery = SelectAst.from(childScope.current.tableSource(context.contract)).withProjection([ProjectionItem.of("_exists", childScope.current.column(selectProjectionColumn))]).withWhere(filterPlan.where);
2584
2670
  return filterPlan.notExists ? ExistsExpr.notExists(subquery) : ExistsExpr.exists(subquery);
2585
2671
  }
2586
- function buildManyToManyExistsExpr(context, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relationName, relation, options) {
2672
+ function buildManyToManyExistsExpr(context, parentNamespaceId, parentModelName, parentScope, relatedTableName, relation, options) {
2587
2673
  const { through } = relation;
2588
- const junctionTable = through.table;
2589
- const relatedTableAlias = parentNamespaceId === relation.toNamespace && parentTableName === relatedTableName ? `${relationName}__child` : void 0;
2590
- const relatedTableRef = relatedTableAlias ?? relatedTableName;
2591
- const junctionJoinOn = buildPairedColumnExprs(junctionTable, through.childColumns, relatedTableRef, through.targetColumns);
2674
+ const { childScope, junctionBinding } = parentScope.forManyToManyRelation(relation.toNamespace, relatedTableName, through.namespaceId, through.table);
2675
+ const junctionJoinOn = buildPairedColumnExprs(junctionBinding, through.childColumns, childScope.current, through.targetColumns);
2592
2676
  const parentLocalColumns = relation.on.localFields.map((field) => resolveFieldToColumn(context.contract, parentNamespaceId, parentModelName, field));
2593
- const filterPlan = planRelationFilterMode(buildPairedColumnExprs(junctionTable, through.parentColumns, parentTableName, parentLocalColumns), remapColumnRefs(relatedTableName, relatedTableRef, toRelationWhereExpr(context, relation.toNamespace, relation.to, options.predicate)), options.mode);
2677
+ const filterPlan = planRelationFilterMode(buildPairedColumnExprs(junctionBinding, through.parentColumns, parentScope.current, parentLocalColumns), toRelationWhereExpr(context, relation.toNamespace, relation.to, options.predicate, childScope), options.mode);
2594
2678
  if (filterPlan.kind === "constantTrue") return AndExpr.true();
2595
2679
  const firstTargetCol = firstJoinColumn(through.targetColumns, "targetColumns");
2596
- const subquery = SelectAst.from(tableSourceForContract(context.contract, relation.toNamespace, relatedTableName, relatedTableAlias)).withJoins([JoinAst.inner(TableSource.named(junctionTable, void 0, through.namespaceId), junctionJoinOn)]).withProjection([ProjectionItem.of("_exists", ColumnRef.of(relatedTableRef, firstTargetCol))]).withWhere(filterPlan.where);
2680
+ const subquery = SelectAst.from(childScope.current.tableSource(context.contract)).withJoins([JoinAst.inner(junctionBinding.tableSource(context.contract), junctionJoinOn)]).withProjection([ProjectionItem.of("_exists", childScope.current.column(firstTargetCol))]).withWhere(filterPlan.where);
2597
2681
  return filterPlan.notExists ? ExistsExpr.notExists(subquery) : ExistsExpr.exists(subquery);
2598
2682
  }
2599
2683
  function planRelationFilterMode(joinWhere, childWhere, mode) {
@@ -2616,10 +2700,6 @@ function planRelationFilterMode(joinWhere, childWhere, mode) {
2616
2700
  where: childWhere ? and(joinWhere, childWhere) : joinWhere
2617
2701
  };
2618
2702
  }
2619
- function remapColumnRefs(tableName, tableRef, expr) {
2620
- if (!expr || tableName === tableRef) return expr;
2621
- return expr.rewrite({ columnRef: (column) => column.table === tableName ? ColumnRef.of(tableRef, column.column) : column });
2622
- }
2623
2703
  function firstJoinColumn(columns, label) {
2624
2704
  const first = columns[0];
2625
2705
  if (!first) throw new InternalError(`Relation metadata is missing ${label}`);
@@ -2633,14 +2713,14 @@ function buildPairedColumnExprs(leftTable, leftColumns, rightTable, rightColumns
2633
2713
  const left = leftColumns[i];
2634
2714
  const right = rightColumns[i];
2635
2715
  if (!left || !right) throw new InternalError(`Relation metadata is missing a join column pair at index ${i}`);
2636
- exprs.push(BinaryExpr.eq(ColumnRef.of(leftTable, left), ColumnRef.of(rightTable, right)));
2716
+ exprs.push(BinaryExpr.eq(leftTable.column(left), rightTable.column(right)));
2637
2717
  }
2638
2718
  if (exprs.length === 1 && exprs[0]) return exprs[0];
2639
2719
  return and(...exprs);
2640
2720
  }
2641
- function toRelationWhereExpr(context, relatedNamespaceId, relatedModelName, predicate) {
2721
+ function toRelationWhereExpr(context, relatedNamespaceId, relatedModelName, predicate, scope) {
2642
2722
  if (!predicate) return;
2643
- const accessor = createModelAccessor(context, relatedNamespaceId, relatedModelName);
2723
+ const accessor = createModelAccessorInScope(context, relatedNamespaceId, relatedModelName, void 0, scope);
2644
2724
  if (typeof predicate === "function") return predicate(accessor);
2645
2725
  const exprs = [];
2646
2726
  for (const [fieldName, value] of Object.entries(predicate)) {
@@ -2665,7 +2745,7 @@ function toRelationWhereExpr(context, relatedNamespaceId, relatedModelName, pred
2665
2745
  if (exprs.length === 0) return;
2666
2746
  return exprs.length === 1 ? exprs[0] : and(...exprs);
2667
2747
  }
2668
- function buildJoinWhere(contract, parentNamespaceId, parentModelName, parentTableName, relatedTableName, relation) {
2748
+ function buildJoinWhere(contract, parentNamespaceId, parentModelName, parentTable, relatedTable, relation) {
2669
2749
  const localFields = relation.on?.localFields ?? [];
2670
2750
  const targetFields = relation.on?.targetFields ?? [];
2671
2751
  const joinExprs = [];
@@ -2676,7 +2756,7 @@ function buildJoinWhere(contract, parentNamespaceId, parentModelName, parentTabl
2676
2756
  if (!localField || !targetField) continue;
2677
2757
  const localColumn = resolveFieldToColumn(contract, parentNamespaceId, parentModelName, localField);
2678
2758
  const targetColumn = resolveFieldToColumn(contract, relation.toNamespace, relation.to, targetField);
2679
- joinExprs.push(BinaryExpr.eq(ColumnRef.of(relatedTableName, targetColumn), ColumnRef.of(parentTableName, localColumn)));
2759
+ joinExprs.push(BinaryExpr.eq(relatedTable.column(targetColumn), parentTable.column(localColumn)));
2680
2760
  }
2681
2761
  if (joinExprs.length === 0) throw new InternalError("Relation metadata is missing join columns");
2682
2762
  const firstExpr = joinExprs[0];