metal-orm 1.0.17 → 1.0.18

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.
Files changed (39) hide show
  1. package/README.md +4 -3
  2. package/dist/decorators/index.cjs +192 -46
  3. package/dist/decorators/index.cjs.map +1 -1
  4. package/dist/decorators/index.d.cts +1 -1
  5. package/dist/decorators/index.d.ts +1 -1
  6. package/dist/decorators/index.js +192 -46
  7. package/dist/decorators/index.js.map +1 -1
  8. package/dist/index.cjs +245 -66
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +16 -29
  11. package/dist/index.d.ts +16 -29
  12. package/dist/index.js +243 -66
  13. package/dist/index.js.map +1 -1
  14. package/dist/{select-BPCn6MOH.d.cts → select-BuMpVcVt.d.cts} +83 -11
  15. package/dist/{select-BPCn6MOH.d.ts → select-BuMpVcVt.d.ts} +83 -11
  16. package/package.json +4 -1
  17. package/src/codegen/naming-strategy.ts +15 -10
  18. package/src/core/ast/builders.ts +23 -3
  19. package/src/core/ast/expression-builders.ts +14 -1
  20. package/src/core/ast/expression-nodes.ts +11 -9
  21. package/src/core/ast/join-node.ts +5 -3
  22. package/src/core/ast/join.ts +16 -16
  23. package/src/core/ast/query.ts +44 -29
  24. package/src/core/ddl/dialects/mssql-schema-dialect.ts +18 -0
  25. package/src/core/ddl/dialects/mysql-schema-dialect.ts +11 -0
  26. package/src/core/ddl/dialects/postgres-schema-dialect.ts +9 -0
  27. package/src/core/ddl/dialects/sqlite-schema-dialect.ts +9 -0
  28. package/src/core/dialect/base/sql-dialect.ts +58 -46
  29. package/src/core/dialect/mssql/index.ts +53 -28
  30. package/src/core/dialect/sqlite/index.ts +22 -13
  31. package/src/query-builder/column-selector.ts +9 -7
  32. package/src/query-builder/query-ast-service.ts +59 -38
  33. package/src/query-builder/relation-conditions.ts +38 -34
  34. package/src/query-builder/relation-manager.ts +8 -3
  35. package/src/query-builder/relation-service.ts +59 -46
  36. package/src/query-builder/select-query-state.ts +19 -7
  37. package/src/query-builder/select.ts +215 -135
  38. package/src/schema/column.ts +75 -39
  39. package/src/schema/types.ts +1 -0
