metal-orm 1.1.24 → 1.1.25

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 (31) hide show
  1. package/dist/index.cjs +539 -412
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +225 -176
  4. package/dist/index.d.ts +225 -176
  5. package/dist/index.js +519 -412
  6. package/dist/index.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/core/dialect/base/returning-strategy.ts +40 -39
  9. package/src/core/dialect/base/sql-compiler-set.ts +33 -0
  10. package/src/core/dialect/base/sql-dialect.ts +79 -38
  11. package/src/core/dialect/base/upsert-strategy.ts +45 -0
  12. package/src/core/dialect/capabilities/procedure-compiler.ts +10 -8
  13. package/src/core/dialect/mssql/compiler-factory.ts +12 -0
  14. package/src/core/dialect/mssql/delete-compiler.ts +40 -0
  15. package/src/core/dialect/mssql/index.ts +24 -371
  16. package/src/core/dialect/mssql/insert-compiler.ts +112 -0
  17. package/src/core/dialect/mssql/output.ts +46 -0
  18. package/src/core/dialect/mssql/procedure-compiler.ts +81 -0
  19. package/src/core/dialect/mssql/select-compiler.ts +116 -0
  20. package/src/core/dialect/mssql/update-compiler.ts +37 -0
  21. package/src/core/dialect/mysql/index.ts +24 -117
  22. package/src/core/dialect/mysql/procedure-compiler.ts +67 -0
  23. package/src/core/dialect/mysql/upsert.ts +42 -0
  24. package/src/core/dialect/postgres/index.ts +34 -101
  25. package/src/core/dialect/postgres/procedure-compiler.ts +41 -0
  26. package/src/core/dialect/postgres/returning.ts +4 -0
  27. package/src/core/dialect/postgres/upsert.ts +43 -0
  28. package/src/core/dialect/sqlite/index.ts +15 -70
  29. package/src/core/dialect/sqlite/returning.ts +30 -0
  30. package/src/core/dialect/sqlite/upsert.ts +43 -0
  31. package/src/index.ts +22 -10
