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.js CHANGED
@@ -1704,23 +1704,12 @@ var StandardLimitOffsetPagination = class {
1704
1704
 
1705
1705
  // src/core/dialect/base/returning-strategy.ts
1706
1706
  var NoReturningStrategy = class {
1707
- /**
1708
- * Throws an error as RETURNING is not supported.
1709
- * @param returning - Columns to return (causes error if non-empty).
1710
- * @param _ctx - Compiler context (unused).
1711
- * @throws Error indicating RETURNING is not supported.
1712
- */
1713
- compileReturning(returning, _ctx) {
1707
+ compileReturning(returning, _ctx, _quoteIdentifier) {
1714
1708
  void _ctx;
1709
+ void _quoteIdentifier;
1715
1710
  if (!returning || returning.length === 0) return "";
1716
1711
  throw new Error("RETURNING is not supported by this dialect.");
1717
1712
  }
1718
- /**
1719
- * Formats column names for RETURNING clause.
1720
- * @param returning - Columns to format.
1721
- * @param quoteIdentifier - Function to quote identifiers according to dialect rules.
1722
- * @returns Simple comma-separated column names.
1723
- */
1724
1713
  formatReturningColumns(returning, quoteIdentifier) {
1725
1714
  return returning.map((column) => {
1726
1715
  const tablePart = column.table ? `${quoteIdentifier(column.table)}.` : "";
@@ -1729,6 +1718,24 @@ var NoReturningStrategy = class {
1729
1718
  }).join(", ");
1730
1719
  }
1731
1720
  };
1721
+ var StandardReturningStrategy = class extends NoReturningStrategy {
1722
+ compileReturning(returning, _ctx, quoteIdentifier) {
1723
+ void _ctx;
1724
+ if (!returning || returning.length === 0) return "";
1725
+ return ` RETURNING ${this.formatReturningColumns(returning, quoteIdentifier)}`;
1726
+ }
1727
+ };
1728
+
1729
+ // src/core/dialect/base/upsert-strategy.ts
1730
+ var NoUpsertStrategy = class {
1731
+ compile(ast, _ctx, services) {
1732
+ void _ctx;
1733
+ if (!ast.onConflict) return "";
1734
+ throw new Error(
1735
+ `UPSERT/ON CONFLICT is not supported by dialect "${services.getDialectName()}".`
1736
+ );
1737
+ }
1738
+ };
1732
1739
 
1733
1740
  // src/core/dialect/base/function-table-formatter.ts
1734
1741
  var FunctionTableFormatter = class {
@@ -2077,15 +2084,19 @@ var StandardDeleteCompiler = class {
2077
2084
 
2078
2085
  // src/core/dialect/base/sql-dialect.ts
2079
2086
  var SqlDialectBase = class extends DialectBase {
2080
- paginationStrategy = new StandardLimitOffsetPagination();
2081
- returningStrategy = new NoReturningStrategy();
2087
+ paginationStrategy;
2088
+ returningStrategy;
2089
+ upsertStrategy;
2090
+ dmlReturningSupported;
2082
2091
  sourceCompiler;
2083
- selectCompiler;
2084
- insertCompiler;
2085
- updateCompiler;
2086
- deleteCompiler;
2087
- constructor(functionStrategy, tableFunctionStrategy) {
2088
- super(functionStrategy, tableFunctionStrategy);
2092
+ standardUpdateCompiler;
2093
+ compilerSet;
2094
+ constructor(options = {}) {
2095
+ super(options.functionStrategy, options.tableFunctionStrategy);
2096
+ this.paginationStrategy = options.paginationStrategy ?? new StandardLimitOffsetPagination();
2097
+ this.returningStrategy = options.returningStrategy ?? new NoReturningStrategy();
2098
+ this.upsertStrategy = options.upsertStrategy ?? new NoUpsertStrategy();
2099
+ this.dmlReturningSupported = options.supportsDmlReturning ?? false;
2089
2100
  const services = {
2090
2101
  getDialectName: () => this.dialect,
2091
2102
  getPaginationStrategy: () => this.paginationStrategy,
@@ -2103,36 +2114,57 @@ var SqlDialectBase = class extends DialectBase {
2103
2114
  renderOrderByCollation: (order) => this.renderOrderByCollation(order)
2104
2115
  };
2105
2116
  this.sourceCompiler = new StandardSqlSourceCompiler(services);
2106
- this.selectCompiler = new StandardSelectCompiler(services, this.sourceCompiler);
2107
- this.insertCompiler = new StandardInsertCompiler(services, this.sourceCompiler);
2108
- this.updateCompiler = new StandardUpdateCompiler(services, this.sourceCompiler);
2109
- this.deleteCompiler = new StandardDeleteCompiler(services, this.sourceCompiler);
2117
+ const standardSelect = new StandardSelectCompiler(services, this.sourceCompiler);
2118
+ const standardInsert = new StandardInsertCompiler(services, this.sourceCompiler);
2119
+ this.standardUpdateCompiler = new StandardUpdateCompiler(services, this.sourceCompiler);
2120
+ const standardDelete = new StandardDeleteCompiler(services, this.sourceCompiler);
2121
+ const overrides = options.compilerFactory?.({
2122
+ services,
2123
+ sources: this.sourceCompiler
2124
+ }) ?? {};
2125
+ this.compilerSet = {
2126
+ select: overrides.select ?? standardSelect,
2127
+ insert: overrides.insert ?? standardInsert,
2128
+ update: overrides.update ?? this.standardUpdateCompiler,
2129
+ delete: overrides.delete ?? standardDelete
2130
+ };
2131
+ }
2132
+ supportsDmlReturningClause() {
2133
+ return this.dmlReturningSupported;
2110
2134
  }
2111
2135
  compileSelectAst(ast, ctx) {
2112
- return this.selectCompiler.compile(ast, ctx);
2136
+ return this.compilerSet.select.compile(ast, ctx);
2113
2137
  }
2114
2138
  compileInsertAst(ast, ctx) {
2115
- return this.insertCompiler.compile(ast, ctx);
2139
+ return this.compilerSet.insert.compile(ast, ctx);
2116
2140
  }
2117
2141
  compileUpdateAst(ast, ctx) {
2118
- return this.updateCompiler.compile(ast, ctx);
2142
+ return this.compilerSet.update.compile(ast, ctx);
2119
2143
  }
2120
2144
  compileDeleteAst(ast, ctx) {
2121
- return this.deleteCompiler.compile(ast, ctx);
2145
+ return this.compilerSet.delete.compile(ast, ctx);
2122
2146
  }
2123
- compileUpsertClause(ast, _ctx) {
2124
- void _ctx;
2125
- if (!ast.onConflict) return "";
2126
- throw new Error(`UPSERT/ON CONFLICT is not supported by dialect "${this.dialect}".`);
2147
+ compileUpsertClause(ast, ctx) {
2148
+ return this.upsertStrategy.compile(ast, ctx, {
2149
+ getDialectName: () => this.dialect,
2150
+ quoteIdentifier: (id) => this.quoteIdentifier(id),
2151
+ compileOperand: (node, compilerContext) => this.compileOperand(node, compilerContext),
2152
+ compileExpression: (node, compilerContext) => this.compileExpression(node, compilerContext),
2153
+ compileUpdateAssignments: (assignments, table, compilerContext) => this.standardUpdateCompiler.compileAssignments(assignments, table, compilerContext)
2154
+ });
2127
2155
  }
2128
2156
  compileReturning(returning, ctx) {
2129
- return this.returningStrategy.compileReturning(returning, ctx);
2157
+ return this.returningStrategy.compileReturning(
2158
+ returning,
2159
+ ctx,
2160
+ (id) => this.quoteIdentifier(id)
2161
+ );
2130
2162
  }
2131
2163
  ensureConflictColumns(clause, message) {
2132
- this.insertCompiler.ensureConflictColumns(clause, message);
2164
+ if (!clause.target.columns.length) throw new Error(message);
2133
2165
  }
2134
2166
  compileUpdateAssignments(assignments, table, ctx) {
2135
- return this.updateCompiler.compileAssignments(assignments, table, ctx);
2167
+ return this.standardUpdateCompiler.compileAssignments(assignments, table, ctx);
2136
2168
  }
2137
2169
  compileSetTarget(column, table) {
2138
2170
  return this.compileQualifiedColumn(column, table);
@@ -2358,105 +2390,112 @@ var PostgresTableFunctionStrategy = class extends StandardTableFunctionStrategy
2358
2390
  }
2359
2391
  };
2360
2392
 
2393
+ // src/core/dialect/postgres/procedure-compiler.ts
2394
+ var PostgresProcedureCompiler = class {
2395
+ constructor(services) {
2396
+ this.services = services;
2397
+ }
2398
+ compileProcedureCall(ast) {
2399
+ const ctx = this.services.createCompilerContext();
2400
+ const qualifiedName = ast.ref.schema ? `${this.services.quoteIdentifier(ast.ref.schema)}.${this.services.quoteIdentifier(ast.ref.name)}` : this.services.quoteIdentifier(ast.ref.name);
2401
+ const args = [];
2402
+ for (const param of ast.params) {
2403
+ if (param.direction === "out") continue;
2404
+ if (!param.value) {
2405
+ throw new Error(
2406
+ `Procedure parameter "${param.name}" requires a value for direction "${param.direction}".`
2407
+ );
2408
+ }
2409
+ args.push(this.services.compileOperand(param.value, ctx));
2410
+ }
2411
+ const outNames = ast.params.filter((param) => param.direction === "out" || param.direction === "inout").map((param) => param.name);
2412
+ return {
2413
+ sql: `CALL ${qualifiedName}(${args.join(", ")});`,
2414
+ params: [...ctx.params],
2415
+ outParams: {
2416
+ source: outNames.length ? "firstResultSet" : "none",
2417
+ names: outNames
2418
+ }
2419
+ };
2420
+ }
2421
+ };
2422
+
2423
+ // src/core/dialect/postgres/returning.ts
2424
+ var PostgresReturningStrategy = class extends StandardReturningStrategy {
2425
+ };
2426
+
2427
+ // src/core/dialect/postgres/upsert.ts
2428
+ var PostgresUpsertStrategy = class {
2429
+ compile(ast, ctx, services) {
2430
+ if (!ast.onConflict) return "";
2431
+ const clause = ast.onConflict;
2432
+ const target = clause.target.constraint ? ` ON CONFLICT ON CONSTRAINT ${services.quoteIdentifier(clause.target.constraint)}` : (() => {
2433
+ if (!clause.target.columns.length) {
2434
+ throw new Error("PostgreSQL ON CONFLICT requires conflict columns or a constraint name.");
2435
+ }
2436
+ const columns = clause.target.columns.map((column) => services.quoteIdentifier(column.name)).join(", ");
2437
+ return ` ON CONFLICT (${columns})`;
2438
+ })();
2439
+ if (clause.action.type === "DoNothing") {
2440
+ return `${target} DO NOTHING`;
2441
+ }
2442
+ if (!clause.action.set.length) {
2443
+ throw new Error("PostgreSQL ON CONFLICT DO UPDATE requires at least one assignment.");
2444
+ }
2445
+ const assignments = services.compileUpdateAssignments(clause.action.set, ast.into, ctx);
2446
+ const where = clause.action.where ? ` WHERE ${services.compileExpression(clause.action.where, ctx)}` : "";
2447
+ return `${target} DO UPDATE SET ${assignments}${where}`;
2448
+ }
2449
+ };
2450
+
2361
2451
  // src/core/dialect/postgres/index.ts
2362
2452
  var PostgresDialect = class extends SqlDialectBase {
2363
2453
  dialect = "postgres";
2364
- /**
2365
- * Creates a new PostgresDialect instance
2366
- */
2454
+ procedureCompiler;
2367
2455
  constructor() {
2368
- super(new PostgresFunctionStrategy(), new PostgresTableFunctionStrategy());
2456
+ super({
2457
+ functionStrategy: new PostgresFunctionStrategy(),
2458
+ tableFunctionStrategy: new PostgresTableFunctionStrategy(),
2459
+ returningStrategy: new PostgresReturningStrategy(),
2460
+ upsertStrategy: new PostgresUpsertStrategy(),
2461
+ supportsDmlReturning: true
2462
+ });
2463
+ this.procedureCompiler = new PostgresProcedureCompiler({
2464
+ quoteIdentifier: (id) => this.quoteIdentifier(id),
2465
+ createCompilerContext: () => this.createCompilerContext(),
2466
+ compileOperand: (node, ctx) => this.compileOperand(node, ctx)
2467
+ });
2369
2468
  this.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
2370
2469
  const left2 = this.compileOperand(node.left, ctx);
2371
2470
  const right2 = this.compileOperand(node.right, ctx);
2372
- const op = node.operator === "^" ? "#" : node.operator;
2373
- return `${left2} ${op} ${right2}`;
2471
+ const operator = node.operator === "^" ? "#" : node.operator;
2472
+ return `${left2} ${operator} ${right2}`;
2374
2473
  });
2375
2474
  this.registerOperandCompiler("BitwiseExpression", (node, ctx) => {
2376
2475
  const left2 = this.compileOperand(node.left, ctx);
2377
2476
  const right2 = this.compileOperand(node.right, ctx);
2378
- const op = node.operator === "^" ? "#" : node.operator;
2379
- return `(${left2} ${op} ${right2})`;
2477
+ const operator = node.operator === "^" ? "#" : node.operator;
2478
+ return `(${left2} ${operator} ${right2})`;
2380
2479
  });
2381
2480
  }
2382
- /**
2383
- * Quotes an identifier using PostgreSQL double-quote syntax
2384
- * @param id - Identifier to quote
2385
- * @returns Quoted identifier
2386
- */
2387
2481
  quoteIdentifier(id) {
2388
2482
  return `"${id}"`;
2389
2483
  }
2390
2484
  formatPlaceholder(index) {
2391
2485
  return `$${index}`;
2392
2486
  }
2393
- /**
2394
- * Compiles JSON path expression using PostgreSQL syntax
2395
- * @param node - JSON path node
2396
- * @returns PostgreSQL JSON path expression
2397
- */
2398
2487
  compileJsonPath(node) {
2399
- const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
2400
- return `${col2}->>'${node.path}'`;
2488
+ const column = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
2489
+ return `${column}->>'${node.path}'`;
2401
2490
  }
2402
- compileReturning(returning, ctx) {
2403
- void ctx;
2404
- if (!returning || returning.length === 0) return "";
2405
- const columns = this.formatReturningColumns(returning);
2406
- return ` RETURNING ${columns}`;
2407
- }
2408
- compileUpsertClause(ast, ctx) {
2409
- if (!ast.onConflict) return "";
2410
- const clause = ast.onConflict;
2411
- const target = clause.target.constraint ? ` ON CONFLICT ON CONSTRAINT ${this.quoteIdentifier(clause.target.constraint)}` : (() => {
2412
- this.ensureConflictColumns(
2413
- clause,
2414
- "PostgreSQL ON CONFLICT requires conflict columns or a constraint name."
2415
- );
2416
- const cols = clause.target.columns.map((col2) => this.quoteIdentifier(col2.name)).join(", ");
2417
- return ` ON CONFLICT (${cols})`;
2418
- })();
2419
- if (clause.action.type === "DoNothing") {
2420
- return `${target} DO NOTHING`;
2421
- }
2422
- if (!clause.action.set.length) {
2423
- throw new Error("PostgreSQL ON CONFLICT DO UPDATE requires at least one assignment.");
2424
- }
2425
- const assignments = this.compileUpdateAssignments(clause.action.set, ast.into, ctx);
2426
- const where = clause.action.where ? ` WHERE ${this.compileExpression(clause.action.where, ctx)}` : "";
2427
- return `${target} DO UPDATE SET ${assignments}${where}`;
2428
- }
2429
- supportsDmlReturningClause() {
2430
- return true;
2431
- }
2432
- compileProcedureCall(ast) {
2433
- const ctx = this.createCompilerContext();
2434
- const qualifiedName = ast.ref.schema ? `${this.quoteIdentifier(ast.ref.schema)}.${this.quoteIdentifier(ast.ref.name)}` : this.quoteIdentifier(ast.ref.name);
2435
- const args = [];
2436
- for (const param of ast.params) {
2437
- if (param.direction === "out") continue;
2438
- if (!param.value) {
2439
- throw new Error(`Procedure parameter "${param.name}" requires a value for direction "${param.direction}".`);
2440
- }
2441
- args.push(this.compileOperand(param.value, ctx));
2442
- }
2443
- const outNames = ast.params.filter((param) => param.direction === "out" || param.direction === "inout").map((param) => param.name);
2444
- const rawSql = `CALL ${qualifiedName}(${args.join(", ")})`;
2445
- return {
2446
- sql: `${rawSql};`,
2447
- params: [...ctx.params],
2448
- outParams: {
2449
- source: outNames.length ? "firstResultSet" : "none",
2450
- names: outNames
2451
- }
2452
- };
2453
- }
2454
- /**
2455
- * PostgreSQL requires unqualified column names in SET clause
2456
- */
2491
+ /** PostgreSQL requires unqualified column names in SET clauses. */
2457
2492
  compileSetTarget(column, _table) {
2493
+ void _table;
2458
2494
  return this.quoteIdentifier(column.name);
2459
2495
  }
2496
+ compileProcedureCall(ast) {
2497
+ return this.procedureCompiler.compileProcedureCall(ast);
2498
+ }
2460
2499
  };
2461
2500
 
2462
2501
  // src/core/dialect/mysql/functions.ts
@@ -2557,72 +2596,15 @@ var MysqlFunctionStrategy = class extends StandardFunctionStrategy {
2557
2596
  }
2558
2597
  };
2559
2598
 
2560
- // src/core/dialect/mysql/index.ts
2599
+ // src/core/dialect/mysql/procedure-compiler.ts
2561
2600
  var sanitizeVariableSuffix = (value) => value.replace(/[^a-zA-Z0-9_]/g, "_");
2562
- var MySqlDialect = class extends SqlDialectBase {
2563
- dialect = "mysql";
2564
- /**
2565
- * Creates a new MySqlDialect instance
2566
- */
2567
- constructor() {
2568
- super(new MysqlFunctionStrategy());
2569
- this.registerExpressionCompiler(
2570
- "IsDistinctExpression",
2571
- (node, ctx) => {
2572
- const left2 = this.compileOperand(node.left, ctx);
2573
- const right2 = this.compileOperand(node.right, ctx);
2574
- const spaceship = `${left2} <=> ${right2}`;
2575
- if (node.operator === "IS NOT DISTINCT FROM") {
2576
- return spaceship;
2577
- }
2578
- return `NOT (${spaceship})`;
2579
- }
2580
- );
2581
- }
2582
- /**
2583
- * Quotes an identifier using MySQL backtick syntax
2584
- * @param id - Identifier to quote
2585
- * @returns Quoted identifier
2586
- */
2587
- quoteIdentifier(id) {
2588
- return `\`${id}\``;
2589
- }
2590
- /**
2591
- * Compiles JSON path expression using MySQL syntax
2592
- * @param node - JSON path node
2593
- * @returns MySQL JSON path expression
2594
- */
2595
- compileJsonPath(node) {
2596
- const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
2597
- return `${col2}->'${node.path}'`;
2598
- }
2599
- compileUpsertClause(ast, ctx) {
2600
- if (!ast.onConflict) return "";
2601
- const clause = ast.onConflict;
2602
- if (clause.action.type === "DoNothing") {
2603
- const noOpColumn = clause.target.columns[0] ?? ast.columns[0];
2604
- if (!noOpColumn) {
2605
- throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one target column.");
2606
- }
2607
- const col2 = this.quoteIdentifier(noOpColumn.name);
2608
- return ` ON DUPLICATE KEY UPDATE ${col2} = ${col2}`;
2609
- }
2610
- if (clause.action.where) {
2611
- throw new Error("MySQL ON DUPLICATE KEY UPDATE does not support a WHERE clause.");
2612
- }
2613
- if (!clause.action.set.length) {
2614
- throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one assignment.");
2615
- }
2616
- const assignments = clause.action.set.map((assignment) => {
2617
- const target = this.quoteIdentifier(assignment.column.name);
2618
- const value = this.compileOperand(assignment.value, ctx);
2619
- return `${target} = ${value}`;
2620
- }).join(", ");
2621
- return ` ON DUPLICATE KEY UPDATE ${assignments}`;
2601
+ var MySqlProcedureCompiler = class {
2602
+ constructor(services) {
2603
+ this.services = services;
2622
2604
  }
2623
2605
  compileProcedureCall(ast) {
2624
- const ctx = this.createCompilerContext();
2625
- const qualifiedName = ast.ref.schema ? `${this.quoteIdentifier(ast.ref.schema)}.${this.quoteIdentifier(ast.ref.name)}` : this.quoteIdentifier(ast.ref.name);
2606
+ const ctx = this.services.createCompilerContext();
2607
+ const qualifiedName = ast.ref.schema ? `${this.services.quoteIdentifier(ast.ref.schema)}.${this.services.quoteIdentifier(ast.ref.name)}` : this.services.quoteIdentifier(ast.ref.name);
2626
2608
  const prelude = [];
2627
2609
  const callArgs = [];
2628
2610
  const outVars = [];
@@ -2633,25 +2615,23 @@ var MySqlDialect = class extends SqlDialectBase {
2633
2615
  if (!param.value) {
2634
2616
  throw new Error(`Procedure parameter "${param.name}" requires a value for direction "in".`);
2635
2617
  }
2636
- callArgs.push(this.compileOperand(param.value, ctx));
2618
+ callArgs.push(this.services.compileOperand(param.value, ctx));
2637
2619
  return;
2638
2620
  }
2639
2621
  if (param.direction === "inout") {
2640
2622
  if (!param.value) {
2641
2623
  throw new Error(`Procedure parameter "${param.name}" requires a value for direction "inout".`);
2642
2624
  }
2643
- prelude.push(`SET ${variable} = ${this.compileOperand(param.value, ctx)};`);
2625
+ prelude.push(`SET ${variable} = ${this.services.compileOperand(param.value, ctx)};`);
2644
2626
  }
2645
2627
  callArgs.push(variable);
2646
2628
  outVars.push({ variable, name: param.name });
2647
2629
  });
2648
2630
  const statements = [];
2649
- if (prelude.length) {
2650
- statements.push(...prelude);
2651
- }
2631
+ if (prelude.length) statements.push(...prelude);
2652
2632
  statements.push(`CALL ${qualifiedName}(${callArgs.join(", ")});`);
2653
2633
  if (outVars.length) {
2654
- const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.quoteIdentifier(name)}`).join(", ");
2634
+ const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.services.quoteIdentifier(name)}`).join(", ");
2655
2635
  statements.push(`SELECT ${selectOut};`);
2656
2636
  }
2657
2637
  return {
@@ -2665,6 +2645,70 @@ var MySqlDialect = class extends SqlDialectBase {
2665
2645
  }
2666
2646
  };
2667
2647
 
2648
+ // src/core/dialect/mysql/upsert.ts
2649
+ var MySqlUpsertStrategy = class {
2650
+ compile(ast, ctx, services) {
2651
+ if (!ast.onConflict) return "";
2652
+ const clause = ast.onConflict;
2653
+ if (clause.action.type === "DoNothing") {
2654
+ const noOpColumn = clause.target.columns[0] ?? ast.columns[0];
2655
+ if (!noOpColumn) {
2656
+ throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one target column.");
2657
+ }
2658
+ const col2 = services.quoteIdentifier(noOpColumn.name);
2659
+ return ` ON DUPLICATE KEY UPDATE ${col2} = ${col2}`;
2660
+ }
2661
+ if (clause.action.where) {
2662
+ throw new Error("MySQL ON DUPLICATE KEY UPDATE does not support a WHERE clause.");
2663
+ }
2664
+ if (!clause.action.set.length) {
2665
+ throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one assignment.");
2666
+ }
2667
+ const assignments = clause.action.set.map((assignment) => {
2668
+ const target = services.quoteIdentifier(assignment.column.name);
2669
+ const value = services.compileOperand(assignment.value, ctx);
2670
+ return `${target} = ${value}`;
2671
+ }).join(", ");
2672
+ return ` ON DUPLICATE KEY UPDATE ${assignments}`;
2673
+ }
2674
+ };
2675
+
2676
+ // src/core/dialect/mysql/index.ts
2677
+ var MySqlDialect = class extends SqlDialectBase {
2678
+ dialect = "mysql";
2679
+ procedureCompiler;
2680
+ constructor() {
2681
+ super({
2682
+ functionStrategy: new MysqlFunctionStrategy(),
2683
+ upsertStrategy: new MySqlUpsertStrategy()
2684
+ });
2685
+ this.procedureCompiler = new MySqlProcedureCompiler({
2686
+ quoteIdentifier: (id) => this.quoteIdentifier(id),
2687
+ createCompilerContext: () => this.createCompilerContext(),
2688
+ compileOperand: (node, ctx) => this.compileOperand(node, ctx)
2689
+ });
2690
+ this.registerExpressionCompiler(
2691
+ "IsDistinctExpression",
2692
+ (node, ctx) => {
2693
+ const left2 = this.compileOperand(node.left, ctx);
2694
+ const right2 = this.compileOperand(node.right, ctx);
2695
+ const spaceship = `${left2} <=> ${right2}`;
2696
+ return node.operator === "IS NOT DISTINCT FROM" ? spaceship : `NOT (${spaceship})`;
2697
+ }
2698
+ );
2699
+ }
2700
+ quoteIdentifier(id) {
2701
+ return `\`${id}\``;
2702
+ }
2703
+ compileJsonPath(node) {
2704
+ const column = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
2705
+ return `${column}->'${node.path}'`;
2706
+ }
2707
+ compileProcedureCall(ast) {
2708
+ return this.procedureCompiler.compileProcedureCall(ast);
2709
+ }
2710
+ };
2711
+
2668
2712
  // src/core/dialect/sqlite/functions.ts
2669
2713
  var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
2670
2714
  constructor() {
@@ -2802,14 +2846,56 @@ var SqliteFunctionStrategy = class extends StandardFunctionStrategy {
2802
2846
  }
2803
2847
  };
2804
2848
 
2849
+ // src/core/dialect/sqlite/returning.ts
2850
+ var SqliteReturningStrategy = class {
2851
+ compileReturning(returning, _ctx, quoteIdentifier) {
2852
+ void _ctx;
2853
+ if (!returning || returning.length === 0) return "";
2854
+ return ` RETURNING ${this.formatReturningColumns(returning, quoteIdentifier)}`;
2855
+ }
2856
+ formatReturningColumns(returning, quoteIdentifier) {
2857
+ return returning.map((column) => {
2858
+ const alias = column.alias ? ` AS ${quoteIdentifier(column.alias)}` : "";
2859
+ return `${quoteIdentifier(column.name)}${alias}`;
2860
+ }).join(", ");
2861
+ }
2862
+ };
2863
+
2864
+ // src/core/dialect/sqlite/upsert.ts
2865
+ var SqliteUpsertStrategy = class {
2866
+ compile(ast, ctx, services) {
2867
+ if (!ast.onConflict) return "";
2868
+ const clause = ast.onConflict;
2869
+ if (clause.target.constraint) {
2870
+ throw new Error("SQLite ON CONFLICT does not support named constraints.");
2871
+ }
2872
+ if (!clause.target.columns.length) {
2873
+ throw new Error("SQLite ON CONFLICT requires conflict columns.");
2874
+ }
2875
+ const columns = clause.target.columns.map((column) => services.quoteIdentifier(column.name)).join(", ");
2876
+ const target = ` ON CONFLICT (${columns})`;
2877
+ if (clause.action.type === "DoNothing") {
2878
+ return `${target} DO NOTHING`;
2879
+ }
2880
+ if (!clause.action.set.length) {
2881
+ throw new Error("SQLite ON CONFLICT DO UPDATE requires at least one assignment.");
2882
+ }
2883
+ const assignments = services.compileUpdateAssignments(clause.action.set, ast.into, ctx);
2884
+ const where = clause.action.where ? ` WHERE ${services.compileExpression(clause.action.where, ctx)}` : "";
2885
+ return `${target} DO UPDATE SET ${assignments}${where}`;
2886
+ }
2887
+ };
2888
+
2805
2889
  // src/core/dialect/sqlite/index.ts
2806
2890
  var SqliteDialect = class extends SqlDialectBase {
2807
2891
  dialect = "sqlite";
2808
- /**
2809
- * Creates a new SqliteDialect instance
2810
- */
2811
2892
  constructor() {
2812
- super(new SqliteFunctionStrategy());
2893
+ super({
2894
+ functionStrategy: new SqliteFunctionStrategy(),
2895
+ returningStrategy: new SqliteReturningStrategy(),
2896
+ upsertStrategy: new SqliteUpsertStrategy(),
2897
+ supportsDmlReturning: true
2898
+ });
2813
2899
  this.registerExpressionCompiler("BitwiseExpression", (node, ctx) => {
2814
2900
  const left2 = this.compileOperand(node.left, ctx);
2815
2901
  const right2 = this.compileOperand(node.right, ctx);
@@ -2827,61 +2913,17 @@ var SqliteDialect = class extends SqlDialectBase {
2827
2913
  return `(${left2} ${node.operator} ${right2})`;
2828
2914
  });
2829
2915
  }
2830
- /**
2831
- * Quotes an identifier using SQLite double-quote syntax
2832
- * @param id - Identifier to quote
2833
- * @returns Quoted identifier
2834
- */
2835
2916
  quoteIdentifier(id) {
2836
2917
  return `"${id}"`;
2837
2918
  }
2838
- /**
2839
- * Compiles JSON path expression using SQLite syntax
2840
- * @param node - JSON path node
2841
- * @returns SQLite JSON path expression
2842
- */
2843
2919
  compileJsonPath(node) {
2844
- const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
2845
- return `json_extract(${col2}, '${node.path}')`;
2920
+ const column = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
2921
+ return `json_extract(${column}, '${node.path}')`;
2846
2922
  }
2847
2923
  compileQualifiedColumn(column, _table) {
2848
2924
  void _table;
2849
2925
  return this.quoteIdentifier(column.name);
2850
2926
  }
2851
- compileReturning(returning, ctx) {
2852
- void ctx;
2853
- if (!returning || returning.length === 0) return "";
2854
- const columns = this.formatReturningColumns(returning);
2855
- return ` RETURNING ${columns}`;
2856
- }
2857
- formatReturningColumns(returning) {
2858
- return returning.map((column) => {
2859
- const alias = column.alias ? ` AS ${this.quoteIdentifier(column.alias)}` : "";
2860
- return `${this.quoteIdentifier(column.name)}${alias}`;
2861
- }).join(", ");
2862
- }
2863
- compileUpsertClause(ast, ctx) {
2864
- if (!ast.onConflict) return "";
2865
- const clause = ast.onConflict;
2866
- if (clause.target.constraint) {
2867
- throw new Error("SQLite ON CONFLICT does not support named constraints.");
2868
- }
2869
- this.ensureConflictColumns(clause, "SQLite ON CONFLICT requires conflict columns.");
2870
- const cols = clause.target.columns.map((col2) => this.quoteIdentifier(col2.name)).join(", ");
2871
- const target = ` ON CONFLICT (${cols})`;
2872
- if (clause.action.type === "DoNothing") {
2873
- return `${target} DO NOTHING`;
2874
- }
2875
- if (!clause.action.set.length) {
2876
- throw new Error("SQLite ON CONFLICT DO UPDATE requires at least one assignment.");
2877
- }
2878
- const assignments = this.compileUpdateAssignments(clause.action.set, ast.into, ctx);
2879
- const where = clause.action.where ? ` WHERE ${this.compileExpression(clause.action.where, ctx)}` : "";
2880
- return `${target} DO UPDATE SET ${assignments}${where}`;
2881
- }
2882
- supportsDmlReturningClause() {
2883
- return true;
2884
- }
2885
2927
  };
2886
2928
 
2887
2929
  // src/core/dialect/mssql/functions.ts
@@ -3008,202 +3050,107 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
3008
3050
  }
3009
3051
  };
3010
3052
 
3011
- // src/core/dialect/mssql/index.ts
3012
- var sanitizeVariableSuffix2 = (value) => value.replace(/[^a-zA-Z0-9_]/g, "_");
3013
- var toProcedureParamReference = (value) => value.startsWith("@") ? value : `@${value}`;
3014
- var SqlServerDialect = class extends SqlDialectBase {
3015
- dialect = "mssql";
3016
- /**
3017
- * Creates a new SqlServerDialect instance
3018
- */
3019
- constructor() {
3020
- super(new MssqlFunctionStrategy());
3021
- }
3022
- /**
3023
- * Quotes an identifier using SQL Server bracket syntax
3024
- * @param id - Identifier to quote
3025
- * @returns Quoted identifier
3026
- */
3027
- quoteIdentifier(id) {
3028
- return `[${id}]`;
3053
+ // src/core/dialect/mssql/output.ts
3054
+ var MssqlOutputStrategy = class {
3055
+ compileReturning(returning, _ctx, quoteIdentifier) {
3056
+ void _ctx;
3057
+ return this.compileOutput(returning, "inserted", quoteIdentifier);
3029
3058
  }
3030
- /**
3031
- * Compiles JSON path expression using SQL Server syntax
3032
- * @param node - JSON path node
3033
- * @returns SQL Server JSON path expression
3034
- */
3035
- compileJsonPath(node) {
3036
- const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3037
- return `JSON_VALUE(${col2}, '${node.path}')`;
3059
+ compileOutput(returning, prefix, quoteIdentifier) {
3060
+ if (!returning || returning.length === 0) return "";
3061
+ const columns = returning.map((column) => {
3062
+ const alias = column.alias ? ` AS ${quoteIdentifier(column.alias)}` : "";
3063
+ return `${prefix}.${quoteIdentifier(column.name)}${alias}`;
3064
+ }).join(", ");
3065
+ return ` OUTPUT ${columns}`;
3038
3066
  }
3039
- /**
3040
- * Formats parameter placeholders using SQL Server named parameter syntax
3041
- * @param index - Parameter index
3042
- * @returns Named parameter placeholder
3043
- */
3044
- formatPlaceholder(index) {
3045
- return `@p${index}`;
3067
+ formatReturningColumns(returning, quoteIdentifier) {
3068
+ return returning.map((column) => {
3069
+ const alias = column.alias ? ` AS ${quoteIdentifier(column.alias)}` : "";
3070
+ return `${quoteIdentifier(column.name)}${alias}`;
3071
+ }).join(", ");
3046
3072
  }
3047
- /**
3048
- * Compiles SELECT query AST to SQL Server SQL
3049
- * @param ast - Query AST
3050
- * @param ctx - Compiler context
3051
- * @returns SQL Server SQL string
3052
- */
3053
- compileSelectAst(ast, ctx) {
3054
- const hasSetOps = !!(ast.setOps && ast.setOps.length);
3055
- const ctes = this.compileCtes(ast, ctx);
3056
- const baseAst = hasSetOps ? { ...ast, setOps: void 0, orderBy: void 0, limit: void 0, offset: void 0 } : ast;
3057
- const baseSelect = this.compileSelectCoreForMssql(baseAst, ctx);
3058
- if (!hasSetOps) {
3059
- return `${ctes}${baseSelect}`;
3060
- }
3061
- const compound = ast.setOps.map((op) => `${op.operator} ${this.wrapSetOperand(this.compileSelectAst(op.query, ctx))}`).join(" ");
3062
- const orderBy = this.compileOrderBy(ast, ctx);
3063
- const pagination = this.compilePagination(ast, orderBy);
3064
- const combined = `${this.wrapSetOperand(baseSelect)} ${compound}`;
3065
- const tail = pagination || orderBy;
3066
- return `${ctes}${combined}${tail}`;
3073
+ };
3074
+
3075
+ // src/core/dialect/mssql/delete-compiler.ts
3076
+ var MssqlDeleteCompiler = class {
3077
+ constructor(services, sources) {
3078
+ this.services = services;
3079
+ this.sources = sources;
3067
3080
  }
3068
- compileDeleteAst(ast, ctx) {
3081
+ output = new MssqlOutputStrategy();
3082
+ compile(ast, ctx) {
3069
3083
  if (ast.using) {
3070
3084
  throw new Error("DELETE ... USING is not supported in the MSSQL dialect; use join() instead.");
3071
3085
  }
3072
- if (ast.from.type !== "Table") {
3073
- throw new Error("DELETE only supports base tables in the MSSQL dialect.");
3074
- }
3075
3086
  const alias = ast.from.alias ?? ast.from.name;
3076
- const target = this.compileTableReference(ast.from);
3087
+ const target = this.sources.compileTableReference(ast.from);
3077
3088
  const joins = JoinCompiler.compileJoins(
3078
3089
  ast.joins,
3079
3090
  ctx,
3080
- this.compileFrom.bind(this),
3081
- this.compileExpression.bind(this)
3091
+ (source, compilerContext) => this.sources.compileFrom(source, compilerContext),
3092
+ (expression, compilerContext) => this.services.compileExpression(expression, compilerContext)
3082
3093
  );
3083
- const whereClause = this.compileWhere(ast.where, ctx);
3084
- const returning = this.compileOutputClause(ast.returning, "deleted");
3085
- return `DELETE ${this.quoteIdentifier(alias)}${returning} FROM ${target}${joins}${whereClause}`;
3086
- }
3087
- compileUpdateAst(ast, ctx) {
3088
- const target = this.compileTableReference(ast.table);
3089
- const assignments = this.compileUpdateAssignments(ast.set, ast.table, ctx);
3090
- const output = this.compileReturning(ast.returning, ctx);
3091
- const fromClause = ast.from ? ` FROM ${this.compileFrom(ast.from, ctx)}` : "";
3092
- const joins = ast.joins ? ast.joins.map((j) => {
3093
- const table = this.compileFrom(j.table, ctx);
3094
- const cond = this.compileExpression(j.condition, ctx);
3095
- return ` ${j.kind} JOIN ${table} ON ${cond}`;
3096
- }).join("") : "";
3097
- const whereClause = this.compileWhere(ast.where, ctx);
3098
- return `UPDATE ${target} SET ${assignments}${output}${fromClause}${joins}${whereClause}`;
3099
- }
3100
- compileSelectCoreForMssql(ast, ctx) {
3101
- const columns = ast.columns.map((c) => {
3102
- const expr = c.type === "Column" ? `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}` : this.compileOperand(c, ctx);
3103
- if (c.alias) {
3104
- if (c.alias.includes("(")) return c.alias;
3105
- return `${expr} AS ${this.quoteIdentifier(c.alias)}`;
3106
- }
3107
- return expr;
3108
- }).join(", ");
3109
- const distinct = ast.distinct ? "DISTINCT " : "";
3110
- const from = this.compileFrom(ast.from, ctx);
3111
- const joins = ast.joins.map((j) => {
3112
- const table = this.compileFrom(j.table, ctx);
3113
- const cond = this.compileExpression(j.condition, ctx);
3114
- return `${j.kind} JOIN ${table} ON ${cond}`;
3115
- }).join(" ");
3116
- const whereClause = this.compileWhere(ast.where, ctx);
3117
- const groupBy = ast.groupBy && ast.groupBy.length > 0 ? " GROUP BY " + ast.groupBy.map((term) => this.compileOrderingTerm(term, ctx)).join(", ") : "";
3118
- const having = ast.having ? ` HAVING ${this.compileExpression(ast.having, ctx)}` : "";
3119
- const orderBy = this.compileOrderBy(ast, ctx);
3120
- const pagination = this.compilePagination(ast, orderBy);
3121
- if (pagination) {
3122
- return `SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${pagination}`;
3123
- }
3124
- return `SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${orderBy}`;
3125
- }
3126
- compileOrderBy(ast, ctx) {
3127
- return OrderByCompiler.compileOrderBy(
3128
- ast,
3129
- (term) => this.compileOrderingTerm(term, ctx),
3130
- this.renderOrderByNulls.bind(this),
3131
- this.renderOrderByCollation.bind(this)
3094
+ const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
3095
+ const returning = this.output.compileOutput(
3096
+ ast.returning,
3097
+ "deleted",
3098
+ (id) => this.services.quoteIdentifier(id)
3132
3099
  );
3100
+ return `DELETE ${this.services.quoteIdentifier(alias)}${returning} FROM ${target}${joins}${where}`;
3133
3101
  }
3134
- compilePagination(ast, orderBy) {
3135
- const hasLimit = ast.limit !== void 0;
3136
- const hasOffset = ast.offset !== void 0;
3137
- if (!hasLimit && !hasOffset) return "";
3138
- const off = ast.offset ?? 0;
3139
- let orderClause = orderBy;
3140
- if (!orderClause) {
3141
- orderClause = ast.distinct && ast.distinct.length > 0 ? " ORDER BY 1" : " ORDER BY (SELECT NULL)";
3142
- }
3143
- let pagination = `${orderClause} OFFSET ${off} ROWS`;
3144
- if (hasLimit) {
3145
- pagination += ` FETCH NEXT ${ast.limit} ROWS ONLY`;
3146
- }
3147
- return pagination;
3148
- }
3149
- supportsDmlReturningClause() {
3150
- return true;
3151
- }
3152
- compileReturning(returning, _ctx) {
3153
- void _ctx;
3154
- return this.compileOutputClause(returning, "inserted");
3155
- }
3156
- compileOutputClause(returning, prefix) {
3157
- if (!returning || returning.length === 0) return "";
3158
- const columns = returning.map((column) => {
3159
- const colName = this.quoteIdentifier(column.name);
3160
- const alias = column.alias ? ` AS ${this.quoteIdentifier(column.alias)}` : "";
3161
- return `${prefix}.${colName}${alias}`;
3162
- }).join(", ");
3163
- return ` OUTPUT ${columns}`;
3102
+ };
3103
+
3104
+ // src/core/dialect/mssql/insert-compiler.ts
3105
+ var MssqlInsertCompiler = class {
3106
+ constructor(services, sources) {
3107
+ this.services = services;
3108
+ this.sources = sources;
3164
3109
  }
3165
- compileInsertAst(ast, ctx) {
3110
+ compile(ast, ctx) {
3166
3111
  if (!ast.columns.length) {
3167
3112
  throw new Error("INSERT queries must specify columns.");
3168
3113
  }
3169
- if (ast.onConflict) {
3170
- return this.compileMergeInsert(ast, ctx);
3171
- }
3172
- const table = this.compileTableName(ast.into);
3173
- const columnList = ast.columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
3174
- const output = this.compileReturning(ast.returning, ctx);
3175
- const source = this.compileInsertValues(ast, ctx);
3176
- return `INSERT INTO ${table} (${columnList})${output} ${source}`;
3114
+ if (ast.onConflict) return this.compileMerge(ast, ctx);
3115
+ const table = this.sources.compileTableName(ast.into);
3116
+ const columns = ast.columns.map((column) => this.services.quoteIdentifier(column.name)).join(", ");
3117
+ const output = this.services.compileReturning(ast.returning, ctx);
3118
+ const source = this.compileInsertSource(ast, ctx);
3119
+ return `INSERT INTO ${table} (${columns})${output} ${source}`;
3177
3120
  }
3178
- compileMergeInsert(ast, ctx) {
3121
+ compileMerge(ast, ctx) {
3179
3122
  const clause = ast.onConflict;
3180
3123
  if (clause.target.constraint) {
3181
3124
  throw new Error("MSSQL MERGE does not support conflict target by constraint name.");
3182
3125
  }
3183
- this.ensureConflictColumns(clause, "MSSQL MERGE requires conflict columns for the ON clause.");
3184
- const table = this.compileTableName(ast.into);
3185
- const targetRef = this.quoteIdentifier(ast.into.alias ?? ast.into.name);
3186
- const sourceAlias = this.quoteIdentifier("src");
3187
- const sourceColumns = ast.columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
3126
+ if (!clause.target.columns.length) {
3127
+ throw new Error("MSSQL MERGE requires conflict columns for the ON clause.");
3128
+ }
3129
+ const table = this.sources.compileTableName(ast.into);
3130
+ const targetRef = this.services.quoteIdentifier(ast.into.alias ?? ast.into.name);
3131
+ const sourceAlias = this.services.quoteIdentifier("src");
3132
+ const sourceColumns = ast.columns.map((column) => this.services.quoteIdentifier(column.name)).join(", ");
3188
3133
  const usingSource = this.compileMergeUsingSource(ast, ctx);
3189
- const onClause = clause.target.columns.map((column) => `${targetRef}.${this.quoteIdentifier(column.name)} = ${sourceAlias}.${this.quoteIdentifier(column.name)}`).join(" AND ");
3134
+ const onClause = clause.target.columns.map(
3135
+ (column) => `${targetRef}.${this.services.quoteIdentifier(column.name)} = ${sourceAlias}.${this.services.quoteIdentifier(column.name)}`
3136
+ ).join(" AND ");
3190
3137
  const branches = [];
3191
3138
  if (clause.action.type === "DoUpdate") {
3192
3139
  if (!clause.action.set.length) {
3193
3140
  throw new Error("MSSQL MERGE WHEN MATCHED UPDATE requires at least one assignment.");
3194
3141
  }
3195
3142
  const assignments = clause.action.set.map((assignment) => {
3196
- const target = `${targetRef}.${this.quoteIdentifier(assignment.column.name)}`;
3197
- const value = this.compileOperand(assignment.value, ctx);
3143
+ const target = `${targetRef}.${this.services.quoteIdentifier(assignment.column.name)}`;
3144
+ const value = this.services.compileOperand(assignment.value, ctx);
3198
3145
  return `${target} = ${value}`;
3199
3146
  }).join(", ");
3200
- const guard = clause.action.where ? ` AND ${this.compileExpression(clause.action.where, ctx)}` : "";
3147
+ const guard = clause.action.where ? ` AND ${this.services.compileExpression(clause.action.where, ctx)}` : "";
3201
3148
  branches.push(`WHEN MATCHED${guard} THEN UPDATE SET ${assignments}`);
3202
3149
  }
3203
- const insertColumns = ast.columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
3204
- const insertValues = ast.columns.map((column) => `${sourceAlias}.${this.quoteIdentifier(column.name)}`).join(", ");
3150
+ const insertColumns = ast.columns.map((column) => this.services.quoteIdentifier(column.name)).join(", ");
3151
+ const insertValues = ast.columns.map((column) => `${sourceAlias}.${this.services.quoteIdentifier(column.name)}`).join(", ");
3205
3152
  branches.push(`WHEN NOT MATCHED THEN INSERT (${insertColumns}) VALUES (${insertValues})`);
3206
- const output = this.compileReturning(ast.returning, ctx);
3153
+ const output = this.services.compileReturning(ast.returning, ctx);
3207
3154
  return `MERGE INTO ${table} USING ${usingSource} AS ${sourceAlias} (${sourceColumns}) ON ${onClause} ${branches.join(" ")}${output}`;
3208
3155
  }
3209
3156
  compileMergeUsingSource(ast, ctx) {
@@ -3211,38 +3158,146 @@ var SqlServerDialect = class extends SqlDialectBase {
3211
3158
  if (!ast.source.rows.length) {
3212
3159
  throw new Error("INSERT ... VALUES requires at least one row.");
3213
3160
  }
3214
- const rows = ast.source.rows.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
3161
+ const rows = ast.source.rows.map((row) => `(${row.map((value) => this.services.compileOperand(value, ctx)).join(", ")})`).join(", ");
3215
3162
  return `(VALUES ${rows})`;
3216
3163
  }
3217
- const normalized = this.normalizeSelectAst(ast.source.query);
3218
- const selectSql = this.compileSelectAst(normalized, ctx).trim().replace(/;$/, "");
3164
+ const normalized = this.services.normalizeSelectAst(ast.source.query);
3165
+ const selectSql = this.sources.stripTrailingSemicolon(
3166
+ this.services.compileSelectAst(normalized, ctx)
3167
+ );
3219
3168
  return `(${selectSql})`;
3220
3169
  }
3221
- compileInsertValues(ast, ctx) {
3222
- const source = ast.source;
3223
- if (source.type === "InsertValues") {
3224
- if (!source.rows.length) {
3170
+ compileInsertSource(ast, ctx) {
3171
+ if (ast.source.type === "InsertValues") {
3172
+ if (!ast.source.rows.length) {
3225
3173
  throw new Error("INSERT ... VALUES requires at least one row.");
3226
3174
  }
3227
- const values = source.rows.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
3175
+ const values = ast.source.rows.map((row) => `(${row.map((value) => this.services.compileOperand(value, ctx)).join(", ")})`).join(", ");
3228
3176
  return `VALUES ${values}`;
3229
3177
  }
3230
- const normalized = this.normalizeSelectAst(source.query);
3231
- return this.compileSelectAst(normalized, ctx).trim();
3178
+ const normalized = this.services.normalizeSelectAst(ast.source.query);
3179
+ return this.services.compileSelectAst(normalized, ctx).trim();
3180
+ }
3181
+ };
3182
+
3183
+ // src/core/dialect/mssql/select-compiler.ts
3184
+ var MssqlSelectCompiler = class {
3185
+ constructor(services, sources) {
3186
+ this.services = services;
3187
+ this.sources = sources;
3188
+ }
3189
+ compile(ast, ctx) {
3190
+ const hasSetOps = !!(ast.setOps && ast.setOps.length);
3191
+ const ctes = this.compileCtes(ast, ctx);
3192
+ const baseAst = hasSetOps ? { ...ast, setOps: void 0, orderBy: void 0, limit: void 0, offset: void 0 } : ast;
3193
+ const baseSelect = this.compileCore(baseAst, ctx);
3194
+ if (!hasSetOps) return `${ctes}${baseSelect}`;
3195
+ const compound = ast.setOps.map((op) => `${op.operator} ${this.sources.wrapSetOperand(this.services.compileSelectAst(op.query, ctx))}`).join(" ");
3196
+ const orderBy = this.compileOrderBy(ast, ctx);
3197
+ const pagination = this.compilePagination(ast, orderBy);
3198
+ const combined = `${this.sources.wrapSetOperand(baseSelect)} ${compound}`;
3199
+ return `${ctes}${combined}${pagination || orderBy}`;
3200
+ }
3201
+ compileCore(ast, ctx) {
3202
+ const columns = ast.columns.map((column) => {
3203
+ const expr = column.type === "Column" ? `${this.services.quoteIdentifier(column.table)}.${this.services.quoteIdentifier(column.name)}` : this.services.compileOperand(column, ctx);
3204
+ if (!column.alias) return expr;
3205
+ if (column.alias.includes("(")) return column.alias;
3206
+ return `${expr} AS ${this.services.quoteIdentifier(column.alias)}`;
3207
+ }).join(", ");
3208
+ const distinct = ast.distinct ? "DISTINCT " : "";
3209
+ const from = this.sources.compileFrom(ast.from, ctx);
3210
+ const joins = ast.joins.map((join) => {
3211
+ const table = this.sources.compileFrom(join.table, ctx);
3212
+ const condition = this.services.compileExpression(join.condition, ctx);
3213
+ return `${join.kind} JOIN ${table} ON ${condition}`;
3214
+ }).join(" ");
3215
+ const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
3216
+ const groupBy = ast.groupBy && ast.groupBy.length > 0 ? ` GROUP BY ${ast.groupBy.map((term) => this.services.compileOrderingTerm(term, ctx)).join(", ")}` : "";
3217
+ const having = ast.having ? ` HAVING ${this.services.compileExpression(ast.having, ctx)}` : "";
3218
+ const orderBy = this.compileOrderBy(ast, ctx);
3219
+ const pagination = this.compilePagination(ast, orderBy);
3220
+ if (pagination) {
3221
+ return `SELECT ${distinct}${columns} FROM ${from}${joins ? ` ${joins}` : ""}${where}${groupBy}${having}${pagination}`;
3222
+ }
3223
+ return `SELECT ${distinct}${columns} FROM ${from}${joins ? ` ${joins}` : ""}${where}${groupBy}${having}${orderBy}`;
3224
+ }
3225
+ compileOrderBy(ast, ctx) {
3226
+ return OrderByCompiler.compileOrderBy(
3227
+ ast,
3228
+ (term) => this.services.compileOrderingTerm(term, ctx),
3229
+ (order) => this.services.renderOrderByNulls(order),
3230
+ (order) => this.services.renderOrderByCollation(order)
3231
+ );
3232
+ }
3233
+ compilePagination(ast, orderBy) {
3234
+ const hasLimit = ast.limit !== void 0;
3235
+ const hasOffset = ast.offset !== void 0;
3236
+ if (!hasLimit && !hasOffset) return "";
3237
+ const offset = ast.offset ?? 0;
3238
+ let orderClause = orderBy;
3239
+ if (!orderClause) {
3240
+ orderClause = ast.distinct && ast.distinct.length > 0 ? " ORDER BY 1" : " ORDER BY (SELECT NULL)";
3241
+ }
3242
+ let pagination = `${orderClause} OFFSET ${offset} ROWS`;
3243
+ if (hasLimit) pagination += ` FETCH NEXT ${ast.limit} ROWS ONLY`;
3244
+ return pagination;
3232
3245
  }
3233
3246
  compileCtes(ast, ctx) {
3234
3247
  if (!ast.ctes || ast.ctes.length === 0) return "";
3235
- const defs = ast.ctes.map((cte) => {
3236
- const name = this.quoteIdentifier(cte.name);
3237
- const cols = cte.columns ? `(${cte.columns.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
3238
- const query = this.compileSelectAst(this.normalizeSelectAst(cte.query), ctx).trim().replace(/;$/, "");
3239
- return `${name}${cols} AS (${query})`;
3248
+ const definitions = ast.ctes.map((cte) => {
3249
+ const name = this.services.quoteIdentifier(cte.name);
3250
+ const columns = cte.columns ? `(${cte.columns.map((column) => this.services.quoteIdentifier(column)).join(", ")})` : "";
3251
+ const query = this.sources.stripTrailingSemicolon(
3252
+ this.services.compileSelectAst(this.services.normalizeSelectAst(cte.query), ctx)
3253
+ );
3254
+ return `${name}${columns} AS (${query})`;
3240
3255
  }).join(", ");
3241
- return `WITH ${defs} `;
3256
+ return `WITH ${definitions} `;
3257
+ }
3258
+ };
3259
+
3260
+ // src/core/dialect/mssql/update-compiler.ts
3261
+ var MssqlUpdateCompiler = class {
3262
+ constructor(services, sources) {
3263
+ this.services = services;
3264
+ this.sources = sources;
3265
+ this.standardUpdate = new StandardUpdateCompiler(services, sources);
3266
+ }
3267
+ standardUpdate;
3268
+ compile(ast, ctx) {
3269
+ const target = this.sources.compileTableReference(ast.table);
3270
+ const assignments = this.standardUpdate.compileAssignments(ast.set, ast.table, ctx);
3271
+ const output = this.services.compileReturning(ast.returning, ctx);
3272
+ const from = ast.from ? ` FROM ${this.sources.compileFrom(ast.from, ctx)}` : "";
3273
+ const joins = ast.joins ? ast.joins.map((join) => {
3274
+ const table = this.sources.compileFrom(join.table, ctx);
3275
+ const condition = this.services.compileExpression(join.condition, ctx);
3276
+ return ` ${join.kind} JOIN ${table} ON ${condition}`;
3277
+ }).join("") : "";
3278
+ const where = ast.where ? ` WHERE ${this.services.compileExpression(ast.where, ctx)}` : "";
3279
+ return `UPDATE ${target} SET ${assignments}${output}${from}${joins}${where}`;
3280
+ }
3281
+ };
3282
+
3283
+ // src/core/dialect/mssql/compiler-factory.ts
3284
+ var createMssqlCompilerSet = ({ services, sources }) => ({
3285
+ select: new MssqlSelectCompiler(services, sources),
3286
+ insert: new MssqlInsertCompiler(services, sources),
3287
+ update: new MssqlUpdateCompiler(services, sources),
3288
+ delete: new MssqlDeleteCompiler(services, sources)
3289
+ });
3290
+
3291
+ // src/core/dialect/mssql/procedure-compiler.ts
3292
+ var sanitizeVariableSuffix2 = (value) => value.replace(/[^a-zA-Z0-9_]/g, "_");
3293
+ var toProcedureParamReference = (value) => value.startsWith("@") ? value : `@${value}`;
3294
+ var MssqlProcedureCompiler = class {
3295
+ constructor(services) {
3296
+ this.services = services;
3242
3297
  }
3243
3298
  compileProcedureCall(ast) {
3244
- const ctx = this.createCompilerContext();
3245
- const qualifiedName = ast.ref.schema ? `${this.quoteIdentifier(ast.ref.schema)}.${this.quoteIdentifier(ast.ref.name)}` : this.quoteIdentifier(ast.ref.name);
3299
+ const ctx = this.services.createCompilerContext();
3300
+ const qualifiedName = ast.ref.schema ? `${this.services.quoteIdentifier(ast.ref.schema)}.${this.services.quoteIdentifier(ast.ref.name)}` : this.services.quoteIdentifier(ast.ref.name);
3246
3301
  const declarations = [];
3247
3302
  const assignments = [];
3248
3303
  const execArgs = [];
@@ -3253,7 +3308,7 @@ var SqlServerDialect = class extends SqlDialectBase {
3253
3308
  if (!param.value) {
3254
3309
  throw new Error(`Procedure parameter "${param.name}" requires a value for direction "in".`);
3255
3310
  }
3256
- execArgs.push(`${targetParam} = ${this.compileOperand(param.value, ctx)}`);
3311
+ execArgs.push(`${targetParam} = ${this.services.compileOperand(param.value, ctx)}`);
3257
3312
  return;
3258
3313
  }
3259
3314
  if (!param.dbType) {
@@ -3268,7 +3323,7 @@ var SqlServerDialect = class extends SqlDialectBase {
3268
3323
  if (!param.value) {
3269
3324
  throw new Error(`Procedure parameter "${param.name}" requires a value for direction "inout".`);
3270
3325
  }
3271
- assignments.push(`SET ${variable} = ${this.compileOperand(param.value, ctx)};`);
3326
+ assignments.push(`SET ${variable} = ${this.services.compileOperand(param.value, ctx)};`);
3272
3327
  }
3273
3328
  execArgs.push(`${targetParam} = ${variable} OUTPUT`);
3274
3329
  outVars.push({ variable, name: param.name });
@@ -3279,7 +3334,7 @@ var SqlServerDialect = class extends SqlDialectBase {
3279
3334
  const argsSql = execArgs.length ? ` ${execArgs.join(", ")}` : "";
3280
3335
  statements.push(`EXEC ${qualifiedName}${argsSql};`);
3281
3336
  if (outVars.length) {
3282
- const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.quoteIdentifier(name)}`).join(", ");
3337
+ const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.services.quoteIdentifier(name)}`).join(", ");
3283
3338
  statements.push(`SELECT ${selectOut};`);
3284
3339
  }
3285
3340
  return {
@@ -3293,6 +3348,38 @@ var SqlServerDialect = class extends SqlDialectBase {
3293
3348
  }
3294
3349
  };
3295
3350
 
3351
+ // src/core/dialect/mssql/index.ts
3352
+ var SqlServerDialect = class extends SqlDialectBase {
3353
+ dialect = "mssql";
3354
+ procedureCompiler;
3355
+ constructor() {
3356
+ super({
3357
+ functionStrategy: new MssqlFunctionStrategy(),
3358
+ returningStrategy: new MssqlOutputStrategy(),
3359
+ compilerFactory: createMssqlCompilerSet,
3360
+ supportsDmlReturning: true
3361
+ });
3362
+ this.procedureCompiler = new MssqlProcedureCompiler({
3363
+ quoteIdentifier: (id) => this.quoteIdentifier(id),
3364
+ createCompilerContext: () => this.createCompilerContext(),
3365
+ compileOperand: (node, ctx) => this.compileOperand(node, ctx)
3366
+ });
3367
+ }
3368
+ quoteIdentifier(id) {
3369
+ return `[${id}]`;
3370
+ }
3371
+ compileJsonPath(node) {
3372
+ const column = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3373
+ return `JSON_VALUE(${column}, '${node.path}')`;
3374
+ }
3375
+ formatPlaceholder(index) {
3376
+ return `@p${index}`;
3377
+ }
3378
+ compileProcedureCall(ast) {
3379
+ return this.procedureCompiler.compileProcedureCall(ast);
3380
+ }
3381
+ };
3382
+
3296
3383
  // src/core/dialect/dialect-factory.ts
3297
3384
  var DialectFactory = class {
3298
3385
  static registry = /* @__PURE__ */ new Map();
@@ -21770,13 +21857,26 @@ export {
21770
21857
  MorphMany,
21771
21858
  MorphOne,
21772
21859
  MorphTo,
21860
+ MssqlDeleteCompiler,
21861
+ MssqlInsertCompiler,
21862
+ MssqlOutputStrategy,
21863
+ MssqlProcedureCompiler,
21864
+ MssqlSelectCompiler,
21865
+ MssqlUpdateCompiler,
21773
21866
  MySqlDialect,
21867
+ MySqlProcedureCompiler,
21868
+ MySqlUpsertStrategy,
21774
21869
  NestedSetStrategy,
21870
+ NoReturningStrategy,
21871
+ NoUpsertStrategy,
21775
21872
  Orm,
21776
21873
  OrmSession,
21777
21874
  Pattern,
21778
21875
  Pool,
21779
21876
  PostgresDialect,
21877
+ PostgresProcedureCompiler,
21878
+ PostgresReturningStrategy,
21879
+ PostgresUpsertStrategy,
21780
21880
  PrimaryKey,
21781
21881
  ProcedureCallBuilder,
21782
21882
  PrototypeMaterializationStrategy,
@@ -21785,12 +21885,18 @@ export {
21785
21885
  RelationKinds,
21786
21886
  STANDARD_COLUMN_TYPES,
21787
21887
  SelectQueryBuilder,
21888
+ SqlDialectBase,
21788
21889
  SqlServerDialect,
21789
21890
  SqliteDialect,
21891
+ SqliteReturningStrategy,
21892
+ SqliteUpsertStrategy,
21790
21893
  StandardDeleteCompiler,
21791
21894
  StandardInsertCompiler,
21895
+ StandardLimitOffsetPagination,
21896
+ StandardReturningStrategy,
21792
21897
  StandardSelectCompiler,
21793
21898
  StandardSqlSourceCompiler,
21899
+ StandardTableFunctionStrategy,
21794
21900
  StandardUpdateCompiler,
21795
21901
  StringTypeStrategy,
21796
21902
  TagIndex,
@@ -21878,6 +21984,7 @@ export {
21878
21984
  createEntityFromRow,
21879
21985
  createEntityProxy,
21880
21986
  createExecutorFromQueryRunner,
21987
+ createMssqlCompilerSet,
21881
21988
  createMssqlExecutor,
21882
21989
  createMysqlExecutor,
21883
21990
  createPooledExecutorFactory,