metal-orm 1.1.3 → 1.1.4

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 (37) hide show
  1. package/README.md +715 -703
  2. package/dist/index.cjs +655 -75
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +170 -8
  5. package/dist/index.d.ts +170 -8
  6. package/dist/index.js +649 -75
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/scripts/naming-strategy.mjs +16 -1
  10. package/src/core/ast/procedure.ts +21 -0
  11. package/src/core/ast/query.ts +47 -19
  12. package/src/core/ddl/introspect/utils.ts +56 -56
  13. package/src/core/dialect/abstract.ts +560 -547
  14. package/src/core/dialect/base/sql-dialect.ts +43 -29
  15. package/src/core/dialect/mssql/index.ts +369 -232
  16. package/src/core/dialect/mysql/index.ts +99 -7
  17. package/src/core/dialect/postgres/index.ts +121 -60
  18. package/src/core/dialect/sqlite/index.ts +97 -64
  19. package/src/core/execution/db-executor.ts +108 -90
  20. package/src/core/execution/executors/mssql-executor.ts +28 -24
  21. package/src/core/execution/executors/mysql-executor.ts +62 -27
  22. package/src/core/execution/executors/sqlite-executor.ts +10 -9
  23. package/src/index.ts +9 -6
  24. package/src/orm/execute-procedure.ts +77 -0
  25. package/src/orm/execute.ts +74 -73
  26. package/src/orm/interceptor-pipeline.ts +21 -17
  27. package/src/orm/pooled-executor-factory.ts +41 -20
  28. package/src/orm/unit-of-work.ts +6 -4
  29. package/src/query/index.ts +8 -5
  30. package/src/query-builder/delete.ts +3 -2
  31. package/src/query-builder/insert-query-state.ts +47 -19
  32. package/src/query-builder/insert.ts +142 -28
  33. package/src/query-builder/procedure-call.ts +122 -0
  34. package/src/query-builder/select/select-operations.ts +5 -2
  35. package/src/query-builder/select.ts +1146 -1105
  36. package/src/query-builder/update.ts +3 -2
  37. package/src/tree/tree-manager.ts +754 -754