package/dist/index.cjs CHANGED
@@ -92,13 +92,26 @@ __export(index_exports, {
92
92
  MorphMany: () => MorphMany,
93
93
  MorphOne: () => MorphOne,
94
94
  MorphTo: () => MorphTo,
95
+ MssqlDeleteCompiler: () => MssqlDeleteCompiler,
96
+ MssqlInsertCompiler: () => MssqlInsertCompiler,
97
+ MssqlOutputStrategy: () => MssqlOutputStrategy,
98
+ MssqlProcedureCompiler: () => MssqlProcedureCompiler,
99
+ MssqlSelectCompiler: () => MssqlSelectCompiler,
100
+ MssqlUpdateCompiler: () => MssqlUpdateCompiler,
95
101
  MySqlDialect: () => MySqlDialect,
102
+ MySqlProcedureCompiler: () => MySqlProcedureCompiler,
103
+ MySqlUpsertStrategy: () => MySqlUpsertStrategy,
96
104
  NestedSetStrategy: () => NestedSetStrategy,
105
+ NoReturningStrategy: () => NoReturningStrategy,
106
+ NoUpsertStrategy: () => NoUpsertStrategy,
97
107
  Orm: () => Orm,
98
108
  OrmSession: () => OrmSession,
99
109
  Pattern: () => Pattern,
100
110
  Pool: () => Pool,
101
111
  PostgresDialect: () => PostgresDialect,
112
+ PostgresProcedureCompiler: () => PostgresProcedureCompiler,
113
+ PostgresReturningStrategy: () => PostgresReturningStrategy,
114
+ PostgresUpsertStrategy: () => PostgresUpsertStrategy,
102
115
  PrimaryKey: () => PrimaryKey,
103
116
  ProcedureCallBuilder: () => ProcedureCallBuilder,
104
117
  PrototypeMaterializationStrategy: () => PrototypeMaterializationStrategy,
@@ -107,12 +120,18 @@ __export(index_exports, {
107
120
  RelationKinds: () => RelationKinds,
108
121
  STANDARD_COLUMN_TYPES: () => STANDARD_COLUMN_TYPES,
109
122
  SelectQueryBuilder: () => SelectQueryBuilder,
123
+ SqlDialectBase: () => SqlDialectBase,
110
124
  SqlServerDialect: () => SqlServerDialect,
111
125
  SqliteDialect: () => SqliteDialect,
126
+ SqliteReturningStrategy: () => SqliteReturningStrategy,
127
+ SqliteUpsertStrategy: () => SqliteUpsertStrategy,
112
128
  StandardDeleteCompiler: () => StandardDeleteCompiler,
113
129
  StandardInsertCompiler: () => StandardInsertCompiler,
130
+ StandardLimitOffsetPagination: () => StandardLimitOffsetPagination,
131
+ StandardReturningStrategy: () => StandardReturningStrategy,
114
132
  StandardSelectCompiler: () => StandardSelectCompiler,
115
133
  StandardSqlSourceCompiler: () => StandardSqlSourceCompiler,
134
+ StandardTableFunctionStrategy: () => StandardTableFunctionStrategy,
116
135
  StandardUpdateCompiler: () => StandardUpdateCompiler,
117
136
  StringTypeStrategy: () => StringTypeStrategy,
118
137
  TagIndex: () => TagIndex,
@@ -200,6 +219,7 @@ __export(index_exports, {
200
219
  createEntityFromRow: () => createEntityFromRow,
201
220
  createEntityProxy: () => createEntityProxy,
202
221
  createExecutorFromQueryRunner: () => createExecutorFromQueryRunner,
222
+ createMssqlCompilerSet: () => createMssqlCompilerSet,
203
223
  createMssqlExecutor: () => createMssqlExecutor,
204
224
  createMysqlExecutor: () => createMysqlExecutor,
205
225
  createPooledExecutorFactory: () => createPooledExecutorFactory,
@@ -2155,23 +2175,12 @@ var StandardLimitOffsetPagination = class {
2155
2175
 
2156
2176
  // src/core/dialect/base/returning-strategy.ts
2157
2177
  var NoReturningStrategy = class {
2158
- /**
2159
- * Throws an error as RETURNING is not supported.
2160
- * @param returning - Columns to return (causes error if non-empty).
2161
- * @param _ctx - Compiler context (unused).
2162
- * @throws Error indicating RETURNING is not supported.
2163
- */
2164
- compileReturning(returning, _ctx) {
2178
+ compileReturning(returning, _ctx, _quoteIdentifier) {
2165
2179
  void _ctx;
2180
+ void _quoteIdentifier;
2166
2181
  if (!returning || returning.length === 0) return "";
2167
2182
  throw new Error("RETURNING is not supported by this dialect.");
2168
2183
  }
2169
- /**
2170
- * Formats column names for RETURNING clause.
2171
- * @param returning - Columns to format.
2172
- * @param quoteIdentifier - Function to quote identifiers according to dialect rules.
2173
- * @returns Simple comma-separated column names.
2174
- */
2175
2184
  formatReturningColumns(returning, quoteIdentifier) {
2176
2185
  return returning.map((column) => {
2177
2186
  const tablePart = column.table ? `${quoteIdentifier(column.table)}.` : "";
@@ -2180,6 +2189,24 @@ var NoReturningStrategy = class {
2180
2189
  }).join(", ");
2181
2190
  }
2182
2191
  };
2192
+ var StandardReturningStrategy = class extends NoReturningStrategy {
2193
+ compileReturning(returning, _ctx, quoteIdentifier) {
2194
+ void _ctx;
2195
+ if (!returning || returning.length === 0) return "";
2196
+ return ` RETURNING ${this.formatReturningColumns(returning, quoteIdentifier)}`;
2197
+ }
2198
+ };
2199
+
2200
+ // src/core/dialect/base/upsert-strategy.ts
2201
+ var NoUpsertStrategy = class {
2202
+ compile(ast, _ctx, services) {
2203
+ void _ctx;
2204
+ if (!ast.onConflict) return "";
2205
+ throw new Error(
2206
+ `UPSERT/ON CONFLICT is not supported by dialect "${services.getDialectName()}".`
2207
+ );
2208
+ }
2209
+ };
2183
2210
 
2184
2211
  // src/core/dialect/base/function-table-formatter.ts
2185
2212
  var FunctionTableFormatter = class {
@@ -2528,15 +2555,19 @@ var StandardDeleteCompiler = class {
2528
2555
 
2529
2556
  // src/core/dialect/base/sql-dialect.ts
2530
2557
  var SqlDialectBase = class extends DialectBase {
2531
- paginationStrategy = new StandardLimitOffsetPagination();
2532
- returningStrategy = new NoReturningStrategy();
2558
+ paginationStrategy;
2559
+ returningStrategy;
2560
+ upsertStrategy;
2561
+ dmlReturningSupported;
2533
2562
  sourceCompiler;
2534
- selectCompiler;
2535
- insertCompiler;
2536
- updateCompiler;
2537
- deleteCompiler;
2538
- constructor(functionStrategy, tableFunctionStrategy) {
2539
- super(functionStrategy, tableFunctionStrategy);
2563
+ standardUpdateCompiler;
2564
+ compilerSet;
2565
+ constructor(options = {}) {
2566
+ super(options.functionStrategy, options.tableFunctionStrategy);
2567
+ this.paginationStrategy = options.paginationStrategy ?? new StandardLimitOffsetPagination();
2568
+ this.returningStrategy = options.returningStrategy ?? new NoReturningStrategy();
2569
+ this.upsertStrategy = options.upsertStrategy ?? new NoUpsertStrategy();
2570
+ this.dmlReturningSupported = options.supportsDmlReturning ?? false;
2540
2571
  const services = {
2541
2572
  getDialectName: () => this.dialect,
2542
2573
  getPaginationStrategy: () => this.paginationStrategy,
@@ -2554,36 +2585,57 @@ var SqlDialectBase = class extends DialectBase {
2554
2585
  renderOrderByCollation: (order) => this.renderOrderByCollation(order)
2555
2586
  };
2556
2587
  this.sourceCompiler = new StandardSqlSourceCompiler(services);
2557
- this.selectCompiler = new StandardSelectCompiler(services, this.sourceCompiler);
2558
- this.insertCompiler = new StandardInsertCompiler(services, this.sourceCompiler);
2559
- this.updateCompiler = new StandardUpdateCompiler(services, this.sourceCompiler);
2560
- this.deleteCompiler = new StandardDeleteCompiler(services, this.sourceCompiler);
2588
+ const standardSelect = new StandardSelectCompiler(services, this.sourceCompiler);
2589
+ const standardInsert = new StandardInsertCompiler(services, this.sourceCompiler);
2590
+ this.standardUpdateCompiler = new StandardUpdateCompiler(services, this.sourceCompiler);
2591
+ const standardDelete = new StandardDeleteCompiler(services, this.sourceCompiler);
2592
+ const overrides = options.compilerFactory?.({
2593
+ services,
2594
+ sources: this.sourceCompiler
2595
+ }) ?? {};
2596
+ this.compilerSet = {
2597
+ select: overrides.select ?? standardSelect,
2598
+ insert: overrides.insert ?? standardInsert,
2599
+ update: overrides.update ?? this.standardUpdateCompiler,
2600
+ delete: overrides.delete ?? standardDelete
2601
+ };
2602
+ }
2603
+ supportsDmlReturningClause() {
2604
+ return this.dmlReturningSupported;
2561
2605
  }
2562
2606
  compileSelectAst(ast, ctx) {
2563
- return this.selectCompiler.compile(ast, ctx);
2607
+ return this.compilerSet.select.compile(ast, ctx);
2564
2608
  }
2565
2609
  compileInsertAst(ast, ctx) {
2566
- return this.insertCompiler.compile(ast, ctx);
2610
+ return this.compilerSet.insert.compile(ast, ctx);
2567
2611
  }
2568
2612
  compileUpdateAst(ast, ctx) {
2569
- return this.updateCompiler.compile(ast, ctx);
2613
+ return this.compilerSet.update.compile(ast, ctx);
2570
2614
  }
2571
2615
  compileDeleteAst(ast, ctx) {
2572
- return this.deleteCompiler.compile(ast, ctx);
2616
+ return this.compilerSet.delete.compile(ast, ctx);
2573
2617
  }
2574
- compileUpsertClause(ast, _ctx) {
2575
- void _ctx;
2576
- if (!ast.onConflict) return "";
2577
- throw new Error(`UPSERT/ON CONFLICT is not supported by dialect "${this.dialect}".`);
2618
+ compileUpsertClause(ast, ctx) {
2619
+ return this.upsertStrategy.compile(ast, ctx, {
2620
+ getDialectName: () => this.dialect,
2621
+ quoteIdentifier: (id) => this.quoteIdentifier(id),
2622
+ compileOperand: (node, compilerContext) => this.compileOperand(node, compilerContext),
2623
+ compileExpression: (node, compilerContext) => this.compileExpression(node, compilerContext),
2624
+ compileUpdateAssignments: (assignments, table, compilerContext) => this.standardUpdateCompiler.compileAssignments(assignments, table, compilerContext)
2625
+ });
2578
2626
  }
2579
2627
  compileReturning(returning, ctx) {
2580
- return this.returningStrategy.compileReturning(returning, ctx);
2628
+ return this.returningStrategy.compileReturning(
2629
+ returning,
2630
+ ctx,
2631
+ (id) => this.quoteIdentifier(id)
2632
+ );
2581
2633
  }
2582
2634
  ensureConflictColumns(clause, message) {
2583
- this.insertCompiler.ensureConflictColumns(clause, message);
2635
+ if (!clause.target.columns.length) throw new Error(message);
2584
2636
  }
2585
2637
  compileUpdateAssignments(assignments, table, ctx) {
2586
- return this.updateCompiler.compileAssignments(assignments, table, ctx);
2638
+ return this.standardUpdateCompiler.compileAssignments(assignments, table, ctx);
2587
2639
  }
2588
2640
  compileSetTarget(column, table) {
2589
2641
  return this.compileQualifiedColumn(column, table);
@@ -2809,105 +2861,112 @@ var PostgresTableFunctionStrategy = class extends StandardTableFunctionStrategy
2809
2861
  }
2810
2862
  };
2811
2863
 
2864
+ // src/core/dialect/postgres/procedure-compiler.ts
2865
+ var PostgresProcedureCompiler = class {
2866
+ constructor(services) {
2867
+ this.services = services;
2868
+ }
2869
+ compileProcedureCall(ast) {
2870
+ const ctx = this.services.createCompilerContext();
2871
+ const qualifiedName = ast.ref.schema ? `${this.services.quoteIdentifier(ast.ref.schema)}.${this.services.quoteIdentifier(ast.ref.name)}` : this.services.quoteIdentifier(ast.ref.name);
2872
+ const args = [];
2873
+ for (const param of ast.params) {
2874
+ if (param.direction === "out") continue;
2875
+ if (!param.value) {
2876
+ throw new Error(
2877
+ `Procedure parameter "${param.name}" requires a value for direction "${param.direction}".`
2878
+ );
2879
+ }
2880
+ args.push(this.services.compileOperand(param.value, ctx));
2881
+ }
2882
+ const outNames = ast.params.filter((param) => param.direction === "out" || param.direction === "inout").map((param) => param.name);
2883
+ return {
2884
+ sql: `CALL ${qualifiedName}(${args.join(", ")});`,
2885
+ params: [...ctx.params],
2886
+ outParams: {
2887
+ source: outNames.length ? "firstResultSet" : "none",
2888
+ names: outNames
2889
+ }
2890
+ };
2891
+ }
2892
+ };
2893
+
2894
+ // src/core/dialect/postgres/returning.ts
2895
+ var PostgresReturningStrategy = class extends StandardReturningStrategy {
2896
+ };
2897
+
2898
+ // src/core/dialect/postgres/upsert.ts
2899
+ var PostgresUpsertStrategy = class {
2900
+ compile(ast, ctx, services) {
2901
+ if (!ast.onConflict) return "";
2902
+ const clause = ast.onConflict;
2903
+ const target = clause.target.constraint ? ` ON CONFLICT ON CONSTRAINT ${services.quoteIdentifier(clause.target.constraint)}` : (() => {
2904
+ if (!clause.target.columns.length) {
2905
+ throw new Error("PostgreSQL ON CONFLICT requires conflict columns or a constraint name.");
2906
+ }
2907
+ const columns = clause.target.columns.map((column) => services.quoteIdentifier(column.name)).join(", ");
2908
+ return ` ON CONFLICT (${columns})`;
2909
+ })();
2910
+ if (clause.action.type === "DoNothing") {
2911
+ return `${target} DO NOTHING`;
2912
+ }
2913
+ if (!clause.action.set.length) {
2914
+ throw new Error("PostgreSQL ON CONFLICT DO UPDATE requires at least one assignment.");
2915
+ }
2916
+ const assignments = services.compileUpdateAssignments(clause.action.set, ast.into, ctx);
2917
+ const where = clause.action.where ? ` WHERE ${services.compileExpression(clause.action.where, ctx)}` : "";
2918
+ return `${target} DO UPDATE SET ${assignments}${where}`;
2919
+ }
2920
+ };
2921
+
2812
2922
  // src/core/dialect/postgres/index.ts
2813
2923
  var PostgresDialect = class extends SqlDialectBase {
2814
2924
  dialect = "postgres";
2815
- /**
2816
- * Creates a new PostgresDialect instance
2817
- */
2925
+ procedureCompiler;
2818
2926
  constructor() {
2819
- super(new PostgresFunctionStrategy(), new PostgresTableFunctionStrategy());
2927
+ super({
2928
+ functionStrategy: new PostgresFunctionStrategy(),
2929
+ tableFunctionStrategy: new PostgresTableFunctionStrategy(),
2930
+ returningStrategy: new PostgresReturningStrategy(),
2931
+ upsertStrategy: new PostgresUpsertStrategy(),
2932
+ supportsDmlReturning: true
2933
+ });
2934
+ this.procedureCompiler = new PostgresProcedureCompiler({
2935
+ quoteIdentifier: (id) => this.quoteIdentifier(id),
2936
+ createCompilerContext: () => this.createCompilerContext(),
2937
+ compileOperand: (node, ctx) => this.compileOperand(node, ctx)
2938
+ });
2820
2939
  this.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
2821
2940
  const left2 = this.compileOperand(node.left, ctx);
2822
2941
  const right2 = this.compileOperand(node.right, ctx);
2823
- const op = node.operator === "^" ? "#" : node.operator;
2824
- return `${left2} ${op} ${right2}`;
2942
+ const operator = node.operator === "^" ? "#" : node.operator;
2943
+ return `${left2} ${operator} ${right2}`;
2825
2944
  });
2826
2945
  this.registerOperandCompiler("BitwiseExpression", (node, ctx) => {
2827
2946
  const left2 = this.compileOperand(node.left, ctx);
2828
2947
  const right2 = this.compileOperand(node.right, ctx);
2829
- const op = node.operator === "^" ? "#" : node.operator;
2830
- return `(${left2} ${op} ${right2})`;
2948
+ const operator = node.operator === "^" ? "#" : node.operator;
2949
+ return `(${left2} ${operator} ${right2})`;
2831
2950
  });
2832
2951
  }
2833
- /**
2834
- * Quotes an identifier using PostgreSQL double-quote syntax
2835
- * @param id - Identifier to quote
2836
- * @returns Quoted identifier
2837
- */
2838
2952
  quoteIdentifier(id) {
2839
2953
  return `"${id}"`;
2840
2954
  }
2841
2955
  formatPlaceholder(index) {
2842
2956
  return `$${index}`;
2843
2957
  }
2844
- /**
2845
- * Compiles JSON path expression using PostgreSQL syntax
2846
- * @param node - JSON path node
2847
- * @returns PostgreSQL JSON path expression
2848
- */
2849
2958
  compileJsonPath(node) {
2850
- const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
2851
- return `${col2}->>'${node.path}'`;
2959
+ const column = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
2960
+ return `${column}->>'${node.path}'`;
2852
2961
  }
2853
- compileReturning(returning, ctx) {
2854
- void ctx;
2855
- if (!returning || returning.length === 0) return "";
2856
- const columns = this.formatReturningColumns(returning);
2857
- return ` RETURNING ${columns}`;
2858
- }
2859
- compileUpsertClause(ast, ctx) {
2860
- if (!ast.onConflict) return "";
2861
- const clause = ast.onConflict;
2862
- const target = clause.target.constraint ? ` ON CONFLICT ON CONSTRAINT ${this.quoteIdentifier(clause.target.constraint)}` : (() => {
2863
- this.ensureConflictColumns(
2864
- clause,
2865
- "PostgreSQL ON CONFLICT requires conflict columns or a constraint name."
2866
- );
2867
- const cols = clause.target.columns.map((col2) => this.quoteIdentifier(col2.name)).join(", ");
2868
- return ` ON CONFLICT (${cols})`;
2869
- })();
2870
- if (clause.action.type === "DoNothing") {
2871
- return `${target} DO NOTHING`;
2872
- }
2873
- if (!clause.action.set.length) {
2874
- throw new Error("PostgreSQL ON CONFLICT DO UPDATE requires at least one assignment.");
2875
- }
2876
- const assignments = this.compileUpdateAssignments(clause.action.set, ast.into, ctx);
2877
- const where = clause.action.where ? ` WHERE ${this.compileExpression(clause.action.where, ctx)}` : "";
2878
- return `${target} DO UPDATE SET ${assignments}${where}`;
2879
- }
2880
- supportsDmlReturningClause() {
2881
- return true;
2882
- }
2883
- compileProcedureCall(ast) {
2884
- const ctx = this.createCompilerContext();
2885
- const qualifiedName = ast.ref.schema ? `${this.quoteIdentifier(ast.ref.schema)}.${this.quoteIdentifier(ast.ref.name)}` : this.quoteIdentifier(ast.ref.name);
2886
- const args = [];
2887
- for (const param of ast.params) {
2888
- if (param.direction === "out") continue;
2889
- if (!param.value) {
2890
- throw new Error(`Procedure parameter "${param.name}" requires a value for direction "${param.direction}".`);
2891
- }
2892
- args.push(this.compileOperand(param.value, ctx));
2893
- }
2894
- const outNames = ast.params.filter((param) => param.direction === "out" || param.direction === "inout").map((param) => param.name);
2895
- const rawSql = `CALL ${qualifiedName}(${args.join(", ")})`;
2896
- return {
2897
- sql: `${rawSql};`,
2898
- params: [...ctx.params],
2899
- outParams: {
2900
- source: outNames.length ? "firstResultSet" : "none",
2901
- names: outNames
2902
- }
2903
- };
2904
- }
2905
- /**
2906
- * PostgreSQL requires unqualified column names in SET clause
2907
- */
2962
+ /** PostgreSQL requires unqualified column names in SET clauses. */
2908
2963
  compileSetTarget(column, _table) {
2964
+ void _table;
2909
2965
  return this.quoteIdentifier(column.name);
2910
2966
  }
2967
+ compileProcedureCall(ast) {
2968
+ return this.procedureCompiler.compileProcedureCall(ast);
2969
+ }
2911
2970
  };
2912
2971
 
2913
2972
  // src/core/dialect/mysql/functions.ts
@@ -3008,72 +3067,15 @@ var MysqlFunctionStrategy = class extends StandardFunctionStrategy {
3008
3067
  }
3009
3068
  };
3010
3069
 
3011
- // src/core/dialect/mysql/index.ts
3070
+ // src/core/dialect/mysql/procedure-compiler.ts
3012
3071
  var sanitizeVariableSuffix = (value) => value.replace(/[^a-zA-Z0-9_]/g, "_");
3013
- var MySqlDialect = class extends SqlDialectBase {
3014
- dialect = "mysql";
3015
- /**
3016
- * Creates a new MySqlDialect instance
3017
- */
3018
- constructor() {
3019
- super(new MysqlFunctionStrategy());
3020
- this.registerExpressionCompiler(
3021
- "IsDistinctExpression",
3022
- (node, ctx) => {
3023
- const left2 = this.compileOperand(node.left, ctx);
3024
- const right2 = this.compileOperand(node.right, ctx);
3025
- const spaceship = `${left2} <=> ${right2}`;
3026
- if (node.operator === "IS NOT DISTINCT FROM") {
3027
- return spaceship;
3028
- }
3029
- return `NOT (${spaceship})`;
3030
- }
3031
- );
3032
- }
3033
- /**
3034
- * Quotes an identifier using MySQL backtick syntax
3035
- * @param id - Identifier to quote
3036
- * @returns Quoted identifier
3037
- */
3038
- quoteIdentifier(id) {
3039
- return `\`${id}\``;
3040
- }
3041
- /**
3042
- * Compiles JSON path expression using MySQL syntax
3043
- * @param node - JSON path node
3044
- * @returns MySQL JSON path expression
3045
- */
3046
- compileJsonPath(node) {
3047
- const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3048
- return `${col2}->'${node.path}'`;
3049
- }
3050
- compileUpsertClause(ast, ctx) {
3051
- if (!ast.onConflict) return "";
3052
- const clause = ast.onConflict;
3053
- if (clause.action.type === "DoNothing") {
3054
- const noOpColumn = clause.target.columns[0] ?? ast.columns[0];
3055
- if (!noOpColumn) {
3056
- throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one target column.");
3057
- }
3058
- const col2 = this.quoteIdentifier(noOpColumn.name);
3059
- return ` ON DUPLICATE KEY UPDATE ${col2} = ${col2}`;
3060
- }
3061
- if (clause.action.where) {
3062
- throw new Error("MySQL ON DUPLICATE KEY UPDATE does not support a WHERE clause.");
3063
- }
3064
- if (!clause.action.set.length) {
3065
- throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one assignment.");
3066
- }
3067
- const assignments = clause.action.set.map((assignment) => {
3068
- const target = this.quoteIdentifier(assignment.column.name);
3069
- const value = this.compileOperand(assignment.value, ctx);
3070
- return `${target} = ${value}`;
3071
- }).join(", ");
3072
- return ` ON DUPLICATE KEY UPDATE ${assignments}`;
3072
+ var MySqlProcedureCompiler = class {
3073
+ constructor(services) {
3074
+ this.services = services;
3073
3075
  }
3074
3076
  compileProcedureCall(ast) {
3075
- const ctx = this.createCompilerContext();
3076
- const qualifiedName = ast.ref.schema ? `${this.quoteIdentifier(ast.ref.schema)}.${this.quoteIdentifier(ast.ref.name)}` : this.quoteIdentifier(ast.ref.name);
3077
+ const ctx = this.services.createCompilerContext();
3078
+ const qualifiedName = ast.ref.schema ? `${this.services.quoteIdentifier(ast.ref.schema)}.${this.services.quoteIdentifier(ast.ref.name)}` : this.services.quoteIdentifier(ast.ref.name);
3077
3079
  const prelude = [];
3078
3080
  const callArgs = [];
3079
3081
  const outVars = [];
@@ -3084,25 +3086,23 @@ var MySqlDialect = class extends SqlDialectBase {
3084
3086
  if (!param.value) {
3085
3087
  throw new Error(`Procedure parameter "${param.name}" requires a value for direction "in".`);
3086
3088
  }
3087
- callArgs.push(this.compileOperand(param.value, ctx));
3089
+ callArgs.push(this.services.compileOperand(param.value, ctx));
3088
3090
  return;
3089
3091
  }
3090
3092
  if (param.direction === "inout") {
3091
3093
  if (!param.value) {
3092
3094
  throw new Error(`Procedure parameter "${param.name}" requires a value for direction "inout".`);
3093
3095
  }
3094
- prelude.push(`SET ${variable} = ${this.compileOperand(param.value, ctx)};`);
3096
+ prelude.push(`SET ${variable} = ${this.services.compileOperand(param.value, ctx)};`);
3095
3097
  }
3096
3098
  callArgs.push(variable);
3097
3099
  outVars.push({ variable, name: param.name });
3098
3100
  });
3099
3101
  const statements = [];
3100
- if (prelude.length) {
3101
- statements.push(...prelude);
3102
- }
3102
+ if (prelude.length) statements.push(...prelude);
3103
3103
  statements.push(`CALL ${qualifiedName}(${callArgs.join(", ")});`);
3104
3104
  if (outVars.length) {
3105
- const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.quoteIdentifier(name)}`).join(", ");
3105
+ const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.services.quoteIdentifier(name)}`).join(", ");
3106
3106
  statements.push(`SELECT ${selectOut};`);
3107
3107
  }
3108
3108
  return {
@@ -3116,6 +3116,70 @@ var MySqlDialect = class extends SqlDialectBase {
3116
3116
  }
3117
3117
  };
3118
3118
 
3119
+ // src/core/dialect/mysql/upsert.ts
3120
+ var MySqlUpsertStrategy = class {
3121
+ compile(ast, ctx, services) {
3122
+ if (!ast.onConflict) return "";
3123
+ const clause = ast.onConflict;
3124
+ if (clause.action.type === "DoNothing") {
3125
+ const noOpColumn = clause.target.columns[0] ?? ast.columns[0];
3126
+ if (!noOpColumn) {
3127
+ throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one target column.");
3128
+ }
3129
+ const col2 = services.quoteIdentifier(noOpColumn.name);
3130
+ return ` ON DUPLICATE KEY UPDATE ${col2} = ${col2}`;
3131
+ }
3132
+ if (clause.action.where) {
3133
+ throw new Error("MySQL ON DUPLICATE KEY UPDATE does not support a WHERE clause.");
3134
+ }
3135
+ if (!clause.action.set.length) {
3136
+ throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one assignment.");
3137
+ }
3138
+ const assignments = clause.action.set.map((assignment) => {
3139
+ const target = services.quoteIdentifier(assignment.column.name);
3140
+ const value = services.compileOperand(assignment.value, ctx);
3141
+ return `${target} = ${value}`;
3142
+ }).join(", ");
3143
+ return ` ON DUPLICATE KEY UPDATE ${assignments}`;
3144
+ }
3145
+ };
3146
+
3147
+ // src/core/dialect/mysql/index.ts
3148
+ var MySqlDialect = class extends SqlDialectBase {
3149
+ dialect = "mysql";
3150
+ procedureCompiler;
3151
+ constructor() {
3152
+ super({
3153
+ functionStrategy: new MysqlFunctionStrategy(),
3154
+ upsertStrategy: new MySqlUpsertStrategy()
3155
+ });
3156
+ this.procedureCompiler = new MySqlProcedureCompiler({
3157
+ quoteIdentifier: (id) => this.quoteIdentifier(id),
3158
+ createCompilerContext: () => this.createCompilerContext(),
3159
+ compileOperand: (node, ctx) => this.compileOperand(node, ctx)
3160
+ });
3161
+ this.registerExpressionCompiler(
3162
+ "IsDistinctExpression",
3163
+ (node, ctx) => {
3164
+ const left2 = this.compileOperand(node.left, ctx);
3165
+ const right2 = this.compileOperand(node.right, ctx);
3166
+ const spaceship = `${left2} <=> ${right2}`;
3167
+ return node.operator === "IS NOT DISTINCT FROM" ? spaceship : `NOT (${spaceship})`;
3168
+ }
3169
+ );
3170
+ }
3171
+ quoteIdentifier(id) {
3172
+ return `\`${id}\``;
3173
+ }
3174
+ compileJsonPath(node) {
3175
+ const column = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3176
+ return `${column}->'${node.path}'`;
3177
+ }
3178
+ compileProcedureCall(ast) {
3179
+ return this.procedureCompiler.compileProcedureCall(ast);
3180
+ }
3181
+ };
3182
+
3119
3183
  // src/core/dialect/sqlite/functions.ts
3120
3184
  var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
3121
3185
  constructor() {
@@ -3253,14 +3317,56 @@ var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
3253
3317
  }
3254
3318
  };
3255
3319
 
3320
+ // src/core/dialect/sqlite/returning.ts
3321
+ var SqliteReturningStrategy = class {
3322
+ compileReturning(returning, _ctx, quoteIdentifier) {
3323
+ void _ctx;
3324
+ if (!returning || returning.length === 0) return "";
3325
+ return ` RETURNING ${this.formatReturningColumns(returning, quoteIdentifier)}`;
3326
+ }
3327
+ formatReturningColumns(returning, quoteIdentifier) {
3328
+ return returning.map((column) => {
3329
+ const alias = column.alias ? ` AS ${quoteIdentifier(column.alias)}` : "";
3330
+ return `${quoteIdentifier(column.name)}${alias}`;
3331
+ }).join(", ");
3332
+ }
3333
+ };
3334
+
3335
+ // src/core/dialect/sqlite/upsert.ts
3336
+ var SqliteUpsertStrategy = class {
3337
+ compile(ast, ctx, services) {
3338
+ if (!ast.onConflict) return "";
3339
+ const clause = ast.onConflict;
3340
+ if (clause.target.constraint) {
3341
+ throw new Error("SQLite ON CONFLICT does not support named constraints.");
3342
+ }
3343
+ if (!clause.target.columns.length) {
3344
+ throw new Error("SQLite ON CONFLICT requires conflict columns.");
3345
+ }
3346
+ const columns = clause.target.columns.map((column) => services.quoteIdentifier(column.name)).join(", ");
3347
+ const target = ` ON CONFLICT (${columns})`;
3348
+ if (clause.action.type === "DoNothing") {
3349
+ return `${target} DO NOTHING`;
3350
+ }
3351
+ if (!clause.action.set.length) {
3352
+ throw new Error("SQLite ON CONFLICT DO UPDATE requires at least one assignment.");
3353
+ }
3354
+ const assignments = services.compileUpdateAssignments(clause.action.set, ast.into, ctx);
3355
+ const where = clause.action.where ? ` WHERE ${services.compileExpression(clause.action.where, ctx)}` : "";
3356
+ return `${target} DO UPDATE SET ${assignments}${where}`;
3357
+ }
3358
+ };
3359
+
3256
3360
  // src/core/dialect/sqlite/index.ts
3257
3361
  var SqliteDialect = class extends SqlDialectBase {
3258
3362
  dialect = "sqlite";
3259
- /**
3260
- * Creates a new SqliteDialect instance
3261
- */
3262
3363
  constructor() {
3263
- super(new SqliteFunctionStrategy());
3364
+ super({
3365
+ functionStrategy: new SqliteFunctionStrategy(),
3366
+ returningStrategy: new SqliteReturningStrategy(),
3367
+ upsertStrategy: new SqliteUpsertStrategy(),
3368
+ supportsDmlReturning: true
3369
+ });
3264
3370
  this.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
3265
3371
  const left2 = this.compileOperand(node.left, ctx);
3266
3372
  const right2 = this.compileOperand(node.right, ctx);
@@ -3278,61 +3384,17 @@ var SqliteDialect = class extends SqlDialectBase {
3278
3384
  return `(${left2} ${node.operator} ${right2})`;
3279
3385
  });
3280
3386
  }
3281
- /**
3282
- * Quotes an identifier using SQLite double-quote syntax
3283
- * @param id - Identifier to quote
3284
- * @returns Quoted identifier
3285
- */
3286
3387
  quoteIdentifier(id) {
3287
3388
  return `"${id}"`;
3288
3389
  }
3289
- /**
3290
- * Compiles JSON path expression using SQLite syntax
3291
- * @param node - JSON path node
3292
- * @returns SQLite JSON path expression
3293
- */
3294
3390
  compileJsonPath(node) {
3295
- const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3296
- return `json_extract(${col2}, '${node.path}')`;
3391
+ const column = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3392
+ return `json_extract(${column}, '${node.path}')`;
3297
3393
  }
3298
3394
  compileQualifiedColumn(column, _table) {
3299
3395
  void _table;
3300
3396
  return this.quoteIdentifier(column.name);
3301
3397
  }
3302
- compileReturning(returning, ctx) {
3303
- void ctx;
3304
- if (!returning || returning.length === 0) return "";
3305
- const columns = this.formatReturningColumns(returning);
3306
- return ` RETURNING ${columns}`;
3307
- }
3308
- formatReturningColumns(returning) {
3309
- return returning.map((column) => {
3310
- const alias = column.alias ? ` AS ${this.quoteIdentifier(column.alias)}` : "";
3311
- return `${this.quoteIdentifier(column.name)}${alias}`;
3312
- }).join(", ");
3313
- }
3314
- compileUpsertClause(ast, ctx) {
3315
- if (!ast.onConflict) return "";
3316
- const clause = ast.onConflict;
3317
- if (clause.target.constraint) {
3318
- throw new Error("SQLite ON CONFLICT does not support named constraints.");
3319
- }
3320
- this.ensureConflictColumns(clause, "SQLite ON CONFLICT requires conflict columns.");
3321
- const cols = clause.target.columns.map((col2) => this.quoteIdentifier(col2.name)).join(", ");
3322
- const target = ` ON CONFLICT (${cols})`;
3323
- if (clause.action.type === "DoNothing") {
3324
- return `${target} DO NOTHING`;
3325
- }
3326
- if (!clause.action.set.length) {
3327
- throw new Error("SQLite ON CONFLICT DO UPDATE requires at least one assignment.");
3328
- }
3329
- const assignments = this.compileUpdateAssignments(clause.action.set, ast.into, ctx);
3330
- const where = clause.action.where ? ` WHERE ${this.compileExpression(clause.action.where, ctx)}` : "";
3331
- return `${target} DO UPDATE SET ${assignments}${where}`;
3332
- }
3333
- supportsDmlReturningClause() {
3334
- return true;
3335
- }
3336
3398
  };
3337
3399
 
3338
3400
  // src/core/dialect/mssql/functions.ts
@@ -3459,202 +3521,107 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
3459
3521
  }
3460
3522
  };
3461
3523
 
3462
- // src/core/dialect/mssql/index.ts
3463
- var sanitizeVariableSuffix2 = (value) => value.replace(/[^a-zA-Z0-9_]/g, "_");
3464
- var toProcedureParamReference = (value) => value.startsWith("@") ? value : `@${value}`;
3465
- var SqlServerDialect = class extends SqlDialectBase {
3466
- dialect = "mssql";
3467
- /**
3468
- * Creates a new SqlServerDialect instance
3469
- */
3470
- constructor() {
3471
- super(new MssqlFunctionStrategy());
3472
- }
3473
- /**
3474
- * Quotes an identifier using SQL Server bracket syntax
3475
- * @param id - Identifier to quote
3476
- * @returns Quoted identifier
3477
- */
3478
- quoteIdentifier(id) {
3479
- return `[${id}]`;
3524
+ // src/core/dialect/mssql/output.ts
3525
+ var MssqlOutputStrategy = class {
3526
+ compileReturning(returning, _ctx, quoteIdentifier) {
3527
+ void _ctx;
3528
+ return this.compileOutput(returning, "inserted", quoteIdentifier);
3480
3529
  }
3481
- /**
3482
- * Compiles JSON path expression using SQL Server syntax
3483
- * @param node - JSON path node
3484
- * @returns SQL Server JSON path expression
3485
- */
3486
- compileJsonPath(node) {
3487
- const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3488
- return `JSON_VALUE(${col2}, '${node.path}')`;
3530
+ compileOutput(returning, prefix, quoteIdentifier) {
3531
+ if (!returning || returning.length === 0) return "";
3532
+ const columns = returning.map((column) => {
3533
+ const alias = column.alias ? ` AS ${quoteIdentifier(column.alias)}` : "";
3534
+ return `${prefix}.${quoteIdentifier(column.name)}${alias}`;
3535
+ }).join(", ");
3536
+ return ` OUTPUT ${columns}`;
3489
3537
  }
3490
- /**
3491
- * Formats parameter placeholders using SQL Server named parameter syntax
3492
- * @param index - Parameter index
3493
- * @returns Named parameter placeholder
3494
- */
3495
- formatPlaceholder(index) {
3496
- return `@p${index}`;
3538
+ formatReturningColumns(returning, quoteIdentifier) {
3539
+ return returning.map((column) => {
3540
+ const alias = column.alias ? ` AS ${quoteIdentifier(column.alias)}` : "";
3541
+ return `${quoteIdentifier(column.name)}${alias}`;
3542
+ }).join(", ");
3497
3543
  }
3498
- /**
3499
- * Compiles SELECT query AST to SQL Server SQL
3500
- * @param ast - Query AST
3501
- * @param ctx - Compiler context
3502
- * @returns SQL Server SQL string
3503
- */
3504
- compileSelectAst(ast, ctx) {
3505
- const hasSetOps = !!(ast.setOps && ast.setOps.length);
3506
- const ctes = this.compileCtes(ast, ctx);
3507
- const baseAst = hasSetOps ? { ...ast, setOps: void 0, orderBy: void 0, limit: void 0, offset: void 0 } : ast;
3508
- const baseSelect = this.compileSelectCoreForMssql(baseAst, ctx);
3509
- if (!hasSetOps) {
3510
- return `${ctes}${baseSelect}`;
3511
- }
3512
- const compound = ast.setOps.map((op) => `${op.operator} ${this.wrapSetOperand(this.compileSelectAst(op.query, ctx))}`).join(" ");
3513
- const orderBy = this.compileOrderBy(ast, ctx);
3514
- const pagination = this.compilePagination(ast, orderBy);
3515
- const combined = `${this.wrapSetOperand(baseSelect)} ${compound}`;
3516
- const tail = pagination || orderBy;
3517
- return `${ctes}${combined}${tail}`;
3544
+ };
3545
+
3546
+ // src/core/dialect/mssql/delete-compiler.ts
3547
+ var MssqlDeleteCompiler = class {
3548
+ constructor(services, sources) {
3549
+ this.services = services;
3550
+ this.sources = sources;
3518
3551
  }
3519
- compileDeleteAst(ast, ctx) {
3552
+ output = new MssqlOutputStrategy();
3553
+ compile(ast, ctx) {
3520
3554
  if (ast.using) {
3521
3555
  throw new Error("DELETE ... USING is not supported in the MSSQL dialect; use join() instead.");
3522
3556
  }
3523
- if (ast.from.type !== "Table") {
3524
- throw new Error("DELETE only supports base tables in the MSSQL dialect.");
3525
- }
3526
3557
  const alias = ast.from.alias ?? ast.from.name;
3527
- const target = this.compileTableReference(ast.from);
3558
+ const target = this.sources.compileTableReference(ast.from);
3528
3559
  const joins = JoinCompiler.compileJoins(
3529
3560
  ast.joins,
3530
3561
  ctx,
3531
- this.compileFrom.bind(this),
3532
- this.compileExpression.bind(this)
3562
+ (source, compilerContext) => this.sources.compileFrom(source, compilerContext),
3563
+ (expression, compilerContext) => this.services.compileExpression(expression, compilerContext)
3533
3564
  );
3534
- const whereClause = this.compileWhere(ast.where, ctx);
3535
- const returning = this.compileOutputClause(ast.returning, "deleted");
3536
- return `DELETE ${this.quoteIdentifier(alias)}${returning} FROM ${target}${joins}${whereClause}`;
3537
- }
3538
- compileUpdateAst(ast, ctx) {
3539
- const target = this.compileTableReference(ast.table);
3540
- const assignments = this.compileUpdateAssignments(ast.set, ast.table, ctx);
3541
- const output = this.compileReturning(ast.returning, ctx);
3542
- const fromClause = ast.from ? ` FROM ${this.compileFrom(ast.from, ctx)}` : "";
3543
- const joins = ast.joins ? ast.joins.map((j) => {
3544
- const table = this.compileFrom(j.table, ctx);
3545
- const cond = this.compileExpression(j.condition, ctx);
3546
- return ` ${j.kind} JOIN ${table} ON ${cond}`;
3547
- }).join("") : "";
3548
- const whereClause = this.compileWhere(ast.where, ctx);
3549
- return `UPDATE ${target} SET ${assignments}${output}${fromClause}${joins}${whereClause}`;
3550
- }
3551
- compileSelectCoreForMssql(ast, ctx) {
3552
- const columns = ast.columns.map((c) => {
3553
- const expr = c.type === "Column" ? `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}` : this.compileOperand(c, ctx);
3554
- if (c.alias) {
3555
- if (c.alias.includes("(")) return c.alias;
3556
- return `${expr} AS ${this.quoteIdentifier(c.alias)}`;
3557
- }
3558
- return expr;
3559
- }).join(", ");
3560
- const distinct = ast.distinct ? "DISTINCT " : "";
3561
- const from = this.compileFrom(ast.from, ctx);
3562
- const joins = ast.joins.map((j) => {
3563
- const table = this.compileFrom(j.table, ctx);
3564
- const cond = this.compileExpression(j.condition, ctx);
3565
- return `${j.kind} JOIN ${table} ON ${cond}`;
3566
- }).join(" ");
3567
- const whereClause = this.compileWhere(ast.where, ctx);
3568
- const groupBy = ast.groupBy && ast.groupBy.length > 0 ? " GROUP BY " + ast.groupBy.map((term) => this.compileOrderingTerm(term, ctx)).join(", ") : "";
3569
- const having = ast.having ? ` HAVING ${this.compileExpression(ast.having, ctx)}` : "";
3570
- const orderBy = this.compileOrderBy(ast, ctx);
3571
- const pagination = this.compilePagination(ast, orderBy);
3572
- if (pagination) {
3573
- return `SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${pagination}`;
3574
- }
3575
- return `SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${orderBy}`;
3576
- }
3577
- compileOrderBy(ast, ctx) {
3578
- return OrderByCompiler.compileOrderBy(
3579
- ast,
3580
- (term) => this.compileOrderingTerm(term, ctx),
3581
- this.renderOrderByNulls.bind(this),
3582
- this.renderOrderByCollation.bind(this)
3565
+ const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
3566
+ const returning = this.output.compileOutput(
3567
+ ast.returning,
3568
+ "deleted",
3569
+ (id) => this.services.quoteIdentifier(id)
3583
3570
  );
3571
+ return `DELETE ${this.services.quoteIdentifier(alias)}${returning} FROM ${target}${joins}${where}`;
3584
3572
  }
3585
- compilePagination(ast, orderBy) {
3586
- const hasLimit = ast.limit !== void 0;
3587
- const hasOffset = ast.offset !== void 0;
3588
- if (!hasLimit && !hasOffset) return "";
3589
- const off = ast.offset ?? 0;
3590
- let orderClause = orderBy;
3591
- if (!orderClause) {
3592
- orderClause = ast.distinct && ast.distinct.length > 0 ? " ORDER BY 1" : " ORDER BY (SELECT NULL)";
3593
- }
3594
- let pagination = `${orderClause} OFFSET ${off} ROWS`;
3595
- if (hasLimit) {
3596
- pagination += ` FETCH NEXT ${ast.limit} ROWS ONLY`;
3597
- }
3598
- return pagination;
3599
- }
3600
- supportsDmlReturningClause() {
3601
- return true;
3602
- }
3603
- compileReturning(returning, _ctx) {
3604
- void _ctx;
3605
- return this.compileOutputClause(returning, "inserted");
3606
- }
3607
- compileOutputClause(returning, prefix) {
3608
- if (!returning || returning.length === 0) return "";
3609
- const columns = returning.map((column) => {
3610
- const colName = this.quoteIdentifier(column.name);
3611
- const alias = column.alias ? ` AS ${this.quoteIdentifier(column.alias)}` : "";
3612
- return `${prefix}.${colName}${alias}`;
3613
- }).join(", ");
3614
- return ` OUTPUT ${columns}`;
3573
+ };
3574
+
3575
+ // src/core/dialect/mssql/insert-compiler.ts
3576
+ var MssqlInsertCompiler = class {
3577
+ constructor(services, sources) {
3578
+ this.services = services;
3579
+ this.sources = sources;
3615
3580
  }
3616
- compileInsertAst(ast, ctx) {
3581
+ compile(ast, ctx) {
3617
3582
  if (!ast.columns.length) {
3618
3583
  throw new Error("INSERT queries must specify columns.");
3619
3584
  }
3620
- if (ast.onConflict) {
3621
- return this.compileMergeInsert(ast, ctx);
3622
- }
3623
- const table = this.compileTableName(ast.into);
3624
- const columnList = ast.columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
3625
- const output = this.compileReturning(ast.returning, ctx);
3626
- const source = this.compileInsertValues(ast, ctx);
3627
- return `INSERT INTO ${table} (${columnList})${output} ${source}`;
3585
+ if (ast.onConflict) return this.compileMerge(ast, ctx);
3586
+ const table = this.sources.compileTableName(ast.into);
3587
+ const columns = ast.columns.map((column) => this.services.quoteIdentifier(column.name)).join(", ");
3588
+ const output = this.services.compileReturning(ast.returning, ctx);
3589
+ const source = this.compileInsertSource(ast, ctx);
3590
+ return `INSERT INTO ${table} (${columns})${output} ${source}`;
3628
3591
  }
3629
- compileMergeInsert(ast, ctx) {
3592
+ compileMerge(ast, ctx) {
3630
3593
  const clause = ast.onConflict;
3631
3594
  if (clause.target.constraint) {
3632
3595
  throw new Error("MSSQL MERGE does not support conflict target by constraint name.");
3633
3596
  }
3634
- this.ensureConflictColumns(clause, "MSSQL MERGE requires conflict columns for the ON clause.");
3635
- const table = this.compileTableName(ast.into);
3636
- const targetRef = this.quoteIdentifier(ast.into.alias ?? ast.into.name);
3637
- const sourceAlias = this.quoteIdentifier("src");
3638
- const sourceColumns = ast.columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
3597
+ if (!clause.target.columns.length) {
3598
+ throw new Error("MSSQL MERGE requires conflict columns for the ON clause.");
3599
+ }
3600
+ const table = this.sources.compileTableName(ast.into);
3601
+ const targetRef = this.services.quoteIdentifier(ast.into.alias ?? ast.into.name);
3602
+ const sourceAlias = this.services.quoteIdentifier("src");
3603
+ const sourceColumns = ast.columns.map((column) => this.services.quoteIdentifier(column.name)).join(", ");
3639
3604
  const usingSource = this.compileMergeUsingSource(ast, ctx);
3640
- const onClause = clause.target.columns.map((column) => `${targetRef}.${this.quoteIdentifier(column.name)} = ${sourceAlias}.${this.quoteIdentifier(column.name)}`).join(" AND ");
3605
+ const onClause = clause.target.columns.map(
3606
+ (column) => `${targetRef}.${this.services.quoteIdentifier(column.name)} = ${sourceAlias}.${this.services.quoteIdentifier(column.name)}`
3607
+ ).join(" AND ");
3641
3608
  const branches = [];
3642
3609
  if (clause.action.type === "DoUpdate") {
3643
3610
  if (!clause.action.set.length) {
3644
3611
  throw new Error("MSSQL MERGE WHEN MATCHED UPDATE requires at least one assignment.");
3645
3612
  }
3646
3613
  const assignments = clause.action.set.map((assignment) => {
3647
- const target = `${targetRef}.${this.quoteIdentifier(assignment.column.name)}`;
3648
- const value = this.compileOperand(assignment.value, ctx);
3614
+ const target = `${targetRef}.${this.services.quoteIdentifier(assignment.column.name)}`;
3615
+ const value = this.services.compileOperand(assignment.value, ctx);
3649
3616
  return `${target} = ${value}`;
3650
3617
  }).join(", ");
3651
- const guard = clause.action.where ? ` AND ${this.compileExpression(clause.action.where, ctx)}` : "";
3618
+ const guard = clause.action.where ? ` AND ${this.services.compileExpression(clause.action.where, ctx)}` : "";
3652
3619
  branches.push(`WHEN MATCHED${guard} THEN UPDATE SET ${assignments}`);
3653
3620
  }
3654
- const insertColumns = ast.columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
3655
- const insertValues = ast.columns.map((column) => `${sourceAlias}.${this.quoteIdentifier(column.name)}`).join(", ");
3621
+ const insertColumns = ast.columns.map((column) => this.services.quoteIdentifier(column.name)).join(", ");
3622
+ const insertValues = ast.columns.map((column) => `${sourceAlias}.${this.services.quoteIdentifier(column.name)}`).join(", ");
3656
3623
  branches.push(`WHEN NOT MATCHED THEN INSERT (${insertColumns}) VALUES (${insertValues})`);
3657
- const output = this.compileReturning(ast.returning, ctx);
3624
+ const output = this.services.compileReturning(ast.returning, ctx);
3658
3625
  return `MERGE INTO ${table} USING ${usingSource} AS ${sourceAlias} (${sourceColumns}) ON ${onClause} ${branches.join(" ")}${output}`;
3659
3626
  }
3660
3627
  compileMergeUsingSource(ast, ctx) {
@@ -3662,38 +3629,146 @@ var SqlServerDialect = class extends SqlDialectBase {
3662
3629
  if (!ast.source.rows.length) {
3663
3630
  throw new Error("INSERT ... VALUES requires at least one row.");
3664
3631
  }
3665
- const rows = ast.source.rows.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
3632
+ const rows = ast.source.rows.map((row) => `(${row.map((value) => this.services.compileOperand(value, ctx)).join(", ")})`).join(", ");
3666
3633
  return `(VALUES ${rows})`;
3667
3634
  }
3668
- const normalized = this.normalizeSelectAst(ast.source.query);
3669
- const selectSql = this.compileSelectAst(normalized, ctx).trim().replace(/;$/, "");
3635
+ const normalized = this.services.normalizeSelectAst(ast.source.query);
3636
+ const selectSql = this.sources.stripTrailingSemicolon(
3637
+ this.services.compileSelectAst(normalized, ctx)
3638
+ );
3670
3639
  return `(${selectSql})`;
3671
3640
  }
3672
- compileInsertValues(ast, ctx) {
3673
- const source = ast.source;
3674
- if (source.type === "InsertValues") {
3675
- if (!source.rows.length) {
3641
+ compileInsertSource(ast, ctx) {
3642
+ if (ast.source.type === "InsertValues") {
3643
+ if (!ast.source.rows.length) {
3676
3644
  throw new Error("INSERT ... VALUES requires at least one row.");
3677
3645
  }
3678
- const values = source.rows.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
3646
+ const values = ast.source.rows.map((row) => `(${row.map((value) => this.services.compileOperand(value, ctx)).join(", ")})`).join(", ");
3679
3647
  return `VALUES ${values}`;
3680
3648
  }
3681
- const normalized = this.normalizeSelectAst(source.query);
3682
- return this.compileSelectAst(normalized, ctx).trim();
3649
+ const normalized = this.services.normalizeSelectAst(ast.source.query);
3650
+ return this.services.compileSelectAst(normalized, ctx).trim();
3651
+ }
3652
+ };
3653
+
3654
+ // src/core/dialect/mssql/select-compiler.ts
3655
+ var MssqlSelectCompiler = class {
3656
+ constructor(services, sources) {
3657
+ this.services = services;
3658
+ this.sources = sources;
3659
+ }
3660
+ compile(ast, ctx) {
3661
+ const hasSetOps = !!(ast.setOps && ast.setOps.length);
3662
+ const ctes = this.compileCtes(ast, ctx);
3663
+ const baseAst = hasSetOps ? { ...ast, setOps: void 0, orderBy: void 0, limit: void 0, offset: void 0 } : ast;
3664
+ const baseSelect = this.compileCore(baseAst, ctx);
3665
+ if (!hasSetOps) return `${ctes}${baseSelect}`;
3666
+ const compound = ast.setOps.map((op) => `${op.operator} ${this.sources.wrapSetOperand(this.services.compileSelectAst(op.query, ctx))}`).join(" ");
3667
+ const orderBy = this.compileOrderBy(ast, ctx);
3668
+ const pagination = this.compilePagination(ast, orderBy);
3669
+ const combined = `${this.sources.wrapSetOperand(baseSelect)} ${compound}`;
3670
+ return `${ctes}${combined}${pagination || orderBy}`;
3671
+ }
3672
+ compileCore(ast, ctx) {
3673
+ const columns = ast.columns.map((column) => {
3674
+ const expr = column.type === "Column" ? `${this.services.quoteIdentifier(column.table)}.${this.services.quoteIdentifier(column.name)}` : this.services.compileOperand(column, ctx);
3675
+ if (!column.alias) return expr;
3676
+ if (column.alias.includes("(")) return column.alias;
3677
+ return `${expr} AS ${this.services.quoteIdentifier(column.alias)}`;
3678
+ }).join(", ");
3679
+ const distinct = ast.distinct ? "DISTINCT " : "";
3680
+ const from = this.sources.compileFrom(ast.from, ctx);
3681
+ const joins = ast.joins.map((join) => {
3682
+ const table = this.sources.compileFrom(join.table, ctx);
3683
+ const condition = this.services.compileExpression(join.condition, ctx);
3684
+ return `${join.kind} JOIN ${table} ON ${condition}`;
3685
+ }).join(" ");
3686
+ const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
3687
+ const groupBy = ast.groupBy && ast.groupBy.length > 0 ? ` GROUP BY ${ast.groupBy.map((term) => this.services.compileOrderingTerm(term, ctx)).join(", ")}` : "";
3688
+ const having = ast.having ? ` HAVING ${this.services.compileExpression(ast.having, ctx)}` : "";
3689
+ const orderBy = this.compileOrderBy(ast, ctx);
3690
+ const pagination = this.compilePagination(ast, orderBy);
3691
+ if (pagination) {
3692
+ return `SELECT ${distinct}${columns} FROM ${from}${joins ? ` ${joins}` : ""}${where}${groupBy}${having}${pagination}`;
3693
+ }
3694
+ return `SELECT ${distinct}${columns} FROM ${from}${joins ? ` ${joins}` : ""}${where}${groupBy}${having}${orderBy}`;
3695
+ }
3696
+ compileOrderBy(ast, ctx) {
3697
+ return OrderByCompiler.compileOrderBy(
3698
+ ast,
3699
+ (term) => this.services.compileOrderingTerm(term, ctx),
3700
+ (order) => this.services.renderOrderByNulls(order),
3701
+ (order) => this.services.renderOrderByCollation(order)
3702
+ );
3703
+ }
3704
+ compilePagination(ast, orderBy) {
3705
+ const hasLimit = ast.limit !== void 0;
3706
+ const hasOffset = ast.offset !== void 0;
3707
+ if (!hasLimit && !hasOffset) return "";
3708
+ const offset = ast.offset ?? 0;
3709
+ let orderClause = orderBy;
3710
+ if (!orderClause) {
3711
+ orderClause = ast.distinct && ast.distinct.length > 0 ? " ORDER BY 1" : " ORDER BY (SELECT NULL)";
3712
+ }
3713
+ let pagination = `${orderClause} OFFSET ${offset} ROWS`;
3714
+ if (hasLimit) pagination += ` FETCH NEXT ${ast.limit} ROWS ONLY`;
3715
+ return pagination;
3683
3716
  }
3684
3717
  compileCtes(ast, ctx) {
3685
3718
  if (!ast.ctes || ast.ctes.length === 0) return "";
3686
- const defs = ast.ctes.map((cte) => {
3687
- const name = this.quoteIdentifier(cte.name);
3688
- const cols = cte.columns ? `(${cte.columns.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
3689
- const query = this.compileSelectAst(this.normalizeSelectAst(cte.query), ctx).trim().replace(/;$/, "");
3690
- return `${name}${cols} AS (${query})`;
3719
+ const definitions = ast.ctes.map((cte) => {
3720
+ const name = this.services.quoteIdentifier(cte.name);
3721
+ const columns = cte.columns ? `(${cte.columns.map((column) => this.services.quoteIdentifier(column)).join(", ")})` : "";
3722
+ const query = this.sources.stripTrailingSemicolon(
3723
+ this.services.compileSelectAst(this.services.normalizeSelectAst(cte.query), ctx)
3724
+ );
3725
+ return `${name}${columns} AS (${query})`;
3691
3726
  }).join(", ");
3692
- return `WITH ${defs} `;
3727
+ return `WITH ${definitions} `;
3728
+ }
3729
+ };
3730
+
3731
+ // src/core/dialect/mssql/update-compiler.ts
3732
+ var MssqlUpdateCompiler = class {
3733
+ constructor(services, sources) {
3734
+ this.services = services;
3735
+ this.sources = sources;
3736
+ this.standardUpdate = new StandardUpdateCompiler(services, sources);
3737
+ }
3738
+ standardUpdate;
3739
+ compile(ast, ctx) {
3740
+ const target = this.sources.compileTableReference(ast.table);
3741
+ const assignments = this.standardUpdate.compileAssignments(ast.set, ast.table, ctx);
3742
+ const output = this.services.compileReturning(ast.returning, ctx);
3743
+ const from = ast.from ? ` FROM ${this.sources.compileFrom(ast.from, ctx)}` : "";
3744
+ const joins = ast.joins ? ast.joins.map((join) => {
3745
+ const table = this.sources.compileFrom(join.table, ctx);
3746
+ const condition = this.services.compileExpression(join.condition, ctx);
3747
+ return ` ${join.kind} JOIN ${table} ON ${condition}`;
3748
+ }).join("") : "";
3749
+ const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
3750
+ return `UPDATE ${target} SET ${assignments}${output}${from}${joins}${where}`;
3751
+ }
3752
+ };
3753
+
3754
+ // src/core/dialect/mssql/compiler-factory.ts
3755
+ var createMssqlCompilerSet = ({ services, sources }) => ({
3756
+ select: new MssqlSelectCompiler(services, sources),
3757
+ insert: new MssqlInsertCompiler(services, sources),
3758
+ update: new MssqlUpdateCompiler(services, sources),
3759
+ delete: new MssqlDeleteCompiler(services, sources)
3760
+ });
3761
+
3762
+ // src/core/dialect/mssql/procedure-compiler.ts
3763
+ var sanitizeVariableSuffix2 = (value) => value.replace(/[^a-zA-Z0-9_]/g, "_");
3764
+ var toProcedureParamReference = (value) => value.startsWith("@") ? value : `@${value}`;
3765
+ var MssqlProcedureCompiler = class {
3766
+ constructor(services) {
3767
+ this.services = services;
3693
3768
  }
3694
3769
  compileProcedureCall(ast) {
3695
- const ctx = this.createCompilerContext();
3696
- const qualifiedName = ast.ref.schema ? `${this.quoteIdentifier(ast.ref.schema)}.${this.quoteIdentifier(ast.ref.name)}` : this.quoteIdentifier(ast.ref.name);
3770
+ const ctx = this.services.createCompilerContext();
3771
+ const qualifiedName = ast.ref.schema ? `${this.services.quoteIdentifier(ast.ref.schema)}.${this.services.quoteIdentifier(ast.ref.name)}` : this.services.quoteIdentifier(ast.ref.name);
3697
3772
  const declarations = [];
3698
3773
  const assignments = [];
3699
3774
  const execArgs = [];
@@ -3704,7 +3779,7 @@ var SqlServerDialect = class extends SqlDialectBase {
3704
3779
  if (!param.value) {
3705
3780
  throw new Error(`Procedure parameter "${param.name}" requires a value for direction "in".`);
3706
3781
  }
3707
- execArgs.push(`${targetParam} = ${this.compileOperand(param.value, ctx)}`);
3782
+ execArgs.push(`${targetParam} = ${this.services.compileOperand(param.value, ctx)}`);
3708
3783
  return;
3709
3784
  }
3710
3785
  if (!param.dbType) {
@@ -3719,7 +3794,7 @@ var SqlServerDialect = class extends SqlDialectBase {
3719
3794
  if (!param.value) {
3720
3795
  throw new Error(`Procedure parameter "${param.name}" requires a value for direction "inout".`);
3721
3796
  }
3722
- assignments.push(`SET ${variable} = ${this.compileOperand(param.value, ctx)};`);
3797
+ assignments.push(`SET ${variable} = ${this.services.compileOperand(param.value, ctx)};`);
3723
3798
  }
3724
3799
  execArgs.push(`${targetParam} = ${variable} OUTPUT`);
3725
3800
  outVars.push({ variable, name: param.name });
@@ -3730,7 +3805,7 @@ var SqlServerDialect = class extends SqlDialectBase {
3730
3805
  const argsSql = execArgs.length ? ` ${execArgs.join(", ")}` : "";
3731
3806
  statements.push(`EXEC ${qualifiedName}${argsSql};`);
3732
3807
  if (outVars.length) {
3733
- const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.quoteIdentifier(name)}`).join(", ");
3808
+ const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.services.quoteIdentifier(name)}`).join(", ");
3734
3809
  statements.push(`SELECT ${selectOut};`);
3735
3810
  }
3736
3811
  return {
@@ -3744,6 +3819,38 @@ var SqlServerDialect = class extends SqlDialectBase {
3744
3819
  }
3745
3820
  };
3746
3821
 
3822
+ // src/core/dialect/mssql/index.ts
3823
+ var SqlServerDialect = class extends SqlDialectBase {
3824
+ dialect = "mssql";
3825
+ procedureCompiler;
3826
+ constructor() {
3827
+ super({
3828
+ functionStrategy: new MssqlFunctionStrategy(),
3829
+ returningStrategy: new MssqlOutputStrategy(),
3830
+ compilerFactory: createMssqlCompilerSet,
3831
+ supportsDmlReturning: true
3832
+ });
3833
+ this.procedureCompiler = new MssqlProcedureCompiler({
3834
+ quoteIdentifier: (id) => this.quoteIdentifier(id),
3835
+ createCompilerContext: () => this.createCompilerContext(),
3836
+ compileOperand: (node, ctx) => this.compileOperand(node, ctx)
3837
+ });
3838
+ }
3839
+ quoteIdentifier(id) {
3840
+ return `[${id}]`;
3841
+ }
3842
+ compileJsonPath(node) {
3843
+ const column = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3844
+ return `JSON_VALUE(${column}, '${node.path}')`;
3845
+ }
3846
+ formatPlaceholder(index) {
3847
+ return `@p${index}`;
3848
+ }
3849
+ compileProcedureCall(ast) {
3850
+ return this.procedureCompiler.compileProcedureCall(ast);
3851
+ }
3852
+ };
3853
+
3747
3854
  // src/core/dialect/dialect-factory.ts
3748
3855
  var DialectFactory = class {
3749
3856
  static registry = /* @__PURE__ */ new Map();
@@ -22222,13 +22329,26 @@ async function bulkUpsert(session, table, rows, options = {}) {
22222
22329
  MorphMany,
22223
22330
  MorphOne,
22224
22331
  MorphTo,
22332
+ MssqlDeleteCompiler,
22333
+ MssqlInsertCompiler,
22334
+ MssqlOutputStrategy,
22335
+ MssqlProcedureCompiler,
22336
+ MssqlSelectCompiler,
22337
+ MssqlUpdateCompiler,
22225
22338
  MySqlDialect,
22339
+ MySqlProcedureCompiler,
22340
+ MySqlUpsertStrategy,
22226
22341
  NestedSetStrategy,
22342
+ NoReturningStrategy,
22343
+ NoUpsertStrategy,
22227
22344
  Orm,
22228
22345
  OrmSession,
22229
22346
  Pattern,
22230
22347
  Pool,
22231
22348
  PostgresDialect,
22349
+ PostgresProcedureCompiler,
22350
+ PostgresReturningStrategy,
22351
+ PostgresUpsertStrategy,
22232
22352
  PrimaryKey,
22233
22353
  ProcedureCallBuilder,
22234
22354
  PrototypeMaterializationStrategy,
@@ -22237,12 +22357,18 @@ async function bulkUpsert(session, table, rows, options = {}) {
22237
22357
  RelationKinds,
22238
22358
  STANDARD_COLUMN_TYPES,
22239
22359
  SelectQueryBuilder,
22360
+ SqlDialectBase,
22240
22361
  SqlServerDialect,
22241
22362
  SqliteDialect,
22363
+ SqliteReturningStrategy,
22364
+ SqliteUpsertStrategy,
22242
22365
  StandardDeleteCompiler,
22243
22366
  StandardInsertCompiler,
22367
+ StandardLimitOffsetPagination,
22368
+ StandardReturningStrategy,
22244
22369
  StandardSelectCompiler,
22245
22370
  StandardSqlSourceCompiler,
22371
+ StandardTableFunctionStrategy,
22246
22372
  StandardUpdateCompiler,
22247
22373
  StringTypeStrategy,
22248
22374
  TagIndex,
@@ -22330,6 +22456,7 @@ async function bulkUpsert(session, table, rows, options = {}) {
22330
22456
  createEntityFromRow,
22331
22457
  createEntityProxy,
22332
22458
  createExecutorFromQueryRunner,
22459
+ createMssqlCompilerSet,
22333
22460
  createMssqlExecutor,
22334
22461
  createMysqlExecutor,
22335
22462
  createPooledExecutorFactory,