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.cjs CHANGED
@@ -84,6 +84,7 @@ __export(index_exports, {
84
84
  columnOperand: () => columnOperand,
85
85
  concat: () => concat,
86
86
  concatWs: () => concatWs,
87
+ correlateBy: () => correlateBy,
87
88
  cos: () => cos,
88
89
  cot: () => cot,
89
90
  count: () => count,
@@ -174,6 +175,7 @@ __export(index_exports, {
174
175
  now: () => now,
175
176
  ntile: () => ntile,
176
177
  or: () => or,
178
+ outerRef: () => outerRef,
177
179
  pi: () => pi,
178
180
  position: () => position,
179
181
  pow: () => pow,
@@ -279,6 +281,30 @@ var col = {
279
281
  * Creates a UUID column definition
280
282
  */
281
283
  uuid: () => ({ name: "", type: "UUID" }),
284
+ /**
285
+ * Creates a binary large object column definition
286
+ */
287
+ blob: () => ({ name: "", type: "BLOB" }),
288
+ /**
289
+ * Creates a fixed-length binary column definition
290
+ */
291
+ binary: (length2) => ({
292
+ name: "",
293
+ type: "BINARY",
294
+ args: length2 !== void 0 ? [length2] : void 0
295
+ }),
296
+ /**
297
+ * Creates a variable-length binary column definition
298
+ */
299
+ varbinary: (length2) => ({
300
+ name: "",
301
+ type: "VARBINARY",
302
+ args: length2 !== void 0 ? [length2] : void 0
303
+ }),
304
+ /**
305
+ * Creates a Postgres bytea column definition
306
+ */
307
+ bytea: () => ({ name: "", type: "BYTEA" }),
282
308
  /**
283
309
  * Creates a timestamp column definition
284
310
  */
@@ -454,6 +480,11 @@ var toOperand = (val) => {
454
480
  return toNode(val);
455
481
  };
456
482
  var columnOperand = (col2) => toNode(col2);
483
+ var outerRef = (col2) => ({
484
+ ...columnOperand(col2),
485
+ scope: "outer"
486
+ });
487
+ var correlateBy = (table, column) => outerRef({ name: column, table });
457
488
  var createBinaryExpression = (operator, left2, right2, escape) => {
458
489
  const node = {
459
490
  type: "BinaryExpression",
@@ -764,6 +795,45 @@ var toTableRef = (table) => ({
764
795
  alias: table.alias
765
796
  });
766
797
 
798
+ // src/core/ast/builders.ts
799
+ var buildColumnNode = (table, column) => {
800
+ if (column.type === "Column") {
801
+ return column;
802
+ }
803
+ const def = column;
804
+ const baseTable = def.table ? table.alias && def.table === table.name ? table.alias : def.table : table.alias || table.name;
805
+ return {
806
+ type: "Column",
807
+ table: baseTable,
808
+ name: def.name
809
+ };
810
+ };
811
+ var buildColumnNodes = (table, names) => names.map((name) => ({
812
+ type: "Column",
813
+ table: table.alias || table.name,
814
+ name
815
+ }));
816
+ var createTableNode = (table) => ({
817
+ type: "Table",
818
+ name: table.name
819
+ });
820
+ var fnTable = (name, args = [], alias, opts) => ({
821
+ type: "FunctionTable",
822
+ name,
823
+ args,
824
+ alias,
825
+ lateral: opts?.lateral,
826
+ withOrdinality: opts?.withOrdinality,
827
+ columnAliases: opts?.columnAliases,
828
+ schema: opts?.schema
829
+ });
830
+ var derivedTable = (query, alias, columnAliases) => ({
831
+ type: "DerivedTable",
832
+ query,
833
+ alias,
834
+ columnAliases
835
+ });
836
+
767
837
  // src/core/functions/standard-strategy.ts
768
838
  var StandardFunctionStrategy = class _StandardFunctionStrategy {
769
839
  constructor() {
@@ -1453,7 +1523,7 @@ var SqlDialectBase = class extends Dialect {
1453
1523
  return this.returningStrategy.compileReturning(returning, ctx);
1454
1524
  }
1455
1525
  compileInsertColumnList(columns) {
1456
- return columns.map((column) => `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`).join(", ");
1526
+ return columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
1457
1527
  }
1458
1528
  compileInsertValues(values, ctx) {
1459
1529
  return values.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
@@ -1479,7 +1549,7 @@ var SqlDialectBase = class extends Dialect {
1479
1549
  compileUpdateAssignments(assignments, ctx) {
1480
1550
  return assignments.map((assignment) => {
1481
1551
  const col2 = assignment.column;
1482
- const target = `${this.quoteIdentifier(col2.table)}.${this.quoteIdentifier(col2.name)}`;
1552
+ const target = this.quoteIdentifier(col2.name);
1483
1553
  const value = this.compileOperand(assignment.value, ctx);
1484
1554
  return `${target} = ${value}`;
1485
1555
  }).join(", ");
@@ -1511,12 +1581,29 @@ var SqlDialectBase = class extends Dialect {
1511
1581
  if (tableSource.type === "FunctionTable") {
1512
1582
  return this.compileFunctionTable(tableSource, ctx);
1513
1583
  }
1584
+ if (tableSource.type === "DerivedTable") {
1585
+ return this.compileDerivedTable(tableSource, ctx);
1586
+ }
1514
1587
  return this.compileTableSource(tableSource);
1515
1588
  }
1516
1589
  compileFunctionTable(fn4, ctx) {
1517
1590
  return FunctionTableFormatter.format(fn4, ctx, this);
1518
1591
  }
1592
+ compileDerivedTable(table, ctx) {
1593
+ if (!table.alias) {
1594
+ throw new Error("Derived tables must have an alias.");
1595
+ }
1596
+ const subquery = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
1597
+ const columns = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
1598
+ return `(${subquery}) AS ${this.quoteIdentifier(table.alias)}${columns}`;
1599
+ }
1519
1600
  compileTableSource(table) {
1601
+ if (table.type === "FunctionTable") {
1602
+ return this.compileFunctionTable(table);
1603
+ }
1604
+ if (table.type === "DerivedTable") {
1605
+ return this.compileDerivedTable(table);
1606
+ }
1520
1607
  const base = this.compileTableName(table);
1521
1608
  return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
1522
1609
  }
@@ -1905,6 +1992,12 @@ var SqliteDialect = class extends SqlDialectBase {
1905
1992
  const columns = this.formatReturningColumns(returning);
1906
1993
  return ` RETURNING ${columns}`;
1907
1994
  }
1995
+ formatReturningColumns(returning) {
1996
+ return returning.map((column) => {
1997
+ const alias = column.alias ? ` AS ${this.quoteIdentifier(column.alias)}` : "";
1998
+ return `${this.quoteIdentifier(column.name)}${alias}`;
1999
+ }).join(", ");
2000
+ }
1908
2001
  supportsReturning() {
1909
2002
  return true;
1910
2003
  }
@@ -2071,6 +2164,9 @@ var SqlServerDialect = class extends Dialect {
2071
2164
  return `UPDATE ${table} SET ${assignments}${whereClause};`;
2072
2165
  }
2073
2166
  compileDeleteAst(ast, ctx) {
2167
+ if (ast.from.type !== "Table") {
2168
+ throw new Error("DELETE only supports base tables in the MSSQL dialect.");
2169
+ }
2074
2170
  const table = this.quoteIdentifier(ast.from.name);
2075
2171
  const whereClause = this.compileWhere(ast.where, ctx);
2076
2172
  return `DELETE FROM ${table}${whereClause};`;
@@ -2094,9 +2190,9 @@ var SqlServerDialect = class extends Dialect {
2094
2190
  return expr;
2095
2191
  }).join(", ");
2096
2192
  const distinct = ast.distinct ? "DISTINCT " : "";
2097
- const from = `${this.quoteIdentifier(ast.from.name)}`;
2193
+ const from = this.compileTableSource(ast.from, ctx);
2098
2194
  const joins = ast.joins.map((j) => {
2099
- const table = this.quoteIdentifier(j.table.name);
2195
+ const table = this.compileTableSource(j.table, ctx);
2100
2196
  const cond = this.compileExpression(j.condition, ctx);
2101
2197
  return `${j.kind} JOIN ${table} ON ${cond}`;
2102
2198
  }).join(" ");
@@ -2126,6 +2222,21 @@ var SqlServerDialect = class extends Dialect {
2126
2222
  }
2127
2223
  return pagination;
2128
2224
  }
2225
+ compileTableSource(table, ctx) {
2226
+ if (table.type === "FunctionTable") {
2227
+ return FunctionTableFormatter.format(table, ctx, this);
2228
+ }
2229
+ if (table.type === "DerivedTable") {
2230
+ return this.compileDerivedTable(table, ctx);
2231
+ }
2232
+ const base = table.schema ? `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(table.name)}` : this.quoteIdentifier(table.name);
2233
+ return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
2234
+ }
2235
+ compileDerivedTable(table, ctx) {
2236
+ const sub = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
2237
+ const cols = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
2238
+ return `(${sub}) AS ${this.quoteIdentifier(table.alias)}${cols}`;
2239
+ }
2129
2240
  compileCtes(ast, ctx) {
2130
2241
  if (!ast.ctes || ast.ctes.length === 0) return "";
2131
2242
  const defs = ast.ctes.map((cte) => {
@@ -2254,6 +2365,17 @@ var SelectQueryState = class _SelectQueryState {
2254
2365
  joins: [...this.ast.joins ?? [], join]
2255
2366
  });
2256
2367
  }
2368
+ /**
2369
+ * Replaces the FROM clause.
2370
+ * @param from - Table source for the FROM clause
2371
+ * @returns New SelectQueryState with updated FROM
2372
+ */
2373
+ withFrom(from) {
2374
+ return this.clone({
2375
+ ...this.ast,
2376
+ from
2377
+ });
2378
+ }
2257
2379
  /**
2258
2380
  * Adds a WHERE clause to the query
2259
2381
  * @param predicate - WHERE predicate expression
@@ -2746,38 +2868,6 @@ var buildDefaultHydrationPlan = (table) => ({
2746
2868
  relations: []
2747
2869
  });
2748
2870
 
2749
- // src/core/ast/builders.ts
2750
- var buildColumnNode = (table, column) => {
2751
- if (column.type === "Column") {
2752
- return column;
2753
- }
2754
- const def = column;
2755
- return {
2756
- type: "Column",
2757
- table: def.table || table.name,
2758
- name: def.name
2759
- };
2760
- };
2761
- var buildColumnNodes = (table, names) => names.map((name) => ({
2762
- type: "Column",
2763
- table: table.name,
2764
- name
2765
- }));
2766
- var createTableNode = (table) => ({
2767
- type: "Table",
2768
- name: table.name
2769
- });
2770
- var fnTable = (name, args = [], alias, opts) => ({
2771
- type: "FunctionTable",
2772
- name,
2773
- args,
2774
- alias,
2775
- lateral: opts?.lateral,
2776
- withOrdinality: opts?.withOrdinality,
2777
- columnAliases: opts?.columnAliases,
2778
- schema: opts?.schema
2779
- });
2780
-
2781
2871
  // src/query-builder/raw-column-parser.ts
2782
2872
  var parseRawColumn = (col2, tableName, ctes) => {
2783
2873
  if (col2.includes("(")) {
@@ -2817,6 +2907,8 @@ var QueryAstService = class {
2817
2907
  const existingAliases = new Set(
2818
2908
  this.state.ast.columns.map((c) => c.alias || c.name)
2819
2909
  );
2910
+ const from = this.state.ast.from;
2911
+ const rootTableName = from.type === "Table" && from.alias ? from.alias : this.table.name;
2820
2912
  const newCols = Object.entries(columns).reduce((acc, [alias, val]) => {
2821
2913
  if (existingAliases.has(alias)) return acc;
2822
2914
  if (isExpressionSelectionNode(val)) {
@@ -2824,9 +2916,10 @@ var QueryAstService = class {
2824
2916
  return acc;
2825
2917
  }
2826
2918
  const colDef = val;
2919
+ const resolvedTable = colDef.table && colDef.table === this.table.name && from.type === "Table" && from.alias ? from.alias : colDef.table || rootTableName;
2827
2920
  acc.push({
2828
2921
  type: "Column",
2829
- table: colDef.table || this.table.name,
2922
+ table: resolvedTable,
2830
2923
  name: colDef.name,
2831
2924
  alias
2832
2925
  });
@@ -2841,7 +2934,9 @@ var QueryAstService = class {
2841
2934
  * @returns Column selection result with updated state and added columns
2842
2935
  */
2843
2936
  selectRaw(cols) {
2844
- const newCols = cols.map((col2) => parseRawColumn(col2, this.table.name, this.state.ast.ctes));
2937
+ const from = this.state.ast.from;
2938
+ const defaultTable = from.type === "Table" && from.alias ? from.alias : this.table.name;
2939
+ const newCols = cols.map((col2) => parseRawColumn(col2, defaultTable, this.state.ast.ctes));
2845
2940
  const nextState = this.state.withColumns(newCols);
2846
2941
  return { state: nextState, addedColumns: newCols };
2847
2942
  }
@@ -2877,6 +2972,14 @@ var QueryAstService = class {
2877
2972
  };
2878
2973
  return this.state.withSetOperation(op);
2879
2974
  }
2975
+ /**
2976
+ * Replaces the FROM clause for the current query.
2977
+ * @param from - Table source to use in the FROM clause
2978
+ * @returns Updated query state with new FROM
2979
+ */
2980
+ withFrom(from) {
2981
+ return this.state.withFrom(from);
2982
+ }
2880
2983
  /**
2881
2984
  * Selects a subquery as a column
2882
2985
  * @param alias - Alias for the subquery
@@ -2910,7 +3013,9 @@ var QueryAstService = class {
2910
3013
  * @returns Updated query state with GROUP BY clause
2911
3014
  */
2912
3015
  withGroupBy(col2) {
2913
- const node = buildColumnNode(this.table, col2);
3016
+ const from = this.state.ast.from;
3017
+ const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
3018
+ const node = buildColumnNode(tableRef, col2);
2914
3019
  return this.state.withGroupBy([node]);
2915
3020
  }
2916
3021
  /**
@@ -2929,7 +3034,9 @@ var QueryAstService = class {
2929
3034
  * @returns Updated query state with ORDER BY clause
2930
3035
  */
2931
3036
  withOrderBy(col2, direction) {
2932
- const node = buildColumnNode(this.table, col2);
3037
+ const from = this.state.ast.from;
3038
+ const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
3039
+ const node = buildColumnNode(tableRef, col2);
2933
3040
  return this.state.withOrderBy([{ type: "OrderBy", column: node, direction }]);
2934
3041
  }
2935
3042
  /**
@@ -3033,7 +3140,8 @@ var RelationProjectionHelper = class {
3033
3140
  var assertNever = (value) => {
3034
3141
  throw new Error(`Unhandled relation type: ${JSON.stringify(value)}`);
3035
3142
  };
3036
- var baseRelationCondition = (root, relation) => {
3143
+ var baseRelationCondition = (root, relation, rootAlias) => {
3144
+ const rootTable = rootAlias || root.name;
3037
3145
  const defaultLocalKey = relation.type === RelationKinds.HasMany || relation.type === RelationKinds.HasOne ? findPrimaryKey(root) : findPrimaryKey(relation.target);
3038
3146
  const localKey = relation.localKey || defaultLocalKey;
3039
3147
  switch (relation.type) {
@@ -3041,12 +3149,12 @@ var baseRelationCondition = (root, relation) => {
3041
3149
  case RelationKinds.HasOne:
3042
3150
  return eq(
3043
3151
  { type: "Column", table: relation.target.name, name: relation.foreignKey },
3044
- { type: "Column", table: root.name, name: localKey }
3152
+ { type: "Column", table: rootTable, name: localKey }
3045
3153
  );
3046
3154
  case RelationKinds.BelongsTo:
3047
3155
  return eq(
3048
3156
  { type: "Column", table: relation.target.name, name: localKey },
3049
- { type: "Column", table: root.name, name: relation.foreignKey }
3157
+ { type: "Column", table: rootTable, name: relation.foreignKey }
3050
3158
  );
3051
3159
  case RelationKinds.BelongsToMany:
3052
3160
  throw new Error("BelongsToMany relations do not support the standard join condition builder");
@@ -3054,12 +3162,13 @@ var baseRelationCondition = (root, relation) => {
3054
3162
  return assertNever(relation);
3055
3163
  }
3056
3164
  };
3057
- var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra) => {
3165
+ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra, rootAlias) => {
3058
3166
  const rootKey = relation.localKey || findPrimaryKey(root);
3059
3167
  const targetKey = relation.targetKey || findPrimaryKey(relation.target);
3168
+ const rootTable = rootAlias || root.name;
3060
3169
  const pivotCondition = eq(
3061
3170
  { type: "Column", table: relation.pivotTable.name, name: relation.pivotForeignKeyToRoot },
3062
- { type: "Column", table: root.name, name: rootKey }
3171
+ { type: "Column", table: rootTable, name: rootKey }
3063
3172
  );
3064
3173
  const pivotJoin = createJoinNode(joinKind, relation.pivotTable.name, pivotCondition);
3065
3174
  let targetCondition = eq(
@@ -3077,12 +3186,12 @@ var buildBelongsToManyJoins = (root, relationName, relation, joinKind, extra) =>
3077
3186
  );
3078
3187
  return [pivotJoin, targetJoin];
3079
3188
  };
3080
- var buildRelationJoinCondition = (root, relation, extra) => {
3081
- const base = baseRelationCondition(root, relation);
3189
+ var buildRelationJoinCondition = (root, relation, extra, rootAlias) => {
3190
+ const base = baseRelationCondition(root, relation, rootAlias);
3082
3191
  return extra ? and(base, extra) : base;
3083
3192
  };
3084
- var buildRelationCorrelation = (root, relation) => {
3085
- return baseRelationCondition(root, relation);
3193
+ var buildRelationCorrelation = (root, relation, rootAlias) => {
3194
+ return baseRelationCondition(root, relation, rootAlias);
3086
3195
  };
3087
3196
 
3088
3197
  // src/core/ast/join-metadata.ts
@@ -3126,7 +3235,7 @@ var RelationService = class {
3126
3235
  match(relationName, predicate) {
3127
3236
  const joined = this.joinRelation(relationName, JOIN_KINDS.INNER, predicate);
3128
3237
  const pk = findPrimaryKey(this.table);
3129
- const distinctCols = [{ type: "Column", table: this.table.name, name: pk }];
3238
+ const distinctCols = [{ type: "Column", table: this.rootTableName(), name: pk }];
3130
3239
  const existingDistinct = joined.state.ast.distinct ? joined.state.ast.distinct : [];
3131
3240
  const nextState = this.astService(joined.state).withDistinct([...existingDistinct, ...distinctCols]);
3132
3241
  return { state: nextState, hydration: joined.hydration };
@@ -3213,9 +3322,13 @@ var RelationService = class {
3213
3322
  * @param ast - Query AST to modify
3214
3323
  * @returns Modified query AST with relation correlation
3215
3324
  */
3216
- applyRelationCorrelation(relationName, ast) {
3325
+ applyRelationCorrelation(relationName, ast, additionalCorrelation) {
3217
3326
  const relation = this.getRelation(relationName);
3218
- const correlation = buildRelationCorrelation(this.table, relation);
3327
+ const rootAlias = this.state.ast.from.type === "Table" ? this.state.ast.from.alias : void 0;
3328
+ let correlation = buildRelationCorrelation(this.table, relation, rootAlias);
3329
+ if (additionalCorrelation) {
3330
+ correlation = and(correlation, additionalCorrelation);
3331
+ }
3219
3332
  const whereInSubquery = ast.where ? and(correlation, ast.where) : correlation;
3220
3333
  return {
3221
3334
  ...ast,
@@ -3232,17 +3345,19 @@ var RelationService = class {
3232
3345
  */
3233
3346
  withJoin(state, relationName, joinKind, extraCondition) {
3234
3347
  const relation = this.getRelation(relationName);
3348
+ const rootAlias = state.ast.from.type === "Table" ? state.ast.from.alias : void 0;
3235
3349
  if (relation.type === RelationKinds.BelongsToMany) {
3236
3350
  const joins = buildBelongsToManyJoins(
3237
3351
  this.table,
3238
3352
  relationName,
3239
3353
  relation,
3240
3354
  joinKind,
3241
- extraCondition
3355
+ extraCondition,
3356
+ rootAlias
3242
3357
  );
3243
3358
  return joins.reduce((current, join) => this.astService(current).withJoin(join), state);
3244
3359
  }
3245
- const condition = buildRelationJoinCondition(this.table, relation, extraCondition);
3360
+ const condition = buildRelationJoinCondition(this.table, relation, extraCondition, rootAlias);
3246
3361
  const joinNode = createJoinNode(joinKind, relation.target.name, condition, relationName);
3247
3362
  return this.astService(state).withJoin(joinNode);
3248
3363
  }
@@ -3281,6 +3396,11 @@ var RelationService = class {
3281
3396
  astService(state = this.state) {
3282
3397
  return this.createQueryAstService(this.table, state);
3283
3398
  }
3399
+ rootTableName() {
3400
+ const from = this.state.ast.from;
3401
+ if (from.type === "Table" && from.alias) return from.alias;
3402
+ return this.table.name;
3403
+ }
3284
3404
  };
3285
3405
 
3286
3406
  // src/query-builder/select-query-builder-deps.ts
@@ -3355,7 +3475,9 @@ var ColumnSelector = class {
3355
3475
  * @returns Updated query context with DISTINCT clause
3356
3476
  */
3357
3477
  distinct(context, columns) {
3358
- const nodes = columns.map((col2) => buildColumnNode(this.env.table, col2));
3478
+ const from = context.state.ast.from;
3479
+ const tableRef = from.type === "Table" && from.alias ? { ...this.env.table, alias: from.alias } : this.env.table;
3480
+ const nodes = columns.map((col2) => buildColumnNode(tableRef, col2));
3359
3481
  const astService = this.env.deps.createQueryAstService(this.env.table, context.state);
3360
3482
  const nextState = astService.withDistinct(nodes);
3361
3483
  return { state: nextState, hydration: context.hydration };
@@ -3412,8 +3534,8 @@ var RelationManager = class {
3412
3534
  * @param ast - Query AST to modify
3413
3535
  * @returns Modified query AST with relation correlation
3414
3536
  */
3415
- applyRelationCorrelation(context, relationName, ast) {
3416
- return this.createService(context).applyRelationCorrelation(relationName, ast);
3537
+ applyRelationCorrelation(context, relationName, ast, additionalCorrelation) {
3538
+ return this.createService(context).applyRelationCorrelation(relationName, ast, additionalCorrelation);
3417
3539
  }
3418
3540
  /**
3419
3541
  * Creates a relation service instance
@@ -4460,9 +4582,30 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4460
4582
  clone(context = this.context, lazyRelations = new Set(this.lazyRelations)) {
4461
4583
  return new _SelectQueryBuilder(this.env.table, context.state, context.hydration, this.env.deps, lazyRelations);
4462
4584
  }
4585
+ /**
4586
+ * Applies an alias to the root FROM table.
4587
+ * @param alias - Alias to apply
4588
+ */
4589
+ as(alias) {
4590
+ const from = this.context.state.ast.from;
4591
+ if (from.type !== "Table") {
4592
+ throw new Error("Cannot alias non-table FROM sources");
4593
+ }
4594
+ const nextFrom = { ...from, alias };
4595
+ const nextContext = this.applyAst(this.context, (service) => service.withFrom(nextFrom));
4596
+ return this.clone(nextContext);
4597
+ }
4463
4598
  resolveQueryNode(query) {
4464
4599
  return typeof query.getAST === "function" ? query.getAST() : query;
4465
4600
  }
4601
+ applyCorrelation(ast, correlation) {
4602
+ if (!correlation) return ast;
4603
+ const combinedWhere = ast.where ? and(correlation, ast.where) : correlation;
4604
+ return {
4605
+ ...ast,
4606
+ where: combinedWhere
4607
+ };
4608
+ }
4466
4609
  createChildBuilder(table) {
4467
4610
  return new _SelectQueryBuilder(table, void 0, void 0, this.env.deps);
4468
4611
  }
@@ -4554,6 +4697,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4554
4697
  const nextContext = this.applyAst(this.context, (service) => service.withCte(name, subAst, columns, true));
4555
4698
  return this.clone(nextContext);
4556
4699
  }
4700
+ /**
4701
+ * Replaces the FROM clause with a derived table (subquery with alias)
4702
+ * @param subquery - Subquery to use as the FROM source
4703
+ * @param alias - Alias for the derived table
4704
+ * @param columnAliases - Optional column alias list
4705
+ * @returns New query builder instance with updated FROM
4706
+ */
4707
+ fromSubquery(subquery, alias, columnAliases) {
4708
+ const subAst = this.resolveQueryNode(subquery);
4709
+ const fromNode = derivedTable(subAst, alias, columnAliases);
4710
+ const nextContext = this.applyAst(this.context, (service) => service.withFrom(fromNode));
4711
+ return this.clone(nextContext);
4712
+ }
4557
4713
  /**
4558
4714
 
4559
4715
  * Selects a subquery as a column
@@ -4569,6 +4725,21 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4569
4725
  const query = this.resolveQueryNode(sub);
4570
4726
  return this.clone(this.columnSelector.selectSubquery(this.context, alias, query));
4571
4727
  }
4728
+ /**
4729
+ * Adds a JOIN against a derived table (subquery with alias)
4730
+ * @param subquery - Subquery to join
4731
+ * @param alias - Alias for the derived table
4732
+ * @param condition - Join condition expression
4733
+ * @param joinKind - Join kind (defaults to INNER)
4734
+ * @param columnAliases - Optional column alias list for the derived table
4735
+ * @returns New query builder instance with the derived-table join
4736
+ */
4737
+ joinSubquery(subquery, alias, condition, joinKind = JOIN_KINDS.INNER, columnAliases) {
4738
+ const subAst = this.resolveQueryNode(subquery);
4739
+ const joinNode = createJoinNode(joinKind, derivedTable(subAst, alias, columnAliases), condition);
4740
+ const nextContext = this.applyAst(this.context, (service) => service.withJoin(joinNode));
4741
+ return this.clone(nextContext);
4742
+ }
4572
4743
  /**
4573
4744
 
4574
4745
  * Adds an INNER JOIN to the query
@@ -4868,9 +5039,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4868
5039
  * @returns New query builder instance with the WHERE EXISTS condition
4869
5040
 
4870
5041
  */
4871
- whereExists(subquery) {
5042
+ whereExists(subquery, correlate) {
4872
5043
  const subAst = this.resolveQueryNode(subquery);
4873
- return this.where(exists(subAst));
5044
+ const correlated = this.applyCorrelation(subAst, correlate);
5045
+ return this.where(exists(correlated));
4874
5046
  }
4875
5047
  /**
4876
5048
 
@@ -4881,9 +5053,10 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4881
5053
  * @returns New query builder instance with the WHERE NOT EXISTS condition
4882
5054
 
4883
5055
  */
4884
- whereNotExists(subquery) {
5056
+ whereNotExists(subquery, correlate) {
4885
5057
  const subAst = this.resolveQueryNode(subquery);
4886
- return this.where(notExists(subAst));
5058
+ const correlated = this.applyCorrelation(subAst, correlate);
5059
+ return this.where(notExists(correlated));
4887
5060
  }
4888
5061
  /**
4889
5062
 
@@ -4896,17 +5069,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4896
5069
  * @returns New query builder instance with the relationship existence check
4897
5070
 
4898
5071
  */
4899
- whereHas(relationName, callback) {
5072
+ whereHas(relationName, callbackOrOptions, maybeOptions) {
4900
5073
  const relation = this.env.table.relations[relationName];
4901
5074
  if (!relation) {
4902
5075
  throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
4903
5076
  }
5077
+ const callback = typeof callbackOrOptions === "function" ? callbackOrOptions : void 0;
5078
+ const options = typeof callbackOrOptions === "function" ? maybeOptions : callbackOrOptions;
4904
5079
  let subQb = this.createChildBuilder(relation.target);
4905
5080
  if (callback) {
4906
5081
  subQb = callback(subQb);
4907
5082
  }
4908
5083
  const subAst = subQb.getAST();
4909
- const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst);
5084
+ const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst, options?.correlate);
4910
5085
  return this.where(exists(finalSubAst));
4911
5086
  }
4912
5087
  /**
@@ -4920,17 +5095,19 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4920
5095
  * @returns New query builder instance with the relationship non-existence check
4921
5096
 
4922
5097
  */
4923
- whereHasNot(relationName, callback) {
5098
+ whereHasNot(relationName, callbackOrOptions, maybeOptions) {
4924
5099
  const relation = this.env.table.relations[relationName];
4925
5100
  if (!relation) {
4926
5101
  throw new Error(`Relation '${relationName}' not found on table '${this.env.table.name}'`);
4927
5102
  }
5103
+ const callback = typeof callbackOrOptions === "function" ? callbackOrOptions : void 0;
5104
+ const options = typeof callbackOrOptions === "function" ? maybeOptions : callbackOrOptions;
4928
5105
  let subQb = this.createChildBuilder(relation.target);
4929
5106
  if (callback) {
4930
5107
  subQb = callback(subQb);
4931
5108
  }
4932
5109
  const subAst = subQb.getAST();
4933
- const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst);
5110
+ const finalSubAst = this.relationManager.applyRelationCorrelation(this.context, relationName, subAst, options?.correlate);
4934
5111
  return this.where(notExists(finalSubAst));
4935
5112
  }
4936
5113
  /**
@@ -6354,7 +6531,7 @@ var DefaultNamingStrategy = class {
6354
6531
  * @returns Capitalized table name (handles schema-qualified names)
6355
6532
  */
6356
6533
  tableToSymbol(table) {
6357
- const tableName = typeof table === "string" ? table : table.name;
6534
+ const tableName = typeof table === "string" ? table : table.type === "DerivedTable" ? table.alias : table.name;
6358
6535
  if (tableName.includes(".")) {
6359
6536
  return tableName.split(".").map((part) => this.capitalize(part)).join("");
6360
6537
  }
@@ -7528,6 +7705,7 @@ function createMssqlExecutor(client) {
7528
7705
  columnOperand,
7529
7706
  concat,
7530
7707
  concatWs,
7708
+ correlateBy,
7531
7709
  cos,
7532
7710
  cot,
7533
7711
  count,
@@ -7618,6 +7796,7 @@ function createMssqlExecutor(client) {
7618
7796
  now,
7619
7797
  ntile,
7620
7798
  or,
7799
+ outerRef,
7621
7800
  pi,
7622
7801
  position,
7623
7802
  pow,