metal-orm 1.0.39 → 1.0.40

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
@@ -70,7 +70,9 @@ __export(index_exports, {
70
70
  UpdateQueryBuilder: () => UpdateQueryBuilder,
71
71
  abs: () => abs,
72
72
  acos: () => acos,
73
+ add: () => add,
73
74
  addDomainEvent: () => addDomainEvent,
75
+ aliasRef: () => aliasRef,
74
76
  and: () => and,
75
77
  ascii: () => ascii,
76
78
  asin: () => asin,
@@ -121,6 +123,7 @@ __export(index_exports, {
121
123
  degrees: () => degrees,
122
124
  denseRank: () => denseRank,
123
125
  diffSchema: () => diffSchema,
126
+ div: () => div,
124
127
  endOfMonth: () => endOfMonth,
125
128
  eq: () => eq,
126
129
  esel: () => esel,
@@ -178,6 +181,7 @@ __export(index_exports, {
178
181
  min: () => min,
179
182
  mod: () => mod,
180
183
  month: () => month,
184
+ mul: () => mul,
181
185
  neq: () => neq,
182
186
  notBetween: () => notBetween,
183
187
  notExists: () => notExists,
@@ -213,6 +217,7 @@ __export(index_exports, {
213
217
  sin: () => sin,
214
218
  space: () => space,
215
219
  sqrt: () => sqrt,
220
+ sub: () => sub,
216
221
  substr: () => substr,
217
222
  sum: () => sum,
218
223
  synchronizeSchema: () => synchronizeSchema,
@@ -450,6 +455,7 @@ var belongsToMany = (target, pivotTable, options) => ({
450
455
 
451
456
  // src/core/ast/expression-nodes.ts
452
457
  var operandTypes = /* @__PURE__ */ new Set([
458
+ "AliasRef",
453
459
  "Column",
454
460
  "Literal",
455
461
  "Function",
@@ -496,6 +502,10 @@ var outerRef = (col2) => ({
496
502
  ...columnOperand(col2),
497
503
  scope: "outer"
498
504
  });
505
+ var aliasRef = (name) => ({
506
+ type: "AliasRef",
507
+ name
508
+ });
499
509
  var correlateBy = (table, column) => outerRef({ name: column, table });
500
510
  var createBinaryExpression = (operator, left2, right2, escape) => {
501
511
  const node = {
@@ -554,6 +564,16 @@ var createBetweenExpression = (operator, left2, lower2, upper2) => ({
554
564
  });
555
565
  var between = (left2, lower2, upper2) => createBetweenExpression("BETWEEN", left2, lower2, upper2);
556
566
  var notBetween = (left2, lower2, upper2) => createBetweenExpression("NOT BETWEEN", left2, lower2, upper2);
567
+ var createArithmeticExpression = (operator, left2, right2) => ({
568
+ type: "ArithmeticExpression",
569
+ left: toOperand(left2),
570
+ operator,
571
+ right: toOperand(right2)
572
+ });
573
+ var add = (left2, right2) => createArithmeticExpression("+", left2, right2);
574
+ var sub = (left2, right2) => createArithmeticExpression("-", left2, right2);
575
+ var mul = (left2, right2) => createArithmeticExpression("*", left2, right2);
576
+ var div = (left2, right2) => createArithmeticExpression("/", left2, right2);
557
577
  var jsonPath = (col2, path) => ({
558
578
  type: "JsonPath",
559
579
  column: columnOperand(col2),
@@ -632,7 +652,7 @@ var windowFunction = (name, args = [], partitionBy, orderBy) => {
632
652
  const partitionNodes = partitionBy?.map((col2) => columnOperand(col2)) ?? void 0;
633
653
  const orderNodes = orderBy?.map((o) => ({
634
654
  type: "OrderBy",
635
- column: columnOperand(o.column),
655
+ term: columnOperand(o.column),
636
656
  direction: o.direction
637
657
  }));
638
658
  return buildWindowFunction(name, nodeArgs, partitionNodes, orderNodes);
@@ -707,7 +727,7 @@ var min = buildAggregate("MIN");
707
727
  var max = buildAggregate("MAX");
708
728
  var toOrderByNode = (order) => ({
709
729
  type: "OrderBy",
710
- column: columnOperand(order.column),
730
+ term: columnOperand(order.column),
711
731
  direction: order.direction ?? ORDER_DIRECTIONS.ASC
712
732
  });
713
733
  var groupConcat = (col2, options) => ({
@@ -757,6 +777,9 @@ var visitExpression = (node, visitor) => {
757
777
  case "BetweenExpression":
758
778
  if (visitor.visitBetweenExpression) return visitor.visitBetweenExpression(node);
759
779
  break;
780
+ case "ArithmeticExpression":
781
+ if (visitor.visitArithmeticExpression) return visitor.visitArithmeticExpression(node);
782
+ break;
760
783
  default:
761
784
  break;
762
785
  }
@@ -788,6 +811,9 @@ var visitOperand = (node, visitor) => {
788
811
  case "WindowFunction":
789
812
  if (visitor.visitWindowFunction) return visitor.visitWindowFunction(node);
790
813
  break;
814
+ case "AliasRef":
815
+ if (visitor.visitAliasRef) return visitor.visitAliasRef(node);
816
+ break;
791
817
  default:
792
818
  break;
793
819
  }
@@ -904,7 +930,14 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
904
930
  if (!orderBy || orderBy.length === 0) {
905
931
  return "";
906
932
  }
907
- const parts = orderBy.map((order) => `${ctx.compileOperand(order.column)} ${order.direction}`);
933
+ const parts = orderBy.map((order) => {
934
+ const term = isOperandNode(order.term) ? ctx.compileOperand(order.term) : (() => {
935
+ throw new Error("ORDER BY expressions inside functions must be operands");
936
+ })();
937
+ const collation = order.collation ? ` COLLATE ${order.collation}` : "";
938
+ const nulls = order.nulls ? ` NULLS ${order.nulls}` : "";
939
+ return `${term} ${order.direction}${collation}${nulls}`;
940
+ });
908
941
  return `ORDER BY ${parts.join(", ")}`;
909
942
  }
910
943
  formatGroupConcatSeparator(ctx) {
@@ -1169,6 +1202,16 @@ var Dialect = class _Dialect {
1169
1202
  }
1170
1203
  return compiler(node, ctx);
1171
1204
  }
1205
+ /**
1206
+ * Compiles an ordering term (operand, expression, or alias reference).
1207
+ */
1208
+ compileOrderingTerm(term, ctx) {
1209
+ if (isOperandNode(term)) {
1210
+ return this.compileOperand(term, ctx);
1211
+ }
1212
+ const expr = this.compileExpression(term, ctx);
1213
+ return `(${expr})`;
1214
+ }
1172
1215
  registerDefaultExpressionCompilers() {
1173
1216
  this.registerExpressionCompiler("BinaryExpression", (binary, ctx) => {
1174
1217
  const left2 = this.compileOperand(binary.left, ctx);
@@ -1207,9 +1250,15 @@ var Dialect = class _Dialect {
1207
1250
  const upper2 = this.compileOperand(betweenExpr.upper, ctx);
1208
1251
  return `${left2} ${betweenExpr.operator} ${lower2} AND ${upper2}`;
1209
1252
  });
1253
+ this.registerExpressionCompiler("ArithmeticExpression", (arith, ctx) => {
1254
+ const left2 = this.compileOperand(arith.left, ctx);
1255
+ const right2 = this.compileOperand(arith.right, ctx);
1256
+ return `${left2} ${arith.operator} ${right2}`;
1257
+ });
1210
1258
  }
1211
1259
  registerDefaultOperandCompilers() {
1212
1260
  this.registerOperandCompiler("Literal", (literal, ctx) => ctx.addParameter(literal.value));
1261
+ this.registerOperandCompiler("AliasRef", (alias, _ctx) => this.quoteIdentifier(alias.name));
1213
1262
  this.registerOperandCompiler("Column", (column, _ctx) => {
1214
1263
  return `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`;
1215
1264
  });
@@ -1247,9 +1296,12 @@ var Dialect = class _Dialect {
1247
1296
  parts.push(partitionClause);
1248
1297
  }
1249
1298
  if (node.orderBy && node.orderBy.length > 0) {
1250
- const orderClause = "ORDER BY " + node.orderBy.map(
1251
- (o) => `${this.quoteIdentifier(o.column.table)}.${this.quoteIdentifier(o.column.name)} ${o.direction}`
1252
- ).join(", ");
1299
+ const orderClause = "ORDER BY " + node.orderBy.map((o) => {
1300
+ const term = this.compileOrderingTerm(o.term, ctx);
1301
+ const collation = o.collation ? ` COLLATE ${o.collation}` : "";
1302
+ const nulls = o.nulls ? ` NULLS ${o.nulls}` : "";
1303
+ return `${term} ${o.direction}${collation}${nulls}`;
1304
+ }).join(", ");
1253
1305
  parts.push(orderClause);
1254
1306
  }
1255
1307
  result += parts.join(" ");
@@ -1468,12 +1520,12 @@ var GroupByCompiler = class {
1468
1520
  /**
1469
1521
  * Compiles GROUP BY clause from a SELECT query AST.
1470
1522
  * @param ast - The SELECT query AST containing grouping columns.
1471
- * @param quoteIdentifier - Function to quote identifiers according to dialect rules.
1523
+ * @param renderTerm - Function to render a grouping term.
1472
1524
  * @returns SQL GROUP BY clause (e.g., " GROUP BY table.col1, table.col2") or empty string if no grouping.
1473
1525
  */
1474
- static compileGroupBy(ast, quoteIdentifier) {
1526
+ static compileGroupBy(ast, renderTerm) {
1475
1527
  if (!ast.groupBy || ast.groupBy.length === 0) return "";
1476
- const cols = ast.groupBy.map((c) => `${quoteIdentifier(c.table)}.${quoteIdentifier(c.name)}`).join(", ");
1528
+ const cols = ast.groupBy.map(renderTerm).join(", ");
1477
1529
  return ` GROUP BY ${cols}`;
1478
1530
  }
1479
1531
  };
@@ -1483,12 +1535,19 @@ var OrderByCompiler = class {
1483
1535
  /**
1484
1536
  * Compiles ORDER BY clause from a SELECT query AST.
1485
1537
  * @param ast - The SELECT query AST containing sort specifications.
1486
- * @param quoteIdentifier - Function to quote identifiers according to dialect rules.
1538
+ * @param renderTerm - Function to render an ordering term.
1539
+ * @param renderNulls - Optional function to render NULLS FIRST/LAST.
1540
+ * @param renderCollation - Optional function to render COLLATE clause.
1487
1541
  * @returns SQL ORDER BY clause (e.g., " ORDER BY table.col1 ASC, table.col2 DESC") or empty string if no ordering.
1488
1542
  */
1489
- static compileOrderBy(ast, quoteIdentifier) {
1543
+ static compileOrderBy(ast, renderTerm, renderNulls, renderCollation) {
1490
1544
  if (!ast.orderBy || ast.orderBy.length === 0) return "";
1491
- const parts = ast.orderBy.map((o) => `${quoteIdentifier(o.column.table)}.${quoteIdentifier(o.column.name)} ${o.direction}`).join(", ");
1545
+ const parts = ast.orderBy.map((o) => {
1546
+ const term = renderTerm(o.term);
1547
+ const collation = renderCollation ? renderCollation(o) : o.collation ? ` COLLATE ${o.collation}` : "";
1548
+ const nulls = renderNulls ? renderNulls(o) : o.nulls ? ` NULLS ${o.nulls}` : "";
1549
+ return `${term} ${o.direction}${collation}${nulls}`;
1550
+ }).join(", ");
1492
1551
  return ` ORDER BY ${parts}`;
1493
1552
  }
1494
1553
  };
@@ -1519,7 +1578,12 @@ var SqlDialectBase = class extends Dialect {
1519
1578
  }
1520
1579
  compileSelectWithSetOps(ast, baseSelect, ctes, ctx) {
1521
1580
  const compound = ast.setOps.map((op) => `${op.operator} ${this.wrapSetOperand(this.compileSelectAst(op.query, ctx))}`).join(" ");
1522
- const orderBy = OrderByCompiler.compileOrderBy(ast, this.quoteIdentifier.bind(this));
1581
+ const orderBy = OrderByCompiler.compileOrderBy(
1582
+ ast,
1583
+ (term) => this.compileOrderingTerm(term, ctx),
1584
+ this.renderOrderByNulls.bind(this),
1585
+ this.renderOrderByCollation.bind(this)
1586
+ );
1523
1587
  const pagination = this.paginationStrategy.compilePagination(ast.limit, ast.offset);
1524
1588
  const combined = `${this.wrapSetOperand(baseSelect)} ${compound}`;
1525
1589
  return `${ctes}${combined}${orderBy}${pagination}`;
@@ -1545,9 +1609,14 @@ var SqlDialectBase = class extends Dialect {
1545
1609
  const from = this.compileFrom(ast.from, ctx);
1546
1610
  const joins = JoinCompiler.compileJoins(ast, ctx, this.compileFrom.bind(this), this.compileExpression.bind(this));
1547
1611
  const whereClause = this.compileWhere(ast.where, ctx);
1548
- const groupBy = GroupByCompiler.compileGroupBy(ast, this.quoteIdentifier.bind(this));
1612
+ const groupBy = GroupByCompiler.compileGroupBy(ast, (term) => this.compileOrderingTerm(term, ctx));
1549
1613
  const having = this.compileHaving(ast, ctx);
1550
- const orderBy = OrderByCompiler.compileOrderBy(ast, this.quoteIdentifier.bind(this));
1614
+ const orderBy = OrderByCompiler.compileOrderBy(
1615
+ ast,
1616
+ (term) => this.compileOrderingTerm(term, ctx),
1617
+ this.renderOrderByNulls.bind(this),
1618
+ this.renderOrderByCollation.bind(this)
1619
+ );
1551
1620
  const pagination = this.paginationStrategy.compilePagination(ast.limit, ast.offset);
1552
1621
  return `SELECT ${this.compileDistinct(ast)}${columns} FROM ${from}${joins}${whereClause}${groupBy}${having}${orderBy}${pagination}`;
1553
1622
  }
@@ -1636,6 +1705,12 @@ var SqlDialectBase = class extends Dialect {
1636
1705
  const trimmed = this.stripTrailingSemicolon(sql);
1637
1706
  return `(${trimmed})`;
1638
1707
  }
1708
+ renderOrderByNulls(order) {
1709
+ return order.nulls ? ` NULLS ${order.nulls}` : "";
1710
+ }
1711
+ renderOrderByCollation(order) {
1712
+ return order.collation ? ` COLLATE ${order.collation}` : "";
1713
+ }
1639
1714
  };
1640
1715
 
1641
1716
  // src/core/dialect/postgres/functions.ts
@@ -2152,7 +2227,7 @@ var SqlServerDialect = class extends Dialect {
2152
2227
  return `${ctes}${baseSelect}`;
2153
2228
  }
2154
2229
  const compound = ast.setOps.map((op) => `${op.operator} ${this.wrapSetOperand(this.compileSelectAst(op.query, ctx))}`).join(" ");
2155
- const orderBy = this.compileOrderBy(ast);
2230
+ const orderBy = this.compileOrderBy(ast, ctx);
2156
2231
  const pagination = this.compilePagination(ast, orderBy);
2157
2232
  const combined = `${this.wrapSetOperand(baseSelect)} ${compound}`;
2158
2233
  const tail = pagination || orderBy;
@@ -2209,18 +2284,22 @@ var SqlServerDialect = class extends Dialect {
2209
2284
  return `${j.kind} JOIN ${table} ON ${cond}`;
2210
2285
  }).join(" ");
2211
2286
  const whereClause = this.compileWhere(ast.where, ctx);
2212
- const groupBy = ast.groupBy && ast.groupBy.length > 0 ? " GROUP BY " + ast.groupBy.map((c) => `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`).join(", ") : "";
2287
+ const groupBy = ast.groupBy && ast.groupBy.length > 0 ? " GROUP BY " + ast.groupBy.map((term) => this.compileOrderingTerm(term, ctx)).join(", ") : "";
2213
2288
  const having = ast.having ? ` HAVING ${this.compileExpression(ast.having, ctx)}` : "";
2214
- const orderBy = this.compileOrderBy(ast);
2289
+ const orderBy = this.compileOrderBy(ast, ctx);
2215
2290
  const pagination = this.compilePagination(ast, orderBy);
2216
2291
  if (pagination) {
2217
2292
  return `SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${pagination}`;
2218
2293
  }
2219
2294
  return `SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${orderBy}`;
2220
2295
  }
2221
- compileOrderBy(ast) {
2222
- if (!ast.orderBy || ast.orderBy.length === 0) return "";
2223
- return " ORDER BY " + ast.orderBy.map((o) => `${this.quoteIdentifier(o.column.table)}.${this.quoteIdentifier(o.column.name)} ${o.direction}`).join(", ");
2296
+ compileOrderBy(ast, ctx) {
2297
+ return OrderByCompiler.compileOrderBy(
2298
+ ast,
2299
+ (term) => this.compileOrderingTerm(term, ctx),
2300
+ this.renderOrderByNulls.bind(this),
2301
+ this.renderOrderByCollation.bind(this)
2302
+ );
2224
2303
  }
2225
2304
  compilePagination(ast, orderBy) {
2226
2305
  const hasLimit = ast.limit !== void 0;
@@ -2234,6 +2313,12 @@ var SqlServerDialect = class extends Dialect {
2234
2313
  }
2235
2314
  return pagination;
2236
2315
  }
2316
+ renderOrderByNulls(order) {
2317
+ return order.nulls ? ` NULLS ${order.nulls}` : "";
2318
+ }
2319
+ renderOrderByCollation(order) {
2320
+ return order.collation ? ` COLLATE ${order.collation}` : "";
2321
+ }
2237
2322
  compileTableSource(table, ctx) {
2238
2323
  if (table.type === "FunctionTable") {
2239
2324
  return FunctionTableFormatter.format(table, ctx, this);
@@ -2245,9 +2330,9 @@ var SqlServerDialect = class extends Dialect {
2245
2330
  return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
2246
2331
  }
2247
2332
  compileDerivedTable(table, ctx) {
2248
- const sub = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
2333
+ const sub2 = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
2249
2334
  const cols = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
2250
- return `(${sub}) AS ${this.quoteIdentifier(table.alias)}${cols}`;
2335
+ return `(${sub2}) AS ${this.quoteIdentifier(table.alias)}${cols}`;
2251
2336
  }
2252
2337
  compileCtes(ast, ctx) {
2253
2338
  if (!ast.ctes || ast.ctes.length === 0) return "";
@@ -2412,7 +2497,7 @@ var SelectQueryState = class _SelectQueryState {
2412
2497
  }
2413
2498
  /**
2414
2499
  * Adds GROUP BY columns to the query
2415
- * @param columns - Columns to group by
2500
+ * @param columns - Terms to group by
2416
2501
  * @returns New SelectQueryState with GROUP BY clause
2417
2502
  */
2418
2503
  withGroupBy(columns) {
@@ -2695,31 +2780,38 @@ var HydrationManager = class _HydrationManager {
2695
2780
  }
2696
2781
  const mapped = [];
2697
2782
  for (const ob of orderBy) {
2698
- if (ob.column.table !== plan.rootTable) {
2699
- return null;
2700
- }
2701
- const alias = projectionAliases.get(`${ob.column.table}.${ob.column.name}`) ?? ob.column.name;
2702
- if (!availableColumns.has(alias)) {
2703
- return null;
2704
- }
2705
- mapped.push({
2706
- type: "OrderBy",
2707
- column: { type: "Column", table: baseAlias, name: alias },
2708
- direction: ob.direction
2709
- });
2783
+ const mappedTerm = this.mapOrderingTerm(ob.term, plan, projectionAliases, baseAlias, availableColumns);
2784
+ if (!mappedTerm) return null;
2785
+ mapped.push({ ...ob, term: mappedTerm });
2710
2786
  }
2711
2787
  return mapped;
2712
2788
  }
2789
+ mapOrderingTerm(term, plan, projectionAliases, baseAlias, availableColumns) {
2790
+ if (term.type === "Column") {
2791
+ const col2 = term;
2792
+ if (col2.table !== plan.rootTable) return null;
2793
+ const alias = projectionAliases.get(`${col2.table}.${col2.name}`) ?? col2.name;
2794
+ if (!availableColumns.has(alias)) return null;
2795
+ return { type: "Column", table: baseAlias, name: alias };
2796
+ }
2797
+ if (term.type === "AliasRef") {
2798
+ const aliasName = term.name;
2799
+ if (!availableColumns.has(aliasName)) return null;
2800
+ return { type: "Column", table: baseAlias, name: aliasName };
2801
+ }
2802
+ return null;
2803
+ }
2713
2804
  buildPagingColumns(primaryKey, orderBy, tableAlias) {
2714
2805
  const columns = [{ type: "Column", table: tableAlias, name: primaryKey, alias: primaryKey }];
2715
2806
  if (!orderBy) return columns;
2716
2807
  for (const ob of orderBy) {
2717
- if (!columns.some((col2) => col2.name === ob.column.name)) {
2808
+ const term = ob.term;
2809
+ if (!columns.some((col2) => col2.name === term.name)) {
2718
2810
  columns.push({
2719
2811
  type: "Column",
2720
2812
  table: tableAlias,
2721
- name: ob.column.name,
2722
- alias: ob.column.name
2813
+ name: term.name,
2814
+ alias: term.name
2723
2815
  });
2724
2816
  }
2725
2817
  }
@@ -3025,10 +3117,8 @@ var QueryAstService = class {
3025
3117
  * @returns Updated query state with GROUP BY clause
3026
3118
  */
3027
3119
  withGroupBy(col2) {
3028
- const from = this.state.ast.from;
3029
- const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
3030
- const node = buildColumnNode(tableRef, col2);
3031
- return this.state.withGroupBy([node]);
3120
+ const term = this.normalizeOrderingTerm(col2);
3121
+ return this.state.withGroupBy([term]);
3032
3122
  }
3033
3123
  /**
3034
3124
  * Adds a HAVING clause to the query
@@ -3045,11 +3135,9 @@ var QueryAstService = class {
3045
3135
  * @param direction - Order direction (ASC/DESC)
3046
3136
  * @returns Updated query state with ORDER BY clause
3047
3137
  */
3048
- withOrderBy(col2, direction) {
3049
- const from = this.state.ast.from;
3050
- const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
3051
- const node = buildColumnNode(tableRef, col2);
3052
- return this.state.withOrderBy([{ type: "OrderBy", column: node, direction }]);
3138
+ withOrderBy(term, direction, nulls, collation) {
3139
+ const normalized = this.normalizeOrderingTerm(term);
3140
+ return this.state.withOrderBy([{ type: "OrderBy", term: normalized, direction, nulls, collation }]);
3053
3141
  }
3054
3142
  /**
3055
3143
  * Adds a DISTINCT clause to the query
@@ -3084,6 +3172,24 @@ var QueryAstService = class {
3084
3172
  combineExpressions(existing, next) {
3085
3173
  return existing ? and(existing, next) : next;
3086
3174
  }
3175
+ normalizeOrderingTerm(term) {
3176
+ const from = this.state.ast.from;
3177
+ const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
3178
+ const termType = term?.type;
3179
+ if (termType === "Column") {
3180
+ return term;
3181
+ }
3182
+ if (termType === "AliasRef") {
3183
+ return term;
3184
+ }
3185
+ if (isOperandNode(term)) {
3186
+ return term;
3187
+ }
3188
+ if (termType === "BinaryExpression" || termType === "LogicalExpression" || termType === "NullExpression" || termType === "InExpression" || termType === "ExistsExpression" || termType === "BetweenExpression" || termType === "ArithmeticExpression") {
3189
+ return term;
3190
+ }
3191
+ return buildColumnNode(tableRef, term);
3192
+ }
3087
3193
  };
3088
3194
 
3089
3195
  // src/query-builder/relation-projection-helper.ts
@@ -4733,8 +4839,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4733
4839
  * @returns New query builder instance with the subquery selection
4734
4840
 
4735
4841
  */
4736
- selectSubquery(alias, sub) {
4737
- const query = this.resolveQueryNode(sub);
4842
+ selectSubquery(alias, sub2) {
4843
+ const query = this.resolveQueryNode(sub2);
4738
4844
  return this.clone(this.columnSelector.selectSubquery(this.context, alias, query));
4739
4845
  }
4740
4846
  /**
@@ -4916,16 +5022,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4916
5022
  return this.clone(nextContext);
4917
5023
  }
4918
5024
  /**
4919
-
4920
- * Adds a GROUP BY clause to the query
4921
-
4922
- * @param col - Column definition or column node to group by
4923
-
4924
- * @returns New query builder instance with the GROUP BY clause
4925
-
4926
- */
4927
- groupBy(col2) {
4928
- const nextContext = this.applyAst(this.context, (service) => service.withGroupBy(col2));
5025
+ * Adds a GROUP BY clause to the query
5026
+ * @param term - Column definition or ordering term to group by
5027
+ * @returns New query builder instance with the GROUP BY clause
5028
+ */
5029
+ groupBy(term) {
5030
+ const nextContext = this.applyAst(this.context, (service) => service.withGroupBy(term));
4929
5031
  return this.clone(nextContext);
4930
5032
  }
4931
5033
  /**
@@ -4942,18 +5044,18 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4942
5044
  return this.clone(nextContext);
4943
5045
  }
4944
5046
  /**
4945
-
4946
- * Adds an ORDER BY clause to the query
4947
-
4948
- * @param col - Column definition or column node to order by
4949
-
4950
- * @param direction - Order direction (defaults to ASC)
4951
-
4952
- * @returns New query builder instance with the ORDER BY clause
4953
-
4954
- */
4955
- orderBy(col2, direction = ORDER_DIRECTIONS.ASC) {
4956
- const nextContext = this.applyAst(this.context, (service) => service.withOrderBy(col2, direction));
5047
+ * Adds an ORDER BY clause to the query
5048
+ * @param term - Column definition or ordering term to order by
5049
+ * @param directionOrOptions - Order direction or options (defaults to ASC)
5050
+ * @returns New query builder instance with the ORDER BY clause
5051
+ */
5052
+ orderBy(term, directionOrOptions = ORDER_DIRECTIONS.ASC) {
5053
+ const options = typeof directionOrOptions === "string" ? { direction: directionOrOptions } : directionOrOptions;
5054
+ const dir = options.direction ?? ORDER_DIRECTIONS.ASC;
5055
+ const nextContext = this.applyAst(
5056
+ this.context,
5057
+ (service) => service.withOrderBy(term, dir, options.nulls, options.collation)
5058
+ );
4957
5059
  return this.clone(nextContext);
4958
5060
  }
4959
5061
  /**
@@ -6781,7 +6883,7 @@ var TypeScriptGenerator = class {
6781
6883
  lines.push(`.where(${this.printExpression(ast.where)})`);
6782
6884
  }
6783
6885
  if (ast.groupBy && ast.groupBy.length) {
6784
- const cols = ast.groupBy.map((c) => `${this.namingStrategy.tableToSymbol(c.table)}.${c.name}`).join(", ");
6886
+ const cols = ast.groupBy.map((term) => this.printOrderingTerm(term)).join(", ");
6785
6887
  lines.push(`.groupBy(${cols})`);
6786
6888
  }
6787
6889
  if (ast.having) {
@@ -6789,7 +6891,16 @@ var TypeScriptGenerator = class {
6789
6891
  }
6790
6892
  if (ast.orderBy && ast.orderBy.length) {
6791
6893
  ast.orderBy.forEach((o) => {
6792
- lines.push(`.orderBy(${this.namingStrategy.tableToSymbol(o.column.table)}.${o.column.name}, '${o.direction}')`);
6894
+ const term = this.printOrderingTerm(o.term);
6895
+ const opts = [`direction: '${o.direction}'`];
6896
+ if (o.nulls) opts.push(`nulls: '${o.nulls}'`);
6897
+ if (o.collation) opts.push(`collation: '${o.collation}'`);
6898
+ const hasOpts = opts.length > 1;
6899
+ if (hasOpts) {
6900
+ lines.push(`.orderBy(${term}, { ${opts.join(", ")} })`);
6901
+ } else {
6902
+ lines.push(`.orderBy(${term}, '${o.direction}')`);
6903
+ }
6793
6904
  });
6794
6905
  }
6795
6906
  if (ast.limit) lines.push(`.limit(${ast.limit})`);
@@ -6812,6 +6923,29 @@ var TypeScriptGenerator = class {
6812
6923
  printOperand(node) {
6813
6924
  return visitOperand(node, this);
6814
6925
  }
6926
+ /**
6927
+ * Prints an ordering term (operand/expression/alias) to TypeScript code.
6928
+ */
6929
+ printOrderingTerm(term) {
6930
+ if (!term || !term.type) {
6931
+ throw new Error("Unsupported ordering term");
6932
+ }
6933
+ switch (term.type) {
6934
+ case "Column":
6935
+ return `${this.namingStrategy.tableToSymbol(term.table)}.${term.name}`;
6936
+ case "AliasRef":
6937
+ return this.visitAliasRef(term);
6938
+ case "Literal":
6939
+ case "Function":
6940
+ case "JsonPath":
6941
+ case "ScalarSubquery":
6942
+ case "CaseExpression":
6943
+ case "WindowFunction":
6944
+ return this.printOperand(term);
6945
+ default:
6946
+ return this.printExpression(term);
6947
+ }
6948
+ }
6815
6949
  visitBinaryExpression(binary) {
6816
6950
  return this.printBinaryExpression(binary);
6817
6951
  }
@@ -6830,6 +6964,9 @@ var TypeScriptGenerator = class {
6830
6964
  visitBetweenExpression(betweenExpr) {
6831
6965
  return this.printBetweenExpression(betweenExpr);
6832
6966
  }
6967
+ visitArithmeticExpression(arithExpr) {
6968
+ return this.printArithmeticExpression(arithExpr);
6969
+ }
6833
6970
  visitColumn(node) {
6834
6971
  return this.printColumnOperand(node);
6835
6972
  }
@@ -6851,6 +6988,9 @@ var TypeScriptGenerator = class {
6851
6988
  visitWindowFunction(node) {
6852
6989
  return this.printWindowFunctionOperand(node);
6853
6990
  }
6991
+ visitAliasRef(node) {
6992
+ return `aliasRef('${node.name}')`;
6993
+ }
6854
6994
  /**
6855
6995
  * Prints a binary expression to TypeScript code
6856
6996
  * @param binary - Binary expression node
@@ -6881,6 +7021,11 @@ var TypeScriptGenerator = class {
6881
7021
  ${parts.join(",\n ")}
6882
7022
  )`;
6883
7023
  }
7024
+ printArithmeticExpression(expr) {
7025
+ const left2 = this.printOperand(expr.left);
7026
+ const right2 = this.printOperand(expr.right);
7027
+ return `${left2} ${expr.operator} ${right2}`;
7028
+ }
6884
7029
  /**
6885
7030
  * Prints an IN expression to TypeScript code
6886
7031
  * @param inExpr - IN expression node
@@ -6994,7 +7139,12 @@ var TypeScriptGenerator = class {
6994
7139
  parts.push(partitionClause);
6995
7140
  }
6996
7141
  if (node.orderBy && node.orderBy.length > 0) {
6997
- const orderClause = "ORDER BY " + node.orderBy.map((o) => `${this.namingStrategy.tableToSymbol(o.column.table)}.${o.column.name} ${o.direction}`).join(", ");
7142
+ const orderClause = "ORDER BY " + node.orderBy.map((o) => {
7143
+ const term = this.printOrderingTerm(o.term);
7144
+ const collation = o.collation ? ` COLLATE ${o.collation}` : "";
7145
+ const nulls = o.nulls ? ` NULLS ${o.nulls}` : "";
7146
+ return `${term} ${o.direction}${collation}${nulls}`;
7147
+ }).join(", ");
6998
7148
  parts.push(orderClause);
6999
7149
  }
7000
7150
  result += parts.join(" ");
@@ -8172,7 +8322,9 @@ function createTediousExecutor(connection, module2, options) {
8172
8322
  UpdateQueryBuilder,
8173
8323
  abs,
8174
8324
  acos,
8325
+ add,
8175
8326
  addDomainEvent,
8327
+ aliasRef,
8176
8328
  and,
8177
8329
  ascii,
8178
8330
  asin,
@@ -8223,6 +8375,7 @@ function createTediousExecutor(connection, module2, options) {
8223
8375
  degrees,
8224
8376
  denseRank,
8225
8377
  diffSchema,
8378
+ div,
8226
8379
  endOfMonth,
8227
8380
  eq,
8228
8381
  esel,
@@ -8280,6 +8433,7 @@ function createTediousExecutor(connection, module2, options) {
8280
8433
  min,
8281
8434
  mod,
8282
8435
  month,
8436
+ mul,
8283
8437
  neq,
8284
8438
  notBetween,
8285
8439
  notExists,
@@ -8315,6 +8469,7 @@ function createTediousExecutor(connection, module2, options) {
8315
8469
  sin,
8316
8470
  space,
8317
8471
  sqrt,
8472
+ sub,
8318
8473
  substr,
8319
8474
  sum,
8320
8475
  synchronizeSchema,