metal-orm 1.1.2 → 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.
- package/README.md +728 -707
- package/dist/index.cjs +813 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +277 -8
- package/dist/index.d.ts +277 -8
- package/dist/index.js +812 -75
- package/dist/index.js.map +1 -1
- package/package.json +8 -2
- package/scripts/naming-strategy.mjs +16 -1
- package/src/cache/adapters/keyv-cache-adapter.ts +5 -0
- package/src/cache/adapters/memory-cache-adapter.ts +5 -0
- package/src/cache/adapters/redis-cache-adapter.ts +233 -0
- package/src/cache/cache-interfaces.ts +11 -0
- package/src/cache/index.ts +2 -0
- package/src/core/ast/procedure.ts +21 -0
- package/src/core/ast/query.ts +47 -19
- package/src/core/ddl/introspect/utils.ts +56 -56
- package/src/core/dialect/abstract.ts +560 -547
- package/src/core/dialect/base/sql-dialect.ts +43 -29
- package/src/core/dialect/mssql/index.ts +369 -232
- package/src/core/dialect/mysql/index.ts +99 -7
- package/src/core/dialect/postgres/index.ts +121 -60
- package/src/core/dialect/sqlite/index.ts +97 -64
- package/src/core/execution/db-executor.ts +108 -90
- package/src/core/execution/executors/mssql-executor.ts +28 -24
- package/src/core/execution/executors/mysql-executor.ts +62 -27
- package/src/core/execution/executors/sqlite-executor.ts +10 -9
- package/src/index.ts +9 -6
- package/src/orm/execute-procedure.ts +77 -0
- package/src/orm/execute.ts +74 -73
- package/src/orm/interceptor-pipeline.ts +21 -17
- package/src/orm/pooled-executor-factory.ts +41 -20
- package/src/orm/unit-of-work.ts +6 -4
- package/src/query/index.ts +8 -5
- package/src/query-builder/delete.ts +3 -2
- package/src/query-builder/insert-query-state.ts +47 -19
- package/src/query-builder/insert.ts +142 -28
- package/src/query-builder/procedure-call.ts +122 -0
- package/src/query-builder/select/select-operations.ts +5 -2
- package/src/query-builder/select.ts +1146 -1105
- package/src/query-builder/update.ts +3 -2
- 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,8 +88,10 @@ __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,
|
|
94
|
+
RedisCacheAdapter: () => RedisCacheAdapter,
|
|
92
95
|
RelationKinds: () => RelationKinds,
|
|
93
96
|
STANDARD_COLUMN_TYPES: () => STANDARD_COLUMN_TYPES,
|
|
94
97
|
SelectQueryBuilder: () => SelectQueryBuilder,
|
|
@@ -135,6 +138,7 @@ __export(index_exports, {
|
|
|
135
138
|
buildScopeConditions: () => buildScopeConditions,
|
|
136
139
|
calculateRowDepths: () => calculateRowDepths,
|
|
137
140
|
calculateTotalPages: () => calculateTotalPages,
|
|
141
|
+
callProcedure: () => callProcedure,
|
|
138
142
|
canonicalizeSchema: () => canonicalizeSchema,
|
|
139
143
|
caseWhen: () => caseWhen,
|
|
140
144
|
cast: () => cast,
|
|
@@ -207,6 +211,7 @@ __export(index_exports, {
|
|
|
207
211
|
executeHydratedPlain: () => executeHydratedPlain,
|
|
208
212
|
executeHydratedPlainWithContexts: () => executeHydratedPlainWithContexts,
|
|
209
213
|
executeHydratedWithContexts: () => executeHydratedWithContexts,
|
|
214
|
+
executeProcedureAst: () => executeProcedureAst,
|
|
210
215
|
executeSchemaSql: () => executeSchemaSql,
|
|
211
216
|
executeSchemaSqlFor: () => executeSchemaSqlFor,
|
|
212
217
|
exists: () => exists,
|
|
@@ -334,6 +339,7 @@ __export(index_exports, {
|
|
|
334
339
|
paginationParamsSchema: () => paginationParamsSchema,
|
|
335
340
|
parameterToRef: () => parameterToRef,
|
|
336
341
|
parseDuration: () => parseDuration,
|
|
342
|
+
payloadResultSets: () => payloadResultSets,
|
|
337
343
|
pi: () => pi,
|
|
338
344
|
pick: () => pick,
|
|
339
345
|
position: () => position,
|
|
@@ -393,6 +399,7 @@ __export(index_exports, {
|
|
|
393
399
|
threadResults: () => threadResults,
|
|
394
400
|
threadedNodeToOpenApiSchema: () => threadedNodeToOpenApiSchema,
|
|
395
401
|
toColumnRef: () => toColumnRef,
|
|
402
|
+
toExecutionPayload: () => toExecutionPayload,
|
|
396
403
|
toPagedResponse: () => toPagedResponse,
|
|
397
404
|
toPagedResponseBuilder: () => toPagedResponseBuilder,
|
|
398
405
|
toPaginationParams: () => toPaginationParams,
|
|
@@ -1834,6 +1841,9 @@ var Dialect = class _Dialect {
|
|
|
1834
1841
|
compileDeleteAst() {
|
|
1835
1842
|
throw new Error("Not implemented");
|
|
1836
1843
|
}
|
|
1844
|
+
compileProcedureCall() {
|
|
1845
|
+
throw new Error("Not implemented");
|
|
1846
|
+
}
|
|
1837
1847
|
}
|
|
1838
1848
|
return new TestDialect(functionStrategy, tableFunctionStrategy);
|
|
1839
1849
|
}
|
|
@@ -2296,8 +2306,14 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2296
2306
|
const table = this.compileTableName(ast.into);
|
|
2297
2307
|
const columnList = this.compileInsertColumnList(ast.columns);
|
|
2298
2308
|
const source = this.compileInsertSource(ast.source, ctx);
|
|
2309
|
+
const upsert = this.compileUpsertClause(ast, ctx);
|
|
2299
2310
|
const returning = this.compileReturning(ast.returning, ctx);
|
|
2300
|
-
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}".`);
|
|
2301
2317
|
}
|
|
2302
2318
|
compileReturning(returning, ctx) {
|
|
2303
2319
|
return this.returningStrategy.compileReturning(returning, ctx);
|
|
@@ -2316,6 +2332,11 @@ var SqlDialectBase = class extends Dialect {
|
|
|
2316
2332
|
compileInsertColumnList(columns) {
|
|
2317
2333
|
return columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
|
|
2318
2334
|
}
|
|
2335
|
+
ensureConflictColumns(clause, message) {
|
|
2336
|
+
if (!clause.target.columns.length) {
|
|
2337
|
+
throw new Error(message);
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2319
2340
|
compileSelectCore(ast, ctx) {
|
|
2320
2341
|
const columns = this.compileSelectColumns(ast, ctx);
|
|
2321
2342
|
const from = this.compileFrom(ast.from, ctx);
|
|
@@ -2698,9 +2719,52 @@ var PostgresDialect = class extends SqlDialectBase {
|
|
|
2698
2719
|
const columns = this.formatReturningColumns(returning);
|
|
2699
2720
|
return ` RETURNING ${columns}`;
|
|
2700
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
|
+
}
|
|
2701
2743
|
supportsDmlReturningClause() {
|
|
2702
2744
|
return true;
|
|
2703
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
|
+
}
|
|
2704
2768
|
/**
|
|
2705
2769
|
* PostgreSQL requires unqualified column names in SET clause
|
|
2706
2770
|
*/
|
|
@@ -2800,6 +2864,7 @@ var MysqlFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
2800
2864
|
};
|
|
2801
2865
|
|
|
2802
2866
|
// src/core/dialect/mysql/index.ts
|
|
2867
|
+
var sanitizeVariableSuffix = (value) => value.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
2803
2868
|
var MySqlDialect = class extends SqlDialectBase {
|
|
2804
2869
|
dialect = "mysql";
|
|
2805
2870
|
/**
|
|
@@ -2825,6 +2890,73 @@ var MySqlDialect = class extends SqlDialectBase {
|
|
|
2825
2890
|
const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
|
|
2826
2891
|
return `${col2}->'${node.path}'`;
|
|
2827
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
|
+
}
|
|
2828
2960
|
};
|
|
2829
2961
|
|
|
2830
2962
|
// src/core/dialect/sqlite/functions.ts
|
|
@@ -3013,9 +3145,32 @@ var SqliteDialect = class extends SqlDialectBase {
|
|
|
3013
3145
|
return `${this.quoteIdentifier(column.name)}${alias}`;
|
|
3014
3146
|
}).join(", ");
|
|
3015
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
|
+
}
|
|
3016
3167
|
supportsDmlReturningClause() {
|
|
3017
3168
|
return true;
|
|
3018
3169
|
}
|
|
3170
|
+
compileProcedureCall(_ast) {
|
|
3171
|
+
void _ast;
|
|
3172
|
+
throw new Error("Stored procedures are not supported by the SQLite dialect.");
|
|
3173
|
+
}
|
|
3019
3174
|
};
|
|
3020
3175
|
|
|
3021
3176
|
// src/core/dialect/mssql/functions.ts
|
|
@@ -3134,6 +3289,8 @@ var MssqlFunctionStrategy = class extends StandardFunctionStrategy {
|
|
|
3134
3289
|
};
|
|
3135
3290
|
|
|
3136
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}`;
|
|
3137
3294
|
var SqlServerDialect = class extends SqlDialectBase {
|
|
3138
3295
|
dialect = "mssql";
|
|
3139
3296
|
/**
|
|
@@ -3289,12 +3446,58 @@ var SqlServerDialect = class extends SqlDialectBase {
|
|
|
3289
3446
|
if (!ast.columns.length) {
|
|
3290
3447
|
throw new Error("INSERT queries must specify columns.");
|
|
3291
3448
|
}
|
|
3449
|
+
if (ast.onConflict) {
|
|
3450
|
+
return this.compileMergeInsert(ast, ctx);
|
|
3451
|
+
}
|
|
3292
3452
|
const table = this.compileTableName(ast.into);
|
|
3293
3453
|
const columnList = ast.columns.map((column) => this.quoteIdentifier(column.name)).join(", ");
|
|
3294
3454
|
const output = this.compileReturning(ast.returning, ctx);
|
|
3295
3455
|
const source = this.compileInsertValues(ast, ctx);
|
|
3296
3456
|
return `INSERT INTO ${table} (${columnList})${output} ${source}`;
|
|
3297
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
|
+
}
|
|
3298
3501
|
compileInsertValues(ast, ctx) {
|
|
3299
3502
|
const source = ast.source;
|
|
3300
3503
|
if (source.type === "InsertValues") {
|
|
@@ -3317,6 +3520,57 @@ var SqlServerDialect = class extends SqlDialectBase {
|
|
|
3317
3520
|
}).join(", ");
|
|
3318
3521
|
return `WITH ${defs} `;
|
|
3319
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
|
+
}
|
|
3320
3574
|
};
|
|
3321
3575
|
|
|
3322
3576
|
// src/core/dialect/dialect-factory.ts
|
|
@@ -7022,6 +7276,56 @@ var preloadRelationIncludes = async (entities, includeTree, depth = 0) => {
|
|
|
7022
7276
|
}
|
|
7023
7277
|
};
|
|
7024
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
|
+
|
|
7025
7329
|
// src/orm/execute.ts
|
|
7026
7330
|
var flattenResults = (results) => {
|
|
7027
7331
|
const rows = [];
|
|
@@ -7041,7 +7345,7 @@ var executeWithContexts = async (execCtx, entityCtx, qb) => {
|
|
|
7041
7345
|
const ast = qb.getAST();
|
|
7042
7346
|
const compiled = execCtx.dialect.compileSelect(ast);
|
|
7043
7347
|
const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
7044
|
-
const rows = flattenResults(executed);
|
|
7348
|
+
const rows = flattenResults(payloadResultSets(executed));
|
|
7045
7349
|
const lazyRelations = qb.getLazyRelations();
|
|
7046
7350
|
const lazyRelationOptions = qb.getLazyRelationOptions();
|
|
7047
7351
|
const includeTree = qb.getIncludeTree();
|
|
@@ -7061,7 +7365,7 @@ var executePlainWithContexts = async (execCtx, qb) => {
|
|
|
7061
7365
|
const ast = qb.getAST();
|
|
7062
7366
|
const compiled = execCtx.dialect.compileSelect(ast);
|
|
7063
7367
|
const executed = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
7064
|
-
const rows = flattenResults(executed);
|
|
7368
|
+
const rows = flattenResults(payloadResultSets(executed));
|
|
7065
7369
|
if (ast.setOps && ast.setOps.length > 0) {
|
|
7066
7370
|
return rows;
|
|
7067
7371
|
}
|
|
@@ -7329,7 +7633,8 @@ async function executeCount(context, env, session) {
|
|
|
7329
7633
|
};
|
|
7330
7634
|
const execCtx = session.getExecutionContext();
|
|
7331
7635
|
const compiled = execCtx.dialect.compileSelect(countQuery);
|
|
7332
|
-
const
|
|
7636
|
+
const payload = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
7637
|
+
const results = payloadResultSets(payload);
|
|
7333
7638
|
const value = results[0]?.values?.[0]?.[0];
|
|
7334
7639
|
if (typeof value === "number") return value;
|
|
7335
7640
|
if (typeof value === "bigint") return Number(value);
|
|
@@ -7361,7 +7666,8 @@ async function executeCountRows(context, env, session) {
|
|
|
7361
7666
|
};
|
|
7362
7667
|
const execCtx = session.getExecutionContext();
|
|
7363
7668
|
const compiled = execCtx.dialect.compileSelect(countQuery);
|
|
7364
|
-
const
|
|
7669
|
+
const payload = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
7670
|
+
const results = payloadResultSets(payload);
|
|
7365
7671
|
const value = results[0]?.values?.[0]?.[0];
|
|
7366
7672
|
if (typeof value === "number") return value;
|
|
7367
7673
|
if (typeof value === "bigint") return Number(value);
|
|
@@ -8335,6 +8641,45 @@ var SelectQueryBuilder = class _SelectQueryBuilder {
|
|
|
8335
8641
|
* // rows is EntityInstance<UserTable>[] (plain objects)
|
|
8336
8642
|
* rows[0] instanceof User; // false
|
|
8337
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
|
+
}
|
|
8338
8683
|
async executePlain(ctx) {
|
|
8339
8684
|
const builder = this.ensureDefaultSelection();
|
|
8340
8685
|
const rows = await executeHydratedPlain(ctx, builder);
|
|
@@ -9034,9 +9379,95 @@ var InsertQueryState = class _InsertQueryState {
|
|
|
9034
9379
|
returning: [...columns]
|
|
9035
9380
|
});
|
|
9036
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
|
+
}
|
|
9037
9406
|
};
|
|
9038
9407
|
|
|
9039
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
|
+
};
|
|
9040
9471
|
var InsertQueryBuilder = class _InsertQueryBuilder {
|
|
9041
9472
|
table;
|
|
9042
9473
|
state;
|
|
@@ -9052,6 +9483,9 @@ var InsertQueryBuilder = class _InsertQueryBuilder {
|
|
|
9052
9483
|
clone(state) {
|
|
9053
9484
|
return new _InsertQueryBuilder(this.table, state);
|
|
9054
9485
|
}
|
|
9486
|
+
withOnConflict(clause) {
|
|
9487
|
+
return this.clone(this.state.withOnConflict(clause));
|
|
9488
|
+
}
|
|
9055
9489
|
/**
|
|
9056
9490
|
* Adds VALUES to the INSERT query
|
|
9057
9491
|
* @param rowOrRows - Single row object or array of row objects to insert
|
|
@@ -9083,6 +9517,21 @@ var InsertQueryBuilder = class _InsertQueryBuilder {
|
|
|
9083
9517
|
const nodes = columns.length ? this.resolveColumnNodes(columns) : [];
|
|
9084
9518
|
return this.clone(this.state.withSelect(ast, nodes));
|
|
9085
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
|
+
}
|
|
9086
9535
|
/**
|
|
9087
9536
|
* Adds a RETURNING clause to the INSERT query
|
|
9088
9537
|
* @param columns - Columns to return after insertion
|
|
@@ -9360,7 +9809,8 @@ var UpdateQueryBuilder = class _UpdateQueryBuilder {
|
|
|
9360
9809
|
async execute(session) {
|
|
9361
9810
|
const execCtx = session.getExecutionContext();
|
|
9362
9811
|
const compiled = this.compile(execCtx.dialect);
|
|
9363
|
-
|
|
9812
|
+
const payload = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
9813
|
+
return payloadResultSets(payload);
|
|
9364
9814
|
}
|
|
9365
9815
|
/**
|
|
9366
9816
|
* Returns the Abstract Syntax Tree (AST) representation of the query
|
|
@@ -9550,7 +10000,8 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
|
|
|
9550
10000
|
async execute(session) {
|
|
9551
10001
|
const execCtx = session.getExecutionContext();
|
|
9552
10002
|
const compiled = this.compile(execCtx.dialect);
|
|
9553
|
-
|
|
10003
|
+
const payload = await execCtx.interceptors.run({ sql: compiled.sql, params: compiled.params }, execCtx.executor);
|
|
10004
|
+
return payloadResultSets(payload);
|
|
9554
10005
|
}
|
|
9555
10006
|
/**
|
|
9556
10007
|
* Returns the Abstract Syntax Tree (AST) representation of the query
|
|
@@ -9562,6 +10013,149 @@ var DeleteQueryBuilder = class _DeleteQueryBuilder {
|
|
|
9562
10013
|
};
|
|
9563
10014
|
var isTableSourceNode2 = (source) => typeof source.type === "string";
|
|
9564
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
|
+
|
|
9565
10159
|
// src/query/target.ts
|
|
9566
10160
|
var resolveEntityTarget = (ctor) => {
|
|
9567
10161
|
const table = getTableDefFromEntity(ctor);
|
|
@@ -12740,7 +13334,8 @@ var UnitOfWork = class {
|
|
|
12740
13334
|
* @returns Query results
|
|
12741
13335
|
*/
|
|
12742
13336
|
async executeCompiled(compiled) {
|
|
12743
|
-
|
|
13337
|
+
const payload = await this.executor.executeSql(compiled.sql, compiled.params);
|
|
13338
|
+
return payloadResultSets(payload);
|
|
12744
13339
|
}
|
|
12745
13340
|
/**
|
|
12746
13341
|
* Gets columns for RETURNING clause.
|
|
@@ -13884,9 +14479,9 @@ var InterceptorPipeline = class {
|
|
|
13884
14479
|
const dispatch = async () => {
|
|
13885
14480
|
const interceptor = this.interceptors[i++];
|
|
13886
14481
|
if (!interceptor) {
|
|
13887
|
-
return executor.executeSql(ctx.sql, ctx.params);
|
|
14482
|
+
return toExecutionPayload(await executor.executeSql(ctx.sql, ctx.params));
|
|
13888
14483
|
}
|
|
13889
|
-
return interceptor(ctx, dispatch);
|
|
14484
|
+
return toExecutionPayload(await interceptor(ctx, dispatch));
|
|
13890
14485
|
};
|
|
13891
14486
|
return dispatch();
|
|
13892
14487
|
}
|
|
@@ -14009,6 +14604,11 @@ function isValidDuration(value) {
|
|
|
14009
14604
|
// src/cache/adapters/memory-cache-adapter.ts
|
|
14010
14605
|
var MemoryCacheAdapter = class {
|
|
14011
14606
|
name = "memory";
|
|
14607
|
+
capabilities = {
|
|
14608
|
+
tags: true,
|
|
14609
|
+
prefix: true,
|
|
14610
|
+
ttl: true
|
|
14611
|
+
};
|
|
14012
14612
|
storage = /* @__PURE__ */ new Map();
|
|
14013
14613
|
tagIndex = /* @__PURE__ */ new Map();
|
|
14014
14614
|
async get(key) {
|
|
@@ -15135,50 +15735,6 @@ function CEP(options) {
|
|
|
15135
15735
|
};
|
|
15136
15736
|
}
|
|
15137
15737
|
|
|
15138
|
-
// src/core/execution/db-executor.ts
|
|
15139
|
-
function rowsToQueryResult(rows) {
|
|
15140
|
-
if (rows.length === 0) {
|
|
15141
|
-
return { columns: [], values: [] };
|
|
15142
|
-
}
|
|
15143
|
-
const columns = Object.keys(rows[0]);
|
|
15144
|
-
const values = rows.map((row) => columns.map((c) => row[c]));
|
|
15145
|
-
return { columns, values };
|
|
15146
|
-
}
|
|
15147
|
-
function createExecutorFromQueryRunner(runner) {
|
|
15148
|
-
const supportsTransactions = typeof runner.beginTransaction === "function" && typeof runner.commitTransaction === "function" && typeof runner.rollbackTransaction === "function";
|
|
15149
|
-
return {
|
|
15150
|
-
capabilities: {
|
|
15151
|
-
transactions: supportsTransactions
|
|
15152
|
-
},
|
|
15153
|
-
async executeSql(sql, params) {
|
|
15154
|
-
const rows = await runner.query(sql, params);
|
|
15155
|
-
const result = rowsToQueryResult(rows);
|
|
15156
|
-
return [result];
|
|
15157
|
-
},
|
|
15158
|
-
async beginTransaction() {
|
|
15159
|
-
if (!supportsTransactions) {
|
|
15160
|
-
throw new Error("Transactions are not supported by this executor");
|
|
15161
|
-
}
|
|
15162
|
-
await runner.beginTransaction.call(runner);
|
|
15163
|
-
},
|
|
15164
|
-
async commitTransaction() {
|
|
15165
|
-
if (!supportsTransactions) {
|
|
15166
|
-
throw new Error("Transactions are not supported by this executor");
|
|
15167
|
-
}
|
|
15168
|
-
await runner.commitTransaction.call(runner);
|
|
15169
|
-
},
|
|
15170
|
-
async rollbackTransaction() {
|
|
15171
|
-
if (!supportsTransactions) {
|
|
15172
|
-
throw new Error("Transactions are not supported by this executor");
|
|
15173
|
-
}
|
|
15174
|
-
await runner.rollbackTransaction.call(runner);
|
|
15175
|
-
},
|
|
15176
|
-
async dispose() {
|
|
15177
|
-
await runner.dispose?.call(runner);
|
|
15178
|
-
}
|
|
15179
|
-
};
|
|
15180
|
-
}
|
|
15181
|
-
|
|
15182
15738
|
// src/core/execution/pooling/pool.ts
|
|
15183
15739
|
var deferred = () => {
|
|
15184
15740
|
let resolve;
|
|
@@ -15406,6 +15962,36 @@ function createPostgresExecutor(client) {
|
|
|
15406
15962
|
}
|
|
15407
15963
|
|
|
15408
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
|
+
};
|
|
15409
15995
|
function createMysqlExecutor(client) {
|
|
15410
15996
|
const supportsTransactions = typeof client.beginTransaction === "function" && typeof client.commit === "function" && typeof client.rollback === "function";
|
|
15411
15997
|
return {
|
|
@@ -15414,21 +16000,7 @@ function createMysqlExecutor(client) {
|
|
|
15414
16000
|
},
|
|
15415
16001
|
async executeSql(sql, params) {
|
|
15416
16002
|
const [rows] = await client.query(sql, params);
|
|
15417
|
-
|
|
15418
|
-
const header = rows;
|
|
15419
|
-
return [{
|
|
15420
|
-
columns: [],
|
|
15421
|
-
values: [],
|
|
15422
|
-
meta: {
|
|
15423
|
-
insertId: header.insertId,
|
|
15424
|
-
rowsAffected: header.affectedRows
|
|
15425
|
-
}
|
|
15426
|
-
}];
|
|
15427
|
-
}
|
|
15428
|
-
const result = rowsToQueryResult(
|
|
15429
|
-
rows
|
|
15430
|
-
);
|
|
15431
|
-
return [result];
|
|
16003
|
+
return toExecutionPayload(normalizeMysqlResults(rows));
|
|
15432
16004
|
},
|
|
15433
16005
|
async beginTransaction() {
|
|
15434
16006
|
if (!supportsTransactions) {
|
|
@@ -15463,7 +16035,7 @@ function createSqliteExecutor(client) {
|
|
|
15463
16035
|
async executeSql(sql, params) {
|
|
15464
16036
|
const rows = await client.all(sql, params);
|
|
15465
16037
|
const result = rowsToQueryResult(rows);
|
|
15466
|
-
return [result];
|
|
16038
|
+
return toExecutionPayload([result]);
|
|
15467
16039
|
},
|
|
15468
16040
|
async beginTransaction() {
|
|
15469
16041
|
if (!supportsTransactions) {
|
|
@@ -15496,9 +16068,9 @@ function createMssqlExecutor(client) {
|
|
|
15496
16068
|
transactions: supportsTransactions
|
|
15497
16069
|
},
|
|
15498
16070
|
async executeSql(sql, params) {
|
|
15499
|
-
const { recordset } = await client.query(sql, params);
|
|
15500
|
-
const
|
|
15501
|
-
return [
|
|
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 ?? [])));
|
|
15502
16074
|
},
|
|
15503
16075
|
async beginTransaction() {
|
|
15504
16076
|
if (!supportsTransactions) {
|
|
@@ -15564,7 +16136,7 @@ function createTediousMssqlClient(connection, { Request, TYPES }, options) {
|
|
|
15564
16136
|
connection.execSql(request);
|
|
15565
16137
|
}
|
|
15566
16138
|
);
|
|
15567
|
-
return { recordset: rows };
|
|
16139
|
+
return { recordset: rows, recordsets: [rows] };
|
|
15568
16140
|
},
|
|
15569
16141
|
beginTransaction: connection.beginTransaction ? () => new Promise((resolve, reject) => {
|
|
15570
16142
|
connection.beginTransaction(
|
|
@@ -15589,6 +16161,8 @@ function createTediousExecutor(connection, module2, options) {
|
|
|
15589
16161
|
}
|
|
15590
16162
|
|
|
15591
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));
|
|
15592
16166
|
function createPooledExecutorFactory(opts) {
|
|
15593
16167
|
const { pool, adapter } = opts;
|
|
15594
16168
|
const makeExecutor = (mode) => {
|
|
@@ -15600,7 +16174,13 @@ function createPooledExecutorFactory(opts) {
|
|
|
15600
16174
|
};
|
|
15601
16175
|
const executeWithConn = async (conn, sql, params) => {
|
|
15602
16176
|
const rows = await adapter.query(conn, sql, params);
|
|
15603
|
-
|
|
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)]);
|
|
15604
16184
|
};
|
|
15605
16185
|
return {
|
|
15606
16186
|
capabilities: { transactions: true },
|
|
@@ -18862,6 +19442,11 @@ var KeyvCacheAdapter = class {
|
|
|
18862
19442
|
this.keyv = keyv;
|
|
18863
19443
|
}
|
|
18864
19444
|
name = "keyv";
|
|
19445
|
+
capabilities = {
|
|
19446
|
+
tags: false,
|
|
19447
|
+
prefix: true,
|
|
19448
|
+
ttl: true
|
|
19449
|
+
};
|
|
18865
19450
|
async get(key) {
|
|
18866
19451
|
return this.keyv.get(key);
|
|
18867
19452
|
}
|
|
@@ -18905,6 +19490,152 @@ var KeyvCacheAdapter = class {
|
|
|
18905
19490
|
}
|
|
18906
19491
|
};
|
|
18907
19492
|
|
|
19493
|
+
// src/cache/adapters/redis-cache-adapter.ts
|
|
19494
|
+
var RedisCacheAdapter = class {
|
|
19495
|
+
name = "redis";
|
|
19496
|
+
capabilities = {
|
|
19497
|
+
tags: true,
|
|
19498
|
+
prefix: true,
|
|
19499
|
+
ttl: true
|
|
19500
|
+
};
|
|
19501
|
+
redis;
|
|
19502
|
+
ownsConnection;
|
|
19503
|
+
tagPrefix;
|
|
19504
|
+
/**
|
|
19505
|
+
* Cria um adapter Redis
|
|
19506
|
+
*
|
|
19507
|
+
* @param redis - Instância do ioredis OU opções de conexão
|
|
19508
|
+
* @param options - Opções adicionais
|
|
19509
|
+
* @param options.tagPrefix - Prefixo para chaves de tag (default: 'tag:')
|
|
19510
|
+
*
|
|
19511
|
+
* Exemplos:
|
|
19512
|
+
*
|
|
19513
|
+
* // Com instância existente (recomendado para connection pooling):
|
|
19514
|
+
* const redis = new Redis({ host: 'localhost', port: 6379 });
|
|
19515
|
+
* const adapter = new RedisCacheAdapter(redis);
|
|
19516
|
+
*
|
|
19517
|
+
* // Com opções (adapter gerencia conexão):
|
|
19518
|
+
* const adapter = new RedisCacheAdapter({ host: 'localhost', port: 6379 });
|
|
19519
|
+
*
|
|
19520
|
+
* // Para testes com ioredis-mock:
|
|
19521
|
+
* import Redis from 'ioredis-mock';
|
|
19522
|
+
* const adapter = new RedisCacheAdapter(new Redis());
|
|
19523
|
+
*/
|
|
19524
|
+
constructor(redis, options) {
|
|
19525
|
+
this.tagPrefix = options?.tagPrefix ?? "tag:";
|
|
19526
|
+
if (this.isRedisInstance(redis)) {
|
|
19527
|
+
this.redis = redis;
|
|
19528
|
+
this.ownsConnection = false;
|
|
19529
|
+
} else {
|
|
19530
|
+
this.redis = this.createRedis(redis);
|
|
19531
|
+
this.ownsConnection = true;
|
|
19532
|
+
}
|
|
19533
|
+
}
|
|
19534
|
+
isRedisInstance(obj) {
|
|
19535
|
+
return typeof obj === "object" && obj !== null && "get" in obj && "set" in obj && "del" in obj && typeof obj.get === "function";
|
|
19536
|
+
}
|
|
19537
|
+
createRedis(options) {
|
|
19538
|
+
try {
|
|
19539
|
+
const Redis = require("ioredis");
|
|
19540
|
+
return new Redis(options);
|
|
19541
|
+
} catch {
|
|
19542
|
+
throw new Error(
|
|
19543
|
+
"ioredis is required for RedisCacheAdapter. Install it with: npm install ioredis"
|
|
19544
|
+
);
|
|
19545
|
+
}
|
|
19546
|
+
}
|
|
19547
|
+
async get(key) {
|
|
19548
|
+
const value = await this.redis.get(key);
|
|
19549
|
+
if (value === null) {
|
|
19550
|
+
return void 0;
|
|
19551
|
+
}
|
|
19552
|
+
try {
|
|
19553
|
+
return JSON.parse(value);
|
|
19554
|
+
} catch {
|
|
19555
|
+
return void 0;
|
|
19556
|
+
}
|
|
19557
|
+
}
|
|
19558
|
+
async has(key) {
|
|
19559
|
+
const value = await this.redis.get(key);
|
|
19560
|
+
return value !== null;
|
|
19561
|
+
}
|
|
19562
|
+
async set(key, value, ttlMs, tags) {
|
|
19563
|
+
const serialized = JSON.stringify(value);
|
|
19564
|
+
if (ttlMs) {
|
|
19565
|
+
await this.redis.set(key, serialized, "PX", ttlMs);
|
|
19566
|
+
} else {
|
|
19567
|
+
await this.redis.set(key, serialized);
|
|
19568
|
+
}
|
|
19569
|
+
if (tags && tags.length > 0) {
|
|
19570
|
+
await this.registerTags(key, tags);
|
|
19571
|
+
}
|
|
19572
|
+
}
|
|
19573
|
+
async delete(key) {
|
|
19574
|
+
await this.redis.del(key);
|
|
19575
|
+
}
|
|
19576
|
+
async invalidate(key) {
|
|
19577
|
+
await this.delete(key);
|
|
19578
|
+
}
|
|
19579
|
+
async invalidateTags(tags) {
|
|
19580
|
+
const keysToDelete = /* @__PURE__ */ new Set();
|
|
19581
|
+
for (const tag of tags) {
|
|
19582
|
+
const tagKey = `${this.tagPrefix}${tag}`;
|
|
19583
|
+
const keys = await this.redis.smembers(tagKey);
|
|
19584
|
+
for (const key of keys) {
|
|
19585
|
+
keysToDelete.add(key);
|
|
19586
|
+
}
|
|
19587
|
+
await this.redis.del(tagKey);
|
|
19588
|
+
}
|
|
19589
|
+
if (keysToDelete.size > 0) {
|
|
19590
|
+
await this.redis.del(...Array.from(keysToDelete));
|
|
19591
|
+
}
|
|
19592
|
+
}
|
|
19593
|
+
async invalidatePrefix(prefix) {
|
|
19594
|
+
const keysToDelete = [];
|
|
19595
|
+
let cursor = "0";
|
|
19596
|
+
do {
|
|
19597
|
+
const [nextCursor, keys] = await this.redis.scan(
|
|
19598
|
+
cursor,
|
|
19599
|
+
"MATCH",
|
|
19600
|
+
`${prefix}*`,
|
|
19601
|
+
"COUNT",
|
|
19602
|
+
100
|
|
19603
|
+
);
|
|
19604
|
+
cursor = nextCursor;
|
|
19605
|
+
keysToDelete.push(...keys);
|
|
19606
|
+
} while (cursor !== "0");
|
|
19607
|
+
if (keysToDelete.length > 0) {
|
|
19608
|
+
const batchSize = 1e3;
|
|
19609
|
+
for (let i = 0; i < keysToDelete.length; i += batchSize) {
|
|
19610
|
+
const batch = keysToDelete.slice(i, i + batchSize);
|
|
19611
|
+
await this.redis.del(...batch);
|
|
19612
|
+
}
|
|
19613
|
+
}
|
|
19614
|
+
}
|
|
19615
|
+
async registerTags(key, tags) {
|
|
19616
|
+
for (const tag of tags) {
|
|
19617
|
+
const tagKey = `${this.tagPrefix}${tag}`;
|
|
19618
|
+
await this.redis.sadd(tagKey, key);
|
|
19619
|
+
}
|
|
19620
|
+
}
|
|
19621
|
+
async dispose() {
|
|
19622
|
+
if (this.ownsConnection) {
|
|
19623
|
+
try {
|
|
19624
|
+
await this.redis.quit();
|
|
19625
|
+
} catch {
|
|
19626
|
+
this.redis.disconnect?.();
|
|
19627
|
+
}
|
|
19628
|
+
}
|
|
19629
|
+
}
|
|
19630
|
+
/**
|
|
19631
|
+
* Retorna a instância Redis subjacente
|
|
19632
|
+
* Útil para operações avançadas ou health checks
|
|
19633
|
+
*/
|
|
19634
|
+
getRedis() {
|
|
19635
|
+
return this.redis;
|
|
19636
|
+
}
|
|
19637
|
+
};
|
|
19638
|
+
|
|
18908
19639
|
// src/cache/tag-index.ts
|
|
18909
19640
|
var TagIndex = class {
|
|
18910
19641
|
tagToKeys = /* @__PURE__ */ new Map();
|
|
@@ -19025,6 +19756,7 @@ var TagIndex = class {
|
|
|
19025
19756
|
CPF,
|
|
19026
19757
|
Capitalize,
|
|
19027
19758
|
Column,
|
|
19759
|
+
ConflictBuilder,
|
|
19028
19760
|
ConstructorMaterializationStrategy,
|
|
19029
19761
|
DEFAULT_TREE_CONFIG,
|
|
19030
19762
|
DateTimeTypeStrategy,
|
|
@@ -19057,8 +19789,10 @@ var TagIndex = class {
|
|
|
19057
19789
|
Pool,
|
|
19058
19790
|
PostgresDialect,
|
|
19059
19791
|
PrimaryKey,
|
|
19792
|
+
ProcedureCallBuilder,
|
|
19060
19793
|
PrototypeMaterializationStrategy,
|
|
19061
19794
|
QueryCacheManager,
|
|
19795
|
+
RedisCacheAdapter,
|
|
19062
19796
|
RelationKinds,
|
|
19063
19797
|
STANDARD_COLUMN_TYPES,
|
|
19064
19798
|
SelectQueryBuilder,
|
|
@@ -19105,6 +19839,7 @@ var TagIndex = class {
|
|
|
19105
19839
|
buildScopeConditions,
|
|
19106
19840
|
calculateRowDepths,
|
|
19107
19841
|
calculateTotalPages,
|
|
19842
|
+
callProcedure,
|
|
19108
19843
|
canonicalizeSchema,
|
|
19109
19844
|
caseWhen,
|
|
19110
19845
|
cast,
|
|
@@ -19177,6 +19912,7 @@ var TagIndex = class {
|
|
|
19177
19912
|
executeHydratedPlain,
|
|
19178
19913
|
executeHydratedPlainWithContexts,
|
|
19179
19914
|
executeHydratedWithContexts,
|
|
19915
|
+
executeProcedureAst,
|
|
19180
19916
|
executeSchemaSql,
|
|
19181
19917
|
executeSchemaSqlFor,
|
|
19182
19918
|
exists,
|
|
@@ -19304,6 +20040,7 @@ var TagIndex = class {
|
|
|
19304
20040
|
paginationParamsSchema,
|
|
19305
20041
|
parameterToRef,
|
|
19306
20042
|
parseDuration,
|
|
20043
|
+
payloadResultSets,
|
|
19307
20044
|
pi,
|
|
19308
20045
|
pick,
|
|
19309
20046
|
position,
|
|
@@ -19363,6 +20100,7 @@ var TagIndex = class {
|
|
|
19363
20100
|
threadResults,
|
|
19364
20101
|
threadedNodeToOpenApiSchema,
|
|
19365
20102
|
toColumnRef,
|
|
20103
|
+
toExecutionPayload,
|
|
19366
20104
|
toPagedResponse,
|
|
19367
20105
|
toPagedResponseBuilder,
|
|
19368
20106
|
toPaginationParams,
|