package/dist/index.cjs CHANGED
@@ -55,6 +55,7 @@ __export(index_exports, {
55
55
  CPF: () => CPF,
56
56
  Capitalize: () => Capitalize,
57
57
  Column: () => Column,
58
+ ConflictBuilder: () => ConflictBuilder,
58
59
  ConstructorMaterializationStrategy: () => ConstructorMaterializationStrategy,
59
60
  DEFAULT_TREE_CONFIG: () => DEFAULT_TREE_CONFIG,
60
61
  DateTimeTypeStrategy: () => DateTimeTypeStrategy,
@@ -87,6 +88,7 @@ __export(index_exports, {
87
88
  Pool: () => Pool,
88
89
  PostgresDialect: () => PostgresDialect,
89
90
  PrimaryKey: () => PrimaryKey,
91
+ ProcedureCallBuilder: () => ProcedureCallBuilder,
90
92
  PrototypeMaterializationStrategy: () => PrototypeMaterializationStrategy,
91
93
  QueryCacheManager: () => QueryCacheManager,
92
94
  RedisCacheAdapter: () => RedisCacheAdapter,
@@ -136,6 +138,7 @@ __export(index_exports, {
136
138
  buildScopeConditions: () => buildScopeConditions,
137
139
  calculateRowDepths: () => calculateRowDepths,
138
140
  calculateTotalPages: () => calculateTotalPages,
141
+ callProcedure: () => callProcedure,
139
142
  canonicalizeSchema: () => canonicalizeSchema,
140
143
  caseWhen: () => caseWhen,
141
144
  cast: () => cast,
@@ -208,6 +211,7 @@ __export(index_exports, {
208
211
  executeHydratedPlain: () => executeHydratedPlain,
209
212
  executeHydratedPlainWithContexts: () => executeHydratedPlainWithContexts,
210
213
  executeHydratedWithContexts: () => executeHydratedWithContexts,
214
+ executeProcedureAst: () => executeProcedureAst,
211
215
  executeSchemaSql: () => executeSchemaSql,
212
216
  executeSchemaSqlFor: () => executeSchemaSqlFor,
213
217
  exists: () => exists,
@@ -335,6 +339,7 @@ __export(index_exports, {
335
339
  paginationParamsSchema: () => paginationParamsSchema,
336
340
  parameterToRef: () => parameterToRef,
337
341
  parseDuration: () => parseDuration,
342
+ payloadResultSets: () => payloadResultSets,
338
343
  pi: () => pi,
339
344
  pick: () => pick,
340
345
  position: () => position,
@@ -394,6 +399,7 @@ __export(index_exports, {
394
399
  threadResults: () => threadResults,
395
400
  threadedNodeToOpenApiSchema: () => threadedNodeToOpenApiSchema,
396
401
  toColumnRef: () => toColumnRef,
402
+ toExecutionPayload: () => toExecutionPayload,
397
403
  toPagedResponse: () => toPagedResponse,
398
404
  toPagedResponseBuilder: () => toPagedResponseBuilder,
399
405
  toPaginationParams: () => toPaginationParams,
@@ -1835,6 +1841,9 @@ var Dialect = class _Dialect {
1835
1841
  compileDeleteAst() {
1836
1842
  throw new Error("Not implemented");
1837
1843
  }
1844
+ compileProcedureCall() {
1845
+ throw new Error("Not implemented");
1846
+ }
1838
1847
  }
1839
1848
  return new TestDialect(functionStrategy, tableFunctionStrategy);
1840
1849
  }
@@ -2297,8 +2306,14 @@ var SqlDialectBase = class extends Dialect {
2297
2306
  const table = this.compileTableName(ast.into);
2298
2307
  const columnList = this.compileInsertColumnList(ast.columns);
2299
2308
  const source = this.compileInsertSource(ast.source, ctx);
2309
+ const upsert = this.compileUpsertClause(ast, ctx);
2300
2310
  const returning = this.compileReturning(ast.returning, ctx);
2301
- return `INSERT INTO ${table} (${columnList}) ${source}${returning}`;
2311
+ return `INSERT INTO ${table} (${columnList}) ${source}${upsert}${returning}`;
2312
+ }
2313
+ compileUpsertClause(ast, _ctx) {
2314
+ void _ctx;
2315
+ if (!ast.onConflict) return "";
2316
+ throw new Error(`UPSERT/ON CONFLICT is not supported by dialect "${this.dialect}".`);
2302
2317
  }
2303
2318
  compileReturning(returning, ctx) {
2304
2319
  return this.returningStrategy.compileReturning(returning, ctx);
@@ -2317,6 +2332,11 @@ var SqlDialectBase = class extends Dialect {
2317
2332
  compileInsertColumnList(columns) {
2318
2333
  return columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
2319
2334
  }
2335
+ ensureConflictColumns(clause, message) {
2336
+ if (!clause.target.columns.length) {
2337
+ throw new Error(message);
2338
+ }
2339
+ }
2320
2340
  compileSelectCore(ast, ctx) {
2321
2341
  const columns = this.compileSelectColumns(ast, ctx);
2322
2342
  const from = this.compileFrom(ast.from, ctx);
@@ -2699,9 +2719,52 @@ var PostgresDialect = class extends SqlDialectBase {
2699
2719
  const columns = this.formatReturningColumns(returning);
2700
2720
  return ` RETURNING ${columns}`;
2701
2721
  }
2722
+ compileUpsertClause(ast, ctx) {
2723
+ if (!ast.onConflict) return "";
2724
+ const clause = ast.onConflict;
2725
+ const target = clause.target.constraint ? ` ON CONFLICT ON CONSTRAINT ${this.quoteIdentifier(clause.target.constraint)}` : (() => {
2726
+ this.ensureConflictColumns(
2727
+ clause,
2728
+ "PostgreSQL ON CONFLICT requires conflict columns or a constraint name."
2729
+ );
2730
+ const cols = clause.target.columns.map((col2) => this.quoteIdentifier(col2.name)).join(", ");
2731
+ return ` ON CONFLICT (${cols})`;
2732
+ })();
2733
+ if (clause.action.type === "DoNothing") {
2734
+ return `${target} DO NOTHING`;
2735
+ }
2736
+ if (!clause.action.set.length) {
2737
+ throw new Error("PostgreSQL ON CONFLICT DO UPDATE requires at least one assignment.");
2738
+ }
2739
+ const assignments = this.compileUpdateAssignments(clause.action.set, ast.into, ctx);
2740
+ const where = clause.action.where ? ` WHERE ${this.compileExpression(clause.action.where, ctx)}` : "";
2741
+ return `${target} DO UPDATE SET ${assignments}${where}`;
2742
+ }
2702
2743
  supportsDmlReturningClause() {
2703
2744
  return true;
2704
2745
  }
2746
+ compileProcedureCall(ast) {
2747
+ const ctx = this.createCompilerContext();
2748
+ const qualifiedName = ast.ref.schema ? `${this.quoteIdentifier(ast.ref.schema)}.${this.quoteIdentifier(ast.ref.name)}` : this.quoteIdentifier(ast.ref.name);
2749
+ const args = [];
2750
+ for (const param of ast.params) {
2751
+ if (param.direction === "out") continue;
2752
+ if (!param.value) {
2753
+ throw new Error(`Procedure parameter "${param.name}" requires a value for direction "${param.direction}".`);
2754
+ }
2755
+ args.push(this.compileOperand(param.value, ctx));
2756
+ }
2757
+ const outNames = ast.params.filter((param) => param.direction === "out" || param.direction === "inout").map((param) => param.name);
2758
+ const rawSql = `CALL ${qualifiedName}(${args.join(", ")})`;
2759
+ return {
2760
+ sql: `${rawSql};`,
2761
+ params: [...ctx.params],
2762
+ outParams: {
2763
+ source: outNames.length ? "firstResultSet" : "none",
2764
+ names: outNames
2765
+ }
2766
+ };
2767
+ }
2705
2768
  /**
2706
2769
  * PostgreSQL requires unqualified column names in SET clause
2707
2770
  */
@@ -2801,6 +2864,7 @@ var MysqlFunctionStrategy = class extends StandardFunctionStrategy {
2801
2864
  };
2802
2865
 
2803
2866
  // src/core/dialect/mysql/index.ts
2867
+ var sanitizeVariableSuffix = (value) => value.replace(/[^a-zA-Z0-9_]/g, "_");
2804
2868
  var MySqlDialect = class extends SqlDialectBase {
2805
2869
  dialect = "mysql";
2806
2870
  /**
@@ -2826,6 +2890,73 @@ var MySqlDialect = class extends SqlDialectBase {
2826
2890
  const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
2827
2891
  return `${col2}->'${node.path}'`;
2828
2892
  }
2893
+ compileUpsertClause(ast, ctx) {
2894
+ if (!ast.onConflict) return "";
2895
+ const clause = ast.onConflict;
2896
+ if (clause.action.type === "DoNothing") {
2897
+ const noOpColumn = clause.target.columns[0] ?? ast.columns[0];
2898
+ if (!noOpColumn) {
2899
+ throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one target column.");
2900
+ }
2901
+ const col2 = this.quoteIdentifier(noOpColumn.name);
2902
+ return ` ON DUPLICATE KEY UPDATE ${col2} = ${col2}`;
2903
+ }
2904
+ if (clause.action.where) {
2905
+ throw new Error("MySQL ON DUPLICATE KEY UPDATE does not support a WHERE clause.");
2906
+ }
2907
+ if (!clause.action.set.length) {
2908
+ throw new Error("MySQL ON DUPLICATE KEY UPDATE requires at least one assignment.");
2909
+ }
2910
+ const assignments = clause.action.set.map((assignment) => {
2911
+ const target = this.quoteIdentifier(assignment.column.name);
2912
+ const value = this.compileOperand(assignment.value, ctx);
2913
+ return `${target} = ${value}`;
2914
+ }).join(", ");
2915
+ return ` ON DUPLICATE KEY UPDATE ${assignments}`;
2916
+ }
2917
+ compileProcedureCall(ast) {
2918
+ const ctx = this.createCompilerContext();
2919
+ const qualifiedName = ast.ref.schema ? `${this.quoteIdentifier(ast.ref.schema)}.${this.quoteIdentifier(ast.ref.name)}` : this.quoteIdentifier(ast.ref.name);
2920
+ const prelude = [];
2921
+ const callArgs = [];
2922
+ const outVars = [];
2923
+ ast.params.forEach((param, index) => {
2924
+ const suffix = sanitizeVariableSuffix(param.name || `p${index + 1}`);
2925
+ const variable = `@__metal_${suffix}_${index + 1}`;
2926
+ if (param.direction === "in") {
2927
+ if (!param.value) {
2928
+ throw new Error(`Procedure parameter "${param.name}" requires a value for direction "in".`);
2929
+ }
2930
+ callArgs.push(this.compileOperand(param.value, ctx));
2931
+ return;
2932
+ }
2933
+ if (param.direction === "inout") {
2934
+ if (!param.value) {
2935
+ throw new Error(`Procedure parameter "${param.name}" requires a value for direction "inout".`);
2936
+ }
2937
+ prelude.push(`SET ${variable} = ${this.compileOperand(param.value, ctx)};`);
2938
+ }
2939
+ callArgs.push(variable);
2940
+ outVars.push({ variable, name: param.name });
2941
+ });
2942
+ const statements = [];
2943
+ if (prelude.length) {
2944
+ statements.push(...prelude);
2945
+ }
2946
+ statements.push(`CALL ${qualifiedName}(${callArgs.join(", ")});`);
2947
+ if (outVars.length) {
2948
+ const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.quoteIdentifier(name)}`).join(", ");
2949
+ statements.push(`SELECT ${selectOut};`);
2950
+ }
2951
+ return {
2952
+ sql: statements.join(" "),
2953
+ params: [...ctx.params],
2954
+ outParams: {
2955
+ source: outVars.length ? "lastResultSet" : "none",
2956
+ names: outVars.map((item) => item.name)
2957
+ }
2958
+ };
2959
+ }
2829
2960
  };
2830
2961
 
2831
2962
  // src/core/dialect/sqlite/functions.ts
@@ -3014,9 +3145,32 @@ var SqliteDialect = class extends SqlDialectBase {
3014
3145
  return `${this.quoteIdentifier(column.name)}${alias}`;
3015
3146
  }).join(", ");
3016
3147
  }
3148
+ compileUpsertClause(ast, ctx) {
3149
+ if (!ast.onConflict) return "";
3150
+ const clause = ast.onConflict;
3151
+ if (clause.target.constraint) {
3152
+ throw new Error("SQLite ON CONFLICT does not support named constraints.");
3153
+ }
3154
+ this.ensureConflictColumns(clause, "SQLite ON CONFLICT requires conflict columns.");
3155
+ const cols = clause.target.columns.map((col2) => this.quoteIdentifier(col2.name)).join(", ");
3156
+ const target = ` ON CONFLICT (${cols})`;
3157
+ if (clause.action.type === "DoNothing") {
3158
+ return `${target} DO NOTHING`;
3159
+ }
3160
+ if (!clause.action.set.length) {
3161
+ throw new Error("SQLite ON CONFLICT DO UPDATE requires at least one assignment.");
3162
+ }
3163
+ const assignments = this.compileUpdateAssignments(clause.action.set, ast.into, ctx);
3164
+ const where = clause.action.where ? ` WHERE ${this.compileExpression(clause.action.where, ctx)}` : "";
3165
+ return `${target} DO UPDATE SET ${assignments}${where}`;
3166
+ }
3017
3167
  supportsDmlReturningClause() {
3018
3168
  return true;
3019
3169
  }
3170
+ compileProcedureCall(_ast) {
3171
+ void _ast;
3172
+ throw new Error("Stored procedures are not supported by the SQLite dialect.");
3173
+ }
3020
3174
  };
3021
3175
 
3022
3176
  // src/core/dialect/mssql/functions.ts
@@ -3135,6 +3289,8 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
3135
3289
  };
3136
3290
 
3137
3291
  // src/core/dialect/mssql/index.ts
3292
+ var sanitizeVariableSuffix2 = (value) => value.replace(/[^a-zA-Z0-9_]/g, "_");
3293
+ var toProcedureParamReference = (value) => value.startsWith("@") ? value : `@${value}`;
3138
3294
  var SqlServerDialect = class extends SqlDialectBase {
3139
3295
  dialect = "mssql";
3140
3296
  /**
@@ -3290,12 +3446,58 @@ var SqlServerDialect = class extends SqlDialectBase {
3290
3446
  if (!ast.columns.length) {
3291
3447
  throw new Error("INSERT queries must specify columns.");
3292
3448
  }
3449
+ if (ast.onConflict) {
3450
+ return this.compileMergeInsert(ast, ctx);
3451
+ }
3293
3452
  const table = this.compileTableName(ast.into);
3294
3453
  const columnList = ast.columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
3295
3454
  const output = this.compileReturning(ast.returning, ctx);
3296
3455
  const source = this.compileInsertValues(ast, ctx);
3297
3456
  return `INSERT INTO ${table} (${columnList})${output} ${source}`;
3298
3457
  }
3458
+ compileMergeInsert(ast, ctx) {
3459
+ const clause = ast.onConflict;
3460
+ if (clause.target.constraint) {
3461
+ throw new Error("MSSQL MERGE does not support conflict target by constraint name.");
3462
+ }
3463
+ this.ensureConflictColumns(clause, "MSSQL MERGE requires conflict columns for the ON clause.");
3464
+ const table = this.compileTableName(ast.into);
3465
+ const targetRef = this.quoteIdentifier(ast.into.alias ?? ast.into.name);
3466
+ const sourceAlias = this.quoteIdentifier("src");
3467
+ const sourceColumns = ast.columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
3468
+ const usingSource = this.compileMergeUsingSource(ast, ctx);
3469
+ const onClause = clause.target.columns.map((column) => `${targetRef}.${this.quoteIdentifier(column.name)} = ${sourceAlias}.${this.quoteIdentifier(column.name)}`).join(" AND ");
3470
+ const branches = [];
3471
+ if (clause.action.type === "DoUpdate") {
3472
+ if (!clause.action.set.length) {
3473
+ throw new Error("MSSQL MERGE WHEN MATCHED UPDATE requires at least one assignment.");
3474
+ }
3475
+ const assignments = clause.action.set.map((assignment) => {
3476
+ const target = `${targetRef}.${this.quoteIdentifier(assignment.column.name)}`;
3477
+ const value = this.compileOperand(assignment.value, ctx);
3478
+ return `${target} = ${value}`;
3479
+ }).join(", ");
3480
+ const guard = clause.action.where ? ` AND ${this.compileExpression(clause.action.where, ctx)}` : "";
3481
+ branches.push(`WHEN MATCHED${guard} THEN UPDATE SET ${assignments}`);
3482
+ }
3483
+ const insertColumns = ast.columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
3484
+ const insertValues = ast.columns.map((column) => `${sourceAlias}.${this.quoteIdentifier(column.name)}`).join(", ");
3485
+ branches.push(`WHEN NOT MATCHED THEN INSERT (${insertColumns}) VALUES (${insertValues})`);
3486
+ const output = this.compileReturning(ast.returning, ctx);
3487
+ return `MERGE INTO ${table} USING ${usingSource} AS ${sourceAlias} (${sourceColumns}) ON ${onClause} ${branches.join(" ")}${output}`;
3488
+ }
3489
+ compileMergeUsingSource(ast, ctx) {
3490
+ if (ast.source.type === "InsertValues") {
3491
+ if (!ast.source.rows.length) {
3492
+ throw new Error("INSERT ... VALUES requires at least one row.");
3493
+ }
3494
+ const rows = ast.source.rows.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
3495
+ return `(VALUES ${rows})`;
3496
+ }
3497
+ const normalized = this.normalizeSelectAst(ast.source.query);
3498
+ const selectSql = this.compileSelectAst(normalized, ctx).trim().replace(/;$/, "");
3499
+ return `(${selectSql})`;
3500
+ }
3299
3501
  compileInsertValues(ast, ctx) {
3300
3502
  const source = ast.source;
3301
3503
  if (source.type === "InsertValues") {
@@ -3318,6 +3520,57 @@ var SqlServerDialect = class extends SqlDialectBase {
3318
3520
  }).join(", ");
3319
3521
  return `WITH ${defs} `;
3320
3522
  }
3523
+ compileProcedureCall(ast) {
3524
+ const ctx = this.createCompilerContext();
3525
+ const qualifiedName = ast.ref.schema ? `${this.quoteIdentifier(ast.ref.schema)}.${this.quoteIdentifier(ast.ref.name)}` : this.quoteIdentifier(ast.ref.name);
3526
+ const declarations = [];
3527
+ const assignments = [];
3528
+ const execArgs = [];
3529
+ const outVars = [];
3530
+ ast.params.forEach((param, index) => {
3531
+ const targetParam = toProcedureParamReference(param.name);
3532
+ if (param.direction === "in") {
3533
+ if (!param.value) {
3534
+ throw new Error(`Procedure parameter "${param.name}" requires a value for direction "in".`);
3535
+ }
3536
+ execArgs.push(`${targetParam} = ${this.compileOperand(param.value, ctx)}`);
3537
+ return;
3538
+ }
3539
+ if (!param.dbType) {
3540
+ throw new Error(
3541
+ `MSSQL procedure parameter "${param.name}" requires "dbType" for direction "${param.direction}".`
3542
+ );
3543
+ }
3544
+ const suffix = sanitizeVariableSuffix2(param.name || `p${index + 1}`);
3545
+ const variable = `@__metal_${suffix}_${index + 1}`;
3546
+ declarations.push(`DECLARE ${variable} ${param.dbType};`);
3547
+ if (param.direction === "inout") {
3548
+ if (!param.value) {
3549
+ throw new Error(`Procedure parameter "${param.name}" requires a value for direction "inout".`);
3550
+ }
3551
+ assignments.push(`SET ${variable} = ${this.compileOperand(param.value, ctx)};`);
3552
+ }
3553
+ execArgs.push(`${targetParam} = ${variable} OUTPUT`);
3554
+ outVars.push({ variable, name: param.name });
3555
+ });
3556
+ const statements = [];
3557
+ if (declarations.length) statements.push(...declarations);
3558
+ if (assignments.length) statements.push(...assignments);
3559
+ const argsSql = execArgs.length ? ` ${execArgs.join(", ")}` : "";
3560
+ statements.push(`EXEC ${qualifiedName}${argsSql};`);
3561
+ if (outVars.length) {
3562
+ const selectOut = outVars.map(({ variable, name }) => `${variable} AS ${this.quoteIdentifier(name)}`).join(", ");
3563
+ statements.push(`SELECT ${selectOut};`);
3564
+ }
3565
+ return {
3566
+ sql: statements.join(" "),
3567
+ params: [...ctx.params],
3568
+ outParams: {
3569
+ source: outVars.length ? "lastResultSet" : "none",
3570
+ names: outVars.map((item) => item.name)
3571
+ }
3572
+ };
3573
+ }
3321
3574
  };
3322
3575
 
3323
3576
  // src/core/dialect/dialect-factory.ts
@@ -7023,6 +7276,56 @@ var preloadRelationIncludes = async (entities, includeTree, depth = 0) => {
7023
7276
  }
7024
7277
  };
7025
7278
 
7279
+ // src/core/execution/db-executor.ts
7280
+ var toExecutionPayload = (resultSets) => {
7281
+ const payload = resultSets;
7282
+ payload.resultSets = resultSets;
7283
+ return payload;
7284
+ };
7285
+ var payloadResultSets = (payload) => payload.resultSets ?? payload;
7286
+ function rowsToQueryResult(rows) {
7287
+ if (rows.length === 0) {
7288
+ return { columns: [], values: [] };
7289
+ }
7290
+ const columns = Object.keys(rows[0]);
7291
+ const values = rows.map((row) => columns.map((c) => row[c]));
7292
+ return { columns, values };
7293
+ }
7294
+ function createExecutorFromQueryRunner(runner) {
7295
+ const supportsTransactions = typeof runner.beginTransaction === "function" && typeof runner.commitTransaction === "function" && typeof runner.rollbackTransaction === "function";
7296
+ return {
7297
+ capabilities: {
7298
+ transactions: supportsTransactions
7299
+ },
7300
+ async executeSql(sql, params) {
7301
+ const rows = await runner.query(sql, params);
7302
+ const result = rowsToQueryResult(rows);
7303
+ return toExecutionPayload([result]);
7304
+ },
7305
+ async beginTransaction() {
7306
+ if (!supportsTransactions) {
7307
+ throw new Error("Transactions are not supported by this executor");
7308
+ }
7309
+ await runner.beginTransaction.call(runner);
7310
+ },
7311
+ async commitTransaction() {
7312
+ if (!supportsTransactions) {
7313
+ throw new Error("Transactions are not supported by this executor");
7314
+ }
7315
+ await runner.commitTransaction.call(runner);
7316
+ },
7317
+ async rollbackTransaction() {
7318
+ if (!supportsTransactions) {
7319
+ throw new Error("Transactions are not supported by this executor");
7320
+ }
7321
+ await runner.rollbackTransaction.call(runner);
7322
+ },
7323
+ async dispose() {
7324
+ await runner.dispose?.call(runner);
7325
+ }
7326
+ };
7327
+ }
7328
+
7026
7329
  // src/orm/execute.ts
7027
7330
  var flattenResults = (results) => {
7028
7331
  const rows = [];
@@ -7042,7 +7345,7 @@ var executeWithContexts = async (execCtx, entityCtx, qb) => {
7042
7345
  const ast = qb.getAST();
7043
7346
  const compiled = execCtx.dialect.compileSelect(ast);
7044
7347
  const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
7045
- const rows = flattenResults(executed);
7348
+ const rows = flattenResults(payloadResultSets(executed));
7046
7349
  const lazyRelations = qb.getLazyRelations();
7047
7350
  const lazyRelationOptions = qb.getLazyRelationOptions();
7048
7351
  const includeTree = qb.getIncludeTree();
@@ -7062,7 +7365,7 @@ var executePlainWithContexts = async (execCtx, qb) => {
7062
7365
  const ast = qb.getAST();
7063
7366
  const compiled = execCtx.dialect.compileSelect(ast);
7064
7367
  const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
7065
- const rows = flattenResults(executed);
7368
+ const rows = flattenResults(payloadResultSets(executed));
7066
7369
  if (ast.setOps && ast.setOps.length > 0) {
7067
7370
  return rows;
7068
7371
  }
@@ -7330,7 +7633,8 @@ async function executeCount(context, env, session) {
7330
7633
  };
7331
7634
  const execCtx = session.getExecutionContext();
7332
7635
  const compiled = execCtx.dialect.compileSelect(countQuery);
7333
- const results = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
7636
+ const payload = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
7637
+ const results = payloadResultSets(payload);
7334
7638
  const value = results[0]?.values?.[0]?.[0];
7335
7639
  if (typeof value === "number") return value;
7336
7640
  if (typeof value === "bigint") return Number(value);
@@ -7362,7 +7666,8 @@ async function executeCountRows(context, env, session) {
7362
7666
  };
7363
7667
  const execCtx = session.getExecutionContext();
7364
7668
  const compiled = execCtx.dialect.compileSelect(countQuery);
7365
- const results = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
7669
+ const payload = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
7670
+ const results = payloadResultSets(payload);
7366
7671
  const value = results[0]?.values?.[0]?.[0];
7367
7672
  if (typeof value === "number") return value;
7368
7673
  if (typeof value === "bigint") return Number(value);
@@ -8336,6 +8641,45 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
8336
8641
  * // rows is EntityInstance<UserTable>[] (plain objects)
8337
8642
  * rows[0] instanceof User; // false
8338
8643
  */
8644
+ /**
8645
+ * Executes the query with LIMIT 1 and returns the first result.
8646
+ * Throws if no record is found.
8647
+ *
8648
+ * @param ctx - ORM session context
8649
+ * @returns Promise of a single entity instance
8650
+ * @throws Error if no results are found
8651
+ * @example
8652
+ * const user = await selectFromEntity(User)
8653
+ * .where(eq(users.email, 'alice@example.com'))
8654
+ * .firstOrFail(session);
8655
+ */
8656
+ async firstOrFail(ctx) {
8657
+ const rows = await this.limit(1).execute(ctx);
8658
+ if (rows.length === 0) {
8659
+ throw new Error("No results found");
8660
+ }
8661
+ return rows[0];
8662
+ }
8663
+ /**
8664
+ * Executes the query with LIMIT 1 and returns the first result as a plain object (POJO).
8665
+ * Throws if no record is found.
8666
+ *
8667
+ * @param ctx - ORM session context
8668
+ * @returns Promise of a single plain object
8669
+ * @throws Error if no results are found
8670
+ * @example
8671
+ * const user = await selectFromEntity(User)
8672
+ * .where(eq(users.email, 'alice@example.com'))
8673
+ * .firstOrFailPlain(session);
8674
+ * // user is a plain object, not an instance of User
8675
+ */
8676
+ async firstOrFailPlain(ctx) {
8677
+ const rows = await this.limit(1).executePlain(ctx);
8678
+ if (rows.length === 0) {
8679
+ throw new Error("No results found");
8680
+ }
8681
+ return rows[0];
8682
+ }
8339
8683
  async executePlain(ctx) {
8340
8684
  const builder = this.ensureDefaultSelection();
8341
8685
  const rows = await executeHydratedPlain(ctx, builder);
@@ -9035,9 +9379,95 @@ var InsertQueryState = class _InsertQueryState {
9035
9379
  returning: [...columns]
9036
9380
  });
9037
9381
  }
9382
+ /**
9383
+ * Adds an UPSERT conflict clause to the INSERT query
9384
+ * @param clause - Conflict clause and action
9385
+ * @returns A new InsertQueryState with conflict handling configured
9386
+ */
9387
+ withOnConflict(clause) {
9388
+ return this.clone({
9389
+ ...this.ast,
9390
+ onConflict: {
9391
+ target: {
9392
+ columns: [...clause.target.columns],
9393
+ constraint: clause.target.constraint
9394
+ },
9395
+ action: clause.action.type === "DoUpdate" ? {
9396
+ type: "DoUpdate",
9397
+ set: clause.action.set.map((assignment) => ({
9398
+ column: { ...assignment.column },
9399
+ value: assignment.value
9400
+ })),
9401
+ where: clause.action.where
9402
+ } : { type: "DoNothing" }
9403
+ }
9404
+ });
9405
+ }
9038
9406
  };
9039
9407
 
9040
9408
  // src/query-builder/insert.ts
9409
+ var ConflictBuilder = class {
9410
+ table;
9411
+ columns;
9412
+ constraint;
9413
+ applyClause;
9414
+ constructor(table, columns, constraint, applyClause) {
9415
+ this.table = table;
9416
+ this.columns = columns;
9417
+ this.constraint = constraint;
9418
+ this.applyClause = applyClause;
9419
+ }
9420
+ /**
9421
+ * Adds ON CONFLICT ... DO UPDATE
9422
+ * @param set - Column assignments for update branch
9423
+ * @param where - Optional filter for update branch
9424
+ * @returns InsertQueryBuilder with the upsert clause configured
9425
+ */
9426
+ doUpdate(set, where) {
9427
+ const assignments = this.buildAssignments(set);
9428
+ return this.applyClause({
9429
+ target: this.buildTarget(),
9430
+ action: {
9431
+ type: "DoUpdate",
9432
+ set: assignments,
9433
+ where
9434
+ }
9435
+ });
9436
+ }
9437
+ /**
9438
+ * Adds ON CONFLICT ... DO NOTHING
9439
+ * @returns InsertQueryBuilder with the upsert clause configured
9440
+ */
9441
+ doNothing() {
9442
+ return this.applyClause({
9443
+ target: this.buildTarget(),
9444
+ action: { type: "DoNothing" }
9445
+ });
9446
+ }
9447
+ buildTarget() {
9448
+ return {
9449
+ columns: [...this.columns],
9450
+ constraint: this.constraint
9451
+ };
9452
+ }
9453
+ buildAssignments(set) {
9454
+ const entries = Object.entries(set);
9455
+ if (!entries.length) {
9456
+ throw new Error("ON CONFLICT DO UPDATE requires at least one assignment.");
9457
+ }
9458
+ return entries.map(([columnName, rawValue]) => {
9459
+ if (!isValueOperandInput(rawValue)) {
9460
+ throw new Error(
9461
+ `Invalid upsert value for column "${columnName}": only string, number, boolean, Date, Buffer, null, or OperandNodes are allowed`
9462
+ );
9463
+ }
9464
+ return {
9465
+ column: buildColumnNode(this.table, { name: columnName, table: this.table.name }),
9466
+ value: valueToOperand(rawValue)
9467
+ };
9468
+ });
9469
+ }
9470
+ };
9041
9471
  var InsertQueryBuilder = class _InsertQueryBuilder {
9042
9472
  table;
9043
9473
  state;
@@ -9053,6 +9483,9 @@ var InsertQueryBuilder = class _InsertQueryBuilder {
9053
9483
  clone(state) {
9054
9484
  return new _InsertQueryBuilder(this.table, state);
9055
9485
  }
9486
+ withOnConflict(clause) {
9487
+ return this.clone(this.state.withOnConflict(clause));
9488
+ }
9056
9489
  /**
9057
9490
  * Adds VALUES to the INSERT query
9058
9491
  * @param rowOrRows - Single row object or array of row objects to insert
@@ -9084,6 +9517,21 @@ var InsertQueryBuilder = class _InsertQueryBuilder {
9084
9517
  const nodes = columns.length ? this.resolveColumnNodes(columns) : [];
9085
9518
  return this.clone(this.state.withSelect(ast, nodes));
9086
9519
  }
9520
+ /**
9521
+ * Configures UPSERT conflict handling for INSERT.
9522
+ * @param columns - Conflict target columns (ignored by MySQL)
9523
+ * @param constraint - Named unique/primary constraint (PostgreSQL only)
9524
+ * @returns ConflictBuilder for selecting action (DO UPDATE / DO NOTHING)
9525
+ */
9526
+ onConflict(columns = [], constraint) {
9527
+ const resolvedColumns = columns.length ? this.resolveColumnNodes(columns) : [];
9528
+ return new ConflictBuilder(
9529
+ this.table,
9530
+ resolvedColumns,
9531
+ constraint,
9532
+ (clause) => this.withOnConflict(clause)
9533
+ );
9534
+ }
9087
9535
  /**
9088
9536
  * Adds a RETURNING clause to the INSERT query
9089
9537
  * @param columns - Columns to return after insertion
@@ -9361,7 +9809,8 @@ var UpdateQueryBuilder = class _UpdateQueryBuilder {
9361
9809
  async execute(session) {
9362
9810
  const execCtx = session.getExecutionContext();
9363
9811
  const compiled = this.compile(execCtx.dialect);
9364
- return execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
9812
+ const payload = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
9813
+ return payloadResultSets(payload);
9365
9814
  }
9366
9815
  /**
9367
9816
  * Returns the Abstract Syntax Tree (AST) representation of the query
@@ -9551,7 +10000,8 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
9551
10000
  async execute(session) {
9552
10001
  const execCtx = session.getExecutionContext();
9553
10002
  const compiled = this.compile(execCtx.dialect);
9554
- return execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
10003
+ const payload = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
10004
+ return payloadResultSets(payload);
9555
10005
  }
9556
10006
  /**
9557
10007
  * Returns the Abstract Syntax Tree (AST) representation of the query
@@ -9563,6 +10013,149 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
9563
10013
  };
9564
10014
  var isTableSourceNode2 = (source) => typeof source.type === "string";
9565
10015
 
10016
+ // src/orm/execute-procedure.ts
10017
+ var resolveColumnIndex = (columns, expectedName) => {
10018
+ const exact = columns.findIndex((column) => column === expectedName);
10019
+ if (exact >= 0) return exact;
10020
+ const lowerExpected = expectedName.toLowerCase();
10021
+ return columns.findIndex((column) => column.toLowerCase() === lowerExpected);
10022
+ };
10023
+ var extractOutValues = (compiled, resultSets) => {
10024
+ if (!compiled.outParams.names.length || compiled.outParams.source === "none") {
10025
+ return {};
10026
+ }
10027
+ const sourceSet = compiled.outParams.source === "firstResultSet" ? resultSets[0] : resultSets[resultSets.length - 1];
10028
+ if (!sourceSet) {
10029
+ throw new Error(
10030
+ `Procedure expected OUT parameters in ${compiled.outParams.source}, but no result set was returned.`
10031
+ );
10032
+ }
10033
+ if (!sourceSet.values.length) {
10034
+ throw new Error(
10035
+ `Procedure expected OUT parameters in ${compiled.outParams.source}, but the result set has no rows.`
10036
+ );
10037
+ }
10038
+ const firstRow = sourceSet.values[0];
10039
+ const out = {};
10040
+ for (const expectedName of compiled.outParams.names) {
10041
+ const columnIndex = resolveColumnIndex(sourceSet.columns, expectedName);
10042
+ if (columnIndex < 0) {
10043
+ const available = sourceSet.columns.length ? sourceSet.columns.join(", ") : "(none)";
10044
+ throw new Error(
10045
+ `Procedure OUT parameter "${expectedName}" was not found in ${compiled.outParams.source}. Available columns: ${available}.`
10046
+ );
10047
+ }
10048
+ out[expectedName] = firstRow[columnIndex];
10049
+ }
10050
+ return out;
10051
+ };
10052
+ var executeProcedureAst = async (session, ast) => {
10053
+ const execCtx = session.getExecutionContext();
10054
+ const compiled = execCtx.dialect.compileProcedureCall(ast);
10055
+ const payload = await execCtx.interceptors.run(
10056
+ { sql: compiled.sql, params: compiled.params },
10057
+ execCtx.executor
10058
+ );
10059
+ const resultSets = payloadResultSets(payload);
10060
+ return {
10061
+ resultSets,
10062
+ out: extractOutValues(compiled, resultSets)
10063
+ };
10064
+ };
10065
+
10066
+ // src/query-builder/procedure-call.ts
10067
+ var cloneParam = (param) => ({
10068
+ ...param,
10069
+ value: param.value ? { ...param.value } : void 0
10070
+ });
10071
+ var ProcedureCallBuilder = class _ProcedureCallBuilder {
10072
+ ast;
10073
+ constructor(name, options, ast) {
10074
+ this.ast = ast ?? {
10075
+ type: "ProcedureCall",
10076
+ ref: {
10077
+ name,
10078
+ schema: options?.schema
10079
+ },
10080
+ params: []
10081
+ };
10082
+ }
10083
+ clone(nextParams) {
10084
+ return new _ProcedureCallBuilder(
10085
+ this.ast.ref.name,
10086
+ { schema: this.ast.ref.schema },
10087
+ {
10088
+ ...this.ast,
10089
+ ref: { ...this.ast.ref },
10090
+ params: nextParams
10091
+ }
10092
+ );
10093
+ }
10094
+ in(name, value) {
10095
+ return this.clone([
10096
+ ...this.ast.params.map(cloneParam),
10097
+ {
10098
+ name,
10099
+ direction: "in",
10100
+ value: valueToOperand(value)
10101
+ }
10102
+ ]);
10103
+ }
10104
+ out(name, options) {
10105
+ return this.clone([
10106
+ ...this.ast.params.map(cloneParam),
10107
+ {
10108
+ name,
10109
+ direction: "out",
10110
+ dbType: options?.dbType
10111
+ }
10112
+ ]);
10113
+ }
10114
+ inOut(name, value, options) {
10115
+ return this.clone([
10116
+ ...this.ast.params.map(cloneParam),
10117
+ {
10118
+ name,
10119
+ direction: "inout",
10120
+ value: valueToOperand(value),
10121
+ dbType: options?.dbType
10122
+ }
10123
+ ]);
10124
+ }
10125
+ compile(dialect) {
10126
+ const resolved = resolveDialectInput(dialect);
10127
+ this.validateMssqlOutDbType(resolved);
10128
+ return resolved.compileProcedureCall(this.getAST());
10129
+ }
10130
+ toSql(dialect) {
10131
+ return this.compile(dialect).sql;
10132
+ }
10133
+ getAST() {
10134
+ return {
10135
+ ...this.ast,
10136
+ ref: { ...this.ast.ref },
10137
+ params: this.ast.params.map(cloneParam)
10138
+ };
10139
+ }
10140
+ async execute(session) {
10141
+ this.validateMssqlOutDbType(session.getExecutionContext().dialect);
10142
+ return executeProcedureAst(session, this.getAST());
10143
+ }
10144
+ validateMssqlOutDbType(dialect) {
10145
+ const isMssqlDialect = dialect.constructor.name === "SqlServerDialect";
10146
+ if (!isMssqlDialect) return;
10147
+ for (const param of this.ast.params) {
10148
+ const needsDbType = param.direction === "out" || param.direction === "inout";
10149
+ if (needsDbType && !param.dbType) {
10150
+ throw new Error(
10151
+ `MSSQL requires "dbType" for procedure parameter "${param.name}" with direction "${param.direction}".`
10152
+ );
10153
+ }
10154
+ }
10155
+ }
10156
+ };
10157
+ var callProcedure = (name, options) => new ProcedureCallBuilder(name, options);
10158
+
9566
10159
  // src/query/target.ts
9567
10160
  var resolveEntityTarget = (ctor) => {
9568
10161
  const table = getTableDefFromEntity(ctor);
@@ -12741,7 +13334,8 @@ var UnitOfWork = class {
12741
13334
  * @returns Query results
12742
13335
  */
12743
13336
  async executeCompiled(compiled) {
12744
- return this.executor.executeSql(compiled.sql, compiled.params);
13337
+ const payload = await this.executor.executeSql(compiled.sql, compiled.params);
13338
+ return payloadResultSets(payload);
12745
13339
  }
12746
13340
  /**
12747
13341
  * Gets columns for RETURNING clause.
@@ -13885,9 +14479,9 @@ var InterceptorPipeline = class {
13885
14479
  const dispatch = async () => {
13886
14480
  const interceptor = this.interceptors[i++];
13887
14481
  if (!interceptor) {
13888
- return executor.executeSql(ctx.sql, ctx.params);
14482
+ return toExecutionPayload(await executor.executeSql(ctx.sql, ctx.params));
13889
14483
  }
13890
- return interceptor(ctx, dispatch);
14484
+ return toExecutionPayload(await interceptor(ctx, dispatch));
13891
14485
  };
13892
14486
  return dispatch();
13893
14487
  }
@@ -15141,50 +15735,6 @@ function CEP(options) {
15141
15735
  };
15142
15736
  }
15143
15737
 
15144
- // src/core/execution/db-executor.ts
15145
- function rowsToQueryResult(rows) {
15146
- if (rows.length === 0) {
15147
- return { columns: [], values: [] };
15148
- }
15149
- const columns = Object.keys(rows[0]);
15150
- const values = rows.map((row) => columns.map((c) => row[c]));
15151
- return { columns, values };
15152
- }
15153
- function createExecutorFromQueryRunner(runner) {
15154
- const supportsTransactions = typeof runner.beginTransaction === "function" && typeof runner.commitTransaction === "function" && typeof runner.rollbackTransaction === "function";
15155
- return {
15156
- capabilities: {
15157
- transactions: supportsTransactions
15158
- },
15159
- async executeSql(sql, params) {
15160
- const rows = await runner.query(sql, params);
15161
- const result = rowsToQueryResult(rows);
15162
- return [result];
15163
- },
15164
- async beginTransaction() {
15165
- if (!supportsTransactions) {
15166
- throw new Error("Transactions are not supported by this executor");
15167
- }
15168
- await runner.beginTransaction.call(runner);
15169
- },
15170
- async commitTransaction() {
15171
- if (!supportsTransactions) {
15172
- throw new Error("Transactions are not supported by this executor");
15173
- }
15174
- await runner.commitTransaction.call(runner);
15175
- },
15176
- async rollbackTransaction() {
15177
- if (!supportsTransactions) {
15178
- throw new Error("Transactions are not supported by this executor");
15179
- }
15180
- await runner.rollbackTransaction.call(runner);
15181
- },
15182
- async dispose() {
15183
- await runner.dispose?.call(runner);
15184
- }
15185
- };
15186
- }
15187
-
15188
15738
  // src/core/execution/pooling/pool.ts
15189
15739
  var deferred = () => {
15190
15740
  let resolve;
@@ -15412,6 +15962,36 @@ function createPostgresExecutor(client) {
15412
15962
  }
15413
15963
 
15414
15964
  // src/core/execution/executors/mysql-executor.ts
15965
+ var isRowObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
15966
+ var isRowObjectArray = (value) => Array.isArray(value) && value.every(isRowObject);
15967
+ var isMysqlResultHeader = (value) => isRowObject(value) && ("affectedRows" in value || "insertId" in value || "warningStatus" in value || "serverStatus" in value);
15968
+ var headerToQueryResult = (header) => ({
15969
+ columns: [],
15970
+ values: [],
15971
+ meta: {
15972
+ insertId: header.insertId,
15973
+ rowsAffected: header.affectedRows
15974
+ }
15975
+ });
15976
+ var normalizeMysqlResults = (rows) => {
15977
+ if (!Array.isArray(rows)) {
15978
+ return isMysqlResultHeader(rows) ? [headerToQueryResult(rows)] : [rowsToQueryResult([])];
15979
+ }
15980
+ if (isRowObjectArray(rows)) {
15981
+ return [rowsToQueryResult(rows)];
15982
+ }
15983
+ const normalized = [];
15984
+ for (const chunk of rows) {
15985
+ if (isRowObjectArray(chunk)) {
15986
+ normalized.push(rowsToQueryResult(chunk));
15987
+ continue;
15988
+ }
15989
+ if (isMysqlResultHeader(chunk)) {
15990
+ normalized.push(headerToQueryResult(chunk));
15991
+ }
15992
+ }
15993
+ return normalized.length ? normalized : [rowsToQueryResult([])];
15994
+ };
15415
15995
  function createMysqlExecutor(client) {
15416
15996
  const supportsTransactions = typeof client.beginTransaction === "function" && typeof client.commit === "function" && typeof client.rollback === "function";
15417
15997
  return {
@@ -15420,21 +16000,7 @@ function createMysqlExecutor(client) {
15420
16000
  },
15421
16001
  async executeSql(sql, params) {
15422
16002
  const [rows] = await client.query(sql, params);
15423
- if (!Array.isArray(rows)) {
15424
- const header = rows;
15425
- return [{
15426
- columns: [],
15427
- values: [],
15428
- meta: {
15429
- insertId: header.insertId,
15430
- rowsAffected: header.affectedRows
15431
- }
15432
- }];
15433
- }
15434
- const result = rowsToQueryResult(
15435
- rows
15436
- );
15437
- return [result];
16003
+ return toExecutionPayload(normalizeMysqlResults(rows));
15438
16004
  },
15439
16005
  async beginTransaction() {
15440
16006
  if (!supportsTransactions) {
@@ -15469,7 +16035,7 @@ function createSqliteExecutor(client) {
15469
16035
  async executeSql(sql, params) {
15470
16036
  const rows = await client.all(sql, params);
15471
16037
  const result = rowsToQueryResult(rows);
15472
- return [result];
16038
+ return toExecutionPayload([result]);
15473
16039
  },
15474
16040
  async beginTransaction() {
15475
16041
  if (!supportsTransactions) {
@@ -15502,9 +16068,9 @@ function createMssqlExecutor(client) {
15502
16068
  transactions: supportsTransactions
15503
16069
  },
15504
16070
  async executeSql(sql, params) {
15505
- const { recordset } = await client.query(sql, params);
15506
- const result = rowsToQueryResult(recordset ?? []);
15507
- return [result];
16071
+ const { recordset, recordsets } = await client.query(sql, params);
16072
+ const sets = Array.isArray(recordsets) ? recordsets : [recordset ?? []];
16073
+ return toExecutionPayload(sets.map((set) => rowsToQueryResult(set ?? [])));
15508
16074
  },
15509
16075
  async beginTransaction() {
15510
16076
  if (!supportsTransactions) {
@@ -15570,7 +16136,7 @@ function createTediousMssqlClient(connection, { Request, TYPES }, options) {
15570
16136
  connection.execSql(request);
15571
16137
  }
15572
16138
  );
15573
- return { recordset: rows };
16139
+ return { recordset: rows, recordsets: [rows] };
15574
16140
  },
15575
16141
  beginTransaction: connection.beginTransaction ? () => new Promise((resolve, reject) => {
15576
16142
  connection.beginTransaction(
@@ -15595,6 +16161,8 @@ function createTediousExecutor(connection, module2, options) {
15595
16161
  }
15596
16162
 
15597
16163
  // src/orm/pooled-executor-factory.ts
16164
+ var isQueryResult = (value) => typeof value === "object" && value !== null && Array.isArray(value.columns) && Array.isArray(value.values);
16165
+ var isRowArray = (value) => Array.isArray(value) && value.every((item) => typeof item === "object" && item !== null && !Array.isArray(item));
15598
16166
  function createPooledExecutorFactory(opts) {
15599
16167
  const { pool, adapter } = opts;
15600
16168
  const makeExecutor = (mode) => {
@@ -15606,7 +16174,13 @@ function createPooledExecutorFactory(opts) {
15606
16174
  };
15607
16175
  const executeWithConn = async (conn, sql, params) => {
15608
16176
  const rows = await adapter.query(conn, sql, params);
15609
- return [rowsToQueryResult(rows)];
16177
+ if (Array.isArray(rows) && rows.length > 0 && rows.every(isQueryResult)) {
16178
+ return toExecutionPayload(rows);
16179
+ }
16180
+ if (Array.isArray(rows) && rows.length > 0 && rows.every(isRowArray)) {
16181
+ return toExecutionPayload(rows.map((set) => rowsToQueryResult(set)));
16182
+ }
16183
+ return toExecutionPayload([rowsToQueryResult(rows)]);
15610
16184
  };
15611
16185
  return {
15612
16186
  capabilities: { transactions: true },
@@ -19182,6 +19756,7 @@ var TagIndex = class {
19182
19756
  CPF,
19183
19757
  Capitalize,
19184
19758
  Column,
19759
+ ConflictBuilder,
19185
19760
  ConstructorMaterializationStrategy,
19186
19761
  DEFAULT_TREE_CONFIG,
19187
19762
  DateTimeTypeStrategy,
@@ -19214,6 +19789,7 @@ var TagIndex = class {
19214
19789
  Pool,
19215
19790
  PostgresDialect,
19216
19791
  PrimaryKey,
19792
+ ProcedureCallBuilder,
19217
19793
  PrototypeMaterializationStrategy,
19218
19794
  QueryCacheManager,
19219
19795
  RedisCacheAdapter,
@@ -19263,6 +19839,7 @@ var TagIndex = class {
19263
19839
  buildScopeConditions,
19264
19840
  calculateRowDepths,
19265
19841
  calculateTotalPages,
19842
+ callProcedure,
19266
19843
  canonicalizeSchema,
19267
19844
  caseWhen,
19268
19845
  cast,
@@ -19335,6 +19912,7 @@ var TagIndex = class {
19335
19912
  executeHydratedPlain,
19336
19913
  executeHydratedPlainWithContexts,
19337
19914
  executeHydratedWithContexts,
19915
+ executeProcedureAst,
19338
19916
  executeSchemaSql,
19339
19917
  executeSchemaSqlFor,
19340
19918
  exists,
@@ -19462,6 +20040,7 @@ var TagIndex = class {
19462
20040
  paginationParamsSchema,
19463
20041
  parameterToRef,
19464
20042
  parseDuration,
20043
+ payloadResultSets,
19465
20044
  pi,
19466
20045
  pick,
19467
20046
  position,
@@ -19521,6 +20100,7 @@ var TagIndex = class {
19521
20100
  threadResults,
19522
20101
  threadedNodeToOpenApiSchema,
19523
20102
  toColumnRef,
20103
+ toExecutionPayload,
19524
20104
  toPagedResponse,
19525
20105
  toPagedResponseBuilder,
19526
20106
  toPaginationParams,