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.js CHANGED
@@ -245,6 +245,7 @@ var belongsToMany = (target, pivotTable, options) => ({
245
245
 
246
246
  // src/core/ast/expression-nodes.ts
247
247
  var operandTypes = /* @__PURE__ */ new Set([
248
+ "AliasRef",
248
249
  "Column",
249
250
  "Literal",
250
251
  "Function",
@@ -291,6 +292,10 @@ var outerRef = (col2) => ({
291
292
  ...columnOperand(col2),
292
293
  scope: "outer"
293
294
  });
295
+ var aliasRef = (name) => ({
296
+ type: "AliasRef",
297
+ name
298
+ });
294
299
  var correlateBy = (table, column) => outerRef({ name: column, table });
295
300
  var createBinaryExpression = (operator, left2, right2, escape) => {
296
301
  const node = {
@@ -349,6 +354,16 @@ var createBetweenExpression = (operator, left2, lower2, upper2) => ({
349
354
  });
350
355
  var between = (left2, lower2, upper2) => createBetweenExpression("BETWEEN", left2, lower2, upper2);
351
356
  var notBetween = (left2, lower2, upper2) => createBetweenExpression("NOT BETWEEN", left2, lower2, upper2);
357
+ var createArithmeticExpression = (operator, left2, right2) => ({
358
+ type: "ArithmeticExpression",
359
+ left: toOperand(left2),
360
+ operator,
361
+ right: toOperand(right2)
362
+ });
363
+ var add = (left2, right2) => createArithmeticExpression("+", left2, right2);
364
+ var sub = (left2, right2) => createArithmeticExpression("-", left2, right2);
365
+ var mul = (left2, right2) => createArithmeticExpression("*", left2, right2);
366
+ var div = (left2, right2) => createArithmeticExpression("/", left2, right2);
352
367
  var jsonPath = (col2, path) => ({
353
368
  type: "JsonPath",
354
369
  column: columnOperand(col2),
@@ -427,7 +442,7 @@ var windowFunction = (name, args = [], partitionBy, orderBy) => {
427
442
  const partitionNodes = partitionBy?.map((col2) => columnOperand(col2)) ?? void 0;
428
443
  const orderNodes = orderBy?.map((o) => ({
429
444
  type: "OrderBy",
430
- column: columnOperand(o.column),
445
+ term: columnOperand(o.column),
431
446
  direction: o.direction
432
447
  }));
433
448
  return buildWindowFunction(name, nodeArgs, partitionNodes, orderNodes);
@@ -502,7 +517,7 @@ var min = buildAggregate("MIN");
502
517
  var max = buildAggregate("MAX");
503
518
  var toOrderByNode = (order) => ({
504
519
  type: "OrderBy",
505
- column: columnOperand(order.column),
520
+ term: columnOperand(order.column),
506
521
  direction: order.direction ?? ORDER_DIRECTIONS.ASC
507
522
  });
508
523
  var groupConcat = (col2, options) => ({
@@ -552,6 +567,9 @@ var visitExpression = (node, visitor) => {
552
567
  case "BetweenExpression":
553
568
  if (visitor.visitBetweenExpression) return visitor.visitBetweenExpression(node);
554
569
  break;
570
+ case "ArithmeticExpression":
571
+ if (visitor.visitArithmeticExpression) return visitor.visitArithmeticExpression(node);
572
+ break;
555
573
  default:
556
574
  break;
557
575
  }
@@ -583,6 +601,9 @@ var visitOperand = (node, visitor) => {
583
601
  case "WindowFunction":
584
602
  if (visitor.visitWindowFunction) return visitor.visitWindowFunction(node);
585
603
  break;
604
+ case "AliasRef":
605
+ if (visitor.visitAliasRef) return visitor.visitAliasRef(node);
606
+ break;
586
607
  default:
587
608
  break;
588
609
  }
@@ -699,7 +720,14 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
699
720
  if (!orderBy || orderBy.length === 0) {
700
721
  return "";
701
722
  }
702
- const parts = orderBy.map((order) => `${ctx.compileOperand(order.column)} ${order.direction}`);
723
+ const parts = orderBy.map((order) => {
724
+ const term = isOperandNode(order.term) ? ctx.compileOperand(order.term) : (() => {
725
+ throw new Error("ORDER BY expressions inside functions must be operands");
726
+ })();
727
+ const collation = order.collation ? ` COLLATE ${order.collation}` : "";
728
+ const nulls = order.nulls ? ` NULLS ${order.nulls}` : "";
729
+ return `${term} ${order.direction}${collation}${nulls}`;
730
+ });
703
731
  return `ORDER BY ${parts.join(", ")}`;
704
732
  }
705
733
  formatGroupConcatSeparator(ctx) {
@@ -964,6 +992,16 @@ var Dialect = class _Dialect {
964
992
  }
965
993
  return compiler(node, ctx);
966
994
  }
995
+ /**
996
+ * Compiles an ordering term (operand, expression, or alias reference).
997
+ */
998
+ compileOrderingTerm(term, ctx) {
999
+ if (isOperandNode(term)) {
1000
+ return this.compileOperand(term, ctx);
1001
+ }
1002
+ const expr = this.compileExpression(term, ctx);
1003
+ return `(${expr})`;
1004
+ }
967
1005
  registerDefaultExpressionCompilers() {
968
1006
  this.registerExpressionCompiler("BinaryExpression", (binary, ctx) => {
969
1007
  const left2 = this.compileOperand(binary.left, ctx);
@@ -1002,9 +1040,15 @@ var Dialect = class _Dialect {
1002
1040
  const upper2 = this.compileOperand(betweenExpr.upper, ctx);
1003
1041
  return `${left2} ${betweenExpr.operator} ${lower2} AND ${upper2}`;
1004
1042
  });
1043
+ this.registerExpressionCompiler("ArithmeticExpression", (arith, ctx) => {
1044
+ const left2 = this.compileOperand(arith.left, ctx);
1045
+ const right2 = this.compileOperand(arith.right, ctx);
1046
+ return `${left2} ${arith.operator} ${right2}`;
1047
+ });
1005
1048
  }
1006
1049
  registerDefaultOperandCompilers() {
1007
1050
  this.registerOperandCompiler("Literal", (literal, ctx) => ctx.addParameter(literal.value));
1051
+ this.registerOperandCompiler("AliasRef", (alias, _ctx) => this.quoteIdentifier(alias.name));
1008
1052
  this.registerOperandCompiler("Column", (column, _ctx) => {
1009
1053
  return `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`;
1010
1054
  });
@@ -1042,9 +1086,12 @@ var Dialect = class _Dialect {
1042
1086
  parts.push(partitionClause);
1043
1087
  }
1044
1088
  if (node.orderBy && node.orderBy.length > 0) {
1045
- const orderClause = "ORDER BY " + node.orderBy.map(
1046
- (o) => `${this.quoteIdentifier(o.column.table)}.${this.quoteIdentifier(o.column.name)} ${o.direction}`
1047
- ).join(", ");
1089
+ const orderClause = "ORDER BY " + node.orderBy.map((o) => {
1090
+ const term = this.compileOrderingTerm(o.term, ctx);
1091
+ const collation = o.collation ? ` COLLATE ${o.collation}` : "";
1092
+ const nulls = o.nulls ? ` NULLS ${o.nulls}` : "";
1093
+ return `${term} ${o.direction}${collation}${nulls}`;
1094
+ }).join(", ");
1048
1095
  parts.push(orderClause);
1049
1096
  }
1050
1097
  result += parts.join(" ");
@@ -1263,12 +1310,12 @@ var GroupByCompiler = class {
1263
1310
  /**
1264
1311
  * Compiles GROUP BY clause from a SELECT query AST.
1265
1312
  * @param ast - The SELECT query AST containing grouping columns.
1266
- * @param quoteIdentifier - Function to quote identifiers according to dialect rules.
1313
+ * @param renderTerm - Function to render a grouping term.
1267
1314
  * @returns SQL GROUP BY clause (e.g., " GROUP BY table.col1, table.col2") or empty string if no grouping.
1268
1315
  */
1269
- static compileGroupBy(ast, quoteIdentifier) {
1316
+ static compileGroupBy(ast, renderTerm) {
1270
1317
  if (!ast.groupBy || ast.groupBy.length === 0) return "";
1271
- const cols = ast.groupBy.map((c) => `${quoteIdentifier(c.table)}.${quoteIdentifier(c.name)}`).join(", ");
1318
+ const cols = ast.groupBy.map(renderTerm).join(", ");
1272
1319
  return ` GROUP BY ${cols}`;
1273
1320
  }
1274
1321
  };
@@ -1278,12 +1325,19 @@ var OrderByCompiler = class {
1278
1325
  /**
1279
1326
  * Compiles ORDER BY clause from a SELECT query AST.
1280
1327
  * @param ast - The SELECT query AST containing sort specifications.
1281
- * @param quoteIdentifier - Function to quote identifiers according to dialect rules.
1328
+ * @param renderTerm - Function to render an ordering term.
1329
+ * @param renderNulls - Optional function to render NULLS FIRST/LAST.
1330
+ * @param renderCollation - Optional function to render COLLATE clause.
1282
1331
  * @returns SQL ORDER BY clause (e.g., " ORDER BY table.col1 ASC, table.col2 DESC") or empty string if no ordering.
1283
1332
  */
1284
- static compileOrderBy(ast, quoteIdentifier) {
1333
+ static compileOrderBy(ast, renderTerm, renderNulls, renderCollation) {
1285
1334
  if (!ast.orderBy || ast.orderBy.length === 0) return "";
1286
- const parts = ast.orderBy.map((o) => `${quoteIdentifier(o.column.table)}.${quoteIdentifier(o.column.name)} ${o.direction}`).join(", ");
1335
+ const parts = ast.orderBy.map((o) => {
1336
+ const term = renderTerm(o.term);
1337
+ const collation = renderCollation ? renderCollation(o) : o.collation ? ` COLLATE ${o.collation}` : "";
1338
+ const nulls = renderNulls ? renderNulls(o) : o.nulls ? ` NULLS ${o.nulls}` : "";
1339
+ return `${term} ${o.direction}${collation}${nulls}`;
1340
+ }).join(", ");
1287
1341
  return ` ORDER BY ${parts}`;
1288
1342
  }
1289
1343
  };
@@ -1314,7 +1368,12 @@ var SqlDialectBase = class extends Dialect {
1314
1368
  }
1315
1369
  compileSelectWithSetOps(ast, baseSelect, ctes, ctx) {
1316
1370
  const compound = ast.setOps.map((op) => `${op.operator} ${this.wrapSetOperand(this.compileSelectAst(op.query, ctx))}`).join(" ");
1317
- const orderBy = OrderByCompiler.compileOrderBy(ast, this.quoteIdentifier.bind(this));
1371
+ const orderBy = OrderByCompiler.compileOrderBy(
1372
+ ast,
1373
+ (term) => this.compileOrderingTerm(term, ctx),
1374
+ this.renderOrderByNulls.bind(this),
1375
+ this.renderOrderByCollation.bind(this)
1376
+ );
1318
1377
  const pagination = this.paginationStrategy.compilePagination(ast.limit, ast.offset);
1319
1378
  const combined = `${this.wrapSetOperand(baseSelect)} ${compound}`;
1320
1379
  return `${ctes}${combined}${orderBy}${pagination}`;
@@ -1340,9 +1399,14 @@ var SqlDialectBase = class extends Dialect {
1340
1399
  const from = this.compileFrom(ast.from, ctx);
1341
1400
  const joins = JoinCompiler.compileJoins(ast, ctx, this.compileFrom.bind(this), this.compileExpression.bind(this));
1342
1401
  const whereClause = this.compileWhere(ast.where, ctx);
1343
- const groupBy = GroupByCompiler.compileGroupBy(ast, this.quoteIdentifier.bind(this));
1402
+ const groupBy = GroupByCompiler.compileGroupBy(ast, (term) => this.compileOrderingTerm(term, ctx));
1344
1403
  const having = this.compileHaving(ast, ctx);
1345
- const orderBy = OrderByCompiler.compileOrderBy(ast, this.quoteIdentifier.bind(this));
1404
+ const orderBy = OrderByCompiler.compileOrderBy(
1405
+ ast,
1406
+ (term) => this.compileOrderingTerm(term, ctx),
1407
+ this.renderOrderByNulls.bind(this),
1408
+ this.renderOrderByCollation.bind(this)
1409
+ );
1346
1410
  const pagination = this.paginationStrategy.compilePagination(ast.limit, ast.offset);
1347
1411
  return `SELECT ${this.compileDistinct(ast)}${columns} FROM ${from}${joins}${whereClause}${groupBy}${having}${orderBy}${pagination}`;
1348
1412
  }
@@ -1431,6 +1495,12 @@ var SqlDialectBase = class extends Dialect {
1431
1495
  const trimmed = this.stripTrailingSemicolon(sql);
1432
1496
  return `(${trimmed})`;
1433
1497
  }
1498
+ renderOrderByNulls(order) {
1499
+ return order.nulls ? ` NULLS ${order.nulls}` : "";
1500
+ }
1501
+ renderOrderByCollation(order) {
1502
+ return order.collation ? ` COLLATE ${order.collation}` : "";
1503
+ }
1434
1504
  };
1435
1505
 
1436
1506
  // src/core/dialect/postgres/functions.ts
@@ -1947,7 +2017,7 @@ var SqlServerDialect = class extends Dialect {
1947
2017
  return `${ctes}${baseSelect}`;
1948
2018
  }
1949
2019
  const compound = ast.setOps.map((op) => `${op.operator} ${this.wrapSetOperand(this.compileSelectAst(op.query, ctx))}`).join(" ");
1950
- const orderBy = this.compileOrderBy(ast);
2020
+ const orderBy = this.compileOrderBy(ast, ctx);
1951
2021
  const pagination = this.compilePagination(ast, orderBy);
1952
2022
  const combined = `${this.wrapSetOperand(baseSelect)} ${compound}`;
1953
2023
  const tail = pagination || orderBy;
@@ -2004,18 +2074,22 @@ var SqlServerDialect = class extends Dialect {
2004
2074
  return `${j.kind} JOIN ${table} ON ${cond}`;
2005
2075
  }).join(" ");
2006
2076
  const whereClause = this.compileWhere(ast.where, ctx);
2007
- const groupBy = ast.groupBy && ast.groupBy.length > 0 ? " GROUP BY " + ast.groupBy.map((c) => `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`).join(", ") : "";
2077
+ const groupBy = ast.groupBy && ast.groupBy.length > 0 ? " GROUP BY " + ast.groupBy.map((term) => this.compileOrderingTerm(term, ctx)).join(", ") : "";
2008
2078
  const having = ast.having ? ` HAVING ${this.compileExpression(ast.having, ctx)}` : "";
2009
- const orderBy = this.compileOrderBy(ast);
2079
+ const orderBy = this.compileOrderBy(ast, ctx);
2010
2080
  const pagination = this.compilePagination(ast, orderBy);
2011
2081
  if (pagination) {
2012
2082
  return `SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${pagination}`;
2013
2083
  }
2014
2084
  return `SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${orderBy}`;
2015
2085
  }
2016
- compileOrderBy(ast) {
2017
- if (!ast.orderBy || ast.orderBy.length === 0) return "";
2018
- return " ORDER BY " + ast.orderBy.map((o) => `${this.quoteIdentifier(o.column.table)}.${this.quoteIdentifier(o.column.name)} ${o.direction}`).join(", ");
2086
+ compileOrderBy(ast, ctx) {
2087
+ return OrderByCompiler.compileOrderBy(
2088
+ ast,
2089
+ (term) => this.compileOrderingTerm(term, ctx),
2090
+ this.renderOrderByNulls.bind(this),
2091
+ this.renderOrderByCollation.bind(this)
2092
+ );
2019
2093
  }
2020
2094
  compilePagination(ast, orderBy) {
2021
2095
  const hasLimit = ast.limit !== void 0;
@@ -2029,6 +2103,12 @@ var SqlServerDialect = class extends Dialect {
2029
2103
  }
2030
2104
  return pagination;
2031
2105
  }
2106
+ renderOrderByNulls(order) {
2107
+ return order.nulls ? ` NULLS ${order.nulls}` : "";
2108
+ }
2109
+ renderOrderByCollation(order) {
2110
+ return order.collation ? ` COLLATE ${order.collation}` : "";
2111
+ }
2032
2112
  compileTableSource(table, ctx) {
2033
2113
  if (table.type === "FunctionTable") {
2034
2114
  return FunctionTableFormatter.format(table, ctx, this);
@@ -2040,9 +2120,9 @@ var SqlServerDialect = class extends Dialect {
2040
2120
  return table.alias ? `${base} AS ${this.quoteIdentifier(table.alias)}` : base;
2041
2121
  }
2042
2122
  compileDerivedTable(table, ctx) {
2043
- const sub = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
2123
+ const sub2 = this.compileSelectAst(this.normalizeSelectAst(table.query), ctx).trim().replace(/;$/, "");
2044
2124
  const cols = table.columnAliases?.length ? ` (${table.columnAliases.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
2045
- return `(${sub}) AS ${this.quoteIdentifier(table.alias)}${cols}`;
2125
+ return `(${sub2}) AS ${this.quoteIdentifier(table.alias)}${cols}`;
2046
2126
  }
2047
2127
  compileCtes(ast, ctx) {
2048
2128
  if (!ast.ctes || ast.ctes.length === 0) return "";
@@ -2207,7 +2287,7 @@ var SelectQueryState = class _SelectQueryState {
2207
2287
  }
2208
2288
  /**
2209
2289
  * Adds GROUP BY columns to the query
2210
- * @param columns - Columns to group by
2290
+ * @param columns - Terms to group by
2211
2291
  * @returns New SelectQueryState with GROUP BY clause
2212
2292
  */
2213
2293
  withGroupBy(columns) {
@@ -2490,31 +2570,38 @@ var HydrationManager = class _HydrationManager {
2490
2570
  }
2491
2571
  const mapped = [];
2492
2572
  for (const ob of orderBy) {
2493
- if (ob.column.table !== plan.rootTable) {
2494
- return null;
2495
- }
2496
- const alias = projectionAliases.get(`${ob.column.table}.${ob.column.name}`) ?? ob.column.name;
2497
- if (!availableColumns.has(alias)) {
2498
- return null;
2499
- }
2500
- mapped.push({
2501
- type: "OrderBy",
2502
- column: { type: "Column", table: baseAlias, name: alias },
2503
- direction: ob.direction
2504
- });
2573
+ const mappedTerm = this.mapOrderingTerm(ob.term, plan, projectionAliases, baseAlias, availableColumns);
2574
+ if (!mappedTerm) return null;
2575
+ mapped.push({ ...ob, term: mappedTerm });
2505
2576
  }
2506
2577
  return mapped;
2507
2578
  }
2579
+ mapOrderingTerm(term, plan, projectionAliases, baseAlias, availableColumns) {
2580
+ if (term.type === "Column") {
2581
+ const col2 = term;
2582
+ if (col2.table !== plan.rootTable) return null;
2583
+ const alias = projectionAliases.get(`${col2.table}.${col2.name}`) ?? col2.name;
2584
+ if (!availableColumns.has(alias)) return null;
2585
+ return { type: "Column", table: baseAlias, name: alias };
2586
+ }
2587
+ if (term.type === "AliasRef") {
2588
+ const aliasName = term.name;
2589
+ if (!availableColumns.has(aliasName)) return null;
2590
+ return { type: "Column", table: baseAlias, name: aliasName };
2591
+ }
2592
+ return null;
2593
+ }
2508
2594
  buildPagingColumns(primaryKey, orderBy, tableAlias) {
2509
2595
  const columns = [{ type: "Column", table: tableAlias, name: primaryKey, alias: primaryKey }];
2510
2596
  if (!orderBy) return columns;
2511
2597
  for (const ob of orderBy) {
2512
- if (!columns.some((col2) => col2.name === ob.column.name)) {
2598
+ const term = ob.term;
2599
+ if (!columns.some((col2) => col2.name === term.name)) {
2513
2600
  columns.push({
2514
2601
  type: "Column",
2515
2602
  table: tableAlias,
2516
- name: ob.column.name,
2517
- alias: ob.column.name
2603
+ name: term.name,
2604
+ alias: term.name
2518
2605
  });
2519
2606
  }
2520
2607
  }
@@ -2820,10 +2907,8 @@ var QueryAstService = class {
2820
2907
  * @returns Updated query state with GROUP BY clause
2821
2908
  */
2822
2909
  withGroupBy(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);
2826
- return this.state.withGroupBy([node]);
2910
+ const term = this.normalizeOrderingTerm(col2);
2911
+ return this.state.withGroupBy([term]);
2827
2912
  }
2828
2913
  /**
2829
2914
  * Adds a HAVING clause to the query
@@ -2840,11 +2925,9 @@ var QueryAstService = class {
2840
2925
  * @param direction - Order direction (ASC/DESC)
2841
2926
  * @returns Updated query state with ORDER BY clause
2842
2927
  */
2843
- withOrderBy(col2, direction) {
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);
2847
- return this.state.withOrderBy([{ type: "OrderBy", column: node, direction }]);
2928
+ withOrderBy(term, direction, nulls, collation) {
2929
+ const normalized = this.normalizeOrderingTerm(term);
2930
+ return this.state.withOrderBy([{ type: "OrderBy", term: normalized, direction, nulls, collation }]);
2848
2931
  }
2849
2932
  /**
2850
2933
  * Adds a DISTINCT clause to the query
@@ -2879,6 +2962,24 @@ var QueryAstService = class {
2879
2962
  combineExpressions(existing, next) {
2880
2963
  return existing ? and(existing, next) : next;
2881
2964
  }
2965
+ normalizeOrderingTerm(term) {
2966
+ const from = this.state.ast.from;
2967
+ const tableRef = from.type === "Table" && from.alias ? { ...this.table, alias: from.alias } : this.table;
2968
+ const termType = term?.type;
2969
+ if (termType === "Column") {
2970
+ return term;
2971
+ }
2972
+ if (termType === "AliasRef") {
2973
+ return term;
2974
+ }
2975
+ if (isOperandNode(term)) {
2976
+ return term;
2977
+ }
2978
+ if (termType === "BinaryExpression" || termType === "LogicalExpression" || termType === "NullExpression" || termType === "InExpression" || termType === "ExistsExpression" || termType === "BetweenExpression" || termType === "ArithmeticExpression") {
2979
+ return term;
2980
+ }
2981
+ return buildColumnNode(tableRef, term);
2982
+ }
2882
2983
  };
2883
2984
 
2884
2985
  // src/query-builder/relation-projection-helper.ts
@@ -4528,8 +4629,8 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4528
4629
  * @returns New query builder instance with the subquery selection
4529
4630
 
4530
4631
  */
4531
- selectSubquery(alias, sub) {
4532
- const query = this.resolveQueryNode(sub);
4632
+ selectSubquery(alias, sub2) {
4633
+ const query = this.resolveQueryNode(sub2);
4533
4634
  return this.clone(this.columnSelector.selectSubquery(this.context, alias, query));
4534
4635
  }
4535
4636
  /**
@@ -4711,16 +4812,12 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4711
4812
  return this.clone(nextContext);
4712
4813
  }
4713
4814
  /**
4714
-
4715
- * Adds a GROUP BY clause to the query
4716
-
4717
- * @param col - Column definition or column node to group by
4718
-
4719
- * @returns New query builder instance with the GROUP BY clause
4720
-
4721
- */
4722
- groupBy(col2) {
4723
- const nextContext = this.applyAst(this.context, (service) => service.withGroupBy(col2));
4815
+ * Adds a GROUP BY clause to the query
4816
+ * @param term - Column definition or ordering term to group by
4817
+ * @returns New query builder instance with the GROUP BY clause
4818
+ */
4819
+ groupBy(term) {
4820
+ const nextContext = this.applyAst(this.context, (service) => service.withGroupBy(term));
4724
4821
  return this.clone(nextContext);
4725
4822
  }
4726
4823
  /**
@@ -4737,18 +4834,18 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
4737
4834
  return this.clone(nextContext);
4738
4835
  }
4739
4836
  /**
4740
-
4741
- * Adds an ORDER BY clause to the query
4742
-
4743
- * @param col - Column definition or column node to order by
4744
-
4745
- * @param direction - Order direction (defaults to ASC)
4746
-
4747
- * @returns New query builder instance with the ORDER BY clause
4748
-
4749
- */
4750
- orderBy(col2, direction = ORDER_DIRECTIONS.ASC) {
4751
- const nextContext = this.applyAst(this.context, (service) => service.withOrderBy(col2, direction));
4837
+ * Adds an ORDER BY clause to the query
4838
+ * @param term - Column definition or ordering term to order by
4839
+ * @param directionOrOptions - Order direction or options (defaults to ASC)
4840
+ * @returns New query builder instance with the ORDER BY clause
4841
+ */
4842
+ orderBy(term, directionOrOptions = ORDER_DIRECTIONS.ASC) {
4843
+ const options = typeof directionOrOptions === "string" ? { direction: directionOrOptions } : directionOrOptions;
4844
+ const dir = options.direction ?? ORDER_DIRECTIONS.ASC;
4845
+ const nextContext = this.applyAst(
4846
+ this.context,
4847
+ (service) => service.withOrderBy(term, dir, options.nulls, options.collation)
4848
+ );
4752
4849
  return this.clone(nextContext);
4753
4850
  }
4754
4851
  /**
@@ -6576,7 +6673,7 @@ var TypeScriptGenerator = class {
6576
6673
  lines.push(`.where(${this.printExpression(ast.where)})`);
6577
6674
  }
6578
6675
  if (ast.groupBy && ast.groupBy.length) {
6579
- const cols = ast.groupBy.map((c) => `${this.namingStrategy.tableToSymbol(c.table)}.${c.name}`).join(", ");
6676
+ const cols = ast.groupBy.map((term) => this.printOrderingTerm(term)).join(", ");
6580
6677
  lines.push(`.groupBy(${cols})`);
6581
6678
  }
6582
6679
  if (ast.having) {
@@ -6584,7 +6681,16 @@ var TypeScriptGenerator = class {
6584
6681
  }
6585
6682
  if (ast.orderBy && ast.orderBy.length) {
6586
6683
  ast.orderBy.forEach((o) => {
6587
- lines.push(`.orderBy(${this.namingStrategy.tableToSymbol(o.column.table)}.${o.column.name}, '${o.direction}')`);
6684
+ const term = this.printOrderingTerm(o.term);
6685
+ const opts = [`direction: '${o.direction}'`];
6686
+ if (o.nulls) opts.push(`nulls: '${o.nulls}'`);
6687
+ if (o.collation) opts.push(`collation: '${o.collation}'`);
6688
+ const hasOpts = opts.length > 1;
6689
+ if (hasOpts) {
6690
+ lines.push(`.orderBy(${term}, { ${opts.join(", ")} })`);
6691
+ } else {
6692
+ lines.push(`.orderBy(${term}, '${o.direction}')`);
6693
+ }
6588
6694
  });
6589
6695
  }
6590
6696
  if (ast.limit) lines.push(`.limit(${ast.limit})`);
@@ -6607,6 +6713,29 @@ var TypeScriptGenerator = class {
6607
6713
  printOperand(node) {
6608
6714
  return visitOperand(node, this);
6609
6715
  }
6716
+ /**
6717
+ * Prints an ordering term (operand/expression/alias) to TypeScript code.
6718
+ */
6719
+ printOrderingTerm(term) {
6720
+ if (!term || !term.type) {
6721
+ throw new Error("Unsupported ordering term");
6722
+ }
6723
+ switch (term.type) {
6724
+ case "Column":
6725
+ return `${this.namingStrategy.tableToSymbol(term.table)}.${term.name}`;
6726
+ case "AliasRef":
6727
+ return this.visitAliasRef(term);
6728
+ case "Literal":
6729
+ case "Function":
6730
+ case "JsonPath":
6731
+ case "ScalarSubquery":
6732
+ case "CaseExpression":
6733
+ case "WindowFunction":
6734
+ return this.printOperand(term);
6735
+ default:
6736
+ return this.printExpression(term);
6737
+ }
6738
+ }
6610
6739
  visitBinaryExpression(binary) {
6611
6740
  return this.printBinaryExpression(binary);
6612
6741
  }
@@ -6625,6 +6754,9 @@ var TypeScriptGenerator = class {
6625
6754
  visitBetweenExpression(betweenExpr) {
6626
6755
  return this.printBetweenExpression(betweenExpr);
6627
6756
  }
6757
+ visitArithmeticExpression(arithExpr) {
6758
+ return this.printArithmeticExpression(arithExpr);
6759
+ }
6628
6760
  visitColumn(node) {
6629
6761
  return this.printColumnOperand(node);
6630
6762
  }
@@ -6646,6 +6778,9 @@ var TypeScriptGenerator = class {
6646
6778
  visitWindowFunction(node) {
6647
6779
  return this.printWindowFunctionOperand(node);
6648
6780
  }
6781
+ visitAliasRef(node) {
6782
+ return `aliasRef('${node.name}')`;
6783
+ }
6649
6784
  /**
6650
6785
  * Prints a binary expression to TypeScript code
6651
6786
  * @param binary - Binary expression node
@@ -6676,6 +6811,11 @@ var TypeScriptGenerator = class {
6676
6811
  ${parts.join(",\n ")}
6677
6812
  )`;
6678
6813
  }
6814
+ printArithmeticExpression(expr) {
6815
+ const left2 = this.printOperand(expr.left);
6816
+ const right2 = this.printOperand(expr.right);
6817
+ return `${left2} ${expr.operator} ${right2}`;
6818
+ }
6679
6819
  /**
6680
6820
  * Prints an IN expression to TypeScript code
6681
6821
  * @param inExpr - IN expression node
@@ -6789,7 +6929,12 @@ var TypeScriptGenerator = class {
6789
6929
  parts.push(partitionClause);
6790
6930
  }
6791
6931
  if (node.orderBy && node.orderBy.length > 0) {
6792
- const orderClause = "ORDER BY " + node.orderBy.map((o) => `${this.namingStrategy.tableToSymbol(o.column.table)}.${o.column.name} ${o.direction}`).join(", ");
6932
+ const orderClause = "ORDER BY " + node.orderBy.map((o) => {
6933
+ const term = this.printOrderingTerm(o.term);
6934
+ const collation = o.collation ? ` COLLATE ${o.collation}` : "";
6935
+ const nulls = o.nulls ? ` NULLS ${o.nulls}` : "";
6936
+ return `${term} ${o.direction}${collation}${nulls}`;
6937
+ }).join(", ");
6793
6938
  parts.push(orderClause);
6794
6939
  }
6795
6940
  result += parts.join(" ");
@@ -7966,7 +8111,9 @@ export {
7966
8111
  UpdateQueryBuilder,
7967
8112
  abs,
7968
8113
  acos,
8114
+ add,
7969
8115
  addDomainEvent,
8116
+ aliasRef,
7970
8117
  and,
7971
8118
  ascii,
7972
8119
  asin,
@@ -8017,6 +8164,7 @@ export {
8017
8164
  degrees,
8018
8165
  denseRank,
8019
8166
  diffSchema,
8167
+ div,
8020
8168
  endOfMonth,
8021
8169
  eq,
8022
8170
  esel,
@@ -8074,6 +8222,7 @@ export {
8074
8222
  min,
8075
8223
  mod,
8076
8224
  month,
8225
+ mul,
8077
8226
  neq,
8078
8227
  notBetween,
8079
8228
  notExists,
@@ -8109,6 +8258,7 @@ export {
8109
8258
  sin,
8110
8259
  space,
8111
8260
  sqrt,
8261
+ sub,
8112
8262
  substr,
8113
8263
  sum,
8114
8264
  synchronizeSchema,