metal-orm 1.0.56 → 1.0.57

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 (72) hide show
  1. package/README.md +21 -20
  2. package/dist/index.cjs +821 -112
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +429 -70
  5. package/dist/index.d.ts +429 -70
  6. package/dist/index.js +785 -112
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/codegen/naming-strategy.ts +3 -1
  10. package/src/codegen/typescript.ts +20 -10
  11. package/src/core/ast/aggregate-functions.ts +14 -0
  12. package/src/core/ast/builders.ts +38 -20
  13. package/src/core/ast/expression-builders.ts +70 -2
  14. package/src/core/ast/expression-nodes.ts +305 -274
  15. package/src/core/ast/expression-visitor.ts +11 -1
  16. package/src/core/ast/expression.ts +4 -0
  17. package/src/core/ast/query.ts +3 -0
  18. package/src/core/ddl/introspect/catalogs/mysql.ts +5 -0
  19. package/src/core/ddl/introspect/catalogs/sqlite.ts +3 -0
  20. package/src/core/ddl/introspect/functions/mssql.ts +13 -0
  21. package/src/core/ddl/introspect/mssql.ts +4 -0
  22. package/src/core/ddl/introspect/mysql.ts +4 -0
  23. package/src/core/ddl/introspect/sqlite.ts +4 -0
  24. package/src/core/dialect/abstract.ts +552 -531
  25. package/src/core/dialect/base/function-table-formatter.ts +9 -30
  26. package/src/core/dialect/base/sql-dialect.ts +24 -0
  27. package/src/core/dialect/mssql/functions.ts +40 -2
  28. package/src/core/dialect/mysql/functions.ts +16 -2
  29. package/src/core/dialect/postgres/functions.ts +66 -2
  30. package/src/core/dialect/postgres/index.ts +17 -4
  31. package/src/core/dialect/postgres/table-functions.ts +27 -0
  32. package/src/core/dialect/sqlite/functions.ts +34 -0
  33. package/src/core/dialect/sqlite/index.ts +17 -1
  34. package/src/core/driver/database-driver.ts +9 -1
  35. package/src/core/driver/mssql-driver.ts +3 -0
  36. package/src/core/driver/mysql-driver.ts +3 -0
  37. package/src/core/driver/postgres-driver.ts +3 -0
  38. package/src/core/driver/sqlite-driver.ts +3 -0
  39. package/src/core/execution/executors/mssql-executor.ts +5 -0
  40. package/src/core/execution/executors/mysql-executor.ts +5 -0
  41. package/src/core/execution/executors/postgres-executor.ts +5 -0
  42. package/src/core/execution/executors/sqlite-executor.ts +5 -0
  43. package/src/core/functions/array.ts +26 -0
  44. package/src/core/functions/control-flow.ts +69 -0
  45. package/src/core/functions/datetime.ts +50 -0
  46. package/src/core/functions/definitions/aggregate.ts +16 -0
  47. package/src/core/functions/definitions/control-flow.ts +24 -0
  48. package/src/core/functions/definitions/datetime.ts +36 -0
  49. package/src/core/functions/definitions/helpers.ts +29 -0
  50. package/src/core/functions/definitions/json.ts +49 -0
  51. package/src/core/functions/definitions/numeric.ts +55 -0
  52. package/src/core/functions/definitions/string.ts +43 -0
  53. package/src/core/functions/function-registry.ts +48 -0
  54. package/src/core/functions/group-concat-helpers.ts +57 -0
  55. package/src/core/functions/json.ts +38 -0
  56. package/src/core/functions/numeric.ts +14 -0
  57. package/src/core/functions/standard-strategy.ts +86 -115
  58. package/src/core/functions/standard-table-strategy.ts +13 -0
  59. package/src/core/functions/table-types.ts +15 -0
  60. package/src/core/functions/text.ts +57 -0
  61. package/src/core/sql/sql.ts +59 -38
  62. package/src/decorators/bootstrap.ts +5 -4
  63. package/src/index.ts +18 -11
  64. package/src/orm/hydration-context.ts +10 -0
  65. package/src/orm/identity-map.ts +19 -0
  66. package/src/orm/interceptor-pipeline.ts +4 -0
  67. package/src/orm/relations/belongs-to.ts +17 -0
  68. package/src/orm/relations/has-one.ts +17 -0
  69. package/src/orm/relations/many-to-many.ts +41 -0
  70. package/src/query-builder/select.ts +68 -68
  71. package/src/schema/table-guards.ts +6 -0
  72. package/src/schema/types.ts +8 -1
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
3
- var __esm = (fn5, res) => function __init() {
4
- return fn5 && (res = (0, fn5[__getOwnPropNames(fn5)[0]])(fn5 = 0)), res;
3
+ var __esm = (fn8, res) => function __init() {
4
+ return fn8 && (res = (0, fn8[__getOwnPropNames(fn8)[0]])(fn8 = 0)), res;
5
5
  };
6
6
  var __export = (target, all) => {
7
7
  for (var name in all)
@@ -363,7 +363,9 @@ var operandTypes = /* @__PURE__ */ new Set([
363
363
  "CaseExpression",
364
364
  "Cast",
365
365
  "WindowFunction",
366
- "ArithmeticExpression"
366
+ "ArithmeticExpression",
367
+ "BitwiseExpression",
368
+ "Collate"
367
369
  ]);
368
370
  var hasTypeProperty = (value) => typeof value === "object" && value !== null && "type" in value;
369
371
  var isOperandNode = (node) => {
@@ -373,6 +375,7 @@ var isOperandNode = (node) => {
373
375
  var isFunctionNode = (node) => isOperandNode(node) && node.type === "Function";
374
376
  var isCaseExpressionNode = (node) => isOperandNode(node) && node.type === "CaseExpression";
375
377
  var isCastExpressionNode = (node) => isOperandNode(node) && node.type === "Cast";
378
+ var isCollateExpressionNode = (node) => isOperandNode(node) && node.type === "Collate";
376
379
  var isWindowFunctionNode = (node) => isOperandNode(node) && node.type === "WindowFunction";
377
380
  var isExpressionSelectionNode = (node) => isFunctionNode(node) || isCaseExpressionNode(node) || isCastExpressionNode(node) || isWindowFunctionNode(node);
378
381
 
@@ -497,6 +500,17 @@ var add = (left2, right2) => createArithmeticExpression("+", left2, right2);
497
500
  var sub = (left2, right2) => createArithmeticExpression("-", left2, right2);
498
501
  var mul = (left2, right2) => createArithmeticExpression("*", left2, right2);
499
502
  var div = (left2, right2) => createArithmeticExpression("/", left2, right2);
503
+ var createBitwiseExpression = (operator, left2, right2) => ({
504
+ type: "BitwiseExpression",
505
+ left: toOperand(left2),
506
+ operator,
507
+ right: toOperand(right2)
508
+ });
509
+ var bitAnd = (left2, right2) => createBitwiseExpression("&", left2, right2);
510
+ var bitOr = (left2, right2) => createBitwiseExpression("|", left2, right2);
511
+ var bitXor = (left2, right2) => createBitwiseExpression("^", left2, right2);
512
+ var shiftLeft = (left2, right2) => createBitwiseExpression("<<", left2, right2);
513
+ var shiftRight = (left2, right2) => createBitwiseExpression(">>", left2, right2);
500
514
  var jsonPath = (col2, path) => ({
501
515
  type: "JsonPath",
502
516
  column: columnOperand(col2),
@@ -525,6 +539,11 @@ var notExists = (subquery) => ({
525
539
  operator: "NOT EXISTS",
526
540
  subquery
527
541
  });
542
+ var collate = (expression, collation) => ({
543
+ type: "Collate",
544
+ expression: toOperand(expression),
545
+ collation
546
+ });
528
547
 
529
548
  // src/core/ast/window-functions.ts
530
549
  var buildWindowFunction = (name, args = [], partitionBy, orderBy) => {
@@ -670,6 +689,8 @@ var groupConcat = (col2, options) => ({
670
689
  orderBy: options?.orderBy?.map(toOrderByNode),
671
690
  separator: options?.separator !== void 0 ? valueToOperand(options.separator) : void 0
672
691
  });
692
+ var stddev = buildAggregate("STDDEV");
693
+ var variance = buildAggregate("VARIANCE");
673
694
 
674
695
  // src/core/ast/expression-visitor.ts
675
696
  var DispatcherRegistry = class _DispatcherRegistry {
@@ -743,6 +764,9 @@ var visitExpression = (node, visitor) => {
743
764
  case "ArithmeticExpression":
744
765
  if (visitor.visitArithmeticExpression) return visitor.visitArithmeticExpression(node);
745
766
  break;
767
+ case "BitwiseExpression":
768
+ if (visitor.visitBitwiseExpression) return visitor.visitBitwiseExpression(node);
769
+ break;
746
770
  default:
747
771
  break;
748
772
  }
@@ -780,6 +804,9 @@ var visitOperand = (node, visitor) => {
780
804
  case "Cast":
781
805
  if (visitor.visitCast) return visitor.visitCast(node);
782
806
  break;
807
+ case "Collate":
808
+ if (visitor.visitCollate) return visitor.visitCollate(node);
809
+ break;
783
810
  default:
784
811
  break;
785
812
  }
@@ -850,62 +877,337 @@ var derivedTable = (query, alias, columnAliases) => ({
850
877
  columnAliases
851
878
  });
852
879
 
880
+ // src/core/functions/function-registry.ts
881
+ var FunctionRegistry = class {
882
+ constructor() {
883
+ this.renderers = /* @__PURE__ */ new Map();
884
+ }
885
+ /**
886
+ * Registers or overrides a renderer for the given function name.
887
+ */
888
+ add(name, renderer) {
889
+ this.renderers.set(name, renderer);
890
+ }
891
+ /**
892
+ * Registers a batch of definitions.
893
+ */
894
+ register(definitions) {
895
+ for (const definition of definitions) {
896
+ this.add(definition.name, definition.renderer);
897
+ }
898
+ }
899
+ /**
900
+ * Merges another registry into this one, allowing overrides from the other source.
901
+ */
902
+ merge(other) {
903
+ for (const [name, renderer] of other.renderers.entries()) {
904
+ this.renderers.set(name, renderer);
905
+ }
906
+ }
907
+ /**
908
+ * Retrieves a renderer by function name.
909
+ */
910
+ get(name) {
911
+ return this.renderers.get(name);
912
+ }
913
+ };
914
+
915
+ // src/core/functions/definitions/helpers.ts
916
+ function unaryRenderer(name) {
917
+ return ({ compiledArgs }) => `${name}(${compiledArgs[0]})`;
918
+ }
919
+ function binaryRenderer(name) {
920
+ return ({ compiledArgs }) => `${name}(${compiledArgs[0]}, ${compiledArgs[1]})`;
921
+ }
922
+ function variadicRenderer(name) {
923
+ return ({ compiledArgs }) => `${name}(${compiledArgs.join(", ")})`;
924
+ }
925
+ function noArgsRenderer(name) {
926
+ return () => `${name}()`;
927
+ }
928
+
929
+ // src/core/functions/definitions/aggregate.ts
930
+ var aggregateFunctionDefinitions = [
931
+ {
932
+ name: "COUNT",
933
+ renderer: ({ compiledArgs }) => compiledArgs.length ? `COUNT(${compiledArgs.join(", ")})` : "COUNT(*)"
934
+ },
935
+ { name: "SUM", renderer: unaryRenderer("SUM") },
936
+ { name: "AVG", renderer: unaryRenderer("AVG") },
937
+ { name: "MIN", renderer: unaryRenderer("MIN") },
938
+ { name: "MAX", renderer: unaryRenderer("MAX") },
939
+ { name: "STDDEV", renderer: unaryRenderer("STDDEV") },
940
+ { name: "VARIANCE", renderer: unaryRenderer("VARIANCE") }
941
+ ];
942
+
943
+ // src/core/functions/definitions/string.ts
944
+ var stringFunctionDefinitions = [
945
+ { name: "UPPER", renderer: unaryRenderer("UPPER") },
946
+ { name: "LOWER", renderer: unaryRenderer("LOWER") },
947
+ { name: "LENGTH", renderer: unaryRenderer("LENGTH") },
948
+ { name: "CHAR_LENGTH", renderer: unaryRenderer("CHAR_LENGTH") },
949
+ { name: "CHARACTER_LENGTH", renderer: unaryRenderer("CHARACTER_LENGTH") },
950
+ { name: "TRIM", renderer: unaryRenderer("TRIM") },
951
+ { name: "LTRIM", renderer: unaryRenderer("LTRIM") },
952
+ { name: "RTRIM", renderer: unaryRenderer("RTRIM") },
953
+ { name: "SUBSTRING", renderer: variadicRenderer("SUBSTRING") },
954
+ { name: "SUBSTR", renderer: variadicRenderer("SUBSTR") },
955
+ { name: "CONCAT", renderer: variadicRenderer("CONCAT") },
956
+ { name: "CONCAT_WS", renderer: variadicRenderer("CONCAT_WS") },
957
+ { name: "ASCII", renderer: unaryRenderer("ASCII") },
958
+ { name: "CHAR", renderer: variadicRenderer("CHAR") },
959
+ {
960
+ name: "POSITION",
961
+ renderer: ({ compiledArgs }) => `POSITION(${compiledArgs[0]} IN ${compiledArgs[1]})`
962
+ },
963
+ { name: "REPLACE", renderer: ({ compiledArgs }) => `REPLACE(${compiledArgs[0]}, ${compiledArgs[1]}, ${compiledArgs[2]})` },
964
+ { name: "REPEAT", renderer: binaryRenderer("REPEAT") },
965
+ { name: "LPAD", renderer: ({ compiledArgs }) => `LPAD(${compiledArgs[0]}, ${compiledArgs[1]}, ${compiledArgs[2]})` },
966
+ { name: "RPAD", renderer: ({ compiledArgs }) => `RPAD(${compiledArgs[0]}, ${compiledArgs[1]}, ${compiledArgs[2]})` },
967
+ { name: "LEFT", renderer: binaryRenderer("LEFT") },
968
+ { name: "RIGHT", renderer: binaryRenderer("RIGHT") },
969
+ { name: "INSTR", renderer: binaryRenderer("INSTR") },
970
+ {
971
+ name: "LOCATE",
972
+ renderer: ({ compiledArgs }) => compiledArgs.length === 3 ? `LOCATE(${compiledArgs[0]}, ${compiledArgs[1]}, ${compiledArgs[2]})` : `LOCATE(${compiledArgs[0]}, ${compiledArgs[1]})`
973
+ },
974
+ { name: "SPACE", renderer: unaryRenderer("SPACE") },
975
+ { name: "REVERSE", renderer: unaryRenderer("REVERSE") },
976
+ { name: "INITCAP", renderer: unaryRenderer("INITCAP") },
977
+ { name: "MD5", renderer: unaryRenderer("MD5") },
978
+ { name: "SHA1", renderer: unaryRenderer("SHA1") },
979
+ { name: "SHA2", renderer: ({ compiledArgs }) => `SHA2(${compiledArgs[0]}, ${compiledArgs[1]})` }
980
+ ];
981
+
982
+ // src/core/functions/definitions/datetime.ts
983
+ var dateTimeFunctionDefinitions = [
984
+ { name: "NOW", renderer: noArgsRenderer("NOW") },
985
+ { name: "CURRENT_DATE", renderer: () => "CURRENT_DATE" },
986
+ { name: "CURRENT_TIME", renderer: () => "CURRENT_TIME" },
987
+ {
988
+ name: "EXTRACT",
989
+ renderer: ({ compiledArgs }) => `EXTRACT(${compiledArgs[0]} FROM ${compiledArgs[1]})`
990
+ },
991
+ { name: "YEAR", renderer: ({ compiledArgs }) => `EXTRACT(YEAR FROM ${compiledArgs[0]})` },
992
+ { name: "MONTH", renderer: ({ compiledArgs }) => `EXTRACT(MONTH FROM ${compiledArgs[0]})` },
993
+ { name: "DAY", renderer: ({ compiledArgs }) => `EXTRACT(DAY FROM ${compiledArgs[0]})` },
994
+ { name: "HOUR", renderer: ({ compiledArgs }) => `EXTRACT(HOUR FROM ${compiledArgs[0]})` },
995
+ { name: "MINUTE", renderer: ({ compiledArgs }) => `EXTRACT(MINUTE FROM ${compiledArgs[0]})` },
996
+ { name: "SECOND", renderer: ({ compiledArgs }) => `EXTRACT(SECOND FROM ${compiledArgs[0]})` },
997
+ { name: "QUARTER", renderer: ({ compiledArgs }) => `EXTRACT(QUARTER FROM ${compiledArgs[0]})` },
998
+ { name: "DATE_ADD", renderer: ({ compiledArgs }) => `(${compiledArgs[0]} + INTERVAL ${compiledArgs[1]} ${compiledArgs[2]})` },
999
+ { name: "DATE_SUB", renderer: ({ compiledArgs }) => `(${compiledArgs[0]} - INTERVAL ${compiledArgs[1]} ${compiledArgs[2]})` },
1000
+ { name: "DATE_DIFF", renderer: ({ compiledArgs }) => `DATEDIFF(${compiledArgs[0]}, ${compiledArgs[1]})` },
1001
+ { name: "DATE_FORMAT", renderer: ({ compiledArgs }) => `DATE_FORMAT(${compiledArgs[0]}, ${compiledArgs[1]})` },
1002
+ { name: "UNIX_TIMESTAMP", renderer: noArgsRenderer("UNIX_TIMESTAMP") },
1003
+ { name: "FROM_UNIXTIME", renderer: ({ compiledArgs }) => `FROM_UNIXTIME(${compiledArgs[0]})` },
1004
+ { name: "END_OF_MONTH", renderer: ({ compiledArgs }) => `LAST_DAY(${compiledArgs[0]})` },
1005
+ { name: "DAY_OF_WEEK", renderer: ({ compiledArgs }) => `DAYOFWEEK(${compiledArgs[0]})` },
1006
+ { name: "WEEK_OF_YEAR", renderer: ({ compiledArgs }) => `WEEKOFYEAR(${compiledArgs[0]})` },
1007
+ { name: "DATE_TRUNC", renderer: ({ compiledArgs }) => `DATE_TRUNC(${compiledArgs[0]}, ${compiledArgs[1]})` },
1008
+ {
1009
+ name: "AGE",
1010
+ renderer: ({ compiledArgs }) => compiledArgs.length === 1 ? `AGE(${compiledArgs[0]})` : `AGE(${compiledArgs[0]}, ${compiledArgs[1]})`
1011
+ },
1012
+ { name: "LOCALTIME", renderer: () => "LOCALTIME" },
1013
+ { name: "LOCALTIMESTAMP", renderer: () => "LOCALTIMESTAMP" }
1014
+ ];
1015
+
1016
+ // src/core/functions/definitions/numeric.ts
1017
+ var numericFunctionDefinitions = [
1018
+ { name: "ABS", renderer: unaryRenderer("ABS") },
1019
+ { name: "BIT_LENGTH", renderer: unaryRenderer("BIT_LENGTH") },
1020
+ { name: "OCTET_LENGTH", renderer: unaryRenderer("OCTET_LENGTH") },
1021
+ { name: "CHR", renderer: unaryRenderer("CHR") },
1022
+ { name: "LOG2", renderer: unaryRenderer("LOG2") },
1023
+ { name: "CBRT", renderer: unaryRenderer("CBRT") },
1024
+ { name: "ACOS", renderer: unaryRenderer("ACOS") },
1025
+ { name: "ASIN", renderer: unaryRenderer("ASIN") },
1026
+ { name: "ATAN", renderer: unaryRenderer("ATAN") },
1027
+ { name: "ATAN2", renderer: binaryRenderer("ATAN2") },
1028
+ { name: "CEIL", renderer: unaryRenderer("CEIL") },
1029
+ { name: "CEILING", renderer: unaryRenderer("CEILING") },
1030
+ { name: "COS", renderer: unaryRenderer("COS") },
1031
+ { name: "COT", renderer: unaryRenderer("COT") },
1032
+ { name: "DEGREES", renderer: unaryRenderer("DEGREES") },
1033
+ { name: "EXP", renderer: unaryRenderer("EXP") },
1034
+ { name: "FLOOR", renderer: unaryRenderer("FLOOR") },
1035
+ { name: "LN", renderer: unaryRenderer("LN") },
1036
+ {
1037
+ name: "LOG",
1038
+ renderer: ({ compiledArgs }) => compiledArgs.length === 2 ? `LOG(${compiledArgs[0]}, ${compiledArgs[1]})` : `LOG(${compiledArgs[0]})`
1039
+ },
1040
+ { name: "LOG10", renderer: unaryRenderer("LOG10") },
1041
+ { name: "LOG_BASE", renderer: binaryRenderer("LOG") },
1042
+ { name: "MOD", renderer: binaryRenderer("MOD") },
1043
+ { name: "PI", renderer: noArgsRenderer("PI") },
1044
+ { name: "POWER", renderer: binaryRenderer("POWER") },
1045
+ { name: "POW", renderer: binaryRenderer("POW") },
1046
+ { name: "RADIANS", renderer: unaryRenderer("RADIANS") },
1047
+ { name: "RANDOM", renderer: noArgsRenderer("RANDOM") },
1048
+ { name: "RAND", renderer: noArgsRenderer("RAND") },
1049
+ {
1050
+ name: "ROUND",
1051
+ renderer: ({ compiledArgs }) => compiledArgs.length === 2 ? `ROUND(${compiledArgs[0]}, ${compiledArgs[1]})` : `ROUND(${compiledArgs[0]})`
1052
+ },
1053
+ { name: "SIGN", renderer: unaryRenderer("SIGN") },
1054
+ { name: "SIN", renderer: unaryRenderer("SIN") },
1055
+ { name: "SQRT", renderer: unaryRenderer("SQRT") },
1056
+ { name: "TAN", renderer: unaryRenderer("TAN") },
1057
+ {
1058
+ name: "TRUNC",
1059
+ renderer: ({ compiledArgs }) => compiledArgs.length === 2 ? `TRUNC(${compiledArgs[0]}, ${compiledArgs[1]})` : `TRUNC(${compiledArgs[0]})`
1060
+ },
1061
+ {
1062
+ name: "TRUNCATE",
1063
+ renderer: ({ compiledArgs }) => `TRUNCATE(${compiledArgs[0]}, ${compiledArgs[1]})`
1064
+ }
1065
+ ];
1066
+
1067
+ // src/core/functions/definitions/control-flow.ts
1068
+ var controlFlowFunctionDefinitions = [
1069
+ {
1070
+ name: "COALESCE",
1071
+ renderer: ({ compiledArgs }) => `COALESCE(${compiledArgs.join(", ")})`
1072
+ },
1073
+ {
1074
+ name: "NULLIF",
1075
+ renderer: ({ compiledArgs }) => `NULLIF(${compiledArgs[0]}, ${compiledArgs[1]})`
1076
+ },
1077
+ {
1078
+ name: "GREATEST",
1079
+ renderer: ({ compiledArgs }) => `GREATEST(${compiledArgs.join(", ")})`
1080
+ },
1081
+ {
1082
+ name: "LEAST",
1083
+ renderer: ({ compiledArgs }) => `LEAST(${compiledArgs.join(", ")})`
1084
+ },
1085
+ {
1086
+ name: "IFNULL",
1087
+ renderer: ({ compiledArgs }) => `IFNULL(${compiledArgs[0]}, ${compiledArgs[1]})`
1088
+ }
1089
+ ];
1090
+
1091
+ // src/core/functions/definitions/json.ts
1092
+ var jsonFunctionDefinitions = [
1093
+ {
1094
+ name: "JSON_LENGTH",
1095
+ renderer: ({ compiledArgs }) => {
1096
+ if (compiledArgs.length === 0 || compiledArgs.length > 2) {
1097
+ throw new Error("JSON_LENGTH expects 1 or 2 arguments");
1098
+ }
1099
+ return `JSON_LENGTH(${compiledArgs.join(", ")})`;
1100
+ }
1101
+ },
1102
+ {
1103
+ name: "JSON_SET",
1104
+ renderer: ({ compiledArgs }) => {
1105
+ if (compiledArgs.length < 3 || (compiledArgs.length - 1) % 2 !== 0) {
1106
+ throw new Error("JSON_SET expects a JSON document followed by one or more path/value pairs");
1107
+ }
1108
+ return `JSON_SET(${compiledArgs.join(", ")})`;
1109
+ }
1110
+ },
1111
+ {
1112
+ name: "JSON_ARRAYAGG",
1113
+ renderer: ({ compiledArgs }) => {
1114
+ if (compiledArgs.length !== 1) {
1115
+ throw new Error("JSON_ARRAYAGG expects exactly one argument");
1116
+ }
1117
+ return `JSON_ARRAYAGG(${compiledArgs[0]})`;
1118
+ }
1119
+ },
1120
+ {
1121
+ name: "JSON_CONTAINS",
1122
+ renderer: ({ compiledArgs }) => {
1123
+ if (compiledArgs.length < 2 || compiledArgs.length > 3) {
1124
+ throw new Error("JSON_CONTAINS expects two or three arguments");
1125
+ }
1126
+ return `JSON_CONTAINS(${compiledArgs.join(", ")})`;
1127
+ }
1128
+ },
1129
+ {
1130
+ name: "ARRAY_APPEND",
1131
+ renderer: ({ compiledArgs }) => {
1132
+ if (compiledArgs.length !== 2) {
1133
+ throw new Error("ARRAY_APPEND expects exactly two arguments");
1134
+ }
1135
+ return `ARRAY_APPEND(${compiledArgs[0]}, ${compiledArgs[1]})`;
1136
+ }
1137
+ }
1138
+ ];
1139
+
1140
+ // src/core/functions/group-concat-helpers.ts
1141
+ var DEFAULT_GROUP_CONCAT_SEPARATOR = {
1142
+ type: "Literal",
1143
+ value: ","
1144
+ };
1145
+ function buildGroupConcatOrderBy(ctx) {
1146
+ const orderBy = ctx.node.orderBy;
1147
+ if (!orderBy || orderBy.length === 0) {
1148
+ return "";
1149
+ }
1150
+ const parts = orderBy.map((order) => {
1151
+ const term = isOperandNode(order.term) ? ctx.compileOperand(order.term) : (() => {
1152
+ throw new Error("ORDER BY expressions inside functions must be operands");
1153
+ })();
1154
+ const collation = order.collation ? ` COLLATE ${order.collation}` : "";
1155
+ const nulls = order.nulls ? ` NULLS ${order.nulls}` : "";
1156
+ return `${term} ${order.direction}${collation}${nulls}`;
1157
+ });
1158
+ return `ORDER BY ${parts.join(", ")}`;
1159
+ }
1160
+ function formatGroupConcatSeparator(ctx) {
1161
+ if (!ctx.node.separator) {
1162
+ return "";
1163
+ }
1164
+ return ` SEPARATOR ${ctx.compileOperand(ctx.node.separator)}`;
1165
+ }
1166
+ function getGroupConcatSeparatorOperand(ctx) {
1167
+ return ctx.node.separator ?? DEFAULT_GROUP_CONCAT_SEPARATOR;
1168
+ }
1169
+ function renderStandardGroupConcat(ctx) {
1170
+ const arg = ctx.compiledArgs[0];
1171
+ const orderClause = buildGroupConcatOrderBy(ctx);
1172
+ const orderSegment = orderClause ? ` ${orderClause}` : "";
1173
+ const separatorClause = formatGroupConcatSeparator(ctx);
1174
+ return `GROUP_CONCAT(${arg}${orderSegment}${separatorClause})`;
1175
+ }
1176
+
853
1177
  // src/core/functions/standard-strategy.ts
854
- var StandardFunctionStrategy = class _StandardFunctionStrategy {
1178
+ var StandardFunctionStrategy = class {
855
1179
  /**
856
1180
  * Creates a new StandardFunctionStrategy and registers standard functions.
857
1181
  */
858
- constructor() {
859
- this.renderers = /* @__PURE__ */ new Map();
1182
+ constructor(registry2) {
1183
+ this.registry = registry2 ?? new FunctionRegistry();
860
1184
  this.registerStandard();
861
1185
  }
862
1186
  registerStandard() {
863
- this.add("COUNT", ({ compiledArgs }) => compiledArgs.length ? `COUNT(${compiledArgs.join(", ")})` : "COUNT(*)");
864
- this.add("SUM", ({ compiledArgs }) => `SUM(${compiledArgs[0]})`);
865
- this.add("AVG", ({ compiledArgs }) => `AVG(${compiledArgs[0]})`);
866
- this.add("MIN", ({ compiledArgs }) => `MIN(${compiledArgs[0]})`);
867
- this.add("MAX", ({ compiledArgs }) => `MAX(${compiledArgs[0]})`);
868
- this.add("ABS", ({ compiledArgs }) => `ABS(${compiledArgs[0]})`);
869
- this.add("UPPER", ({ compiledArgs }) => `UPPER(${compiledArgs[0]})`);
870
- this.add("LOWER", ({ compiledArgs }) => `LOWER(${compiledArgs[0]})`);
871
- this.add("LENGTH", ({ compiledArgs }) => `LENGTH(${compiledArgs[0]})`);
872
- this.add("TRIM", ({ compiledArgs }) => `TRIM(${compiledArgs[0]})`);
873
- this.add("LTRIM", ({ compiledArgs }) => `LTRIM(${compiledArgs[0]})`);
874
- this.add("RTRIM", ({ compiledArgs }) => `RTRIM(${compiledArgs[0]})`);
875
- this.add("SUBSTRING", ({ compiledArgs }) => `SUBSTRING(${compiledArgs.join(", ")})`);
876
- this.add("CONCAT", ({ compiledArgs }) => `CONCAT(${compiledArgs.join(", ")})`);
877
- this.add("NOW", () => `NOW()`);
878
- this.add("CURRENT_DATE", () => `CURRENT_DATE`);
879
- this.add("CURRENT_TIME", () => `CURRENT_TIME`);
880
- this.add("EXTRACT", ({ compiledArgs }) => `EXTRACT(${compiledArgs[0]} FROM ${compiledArgs[1]})`);
881
- this.add("YEAR", ({ compiledArgs }) => `EXTRACT(YEAR FROM ${compiledArgs[0]})`);
882
- this.add("MONTH", ({ compiledArgs }) => `EXTRACT(MONTH FROM ${compiledArgs[0]})`);
883
- this.add("DAY", ({ compiledArgs }) => `EXTRACT(DAY FROM ${compiledArgs[0]})`);
884
- this.add("DATE_ADD", ({ compiledArgs }) => `(${compiledArgs[0]} + INTERVAL ${compiledArgs[1]} ${compiledArgs[2]})`);
885
- this.add("DATE_SUB", ({ compiledArgs }) => `(${compiledArgs[0]} - INTERVAL ${compiledArgs[1]} ${compiledArgs[2]})`);
886
- this.add("DATE_DIFF", ({ compiledArgs }) => `DATEDIFF(${compiledArgs[0]}, ${compiledArgs[1]})`);
887
- this.add("DATE_FORMAT", ({ compiledArgs }) => `DATE_FORMAT(${compiledArgs[0]}, ${compiledArgs[1]})`);
888
- this.add("UNIX_TIMESTAMP", () => `UNIX_TIMESTAMP()`);
889
- this.add("FROM_UNIXTIME", ({ compiledArgs }) => `FROM_UNIXTIME(${compiledArgs[0]})`);
890
- this.add("END_OF_MONTH", ({ compiledArgs }) => `LAST_DAY(${compiledArgs[0]})`);
891
- this.add("DAY_OF_WEEK", ({ compiledArgs }) => `DAYOFWEEK(${compiledArgs[0]})`);
892
- this.add("WEEK_OF_YEAR", ({ compiledArgs }) => `WEEKOFYEAR(${compiledArgs[0]})`);
893
- this.add("DATE_TRUNC", ({ compiledArgs }) => `DATE_TRUNC(${compiledArgs[0]}, ${compiledArgs[1]})`);
1187
+ this.registerDefinitions(aggregateFunctionDefinitions);
1188
+ this.registerDefinitions(stringFunctionDefinitions);
1189
+ this.registerDefinitions(dateTimeFunctionDefinitions);
1190
+ this.registerDefinitions(numericFunctionDefinitions);
1191
+ this.registerDefinitions(controlFlowFunctionDefinitions);
1192
+ this.registerDefinitions(jsonFunctionDefinitions);
894
1193
  this.add("GROUP_CONCAT", (ctx) => this.renderGroupConcat(ctx));
895
1194
  }
1195
+ registerDefinitions(definitions) {
1196
+ this.registry.register(definitions);
1197
+ }
896
1198
  /**
897
1199
  * Registers a renderer for a function name.
898
1200
  * @param name - The function name.
899
1201
  * @param renderer - The renderer function.
900
1202
  */
901
1203
  add(name, renderer) {
902
- this.renderers.set(name, renderer);
1204
+ this.registry.add(name, renderer);
903
1205
  }
904
1206
  /**
905
1207
  * @inheritDoc
906
1208
  */
907
1209
  getRenderer(name) {
908
- return this.renderers.get(name);
1210
+ return this.registry.get(name);
909
1211
  }
910
1212
  /**
911
1213
  * Renders the GROUP_CONCAT function with optional ORDER BY and SEPARATOR.
@@ -913,11 +1215,7 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
913
1215
  * @returns The rendered SQL string.
914
1216
  */
915
1217
  renderGroupConcat(ctx) {
916
- const arg = ctx.compiledArgs[0];
917
- const orderClause = this.buildOrderByExpression(ctx);
918
- const orderSegment = orderClause ? ` ${orderClause}` : "";
919
- const separatorClause = this.formatGroupConcatSeparator(ctx);
920
- return `GROUP_CONCAT(${arg}${orderSegment}${separatorClause})`;
1218
+ return renderStandardGroupConcat(ctx);
921
1219
  }
922
1220
  /**
923
1221
  * Builds the ORDER BY clause for functions like GROUP_CONCAT.
@@ -925,19 +1223,7 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
925
1223
  * @returns The ORDER BY SQL clause or empty string.
926
1224
  */
927
1225
  buildOrderByExpression(ctx) {
928
- const orderBy = ctx.node.orderBy;
929
- if (!orderBy || orderBy.length === 0) {
930
- return "";
931
- }
932
- const parts = orderBy.map((order) => {
933
- const term = isOperandNode(order.term) ? ctx.compileOperand(order.term) : (() => {
934
- throw new Error("ORDER BY expressions inside functions must be operands");
935
- })();
936
- const collation = order.collation ? ` COLLATE ${order.collation}` : "";
937
- const nulls = order.nulls ? ` NULLS ${order.nulls}` : "";
938
- return `${term} ${order.direction}${collation}${nulls}`;
939
- });
940
- return `ORDER BY ${parts.join(", ")}`;
1226
+ return buildGroupConcatOrderBy(ctx);
941
1227
  }
942
1228
  /**
943
1229
  * Formats the SEPARATOR clause for GROUP_CONCAT.
@@ -945,10 +1231,7 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
945
1231
  * @returns The SEPARATOR SQL clause or empty string.
946
1232
  */
947
1233
  formatGroupConcatSeparator(ctx) {
948
- if (!ctx.node.separator) {
949
- return "";
950
- }
951
- return ` SEPARATOR ${ctx.compileOperand(ctx.node.separator)}`;
1234
+ return formatGroupConcatSeparator(ctx);
952
1235
  }
953
1236
  /**
954
1237
  * Gets the separator operand for GROUP_CONCAT, defaulting to comma.
@@ -956,14 +1239,24 @@ var StandardFunctionStrategy = class _StandardFunctionStrategy {
956
1239
  * @returns The separator operand.
957
1240
  */
958
1241
  getGroupConcatSeparatorOperand(ctx) {
959
- return ctx.node.separator ?? _StandardFunctionStrategy.DEFAULT_GROUP_CONCAT_SEPARATOR;
1242
+ return getGroupConcatSeparatorOperand(ctx);
960
1243
  }
961
1244
  static {
962
1245
  /** Default separator for GROUP_CONCAT, a comma. */
963
- this.DEFAULT_GROUP_CONCAT_SEPARATOR = {
964
- type: "Literal",
965
- value: ","
966
- };
1246
+ this.DEFAULT_GROUP_CONCAT_SEPARATOR = DEFAULT_GROUP_CONCAT_SEPARATOR;
1247
+ }
1248
+ };
1249
+
1250
+ // src/core/functions/standard-table-strategy.ts
1251
+ var StandardTableFunctionStrategy = class {
1252
+ constructor() {
1253
+ this.renderers = /* @__PURE__ */ new Map();
1254
+ }
1255
+ add(key, renderer) {
1256
+ this.renderers.set(key, renderer);
1257
+ }
1258
+ getRenderer(key) {
1259
+ return this.renderers.get(key);
967
1260
  }
968
1261
  };
969
1262
 
@@ -1137,10 +1430,11 @@ var Dialect = class _Dialect {
1137
1430
  const combinedCtes = [...normalized.ctes ?? [], ...hoistedCtes];
1138
1431
  return combinedCtes.length ? { ...normalized, ctes: combinedCtes } : normalized;
1139
1432
  }
1140
- constructor(functionStrategy) {
1433
+ constructor(functionStrategy, tableFunctionStrategy) {
1141
1434
  this.expressionCompilers = /* @__PURE__ */ new Map();
1142
1435
  this.operandCompilers = /* @__PURE__ */ new Map();
1143
1436
  this.functionStrategy = functionStrategy || new StandardFunctionStrategy();
1437
+ this.tableFunctionStrategy = tableFunctionStrategy || new StandardTableFunctionStrategy();
1144
1438
  this.registerDefaultOperandCompilers();
1145
1439
  this.registerDefaultExpressionCompilers();
1146
1440
  }
@@ -1149,7 +1443,7 @@ var Dialect = class _Dialect {
1149
1443
  * @param functionStrategy - Optional function strategy
1150
1444
  * @returns New Dialect instance
1151
1445
  */
1152
- static create(functionStrategy) {
1446
+ static create(functionStrategy, tableFunctionStrategy) {
1153
1447
  class TestDialect extends _Dialect {
1154
1448
  constructor() {
1155
1449
  super(...arguments);
@@ -1171,7 +1465,7 @@ var Dialect = class _Dialect {
1171
1465
  throw new Error("Not implemented");
1172
1466
  }
1173
1467
  }
1174
- return new TestDialect(functionStrategy);
1468
+ return new TestDialect(functionStrategy, tableFunctionStrategy);
1175
1469
  }
1176
1470
  /**
1177
1471
  * Registers an expression compiler for a specific node type
@@ -1272,6 +1566,11 @@ var Dialect = class _Dialect {
1272
1566
  const right2 = this.compileOperand(arith.right, ctx);
1273
1567
  return `${left2} ${arith.operator} ${right2}`;
1274
1568
  });
1569
+ this.registerExpressionCompiler("BitwiseExpression", (bitwise, ctx) => {
1570
+ const left2 = this.compileOperand(bitwise.left, ctx);
1571
+ const right2 = this.compileOperand(bitwise.right, ctx);
1572
+ return `${left2} ${bitwise.operator} ${right2}`;
1573
+ });
1275
1574
  }
1276
1575
  registerDefaultOperandCompilers() {
1277
1576
  this.registerOperandCompiler("Literal", (literal, ctx) => ctx.addParameter(literal.value));
@@ -1341,6 +1640,15 @@ var Dialect = class _Dialect {
1341
1640
  const right2 = this.compileOperand(node.right, ctx);
1342
1641
  return `(${left2} ${node.operator} ${right2})`;
1343
1642
  });
1643
+ this.registerOperandCompiler("BitwiseExpression", (node, ctx) => {
1644
+ const left2 = this.compileOperand(node.left, ctx);
1645
+ const right2 = this.compileOperand(node.right, ctx);
1646
+ return `(${left2} ${node.operator} ${right2})`;
1647
+ });
1648
+ this.registerOperandCompiler("Collate", (node, ctx) => {
1649
+ const expr = this.compileOperand(node.expression, ctx);
1650
+ return `${expr} COLLATE ${node.collation}`;
1651
+ });
1344
1652
  }
1345
1653
  // Default fallback, should be overridden by dialects if supported
1346
1654
  compileJsonPath(_node) {
@@ -1373,13 +1681,13 @@ var FunctionTableFormatter = class {
1373
1681
  * @param dialect - The dialect instance for compiling operands.
1374
1682
  * @returns SQL function table expression (e.g., "LATERAL schema.func(args) WITH ORDINALITY AS alias(col1, col2)").
1375
1683
  */
1376
- static format(fn5, ctx, dialect) {
1377
- const schemaPart = this.formatSchema(fn5, dialect);
1378
- const args = this.formatArgs(fn5, ctx, dialect);
1379
- const base = this.formatBase(fn5, schemaPart, args, dialect);
1380
- const lateral = this.formatLateral(fn5);
1381
- const alias = this.formatAlias(fn5, dialect);
1382
- const colAliases = this.formatColumnAliases(fn5, dialect);
1684
+ static format(fn8, ctx, dialect) {
1685
+ const schemaPart = this.formatSchema(fn8, dialect);
1686
+ const args = this.formatArgs(fn8, ctx, dialect);
1687
+ const base = this.formatBase(fn8, schemaPart, args);
1688
+ const lateral = this.formatLateral(fn8);
1689
+ const alias = this.formatAlias(fn8, dialect);
1690
+ const colAliases = this.formatColumnAliases(fn8, dialect);
1383
1691
  return `${lateral}${base}${alias}${colAliases}`;
1384
1692
  }
1385
1693
  /**
@@ -1389,9 +1697,9 @@ var FunctionTableFormatter = class {
1389
1697
  * @returns Schema prefix (e.g., "schema.") or empty string.
1390
1698
  * @internal
1391
1699
  */
1392
- static formatSchema(fn5, dialect) {
1393
- if (!fn5.schema) return "";
1394
- const quoted = dialect ? dialect.quoteIdentifier(fn5.schema) : fn5.schema;
1700
+ static formatSchema(fn8, dialect) {
1701
+ if (!fn8.schema) return "";
1702
+ const quoted = dialect ? dialect.quoteIdentifier(fn8.schema) : fn8.schema;
1395
1703
  return `${quoted}.`;
1396
1704
  }
1397
1705
  /**
@@ -1402,8 +1710,8 @@ var FunctionTableFormatter = class {
1402
1710
  * @returns Comma-separated function arguments.
1403
1711
  * @internal
1404
1712
  */
1405
- static formatArgs(fn5, ctx, dialect) {
1406
- return (fn5.args || []).map((a) => {
1713
+ static formatArgs(fn8, ctx, dialect) {
1714
+ return (fn8.args || []).map((a) => {
1407
1715
  if (ctx && dialect) {
1408
1716
  return dialect.compileOperand(a, ctx);
1409
1717
  }
@@ -1419,10 +1727,9 @@ var FunctionTableFormatter = class {
1419
1727
  * @returns Base function call expression (e.g., "schema.func(args) WITH ORDINALITY").
1420
1728
  * @internal
1421
1729
  */
1422
- static formatBase(fn5, schemaPart, args, dialect) {
1423
- const ordinality = fn5.withOrdinality ? " WITH ORDINALITY" : "";
1424
- const quoted = dialect ? dialect.quoteIdentifier(fn5.name) : fn5.name;
1425
- return `${schemaPart}${quoted}(${args})${ordinality}`;
1730
+ static formatBase(fn8, schemaPart, args) {
1731
+ const ordinality = fn8.withOrdinality ? " WITH ORDINALITY" : "";
1732
+ return `${schemaPart}${fn8.name}(${args})${ordinality}`;
1426
1733
  }
1427
1734
  /**
1428
1735
  * Formats the LATERAL keyword if present.
@@ -1430,8 +1737,8 @@ var FunctionTableFormatter = class {
1430
1737
  * @returns "LATERAL " or empty string.
1431
1738
  * @internal
1432
1739
  */
1433
- static formatLateral(fn5) {
1434
- return fn5.lateral ? "LATERAL " : "";
1740
+ static formatLateral(fn8) {
1741
+ return fn8.lateral ? "LATERAL " : "";
1435
1742
  }
1436
1743
  /**
1437
1744
  * Formats the table alias for the function table.
@@ -1440,9 +1747,9 @@ var FunctionTableFormatter = class {
1440
1747
  * @returns " AS alias" or empty string.
1441
1748
  * @internal
1442
1749
  */
1443
- static formatAlias(fn5, dialect) {
1444
- if (!fn5.alias) return "";
1445
- const quoted = dialect ? dialect.quoteIdentifier(fn5.alias) : fn5.alias;
1750
+ static formatAlias(fn8, dialect) {
1751
+ if (!fn8.alias) return "";
1752
+ const quoted = dialect ? dialect.quoteIdentifier(fn8.alias) : fn8.alias;
1446
1753
  return ` AS ${quoted}`;
1447
1754
  }
1448
1755
  /**
@@ -1452,9 +1759,9 @@ var FunctionTableFormatter = class {
1452
1759
  * @returns "(col1, col2, ...)" or empty string.
1453
1760
  * @internal
1454
1761
  */
1455
- static formatColumnAliases(fn5, dialect) {
1456
- if (!fn5.columnAliases || !fn5.columnAliases.length) return "";
1457
- const aliases = fn5.columnAliases.map((col2) => dialect ? dialect.quoteIdentifier(col2) : col2).join(", ");
1762
+ static formatColumnAliases(fn8, dialect) {
1763
+ if (!fn8.columnAliases || !fn8.columnAliases.length) return "";
1764
+ const aliases = fn8.columnAliases.map((col2) => dialect ? dialect.quoteIdentifier(col2) : col2).join(", ");
1458
1765
  return `(${aliases})`;
1459
1766
  }
1460
1767
  };
@@ -1722,8 +2029,24 @@ var SqlDialectBase = class extends Dialect {
1722
2029
  }
1723
2030
  return this.compileTableSource(tableSource);
1724
2031
  }
1725
- compileFunctionTable(fn5, ctx) {
1726
- return FunctionTableFormatter.format(fn5, ctx, this);
2032
+ compileFunctionTable(fn8, ctx) {
2033
+ const key = fn8.key ?? fn8.name;
2034
+ if (ctx) {
2035
+ const renderer = this.tableFunctionStrategy.getRenderer(key);
2036
+ if (renderer) {
2037
+ const compiledArgs = (fn8.args ?? []).map((arg) => this.compileOperand(arg, ctx));
2038
+ return renderer({
2039
+ node: fn8,
2040
+ compiledArgs,
2041
+ compileOperand: (operand) => this.compileOperand(operand, ctx),
2042
+ quoteIdentifier: this.quoteIdentifier.bind(this)
2043
+ });
2044
+ }
2045
+ if (fn8.key) {
2046
+ throw new Error(`Table function "${key}" is not supported by dialect "${this.dialect}".`);
2047
+ }
2048
+ }
2049
+ return FunctionTableFormatter.format(fn8, ctx, this);
1727
2050
  }
1728
2051
  compileDerivedTable(table, ctx) {
1729
2052
  if (!table.alias) {
@@ -1882,6 +2205,76 @@ var PostgresFunctionStrategy = class extends StandardFunctionStrategy {
1882
2205
  const separator = ctx.compileOperand(separatorOperand);
1883
2206
  return `STRING_AGG(${arg}, ${separator}${orderSegment})`;
1884
2207
  });
2208
+ this.add("CHR", ({ compiledArgs }) => `CHR(${compiledArgs[0]})`);
2209
+ this.add("HOUR", ({ compiledArgs }) => `EXTRACT(HOUR FROM ${compiledArgs[0]})`);
2210
+ this.add("MINUTE", ({ compiledArgs }) => `EXTRACT(MINUTE FROM ${compiledArgs[0]})`);
2211
+ this.add("SECOND", ({ compiledArgs }) => `EXTRACT(SECOND FROM ${compiledArgs[0]})`);
2212
+ this.add("QUARTER", ({ compiledArgs }) => `EXTRACT(QUARTER FROM ${compiledArgs[0]})`);
2213
+ this.add("JSON_LENGTH", ({ compiledArgs }) => {
2214
+ if (compiledArgs.length !== 1) throw new Error("JSON_LENGTH expects 1 argument on PostgreSQL");
2215
+ return `jsonb_array_length(${compiledArgs[0]})`;
2216
+ });
2217
+ this.add("JSON_ARRAYAGG", ({ compiledArgs }) => {
2218
+ if (compiledArgs.length !== 1) throw new Error("JSON_ARRAYAGG expects 1 argument on PostgreSQL");
2219
+ return `jsonb_agg(${compiledArgs[0]})`;
2220
+ });
2221
+ this.add("JSON_CONTAINS", ({ compiledArgs }) => {
2222
+ if (compiledArgs.length !== 2) throw new Error("JSON_CONTAINS expects 2 arguments on PostgreSQL");
2223
+ return `(${compiledArgs[0]}::jsonb @> ${compiledArgs[1]}::jsonb)`;
2224
+ });
2225
+ this.add("ARRAY_APPEND", ({ compiledArgs }) => {
2226
+ if (compiledArgs.length !== 2) throw new Error("ARRAY_APPEND expects 2 arguments on PostgreSQL");
2227
+ return `array_append(${compiledArgs[0]}, ${compiledArgs[1]})`;
2228
+ });
2229
+ this.add("JSON_SET", ({ node, compiledArgs }) => {
2230
+ if (compiledArgs.length !== 3) throw new Error("JSON_SET expects exactly 3 arguments on PostgreSQL");
2231
+ const pathNode = node.args[1];
2232
+ if (pathNode.type !== "Literal") {
2233
+ throw new Error("PostgreSQL JSON_SET currently supports literal paths only");
2234
+ }
2235
+ const pathArray = this.formatJsonbPathArray(pathNode);
2236
+ return `jsonb_set(${compiledArgs[0]}, ${pathArray}, ${compiledArgs[2]}::jsonb, true)`;
2237
+ });
2238
+ }
2239
+ formatJsonbPathArray(pathNode) {
2240
+ const rawPath = String(pathNode.value ?? "");
2241
+ if (!rawPath.startsWith("$")) {
2242
+ throw new Error('PostgreSQL JSON_SET paths must start with "$"');
2243
+ }
2244
+ const trimmed = rawPath === "$" ? "" : rawPath.startsWith("$.") ? rawPath.slice(2) : rawPath.slice(1);
2245
+ if (!trimmed) {
2246
+ throw new Error("PostgreSQL JSON_SET requires a non-root path");
2247
+ }
2248
+ if (trimmed.includes("[") || trimmed.includes("]")) {
2249
+ throw new Error("PostgreSQL JSON_SET currently only supports simple dot-separated paths");
2250
+ }
2251
+ const segments = trimmed.split(".").map((segment) => segment.replace(/^['"]?/, "").replace(/['"]?$/, "").trim()).filter(Boolean);
2252
+ if (!segments.length) {
2253
+ throw new Error("PostgreSQL JSON_SET requires at least one path segment");
2254
+ }
2255
+ const escapedSegments = segments.map((segment) => `'${segment.replace(/'/g, "''")}'`);
2256
+ return `ARRAY[${escapedSegments.join(", ")}]`;
2257
+ }
2258
+ };
2259
+
2260
+ // src/core/dialect/postgres/table-functions.ts
2261
+ var PostgresTableFunctionStrategy = class extends StandardTableFunctionStrategy {
2262
+ constructor() {
2263
+ super();
2264
+ this.registerOverrides();
2265
+ }
2266
+ registerOverrides() {
2267
+ this.add("ARRAY_UNNEST", ({ node, compiledArgs, quoteIdentifier }) => {
2268
+ const lateral = node.lateral ?? true;
2269
+ const withOrd = node.withOrdinality ?? false;
2270
+ const base = `unnest(${compiledArgs.join(", ")})${withOrd ? " WITH ORDINALITY" : ""}`;
2271
+ if (node.columnAliases?.length && !node.alias) {
2272
+ throw new Error("tvf(ARRAY_UNNEST) with columnAliases requires an alias.");
2273
+ }
2274
+ const alias = node.alias ? ` AS ${quoteIdentifier(node.alias)}` : "";
2275
+ const cols = node.columnAliases?.length ? `(${node.columnAliases.map(quoteIdentifier).join(", ")})` : "";
2276
+ return `${lateral ? "LATERAL " : ""}${base}${alias}${cols}`;
2277
+ });
1885
2278
  }
1886
2279
  };
1887
2280
 
@@ -1891,8 +2284,20 @@ var PostgresDialect = class extends SqlDialectBase {
1891
2284
  * Creates a new PostgresDialect instance
1892
2285
  */
1893
2286
  constructor() {
1894
- super(new PostgresFunctionStrategy());
2287
+ super(new PostgresFunctionStrategy(), new PostgresTableFunctionStrategy());
1895
2288
  this.dialect = "postgres";
2289
+ this.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
2290
+ const left2 = this.compileOperand(node.left, ctx);
2291
+ const right2 = this.compileOperand(node.right, ctx);
2292
+ const op = node.operator === "^" ? "#" : node.operator;
2293
+ return `${left2} ${op} ${right2}`;
2294
+ });
2295
+ this.registerOperandCompiler("BitwiseExpression", (node, ctx) => {
2296
+ const left2 = this.compileOperand(node.left, ctx);
2297
+ const right2 = this.compileOperand(node.right, ctx);
2298
+ const op = node.operator === "^" ? "#" : node.operator;
2299
+ return `(${left2} ${op} ${right2})`;
2300
+ });
1896
2301
  }
1897
2302
  /**
1898
2303
  * Quotes an identifier using PostgreSQL double-quote syntax
@@ -2001,6 +2406,14 @@ var MysqlFunctionStrategy = class extends StandardFunctionStrategy {
2001
2406
  }
2002
2407
  return `DATE(${date})`;
2003
2408
  });
2409
+ this.add("HOUR", ({ compiledArgs }) => `HOUR(${compiledArgs[0]})`);
2410
+ this.add("MINUTE", ({ compiledArgs }) => `MINUTE(${compiledArgs[0]})`);
2411
+ this.add("SECOND", ({ compiledArgs }) => `SECOND(${compiledArgs[0]})`);
2412
+ this.add("QUARTER", ({ compiledArgs }) => `QUARTER(${compiledArgs[0]})`);
2413
+ this.add("ARRAY_APPEND", ({ compiledArgs }) => {
2414
+ if (compiledArgs.length !== 2) throw new Error("ARRAY_APPEND expects 2 arguments (array, value)");
2415
+ return `JSON_ARRAY_APPEND(${compiledArgs[0]}, '$', ${compiledArgs[1]})`;
2416
+ });
2004
2417
  }
2005
2418
  };
2006
2419
 
@@ -2133,6 +2546,30 @@ var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
2133
2546
  const separator = ctx.compileOperand(separatorOperand);
2134
2547
  return `GROUP_CONCAT(${arg}, ${separator})`;
2135
2548
  });
2549
+ this.add("HOUR", ({ compiledArgs }) => `CAST(strftime('%H', ${compiledArgs[0]}) AS INTEGER)`);
2550
+ this.add("MINUTE", ({ compiledArgs }) => `CAST(strftime('%M', ${compiledArgs[0]}) AS INTEGER)`);
2551
+ this.add("SECOND", ({ compiledArgs }) => `CAST(strftime('%S', ${compiledArgs[0]}) AS INTEGER)`);
2552
+ this.add("QUARTER", ({ compiledArgs }) => `((CAST(strftime('%m', ${compiledArgs[0]}) AS INTEGER) + 2) / 3)`);
2553
+ this.add("JSON_LENGTH", ({ compiledArgs }) => {
2554
+ if (compiledArgs.length === 0 || compiledArgs.length > 2) {
2555
+ throw new Error("JSON_LENGTH expects 1 or 2 arguments on SQLite");
2556
+ }
2557
+ return `json_array_length(${compiledArgs.join(", ")})`;
2558
+ });
2559
+ this.add("JSON_ARRAYAGG", ({ compiledArgs }) => {
2560
+ if (compiledArgs.length !== 1) {
2561
+ throw new Error("JSON_ARRAYAGG expects 1 argument on SQLite");
2562
+ }
2563
+ return `json_group_array(${compiledArgs[0]})`;
2564
+ });
2565
+ this.add("JSON_CONTAINS", () => {
2566
+ throw new Error("JSON_CONTAINS is not supported on SQLite");
2567
+ });
2568
+ this.add("ARRAY_APPEND", ({ compiledArgs }) => {
2569
+ if (compiledArgs.length !== 2) throw new Error("ARRAY_APPEND expects 2 arguments (array, value)");
2570
+ return `json_array_append(${compiledArgs[0]}, '$', ${compiledArgs[1]})`;
2571
+ });
2572
+ this.add("CHR", ({ compiledArgs }) => `CHAR(${compiledArgs[0]})`);
2136
2573
  }
2137
2574
  };
2138
2575
 
@@ -2144,6 +2581,22 @@ var SqliteDialect = class extends SqlDialectBase {
2144
2581
  constructor() {
2145
2582
  super(new SqliteFunctionStrategy());
2146
2583
  this.dialect = "sqlite";
2584
+ this.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
2585
+ const left2 = this.compileOperand(node.left, ctx);
2586
+ const right2 = this.compileOperand(node.right, ctx);
2587
+ if (node.operator === "^") {
2588
+ return `(${left2} | ${right2}) & ~(${left2} & ${right2})`;
2589
+ }
2590
+ return `${left2} ${node.operator} ${right2}`;
2591
+ });
2592
+ this.registerOperandCompiler("BitwiseExpression", (node, ctx) => {
2593
+ const left2 = this.compileOperand(node.left, ctx);
2594
+ const right2 = this.compileOperand(node.right, ctx);
2595
+ if (node.operator === "^") {
2596
+ return `((${left2} | ${right2}) & ~(${left2} & ${right2}))`;
2597
+ }
2598
+ return `(${left2} ${node.operator} ${right2})`;
2599
+ });
2147
2600
  }
2148
2601
  /**
2149
2602
  * Quotes an identifier using SQLite double-quote syntax
@@ -2268,6 +2721,33 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
2268
2721
  const withinGroup = orderClause ? ` WITHIN GROUP (${orderClause})` : "";
2269
2722
  return `STRING_AGG(${arg}, ${separator})${withinGroup}`;
2270
2723
  });
2724
+ this.add("LENGTH", ({ compiledArgs }) => `LEN(${compiledArgs[0]})`);
2725
+ this.add("CHAR_LENGTH", ({ compiledArgs }) => `LEN(${compiledArgs[0]})`);
2726
+ this.add("CHARACTER_LENGTH", ({ compiledArgs }) => `LEN(${compiledArgs[0]})`);
2727
+ this.add("POSITION", ({ compiledArgs }) => `CHARINDEX(${compiledArgs[0]}, ${compiledArgs[1]})`);
2728
+ this.add("LOCATE", ({ compiledArgs }) => compiledArgs.length === 3 ? `CHARINDEX(${compiledArgs[0]}, ${compiledArgs[1]}, ${compiledArgs[2]})` : `CHARINDEX(${compiledArgs[0]}, ${compiledArgs[1]})`);
2729
+ this.add("INSTR", ({ compiledArgs }) => `CHARINDEX(${compiledArgs[1]}, ${compiledArgs[0]})`);
2730
+ this.add("CHR", ({ compiledArgs }) => `CHAR(${compiledArgs[0]})`);
2731
+ this.add("HOUR", ({ compiledArgs }) => `DATEPART(hour, ${compiledArgs[0]})`);
2732
+ this.add("MINUTE", ({ compiledArgs }) => `DATEPART(minute, ${compiledArgs[0]})`);
2733
+ this.add("SECOND", ({ compiledArgs }) => `DATEPART(second, ${compiledArgs[0]})`);
2734
+ this.add("QUARTER", ({ compiledArgs }) => `DATEPART(quarter, ${compiledArgs[0]})`);
2735
+ this.add("JSON_SET", ({ compiledArgs }) => {
2736
+ if (compiledArgs.length !== 3) throw new Error("JSON_SET expects 3 arguments on SQL Server");
2737
+ return `JSON_MODIFY(${compiledArgs[0]}, ${compiledArgs[1]}, ${compiledArgs[2]})`;
2738
+ });
2739
+ this.add("JSON_LENGTH", () => {
2740
+ throw new Error("JSON_LENGTH is not supported on SQL Server");
2741
+ });
2742
+ this.add("JSON_ARRAYAGG", () => {
2743
+ throw new Error("JSON_ARRAYAGG is not supported on SQL Server");
2744
+ });
2745
+ this.add("JSON_CONTAINS", () => {
2746
+ throw new Error("JSON_CONTAINS is not supported on SQL Server");
2747
+ });
2748
+ this.add("ARRAY_APPEND", () => {
2749
+ throw new Error("ARRAY_APPEND is not supported on SQL Server");
2750
+ });
2271
2751
  }
2272
2752
  };
2273
2753
 
@@ -4065,6 +4545,17 @@ var hideInternal2 = (obj, keys) => {
4065
4545
  }
4066
4546
  };
4067
4547
  var DefaultHasOneReference = class {
4548
+ /**
4549
+ * @param ctx The entity context for tracking changes.
4550
+ * @param meta Metadata for the parent entity.
4551
+ * @param root The parent entity instance.
4552
+ * @param relationName The name of the relation.
4553
+ * @param relation Relation definition.
4554
+ * @param rootTable Table definition of the parent entity.
4555
+ * @param loader Function to load the child entity.
4556
+ * @param createEntity Function to create entity instances from rows.
4557
+ * @param localKey The local key on the parent entity used for the relation.
4558
+ */
4068
4559
  constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, localKey) {
4069
4560
  this.ctx = ctx;
4070
4561
  this.meta = meta;
@@ -4182,6 +4673,17 @@ var hideInternal3 = (obj, keys) => {
4182
4673
  }
4183
4674
  };
4184
4675
  var DefaultBelongsToReference = class {
4676
+ /**
4677
+ * @param ctx The entity context for tracking changes.
4678
+ * @param meta Metadata for the child entity.
4679
+ * @param root The child entity instance (carrying the foreign key).
4680
+ * @param relationName The name of the relation.
4681
+ * @param relation Relation definition.
4682
+ * @param rootTable Table definition of the child entity.
4683
+ * @param loader Function to load the parent entity.
4684
+ * @param createEntity Function to create entity instances from rows.
4685
+ * @param targetKey The primary key of the target (parent) table.
4686
+ */
4185
4687
  constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, targetKey) {
4186
4688
  this.ctx = ctx;
4187
4689
  this.meta = meta;
@@ -4273,6 +4775,17 @@ var hideInternal4 = (obj, keys) => {
4273
4775
  }
4274
4776
  };
4275
4777
  var DefaultManyToManyCollection = class {
4778
+ /**
4779
+ * @param ctx The entity context for tracking changes.
4780
+ * @param meta Metadata for the root entity.
4781
+ * @param root The root entity instance.
4782
+ * @param relationName The name of the relation.
4783
+ * @param relation Relation definition.
4784
+ * @param rootTable Table definition of the root entity.
4785
+ * @param loader Function to load the collection items.
4786
+ * @param createEntity Function to create entity instances from rows.
4787
+ * @param localKey The local key used for joining.
4788
+ */
4276
4789
  constructor(ctx, meta, root, relationName, relation, rootTable, loader, createEntity, localKey) {
4277
4790
  this.ctx = ctx;
4278
4791
  this.meta = meta;
@@ -4288,6 +4801,10 @@ var DefaultManyToManyCollection = class {
4288
4801
  hideInternal4(this, ["ctx", "meta", "root", "relationName", "relation", "rootTable", "loader", "createEntity", "localKey"]);
4289
4802
  this.hydrateFromCache();
4290
4803
  }
4804
+ /**
4805
+ * Loads the collection items if not already loaded.
4806
+ * @returns A promise that resolves to the array of target entities.
4807
+ */
4291
4808
  async load() {
4292
4809
  if (this.loaded) return this.items;
4293
4810
  const map = await this.loader();
@@ -4303,9 +4820,18 @@ var DefaultManyToManyCollection = class {
4303
4820
  this.loaded = true;
4304
4821
  return this.items;
4305
4822
  }
4823
+ /**
4824
+ * Returns the currently loaded items.
4825
+ * @returns Array of target entities.
4826
+ */
4306
4827
  getItems() {
4307
4828
  return this.items;
4308
4829
  }
4830
+ /**
4831
+ * Attaches an entity to the collection.
4832
+ * Registers an 'attach' change in the entity context.
4833
+ * @param target Entity instance or its primary key value.
4834
+ */
4309
4835
  attach(target) {
4310
4836
  const entity = this.ensureEntity(target);
4311
4837
  const id = this.extractId(entity);
@@ -4325,6 +4851,11 @@ var DefaultManyToManyCollection = class {
4325
4851
  { kind: "attach", entity }
4326
4852
  );
4327
4853
  }
4854
+ /**
4855
+ * Detaches an entity from the collection.
4856
+ * Registers a 'detach' change in the entity context.
4857
+ * @param target Entity instance or its primary key value.
4858
+ */
4328
4859
  detach(target) {
4329
4860
  const id = typeof target === "number" || typeof target === "string" ? target : this.extractId(target);
4330
4861
  if (id == null) return;
@@ -4340,6 +4871,11 @@ var DefaultManyToManyCollection = class {
4340
4871
  { kind: "detach", entity: existing }
4341
4872
  );
4342
4873
  }
4874
+ /**
4875
+ * Syncs the collection with a list of IDs.
4876
+ * Attaches missing IDs and detaches IDs not in the list.
4877
+ * @param ids Array of primary key values to sync with.
4878
+ */
4343
4879
  async syncByIds(ids) {
4344
4880
  await this.load();
4345
4881
  const normalized = new Set(ids.map((id) => toKey5(id)));
@@ -7568,6 +8104,14 @@ var repeat = (value, count2) => fn("REPEAT", [value, count2]);
7568
8104
  var lpad = (value, len, pad) => fn("LPAD", [value, len, pad]);
7569
8105
  var rpad = (value, len, pad) => fn("RPAD", [value, len, pad]);
7570
8106
  var space = (count2) => fn("SPACE", [count2]);
8107
+ var reverse = (value) => fn("REVERSE", [value]);
8108
+ var initcap = (value) => fn("INITCAP", [value]);
8109
+ var md5 = (value) => fn("MD5", [value]);
8110
+ var sha1 = (value) => fn("SHA1", [value]);
8111
+ var sha2 = (value, bits) => fn("SHA2", [value, bits]);
8112
+ var bitLength = (value) => fn("BIT_LENGTH", [value]);
8113
+ var octetLength = (value) => fn("OCTET_LENGTH", [value]);
8114
+ var chr = (code) => fn("CHR", [code]);
7571
8115
 
7572
8116
  // src/core/ddl/introspect/functions/mssql.ts
7573
8117
  var isColumnReference = (value) => typeof value === "object" && value !== null && !("type" in value) && "name" in value && typeof value.name === "string";
@@ -8126,6 +8670,8 @@ var sqrt = (value) => fn3("SQRT", [value]);
8126
8670
  var tan = (value) => fn3("TAN", [value]);
8127
8671
  var trunc = (value, decimals) => decimals === void 0 ? fn3("TRUNC", [value]) : fn3("TRUNC", [value, decimals]);
8128
8672
  var truncate = (value, decimals) => fn3("TRUNCATE", [value, decimals]);
8673
+ var log2 = (value) => fn3("LOG2", [value]);
8674
+ var cbrt = (value) => fn3("CBRT", [value]);
8129
8675
 
8130
8676
  // src/core/functions/datetime.ts
8131
8677
  var isColumnDef3 = (val) => !!val && typeof val === "object" && "type" in val && "name" in val;
@@ -8137,12 +8683,15 @@ var toOperand4 = (input) => {
8137
8683
  var fn4 = (key, args) => ({
8138
8684
  type: "Function",
8139
8685
  name: key,
8686
+ fn: key,
8140
8687
  args: args.map(toOperand4)
8141
8688
  });
8142
8689
  var now = () => fn4("NOW", []);
8143
8690
  var currentDate = () => fn4("CURRENT_DATE", []);
8144
8691
  var currentTime = () => fn4("CURRENT_TIME", []);
8145
8692
  var utcNow = () => fn4("UTC_NOW", []);
8693
+ var localTime = () => fn4("LOCALTIME", []);
8694
+ var localTimestamp = () => fn4("LOCALTIMESTAMP", []);
8146
8695
  var extract = (part, date) => fn4("EXTRACT", [part, date]);
8147
8696
  var year = (date) => fn4("YEAR", [date]);
8148
8697
  var month = (date) => fn4("MONTH", [date]);
@@ -8157,6 +8706,72 @@ var endOfMonth = (date) => fn4("END_OF_MONTH", [date]);
8157
8706
  var dayOfWeek = (date) => fn4("DAY_OF_WEEK", [date]);
8158
8707
  var weekOfYear = (date) => fn4("WEEK_OF_YEAR", [date]);
8159
8708
  var dateTrunc = (part, date) => fn4("DATE_TRUNC", [part, date]);
8709
+ var age = (timestamp, baseTimestamp) => baseTimestamp === void 0 ? fn4("AGE", [timestamp]) : fn4("AGE", [timestamp, baseTimestamp]);
8710
+ var hour = (date) => fn4("HOUR", [date]);
8711
+ var minute = (date) => fn4("MINUTE", [date]);
8712
+ var second = (date) => fn4("SECOND", [date]);
8713
+ var quarter = (date) => fn4("QUARTER", [date]);
8714
+
8715
+ // src/core/functions/control-flow.ts
8716
+ var isColumnDef4 = (val) => !!val && typeof val === "object" && "type" in val && "name" in val;
8717
+ var toOperand5 = (input) => {
8718
+ if (isOperandNode(input)) return input;
8719
+ if (isColumnDef4(input)) return columnOperand(input);
8720
+ return valueToOperand(input);
8721
+ };
8722
+ var fn5 = (key, args) => ({
8723
+ type: "Function",
8724
+ name: key,
8725
+ fn: key,
8726
+ args: args.map(toOperand5)
8727
+ });
8728
+ var coalesce = (...args) => {
8729
+ if (args.length < 2) throw new Error("coalesce() expects at least 2 arguments");
8730
+ return fn5("COALESCE", args);
8731
+ };
8732
+ var nullif = (val1, val2) => fn5("NULLIF", [val1, val2]);
8733
+ var greatest = (...args) => {
8734
+ if (args.length < 2) throw new Error("greatest() expects at least 2 arguments");
8735
+ return fn5("GREATEST", args);
8736
+ };
8737
+ var least = (...args) => {
8738
+ if (args.length < 2) throw new Error("least() expects at least 2 arguments");
8739
+ return fn5("LEAST", args);
8740
+ };
8741
+ var ifNull = (val, defaultValue) => coalesce(val, defaultValue);
8742
+
8743
+ // src/core/functions/json.ts
8744
+ var isColumnDef5 = (val) => !!val && typeof val === "object" && "type" in val && "name" in val;
8745
+ var toOperand6 = (input) => {
8746
+ if (isOperandNode(input)) return input;
8747
+ if (isColumnDef5(input)) return columnOperand(input);
8748
+ return valueToOperand(input);
8749
+ };
8750
+ var fn6 = (key, args) => ({
8751
+ type: "Function",
8752
+ name: key,
8753
+ fn: key,
8754
+ args: args.map(toOperand6)
8755
+ });
8756
+ var jsonLength = (target, path) => path === void 0 ? fn6("JSON_LENGTH", [target]) : fn6("JSON_LENGTH", [target, path]);
8757
+ var jsonSet = (target, path, value) => fn6("JSON_SET", [target, path, value]);
8758
+ var jsonArrayAgg = (value) => fn6("JSON_ARRAYAGG", [value]);
8759
+ var jsonContains = (target, candidate, path) => path === void 0 ? fn6("JSON_CONTAINS", [target, candidate]) : fn6("JSON_CONTAINS", [target, candidate, path]);
8760
+
8761
+ // src/core/functions/array.ts
8762
+ var isColumnDef6 = (val) => !!val && typeof val === "object" && "type" in val && "name" in val;
8763
+ var toOperand7 = (input) => {
8764
+ if (isOperandNode(input)) return input;
8765
+ if (isColumnDef6(input)) return columnOperand(input);
8766
+ return valueToOperand(input);
8767
+ };
8768
+ var fn7 = (key, args) => ({
8769
+ type: "Function",
8770
+ name: key,
8771
+ fn: key,
8772
+ args: args.map(toOperand7)
8773
+ });
8774
+ var arrayAppend = (array, value) => fn7("ARRAY_APPEND", [array, value]);
8160
8775
 
8161
8776
  // src/orm/als.ts
8162
8777
  var AsyncLocalStorage = class {
@@ -8236,7 +8851,7 @@ var DefaultNamingStrategy = class {
8236
8851
  * @returns Capitalized table name (handles schema-qualified names)
8237
8852
  */
8238
8853
  tableToSymbol(table) {
8239
- const tableName = typeof table === "string" ? table : table.type === "DerivedTable" ? table.alias : table.name;
8854
+ const tableName = typeof table === "string" ? table : table.type === "DerivedTable" ? table.alias : table.type === "FunctionTable" ? table.alias ?? table.name : table.name;
8240
8855
  if (tableName.includes(".")) {
8241
8856
  return tableName.split(".").map((part) => this.capitalize(part)).join("");
8242
8857
  }
@@ -8392,6 +9007,7 @@ var TypeScriptGenerator = class {
8392
9007
  case "CaseExpression":
8393
9008
  case "WindowFunction":
8394
9009
  case "Cast":
9010
+ case "Collate":
8395
9011
  return this.printOperand(term);
8396
9012
  default:
8397
9013
  return this.printExpression(term);
@@ -8454,6 +9070,9 @@ var TypeScriptGenerator = class {
8454
9070
  visitCast(node) {
8455
9071
  return this.printCastOperand(node);
8456
9072
  }
9073
+ visitCollate(node) {
9074
+ return this.printCollateOperand(node);
9075
+ }
8457
9076
  visitAliasRef(node) {
8458
9077
  return `aliasRef('${node.name}')`;
8459
9078
  }
@@ -8465,12 +9084,12 @@ var TypeScriptGenerator = class {
8465
9084
  printBinaryExpression(binary) {
8466
9085
  const left2 = this.printOperand(binary.left);
8467
9086
  const right2 = this.printOperand(binary.right);
8468
- const fn5 = this.mapOp(binary.operator);
9087
+ const fn8 = this.mapOp(binary.operator);
8469
9088
  const args = [left2, right2];
8470
9089
  if (binary.escape) {
8471
9090
  args.push(this.printOperand(binary.escape));
8472
9091
  }
8473
- return `${fn5}(${args.join(", ")})`;
9092
+ return `${fn8}(${args.join(", ")})`;
8474
9093
  }
8475
9094
  /**
8476
9095
  * Prints a logical expression to TypeScript code
@@ -8499,13 +9118,13 @@ var TypeScriptGenerator = class {
8499
9118
  */
8500
9119
  printInExpression(inExpr) {
8501
9120
  const left2 = this.printOperand(inExpr.left);
8502
- const fn5 = this.mapOp(inExpr.operator);
9121
+ const fn8 = this.mapOp(inExpr.operator);
8503
9122
  if (Array.isArray(inExpr.right)) {
8504
9123
  const values = inExpr.right.map((v) => this.printOperand(v)).join(", ");
8505
- return `${fn5}(${left2}, [${values}])`;
9124
+ return `${fn8}(${left2}, [${values}])`;
8506
9125
  }
8507
9126
  const subquery = this.inlineChain(this.buildSelectLines(inExpr.right.query));
8508
- return `${fn5}(${left2}, (${subquery}))`;
9127
+ return `${fn8}(${left2}, (${subquery}))`;
8509
9128
  }
8510
9129
  /**
8511
9130
  * Prints a null expression to TypeScript code
@@ -8514,8 +9133,8 @@ var TypeScriptGenerator = class {
8514
9133
  */
8515
9134
  printNullExpression(nullExpr) {
8516
9135
  const left2 = this.printOperand(nullExpr.left);
8517
- const fn5 = this.mapOp(nullExpr.operator);
8518
- return `${fn5}(${left2})`;
9136
+ const fn8 = this.mapOp(nullExpr.operator);
9137
+ return `${fn8}(${left2})`;
8519
9138
  }
8520
9139
  /**
8521
9140
  * Prints a BETWEEN expression to TypeScript code
@@ -8559,9 +9178,9 @@ var TypeScriptGenerator = class {
8559
9178
  * @param fn - Function node
8560
9179
  * @returns TypeScript code representation
8561
9180
  */
8562
- printFunctionOperand(fn5) {
8563
- const args = fn5.args.map((a) => this.printOperand(a)).join(", ");
8564
- return `${fn5.name.toLowerCase()}(${args})`;
9181
+ printFunctionOperand(fn8) {
9182
+ const args = fn8.args.map((a) => this.printOperand(a)).join(", ");
9183
+ return `${fn8.name.toLowerCase()}(${args})`;
8565
9184
  }
8566
9185
  /**
8567
9186
  * Prints a JSON path operand to TypeScript code
@@ -8625,6 +9244,9 @@ var TypeScriptGenerator = class {
8625
9244
  const typeLiteral = node.castType.replace(/'/g, "\\'");
8626
9245
  return `cast(${this.printOperand(node.expression)}, '${typeLiteral}')`;
8627
9246
  }
9247
+ printCollateOperand(node) {
9248
+ return `collate(${this.printOperand(node.expression)}, '${node.collation}')`;
9249
+ }
8628
9250
  /**
8629
9251
  * Converts method chain lines to inline format
8630
9252
  * @param lines - Method chain lines
@@ -8655,10 +9277,20 @@ var IdentityMap = class {
8655
9277
  get bucketsMap() {
8656
9278
  return this.buckets;
8657
9279
  }
9280
+ /**
9281
+ * Retrieves an entity from the identity map if it exists.
9282
+ * @param table The table definition of the entity.
9283
+ * @param pk The primary key value.
9284
+ * @returns The entity instance if found, undefined otherwise.
9285
+ */
8658
9286
  getEntity(table, pk) {
8659
9287
  const bucket = this.buckets.get(table.name);
8660
9288
  return bucket?.get(this.toIdentityKey(pk))?.entity;
8661
9289
  }
9290
+ /**
9291
+ * Registers a tracked entity in the identity map.
9292
+ * @param tracked The tracked entity metadata and instance.
9293
+ */
8662
9294
  register(tracked) {
8663
9295
  if (tracked.pk == null) return;
8664
9296
  const bucket = this.buckets.get(tracked.table.name) ?? /* @__PURE__ */ new Map();
@@ -8670,6 +9302,11 @@ var IdentityMap = class {
8670
9302
  const bucket = this.buckets.get(tracked.table.name);
8671
9303
  bucket?.delete(this.toIdentityKey(tracked.pk));
8672
9304
  }
9305
+ /**
9306
+ * Returns all tracked entities for a specific table.
9307
+ * @param table The table definition.
9308
+ * @returns Array of tracked entities.
9309
+ */
8673
9310
  getEntitiesForTable(table) {
8674
9311
  const bucket = this.buckets.get(table.name);
8675
9312
  return bucket ? Array.from(bucket.values()) : [];
@@ -9794,15 +10431,15 @@ var OrmSession = class {
9794
10431
  * @returns The result of the function
9795
10432
  * @throws If the transaction fails
9796
10433
  */
9797
- async transaction(fn5) {
10434
+ async transaction(fn8) {
9798
10435
  if (!this.executor.capabilities.transactions) {
9799
- const result = await fn5(this);
10436
+ const result = await fn8(this);
9800
10437
  await this.commit();
9801
10438
  return result;
9802
10439
  }
9803
10440
  await this.executor.beginTransaction();
9804
10441
  try {
9805
- const result = await fn5(this);
10442
+ const result = await fn8(this);
9806
10443
  await this.flushWithHooks();
9807
10444
  await this.executor.commitTransaction();
9808
10445
  await this.domainEvents.dispatch(this.unitOfWork.getTracked(), this);
@@ -9905,11 +10542,11 @@ var Orm = class {
9905
10542
  * @returns The result of the function
9906
10543
  * @throws If the transaction fails
9907
10544
  */
9908
- async transaction(fn5) {
10545
+ async transaction(fn8) {
9909
10546
  const executor = this.executorFactory.createTransactionalExecutor();
9910
10547
  const session = new OrmSession({ orm: this, executor });
9911
10548
  try {
9912
- return await session.transaction(() => fn5(session));
10549
+ return await session.transaction(() => fn8(session));
9913
10550
  } finally {
9914
10551
  await session.dispose();
9915
10552
  }
@@ -10734,8 +11371,10 @@ export {
10734
11371
  acos,
10735
11372
  add,
10736
11373
  addDomainEvent,
11374
+ age,
10737
11375
  aliasRef,
10738
11376
  and,
11377
+ arrayAppend,
10739
11378
  ascii,
10740
11379
  asin,
10741
11380
  atan,
@@ -10744,16 +11383,24 @@ export {
10744
11383
  belongsTo,
10745
11384
  belongsToMany,
10746
11385
  between,
11386
+ bitAnd,
11387
+ bitLength,
11388
+ bitOr,
11389
+ bitXor,
10747
11390
  bootstrapEntities,
10748
11391
  caseWhen,
10749
11392
  cast,
11393
+ cbrt,
10750
11394
  ceil,
10751
11395
  ceiling,
10752
11396
  char,
10753
11397
  charLength,
11398
+ chr,
10754
11399
  clearExpressionDispatchers,
10755
11400
  clearOperandDispatchers,
11401
+ coalesce,
10756
11402
  col,
11403
+ collate,
10757
11404
  columnOperand,
10758
11405
  concat,
10759
11406
  concatWs,
@@ -10805,18 +11452,23 @@ export {
10805
11452
  getDecoratorMetadata,
10806
11453
  getSchemaIntrospector,
10807
11454
  getTableDefFromEntity,
11455
+ greatest,
10808
11456
  groupConcat,
10809
11457
  gt,
10810
11458
  gte,
10811
11459
  hasMany,
10812
11460
  hasOne,
11461
+ hour,
10813
11462
  hydrateRows,
11463
+ ifNull,
10814
11464
  inList,
10815
11465
  inSubquery,
11466
+ initcap,
10816
11467
  instr,
10817
11468
  introspectSchema,
10818
11469
  isCaseExpressionNode,
10819
11470
  isCastExpressionNode,
11471
+ isCollateExpressionNode,
10820
11472
  isExpressionSelectionNode,
10821
11473
  isFunctionNode,
10822
11474
  isNotNull,
@@ -10824,11 +11476,16 @@ export {
10824
11476
  isOperandNode,
10825
11477
  isValueOperandInput,
10826
11478
  isWindowFunctionNode,
11479
+ jsonArrayAgg,
11480
+ jsonContains,
11481
+ jsonLength,
10827
11482
  jsonPath,
11483
+ jsonSet,
10828
11484
  jsonify,
10829
11485
  lag,
10830
11486
  lastValue,
10831
11487
  lead,
11488
+ least,
10832
11489
  left,
10833
11490
  length,
10834
11491
  like,
@@ -10837,9 +11494,12 @@ export {
10837
11494
  loadBelongsToRelation,
10838
11495
  loadHasManyRelation,
10839
11496
  loadHasOneRelation,
11497
+ localTime,
11498
+ localTimestamp,
10840
11499
  locate,
10841
11500
  log,
10842
11501
  log10,
11502
+ log2,
10843
11503
  logBase,
10844
11504
  lower,
10845
11505
  lpad,
@@ -10847,7 +11507,9 @@ export {
10847
11507
  lte,
10848
11508
  ltrim,
10849
11509
  max,
11510
+ md5,
10850
11511
  min,
11512
+ minute,
10851
11513
  mod,
10852
11514
  month,
10853
11515
  mul,
@@ -10860,12 +11522,15 @@ export {
10860
11522
  notLike,
10861
11523
  now,
10862
11524
  ntile,
11525
+ nullif,
11526
+ octetLength,
10863
11527
  or,
10864
11528
  outerRef,
10865
11529
  pi,
10866
11530
  position,
10867
11531
  pow,
10868
11532
  power,
11533
+ quarter,
10869
11534
  radians,
10870
11535
  rand,
10871
11536
  random,
@@ -10877,18 +11542,25 @@ export {
10877
11542
  renderTypeWithArgs,
10878
11543
  repeat,
10879
11544
  replace,
11545
+ reverse,
10880
11546
  right,
10881
11547
  round,
10882
11548
  rowNumber,
10883
11549
  rowsToQueryResult,
10884
11550
  rpad,
10885
11551
  rtrim,
11552
+ second,
10886
11553
  sel,
10887
11554
  selectFromEntity,
11555
+ sha1,
11556
+ sha2,
11557
+ shiftLeft,
11558
+ shiftRight,
10888
11559
  sign,
10889
11560
  sin,
10890
11561
  space,
10891
11562
  sqrt,
11563
+ stddev,
10892
11564
  sub,
10893
11565
  substr,
10894
11566
  sum,
@@ -10904,6 +11576,7 @@ export {
10904
11576
  upper,
10905
11577
  utcNow,
10906
11578
  valueToOperand,
11579
+ variance,
10907
11580
  visitExpression,
10908
11581
  visitOperand,
10909
11582
  weekOfYear,