package/dist/index.js CHANGED
@@ -88,6 +88,30 @@ var col = {
88
88
  * Creates a UUID column definition
89
89
  */
90
90
  uuid: () => ({ name: "", type: "UUID" }),
91
+ /**
92
+ * Creates a binary large object column definition
93
+ */
94
+ blob: () => ({ name: "", type: "BLOB" }),
95
+ /**
96
+ * Creates a fixed-length binary column definition
97
+ */
98
+ binary: (length2) => ({
99
+ name: "",
100
+ type: "BINARY",
101
+ args: length2 !== void 0 ? [length2] : void 0
102
+ }),
103
+ /**
104
+ * Creates a variable-length binary column definition
105
+ */
106
+ varbinary: (length2) => ({
107
+ name: "",
108
+ type: "VARBINARY",
109
+ args: length2 !== void 0 ? [length2] : void 0
110
+ }),
111
+ /**
112
+ * Creates a Postgres bytea column definition
113
+ */
114
+ bytea: () => ({ name: "", type: "BYTEA" }),
91
115
  /**
92
116
  * Creates a timestamp column definition
93
117
  */
@@ -263,6 +287,11 @@ var toOperand = (val) => {
263
287
  return toNode(val);
264
288
  };
265
289
  var columnOperand = (col2) => toNode(col2);
290
+ var outerRef = (col2) => ({
291
+ ...columnOperand(col2),
292
+ scope: "outer"
293
+ });
294
+ var correlateBy = (table, column) => outerRef({ name: column, table });
266
295
  var createBinaryExpression = (operator, left2, right2, escape) => {
267
296
  const node = {
268
297
  type: "BinaryExpression",
@@ -573,6 +602,45 @@ var toTableRef = (table) => ({
573
602
  alias: table.alias
574
603
  });
575
604
 
605
+ // src/core/ast/builders.ts
606
+ var buildColumnNode = (table, column) => {
607
+ if (column.type === "Column") {
608
+ return column;
609
+ }
610
+ const def = column;
611
+ const baseTable = def.table ? table.alias && def.table === table.name ? table.alias : def.table : table.alias || table.name;
612
+ return {
613
+ type: "Column",
614
+ table: baseTable,
615
+ name: def.name
616
+ };
617
+ };
618
+ var buildColumnNodes = (table, names) => names.map((name) => ({
619
+ type: "Column",
620
+ table: table.alias || table.name,
621
+ name
622
+ }));
623
+ var createTableNode = (table) => ({
624
+ type: "Table",
625
+ name: table.name
626
+ });
627
+ var fnTable = (name, args = [], alias, opts) => ({
628
+ type: "FunctionTable",
629
+ name,
630
+ args,
631
+ alias,
632
+ lateral: opts?.lateral,
633
+ withOrdinality: opts?.withOrdinality,
634
+ columnAliases: opts?.columnAliases,
635
+ schema: opts?.schema
636
+ });
637
+ var derivedTable = (query, alias, columnAliases) => ({
638
+ type: "DerivedTable",
639
+ query,
640
+ alias,
641
+ columnAliases
642
+ });
643
+
576
644
  // src/core/functions/standard-strategy.ts
577
645
  var StandardFunctionStrategy = class _StandardFunctionStrategy {
578
646
  constructor() {
@@ -1262,7 +1330,7 @@ var SqlDialectBase = class extends Dialect {
1262
1330
  return this.returningStrategy.compileReturning(returning, ctx);
1263
1331
  }
1264
1332
  compileInsertColumnList(columns) {
1265
- return columns.map((column) => `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`).join(", ");
1333
+ return columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
1266
1334
  }
1267
1335
  compileInsertValues(values, ctx) {
1268
1336
  return values.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
@@ -1288,7 +1356,7 @@ var SqlDialectBase = class extends Dialect {
1288
1356
  compileUpdateAssignments(assignments, ctx) {
1289
1357
  return assignments.map((assignment) => {
1290
1358
  const col2 = assignment.column;
1291
- const target = `${this.quoteIdentifier(col2.table)}.${this.quoteIdentifier(col2.name)}`;
1359
+ const target = this.quoteIdentifier(col2.name);
1292
1360
  const value = this.compileOperand(assignment.value, ctx);
1293
1361
  return `${target} = ${value}`;
1294
1362
  }).join(", ");
@@ -1320,12 +1388,29 @@ var SqlDialectBase = class extends Dialect {
1320
1388
  if (tableSource.type === "FunctionTable") {
1321
1389
  return this.compileFunctionTable(tableSource, ctx);
1322
1390
  }
1391
+ if (tableSource.type === "DerivedTable") {
1392
+ return this.compileDerivedTable(tableSource, ctx);
1393
+ }
1323
1394
  return this.compileTableSource(tableSource);
1324
1395
  }
1325
1396
  compileFunctionTable(fn4, ctx) {
1326
1397
  return FunctionTableFormatter.format(fn4, ctx, this);
1327
1398
  }
1399
+ compileDerivedTable(table, ctx) {
1400
+ if (!table.alias) {
1401
+ throw new Error("Derived tables must have an alias.");
1402
+ }
1403
+ const subquery = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
1404
+ const columns = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
1405
+ return `(${subquery}) AS ${this.quoteIdentifier(table.alias)}${columns}`;
1406
+ }
1328
1407
  compileTableSource(table) {
1408
+ if (table.type === "FunctionTable") {
1409
+ return this.compileFunctionTable(table);
1410
+ }
1411
+ if (table.type === "DerivedTable") {
1412
+ return this.compileDerivedTable(table);
1413
+ }
1329
1414
  const base = this.compileTableName(table);
1330
1415
  return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
1331
1416
  }
@@ -1714,6 +1799,12 @@ var SqliteDialect = class extends SqlDialectBase {
1714
1799
  const columns = this.formatReturningColumns(returning);
1715
1800
  return ` RETURNING ${columns}`;
1716
1801
  }
1802
+ formatReturningColumns(returning) {
1803
+ return returning.map((column) => {
1804
+ const alias = column.alias ? ` AS ${this.quoteIdentifier(column.alias)}` : "";
1805
+ return `${this.quoteIdentifier(column.name)}${alias}`;
1806
+ }).join(", ");
1807
+ }
1717
1808
  supportsReturning() {
1718
1809
  return true;
1719
1810
  }
@@ -1880,6 +1971,9 @@ var SqlServerDialect = class extends Dialect {
1880
1971
  return `UPDATE ${table} SET ${assignments}${whereClause};`;
1881
1972
  }
1882
1973
  compileDeleteAst(ast, ctx) {
1974
+ if (ast.from.type !== "Table") {
1975
+ throw new Error("DELETE only supports base tables in the MSSQL dialect.");
1976
+ }
1883
1977
  const table = this.quoteIdentifier(ast.from.name);
1884
1978
  const whereClause = this.compileWhere(ast.where, ctx);
1885
1979
  return `DELETE FROM ${table}${whereClause};`;
@@ -1903,9 +1997,9 @@ var SqlServerDialect = class extends Dialect {
1903
1997
  return expr;
1904
1998
  }).join(", ");
1905
1999
  const distinct = ast.distinct ? "DISTINCT " : "";
1906
- const from = `${this.quoteIdentifier(ast.from.name)}`;
2000
+ const from = this.compileTableSource(ast.from, ctx);
1907
2001
  const joins = ast.joins.map((j) => {
1908
- const table = this.quoteIdentifier(j.table.name);
2002
+ const table = this.compileTableSource(j.table, ctx);
1909
2003
  const cond = this.compileExpression(j.condition, ctx);
1910
2004
  return `${j.kind} JOIN ${table} ON ${cond}`;
1911
2005
  }).join(" ");
@@ -1935,6 +2029,21 @@ var SqlServerDialect = class extends Dialect {
1935
2029
  }
1936
2030
  return pagination;
1937
2031
  }
2032
+ compileTableSource(table, ctx) {
2033
+ if (table.type === "FunctionTable") {
2034
+ return FunctionTableFormatter.format(table, ctx, this);
2035
+ }
2036
+ if (table.type === "DerivedTable") {
2037
+ return this.compileDerivedTable(table, ctx);
2038
+ }
2039
+ const base = table.schema ? `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(table.name)}` : this.quoteIdentifier(table.name);
2040
+ return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
2041
+ }
2042
+ compileDerivedTable(table, ctx) {
2043
+ const sub = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
2044
+ const cols = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
2045
+ return `(${sub}) AS ${this.quoteIdentifier(table.alias)}${cols}`;
2046
+ }
1938
2047
  compileCtes(ast, ctx) {
1939
2048
  if (!ast.ctes || ast.ctes.length === 0) return "";
1940
2049
  const defs = ast.ctes.map((cte) => {
@@ -2063,6 +2172,17 @@ var SelectQueryState = class _SelectQueryState {
2063
2172
  joins: [...this.ast.joins ?? [], join]
2064
2173
  });
2065
2174
  }
2175
+ /**
2176
+ * Replaces the FROM clause.
2177
+ * @param from - Table source for the FROM clause
2178
+ * @returns New SelectQueryState with updated FROM
2179
+ */
2180
+ withFrom(from) {
2181
+ return this.clone({
2182
+ ...this.ast,
2183
+ from
2184
+ });
2185
+ }
2066
2186
  /**
2067
2187
  * Adds a WHERE clause to the query
2068
2188
  * @param predicate - WHERE predicate expression
@@ -2555,38 +2675,6 @@ var buildDefaultHydrationPlan = (table) => ({
2555
2675
  relations: []
2556
2676
  });
2557
2677
 
2558
- // src/core/ast/builders.ts
2559
- var buildColumnNode = (table, column) => {
2560
- if (column.type === "Column") {
2561
- return column;
2562
- }
2563
- const def = column;
2564
- return {
2565
- type: "Column",
2566
- table: def.table || table.name,
2567
- name: def.name
2568
- };
2569
- };
2570
- var buildColumnNodes = (table, names) => names.map((name) => ({
2571
- type: "Column",
2572
- table: table.name,
2573
- name
2574
- }));
2575
- var createTableNode = (table) => ({
2576
- type: "Table",
2577
- name: table.name
2578
- });
2579
- var fnTable = (name, args = [], alias, opts) => ({
2580
- type: "FunctionTable",
2581
- name,
2582
- args,
2583
- alias,
2584
- lateral: opts?.lateral,
2585
- withOrdinality: opts?.withOrdinality,
2586
- columnAliases: opts?.columnAliases,
2587
- schema: opts?.schema
2588
- });
2589
-
2590
2678
  // src/query-builder/raw-column-parser.ts
2591
2679
  var parseRawColumn = (col2, tableName, ctes) => {
2592
2680
  if (col2.includes("(")) {
@@ -2626,6 +2714,8 @@ var QueryAstService = class {
2626
2714
  const existingAliases = new Set(
2627
2715
  this.state.ast.columns.map((c) => c.alias || c.name)
2628
2716
  );
2717
+ const from = this.state.ast.from;
2718
+ const rootTableName = from.type === "Table" && from.alias ? from.alias : this.table.name;
2629
2719
  const newCols = Object.entries(columns).reduce((acc, [alias, val]) => {
2630
2720
  if (existingAliases.has(alias)) return acc;
2631
2721
  if (isExpressionSelectionNode(val)) {
@@ -2633,9 +2723,10 @@ var QueryAstService = class {
2633
2723
  return acc;
2634
2724
  }
2635
2725
  const colDef = val;
2726
+ const resolvedTable = colDef.table && colDef.table === this.table.name && from.type === "Table" && from.alias ? from.alias : colDef.table || rootTableName;
2636
2727
  acc.push({
2637
2728
  type: "Column",
2638
- table: colDef.table || this.table.name,
2729
+ table: resolvedTable,
2639
2730
  name: colDef.name,
2640
2731
  alias
2641
2732
  });
@@ -2650,7 +2741,9 @@ var QueryAstService = class {
2650
2741
  * @returns Column selection result with updated state and added columns
2651
2742
  */
2652
2743
  selectRaw(cols) {
2653
- const newCols = cols.map((col2) => parseRawColumn(col2, this.table.name, this.state.ast.ctes));
2744
+ const from = this.state.ast.from;
2745
+ const defaultTable = from.type === "Table" && from.alias ? from.alias : this.table.name;
2746
+ const newCols = cols.map((col2) => parseRawColumn(col2, defaultTable, this.state.ast.ctes));
2654
2747
  const nextState = this.state.withColumns(newCols);
2655
2748
  return { state: nextState, addedColumns: newCols };
2656
2749
  }
@@ -2686,6 +2779,14 @@ var QueryAstService = class {
2686
2779
  };
2687
2780
  return this.state.withSetOperation(op);
2688
2781
  }
2782
+ /**
2783
+ * Replaces the FROM clause for the current query.
2784
+ * @param from - Table source to use in the FROM clause
2785
+ * @returns Updated query state with new FROM
2786
+ */
2787
+ withFrom(from) {
2788
+ return this.state.withFrom(from);
2789
+ }
2689
2790
  /**
2690
2791
  * Selects a subquery as a column
2691
2792
  * @param alias - Alias for the subquery
@@ -2719,7 +2820,9 @@ var QueryAstService = class {
2719
2820
  * @returns Updated query state with GROUP BY clause
2720
2821
  */
2721
2822
  withGroupBy(col2) {
2722
- const node = buildColumnNode(this.table, col2);
2823
+ const from = this.state.ast.from;
2824
+ const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
2825
+ const node = buildColumnNode(tableRef, col2);
2723
2826
  return this.state.withGroupBy([node]);
2724
2827
  }
2725
2828
  /**
@@ -2738,7 +2841,9 @@ var QueryAstService = class {
2738
2841
  * @returns Updated query state with ORDER BY clause
2739
2842
  */
2740
2843
  withOrderBy(col2, direction) {
2741
- const node = buildColumnNode(this.table, col2);
2844
+ const from = this.state.ast.from;
2845
+ const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
2846
+ const node = buildColumnNode(tableRef, col2);
2742
2847
  return this.state.withOrderBy([{ type: "OrderBy", column: node, direction }]);
2743
2848
  }
2744
2849
  /**
@@ -2842,7 +2947,8 @@ var RelationProjectionHelper = class {
2842
2947
  var assertNever = (value) => {
2843
2948
  throw new Error(`Unhandled relation type: ${JSON.stringify(value)}`);
2844
2949
  };
2845
- var baseRelationCondition = (root, relation) => {
2950
+ var baseRelationCondition = (root, relation, rootAlias) => {
2951
+ const rootTable = rootAlias || root.name;
2846
2952
  const defaultLocalKey = relation.type === RelationKinds.HasMany || relation.type === RelationKinds.HasOne ? findPrimaryKey(root) : findPrimaryKey(relation.target);
2847
2953
  const localKey = relation.localKey || defaultLocalKey;
2848
2954
  switch (relation.type) {
@@ -2850,12 +2956,12 @@ var baseRelationCondition = (root, relation) => {
2850
2956
  case RelationKinds.HasOne:
2851
2957
  return eq(
2852
2958
  { type: "Column", table: relation.target.name, name: relation.foreignKey },
2853
- { type: "Column", table: root.name, name: localKey }
2959
+ { type: "Column", table: rootTable, name: localKey }
2854
2960
  );
2855
2961
  case RelationKinds.BelongsTo:
2856
2962
  return eq(
2857
2963
  { type: "Column", table: relation.target.name, name: localKey },
2858
- { type: "Column", table: root.name, name: relation.foreignKey }
2964
+ { type: "Column", table: rootTable, name: relation.foreignKey }
2859
2965
  );
2860
2966
  case RelationKinds.BelongsToMany:
2861
2967
  throw new Error("BelongsToMany relations do not support the standard join condition builder");
@@ -2863,12 +2969,13 @@ var baseRelationCondition = (root, relation) => {
2863
2969
  return assertNever(relation);
2864
2970
  }
2865
2971
  };
2866
- var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra) => {
2972
+ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra, rootAlias) => {
2867
2973
  const rootKey = relation.localKey || findPrimaryKey(root);
2868
2974
  const targetKey = relation.targetKey || findPrimaryKey(relation.target);
2975
+ const rootTable = rootAlias || root.name;
2869
2976
  const pivotCondition = eq(
2870
2977
  { type: "Column", table: relation.pivotTable.name, name: relation.pivotForeignKeyToRoot },
2871
- { type: "Column", table: root.name, name: rootKey }
2978
+ { type: "Column", table: rootTable, name: rootKey }
2872
2979
  );
2873
2980
  const pivotJoin = createJoinNode(joinKind, relation.pivotTable.name, pivotCondition);
2874
2981
  let targetCondition = eq(
@@ -2886,12 +2993,12 @@ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra) =>
2886
2993
  );
2887
2994
  return [pivotJoin, targetJoin];
2888
2995
  };
2889
- var buildRelationJoinCondition = (root, relation, extra) => {
2890
- const base = baseRelationCondition(root, relation);
2996
+ var buildRelationJoinCondition = (root, relation, extra, rootAlias) => {
2997
+ const base = baseRelationCondition(root, relation, rootAlias);
2891
2998
  return extra ? and(base, extra) : base;
2892
2999
  };
2893
- var buildRelationCorrelation = (root, relation) => {
2894
- return baseRelationCondition(root, relation);
3000
+ var buildRelationCorrelation = (root, relation, rootAlias) => {
3001
+ return baseRelationCondition(root, relation, rootAlias);
2895
3002
  };
2896
3003
 
2897
3004
  // src/core/ast/join-metadata.ts
@@ -2935,7 +3042,7 @@ var RelationService = class {
2935
3042
  match(relationName, predicate) {
2936
3043
  const joined = this.joinRelation(relationName, JOIN_KINDS.INNER, predicate);
2937
3044
  const pk = findPrimaryKey(this.table);
2938
- const distinctCols = [{ type: "Column", table: this.table.name, name: pk }];
3045
+ const distinctCols = [{ type: "Column", table: this.rootTableName(), name: pk }];
2939
3046
  const existingDistinct = joined.state.ast.distinct ? joined.state.ast.distinct : [];
2940
3047
  const nextState = this.astService(joined.state).withDistinct([...existingDistinct, ...distinctCols]);
2941
3048
  return { state: nextState, hydration: joined.hydration };
@@ -3022,9 +3129,13 @@ var RelationService = class {
3022
3129
  * @param ast - Query AST to modify
3023
3130
  * @returns Modified query AST with relation correlation
3024
3131
  */
3025
- applyRelationCorrelation(relationName, ast) {
3132
+ applyRelationCorrelation(relationName, ast, additionalCorrelation) {
3026
3133
  const relation = this.getRelation(relationName);
3027
- const correlation = buildRelationCorrelation(this.table, relation);
3134
+ const rootAlias = this.state.ast.from.type === "Table" ? this.state.ast.from.alias : void 0;
3135
+ let correlation = buildRelationCorrelation(this.table, relation, rootAlias);
3136
+ if (additionalCorrelation) {
3137
+ correlation = and(correlation, additionalCorrelation);
3138
+ }
3028
3139
  const whereInSubquery = ast.where ? and(correlation, ast.where) : correlation;
3029
3140
  return {
3030
3141
  ...ast,
@@ -3041,17 +3152,19 @@ var RelationService = class {
3041
3152
  */
3042
3153
  withJoin(state, relationName, joinKind, extraCondition) {
3043
3154
  const relation = this.getRelation(relationName);
3155
+ const rootAlias = state.ast.from.type === "Table" ? state.ast.from.alias : void 0;
3044
3156
  if (relation.type === RelationKinds.BelongsToMany) {
3045
3157
  const joins = buildBelongsToManyJoins(
3046
3158
  this.table,
3047
3159
  relationName,
3048
3160
  relation,
3049
3161
  joinKind,
3050
- extraCondition
3162
+ extraCondition,
3163
+ rootAlias
3051
3164
  );
3052
3165
  return joins.reduce((current, join) => this.astService(current).withJoin(join), state);
3053
3166
  }
3054
- const condition = buildRelationJoinCondition(this.table, relation, extraCondition);
3167
+ const condition = buildRelationJoinCondition(this.table, relation, extraCondition, rootAlias);
3055
3168
  const joinNode = createJoinNode(joinKind, relation.target.name, condition, relationName);
3056
3169
  return this.astService(state).withJoin(joinNode);
3057
3170
  }
@@ -3090,6 +3203,11 @@ var RelationService = class {
3090
3203
  astService(state = this.state) {
3091
3204
  return this.createQueryAstService(this.table, state);
3092
3205
  }
3206
+ rootTableName() {
3207
+ const from = this.state.ast.from;
3208
+ if (from.type === "Table" && from.alias) return from.alias;
3209
+ return this.table.name;
3210
+ }
3093
3211
  };
3094
3212
 
3095
3213
  // src/query-builder/select-query-builder-deps.ts
@@ -3164,7 +3282,9 @@ var ColumnSelector = class {
3164
3282
  * @returns Updated query context with DISTINCT clause
3165
3283
  */
3166
3284
  distinct(context, columns) {
3167
- const nodes = columns.map((col2) => buildColumnNode(this.env.table, col2));
3285
+ const from = context.state.ast.from;
3286
+ const tableRef = from.type === "Table" && from.alias ? { ...this.env.table, alias: from.alias } : this.env.table;
3287
+ const nodes = columns.map((col2) => buildColumnNode(tableRef, col2));
3168
3288
  const astService = this.env.deps.createQueryAstService(this.env.table, context.state);
3169
3289
  const nextState = astService.withDistinct(nodes);
3170
3290
  return { state: nextState, hydration: context.hydration };
@@ -3221,8 +3341,8 @@ var RelationManager = class {
3221
3341
  * @param ast - Query AST to modify
3222
3342
  * @returns Modified query AST with relation correlation
3223
3343
  */
3224
- applyRelationCorrelation(context, relationName, ast) {
3225
- return this.createService(context).applyRelationCorrelation(relationName, ast);
3344
+ applyRelationCorrelation(context, relationName, ast, additionalCorrelation) {
3345
+ return this.createService(context).applyRelationCorrelation(relationName, ast, additionalCorrelation);
3226
3346
  }
3227
3347
  /**
3228
3348
  * Creates a relation service instance
@@ -4269,9 +4389,30 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4269
4389
  clone(context = this.context, lazyRelations = new Set(this.lazyRelations)) {
4270
4390
  return new _SelectQueryBuilder(this.env.table, context.state, context.hydration, this.env.deps, lazyRelations);
4271
4391
  }
4392
+ /**
4393
+ * Applies an alias to the root FROM table.
4394
+ * @param alias - Alias to apply
4395
+ */
4396
+ as(alias) {
4397
+ const from = this.context.state.ast.from;
4398
+ if (from.type !== "Table") {
4399
+ throw new Error("Cannot alias non-table FROM sources");
4400
+ }
4401
+ const nextFrom = { ...from, alias };
4402
+ const nextContext = this.applyAst(this.context, (service) => service.withFrom(nextFrom));
4403
+ return this.clone(nextContext);
4404
+ }
4272
4405
  resolveQueryNode(query) {
4273
4406
  return typeof query.getAST === "function" ? query.getAST() : query;
4274
4407
  }
4408
+ applyCorrelation(ast, correlation) {
4409
+ if (!correlation) return ast;
4410
+ const combinedWhere = ast.where ? and(correlation, ast.where) : correlation;
4411
+ return {
4412
+ ...ast,
4413
+ where: combinedWhere
4414
+ };
4415
+ }
4275
4416
  createChildBuilder(table) {
4276
4417
  return new _SelectQueryBuilder(table, void 0, void 0, this.env.deps);
4277
4418
  }
@@ -4363,6 +4504,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4363
4504
  const nextContext = this.applyAst(this.context, (service) => service.withCte(name, subAst, columns, true));
4364
4505
  return this.clone(nextContext);
4365
4506
  }
4507
+ /**
4508
+ * Replaces the FROM clause with a derived table (subquery with alias)
4509
+ * @param subquery - Subquery to use as the FROM source
4510
+ * @param alias - Alias for the derived table
4511
+ * @param columnAliases - Optional column alias list
4512
+ * @returns New query builder instance with updated FROM
4513
+ */
4514
+ fromSubquery(subquery, alias, columnAliases) {
4515
+ const subAst = this.resolveQueryNode(subquery);
4516
+ const fromNode = derivedTable(subAst, alias, columnAliases);
4517
+ const nextContext = this.applyAst(this.context, (service) => service.withFrom(fromNode));
4518
+ return this.clone(nextContext);
4519
+ }
4366
4520
  /**
4367
4521
 
4368
4522
  * Selects a subquery as a column
@@ -4378,6 +4532,21 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4378
4532
  const query = this.resolveQueryNode(sub);
4379
4533
  return this.clone(this.columnSelector.selectSubquery(this.context, alias, query));
4380
4534
  }
4535
+ /**
4536
+ * Adds a JOIN against a derived table (subquery with alias)
4537
+ * @param subquery - Subquery to join
4538
+ * @param alias - Alias for the derived table
4539
+ * @param condition - Join condition expression
4540
+ * @param joinKind - Join kind (defaults to INNER)
4541
+ * @param columnAliases - Optional column alias list for the derived table
4542
+ * @returns New query builder instance with the derived-table join
4543
+ */
4544
+ joinSubquery(subquery, alias, condition, joinKind = JOIN_KINDS.INNER, columnAliases) {
4545
+ const subAst = this.resolveQueryNode(subquery);
4546
+ const joinNode = createJoinNode(joinKind, derivedTable(subAst, alias, columnAliases), condition);
4547
+ const nextContext = this.applyAst(this.context, (service) => service.withJoin(joinNode));
4548
+ return this.clone(nextContext);
4549
+ }
4381
4550
  /**
4382
4551
 
4383
4552
  * Adds an INNER JOIN to the query
@@ -4677,9 +4846,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4677
4846
  * @returns New query builder instance with the WHERE EXISTS condition
4678
4847
 
4679
4848
  */
4680
- whereExists(subquery) {
4849
+ whereExists(subquery, correlate) {
4681
4850
  const subAst = this.resolveQueryNode(subquery);
4682
- return this.where(exists(subAst));
4851
+ const correlated = this.applyCorrelation(subAst, correlate);
4852
+ return this.where(exists(correlated));
4683
4853
  }
4684
4854
  /**
4685
4855
 
@@ -4690,9 +4860,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4690
4860
  * @returns New query builder instance with the WHERE NOT EXISTS condition
4691
4861
 
4692
4862
  */
4693
- whereNotExists(subquery) {
4863
+ whereNotExists(subquery, correlate) {
4694
4864
  const subAst = this.resolveQueryNode(subquery);
4695
- return this.where(notExists(subAst));
4865
+ const correlated = this.applyCorrelation(subAst, correlate);
4866
+ return this.where(notExists(correlated));
4696
4867
  }
4697
4868
  /**
4698
4869
 
@@ -4705,17 +4876,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4705
4876
  * @returns New query builder instance with the relationship existence check
4706
4877
 
4707
4878
  */
4708
- whereHas(relationName, callback) {
4879
+ whereHas(relationName, callbackOrOptions, maybeOptions) {
4709
4880
  const relation = this.env.table.relations[relationName];
4710
4881
  if (!relation) {
4711
4882
  throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
4712
4883
  }
4884
+ const callback = typeof callbackOrOptions === "function" ? callbackOrOptions : void 0;
4885
+ const options = typeof callbackOrOptions === "function" ? maybeOptions : callbackOrOptions;
4713
4886
  let subQb = this.createChildBuilder(relation.target);
4714
4887
  if (callback) {
4715
4888
  subQb = callback(subQb);
4716
4889
  }
4717
4890
  const subAst = subQb.getAST();
4718
- const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst);
4891
+ const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst, options?.correlate);
4719
4892
  return this.where(exists(finalSubAst));
4720
4893
  }
4721
4894
  /**
@@ -4729,17 +4902,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4729
4902
  * @returns New query builder instance with the relationship non-existence check
4730
4903
 
4731
4904
  */
4732
- whereHasNot(relationName, callback) {
4905
+ whereHasNot(relationName, callbackOrOptions, maybeOptions) {
4733
4906
  const relation = this.env.table.relations[relationName];
4734
4907
  if (!relation) {
4735
4908
  throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
4736
4909
  }
4910
+ const callback = typeof callbackOrOptions === "function" ? callbackOrOptions : void 0;
4911
+ const options = typeof callbackOrOptions === "function" ? maybeOptions : callbackOrOptions;
4737
4912
  let subQb = this.createChildBuilder(relation.target);
4738
4913
  if (callback) {
4739
4914
  subQb = callback(subQb);
4740
4915
  }
4741
4916
  const subAst = subQb.getAST();
4742
- const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst);
4917
+ const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst, options?.correlate);
4743
4918
  return this.where(notExists(finalSubAst));
4744
4919
  }
4745
4920
  /**
@@ -6163,7 +6338,7 @@ var DefaultNamingStrategy = class {
6163
6338
  * @returns Capitalized table name (handles schema-qualified names)
6164
6339
  */
6165
6340
  tableToSymbol(table) {
6166
- const tableName = typeof table === "string" ? table : table.name;
6341
+ const tableName = typeof table === "string" ? table : table.type === "DerivedTable" ? table.alias : table.name;
6167
6342
  if (tableName.includes(".")) {
6168
6343
  return tableName.split(".").map((part) => this.capitalize(part)).join("");
6169
6344
  }
@@ -7336,6 +7511,7 @@ export {
7336
7511
  columnOperand,
7337
7512
  concat,
7338
7513
  concatWs,
7514
+ correlateBy,
7339
7515
  cos,
7340
7516
  cot,
7341
7517
  count,
@@ -7426,6 +7602,7 @@ export {
7426
7602
  now,
7427
7603
  ntile,
7428
7604
  or,
7605
+ outerRef,
7429
7606
  pi,
7430
7607
  position,
7431
7608
  pow,