forge-sql-orm 2.1.14 → 2.1.16
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 +294 -20
- package/dist/core/ForgeSQLORM.d.ts +16 -7
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/core/ForgeSQLORM.js +73 -15
- package/dist/core/ForgeSQLORM.js.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts +15 -7
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.js.map +1 -1
- package/dist/core/ForgeSQLSelectOperations.d.ts +2 -1
- package/dist/core/ForgeSQLSelectOperations.d.ts.map +1 -1
- package/dist/core/ForgeSQLSelectOperations.js.map +1 -1
- package/dist/core/Rovo.d.ts +40 -0
- package/dist/core/Rovo.d.ts.map +1 -1
- package/dist/core/Rovo.js +164 -138
- package/dist/core/Rovo.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/drizzle/extensions/additionalActions.d.ts.map +1 -1
- package/dist/lib/drizzle/extensions/additionalActions.js +72 -22
- package/dist/lib/drizzle/extensions/additionalActions.js.map +1 -1
- package/dist/utils/cacheTableUtils.d.ts +11 -0
- package/dist/utils/cacheTableUtils.d.ts.map +1 -0
- package/dist/utils/cacheTableUtils.js +450 -0
- package/dist/utils/cacheTableUtils.js.map +1 -0
- package/dist/utils/cacheUtils.d.ts.map +1 -1
- package/dist/utils/cacheUtils.js +3 -22
- package/dist/utils/cacheUtils.js.map +1 -1
- package/dist/utils/forgeDriver.d.ts +3 -2
- package/dist/utils/forgeDriver.d.ts.map +1 -1
- package/dist/utils/forgeDriver.js +24 -27
- package/dist/utils/forgeDriver.js.map +1 -1
- package/dist/utils/metadataContextUtils.d.ts +27 -1
- package/dist/utils/metadataContextUtils.d.ts.map +1 -1
- package/dist/utils/metadataContextUtils.js +237 -10
- package/dist/utils/metadataContextUtils.js.map +1 -1
- package/dist/utils/sqlUtils.d.ts +1 -0
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/dist/utils/sqlUtils.js +217 -119
- package/dist/utils/sqlUtils.js.map +1 -1
- package/dist/webtriggers/applyMigrationsWebTrigger.js +1 -1
- package/dist/webtriggers/index.d.ts +1 -0
- package/dist/webtriggers/index.d.ts.map +1 -1
- package/dist/webtriggers/index.js +1 -0
- package/dist/webtriggers/index.js.map +1 -1
- package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts +60 -0
- package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts.map +1 -0
- package/dist/webtriggers/topSlowestStatementLastHourTrigger.js +55 -0
- package/dist/webtriggers/topSlowestStatementLastHourTrigger.js.map +1 -0
- package/package.json +11 -10
- package/src/core/ForgeSQLORM.ts +78 -14
- package/src/core/ForgeSQLQueryBuilder.ts +15 -5
- package/src/core/ForgeSQLSelectOperations.ts +2 -1
- package/src/core/Rovo.ts +209 -167
- package/src/index.ts +1 -3
- package/src/lib/drizzle/extensions/additionalActions.ts +98 -42
- package/src/utils/cacheTableUtils.ts +511 -0
- package/src/utils/cacheUtils.ts +3 -25
- package/src/utils/forgeDriver.ts +38 -29
- package/src/utils/metadataContextUtils.ts +290 -10
- package/src/utils/sqlUtils.ts +298 -142
- package/src/webtriggers/applyMigrationsWebTrigger.ts +1 -1
- package/src/webtriggers/index.ts +1 -0
- package/src/webtriggers/topSlowestStatementLastHourTrigger.ts +69 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forge-sql-orm",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.16",
|
|
4
4
|
"description": "Drizzle ORM integration for Atlassian @forge/sql. Provides a custom driver, schema migration, two levels of caching (local and global via @forge/kvs), optimistic locking, and query analysis.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"homepage": "https://github.com/vzakharchenko/forge-sql-orm#readme",
|
|
@@ -21,28 +21,29 @@
|
|
|
21
21
|
"drizzle-driver",
|
|
22
22
|
"drizzle-custom-driver",
|
|
23
23
|
"orm",
|
|
24
|
+
"rovo",
|
|
24
25
|
"database"
|
|
25
26
|
],
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"@eslint/js": "^9.39.1",
|
|
28
29
|
"@types/luxon": "^3.7.1",
|
|
29
30
|
"@types/node": "^24.10.1",
|
|
30
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
31
|
-
"@typescript-eslint/parser": "^8.
|
|
32
|
-
"@vitest/coverage-v8": "^4.0.
|
|
33
|
-
"@vitest/ui": "^4.0.
|
|
31
|
+
"@typescript-eslint/eslint-plugin": "^8.48.1",
|
|
32
|
+
"@typescript-eslint/parser": "^8.48.1",
|
|
33
|
+
"@vitest/coverage-v8": "^4.0.15",
|
|
34
|
+
"@vitest/ui": "^4.0.15",
|
|
34
35
|
"eslint": "^9.39.1",
|
|
35
36
|
"eslint-config-prettier": "^10.1.8",
|
|
36
37
|
"eslint-plugin-import": "^2.32.0",
|
|
37
38
|
"eslint-plugin-vitest": "^0.5.4",
|
|
38
39
|
"husky": "^9.1.7",
|
|
39
|
-
"knip": "^5.
|
|
40
|
+
"knip": "^5.71.0",
|
|
40
41
|
"patch-package": "^8.0.1",
|
|
41
|
-
"prettier": "^3.
|
|
42
|
+
"prettier": "^3.7.4",
|
|
42
43
|
"ts-node": "^10.9.2",
|
|
43
44
|
"typescript": "^5.9.3",
|
|
44
45
|
"uuid": "^13.0.0",
|
|
45
|
-
"vitest": "^4.0.
|
|
46
|
+
"vitest": "^4.0.15"
|
|
46
47
|
},
|
|
47
48
|
"license": "MIT",
|
|
48
49
|
"author": "Vasyl Zakharchenko",
|
|
@@ -70,8 +71,8 @@
|
|
|
70
71
|
"README.md"
|
|
71
72
|
],
|
|
72
73
|
"peerDependencies": {
|
|
73
|
-
"@forge/sql": "^3.0.
|
|
74
|
-
"drizzle-orm": "^0.
|
|
74
|
+
"@forge/sql": "^3.0.12",
|
|
75
|
+
"drizzle-orm": "^0.45.0"
|
|
75
76
|
},
|
|
76
77
|
"optionalDependencies": {
|
|
77
78
|
"@forge/kvs": "^1.2.0"
|
package/src/core/ForgeSQLORM.ts
CHANGED
|
@@ -39,7 +39,11 @@ import { cacheApplicationContext, localCacheApplicationContext } from "../utils/
|
|
|
39
39
|
import { clearTablesCache } from "../utils/cacheUtils";
|
|
40
40
|
import { SQLWrapper } from "drizzle-orm/sql/sql";
|
|
41
41
|
import { WithSubquery } from "drizzle-orm/subquery";
|
|
42
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
getLastestMetadata,
|
|
44
|
+
metadataQueryContext,
|
|
45
|
+
MetadataQueryOptions,
|
|
46
|
+
} from "../utils/metadataContextUtils";
|
|
43
47
|
import { operationTypeQueryContext } from "../utils/requestTypeContextUtils";
|
|
44
48
|
import type { MySqlQueryResultKind } from "drizzle-orm/mysql-core/session";
|
|
45
49
|
import { Rovo } from "./Rovo";
|
|
@@ -124,7 +128,15 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
124
128
|
* @param onMetadata - Callback function that receives aggregated execution metadata
|
|
125
129
|
* @param onMetadata.totalDbExecutionTime - Total database execution time across all operations in the query function (in milliseconds)
|
|
126
130
|
* @param onMetadata.totalResponseSize - Total response size across all operations (in bytes)
|
|
127
|
-
* @param onMetadata.
|
|
131
|
+
* @param onMetadata.printQueriesWithPlan - Function to analyze and print query execution plans. Supports two modes:
|
|
132
|
+
* - TopSlowest: Prints execution plans for the slowest queries from the current resolver (default)
|
|
133
|
+
* - SummaryTable: Uses CLUSTER_STATEMENTS_SUMMARY if within time window
|
|
134
|
+
* @param options - Optional configuration for query plan printing behavior
|
|
135
|
+
* @param options.mode - Query plan printing mode: 'TopSlowest' (default) or 'SummaryTable'
|
|
136
|
+
* @param options.summaryTableWindowTime - Time window in milliseconds for summary table queries (default: 15000ms). Only used when mode is 'SummaryTable'
|
|
137
|
+
* @param options.topQueries - Number of top slowest queries to analyze when mode is 'TopSlowest' (default: 1)
|
|
138
|
+
* @param options.showSlowestPlans - Whether to show execution plans for slowest queries in TopSlowest mode (default: true)
|
|
139
|
+
* @param options.normalizeQuery - Whether to normalize SQL queries by replacing parameter values with '?' placeholders (default: true). Set to false to disable normalization if it causes issues
|
|
128
140
|
* @returns Promise with the query result
|
|
129
141
|
*
|
|
130
142
|
* @example
|
|
@@ -136,12 +148,12 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
136
148
|
* const orders = await forgeSQL.selectFrom(ordersTable).where(eq(ordersTable.userId, usersTable.id));
|
|
137
149
|
* return { users, orders };
|
|
138
150
|
* },
|
|
139
|
-
* (totalDbExecutionTime, totalResponseSize,
|
|
151
|
+
* (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
|
|
140
152
|
* const threshold = 500; // ms baseline for this resolver
|
|
141
153
|
*
|
|
142
154
|
* if (totalDbExecutionTime > threshold * 1.5) {
|
|
143
155
|
* console.warn(`[Performance Warning] Resolver exceeded DB time: ${totalDbExecutionTime} ms`);
|
|
144
|
-
* await
|
|
156
|
+
* await printQueriesWithPlan(); // Analyze and print query execution plans
|
|
145
157
|
* } else if (totalDbExecutionTime > threshold) {
|
|
146
158
|
* console.debug(`[Performance Debug] High DB time: ${totalDbExecutionTime} ms`);
|
|
147
159
|
* }
|
|
@@ -164,12 +176,12 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
164
176
|
* .where(eq(demoOrders.userId, demoUsers.id));
|
|
165
177
|
* return { users, orders };
|
|
166
178
|
* },
|
|
167
|
-
* async (totalDbExecutionTime, totalResponseSize,
|
|
179
|
+
* async (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
|
|
168
180
|
* const threshold = 500; // ms baseline for this resolver
|
|
169
181
|
*
|
|
170
182
|
* if (totalDbExecutionTime > threshold * 1.5) {
|
|
171
183
|
* console.warn(`[Performance Warning fetch] Resolver exceeded DB time: ${totalDbExecutionTime} ms`);
|
|
172
|
-
* await
|
|
184
|
+
* await printQueriesWithPlan(); // Optionally log or capture diagnostics for further analysis
|
|
173
185
|
* } else if (totalDbExecutionTime > threshold) {
|
|
174
186
|
* console.debug(`[Performance Debug] High DB time: ${totalDbExecutionTime} ms`);
|
|
175
187
|
* }
|
|
@@ -185,7 +197,47 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
185
197
|
* });
|
|
186
198
|
* ```
|
|
187
199
|
*
|
|
188
|
-
* @
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* // Using TopSlowest mode with custom topQueries
|
|
203
|
+
* const result = await forgeSQL.executeWithMetadata(
|
|
204
|
+
* async () => {
|
|
205
|
+
* const users = await forgeSQL.selectFrom(usersTable);
|
|
206
|
+
* return users;
|
|
207
|
+
* },
|
|
208
|
+
* async (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
|
|
209
|
+
* if (totalDbExecutionTime > 1000) {
|
|
210
|
+
* await printQueriesWithPlan(); // Will print top 3 slowest queries
|
|
211
|
+
* }
|
|
212
|
+
* },
|
|
213
|
+
* {
|
|
214
|
+
* mode: 'TopSlowest', // Print top slowest queries (default)
|
|
215
|
+
* topQueries: 3, // Print top 3 slowest queries
|
|
216
|
+
* }
|
|
217
|
+
* );
|
|
218
|
+
* ```
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```typescript
|
|
222
|
+
* // Using SummaryTable mode for query analysis
|
|
223
|
+
* const result = await forgeSQL.executeWithMetadata(
|
|
224
|
+
* async () => {
|
|
225
|
+
* const users = await forgeSQL.selectFrom(usersTable);
|
|
226
|
+
* return users;
|
|
227
|
+
* },
|
|
228
|
+
* async (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
|
|
229
|
+
* if (totalDbExecutionTime > 1000) {
|
|
230
|
+
* await printQueriesWithPlan(); // Will use CLUSTER_STATEMENTS_SUMMARY if within time window
|
|
231
|
+
* }
|
|
232
|
+
* },
|
|
233
|
+
* {
|
|
234
|
+
* mode: 'SummaryTable', // Use summary tables mode
|
|
235
|
+
* summaryTableWindowTime: 10000, // 10 second window
|
|
236
|
+
* }
|
|
237
|
+
* );
|
|
238
|
+
* ```
|
|
239
|
+
*
|
|
240
|
+
* @note **Important**: When multiple resolvers are running concurrently, their query data may also appear in `printQueriesWithPlan()` analysis, as it queries the global `CLUSTER_STATEMENTS_SUMMARY` table.
|
|
189
241
|
*/
|
|
190
242
|
async executeWithMetadata<T>(
|
|
191
243
|
query: () => Promise<T>,
|
|
@@ -194,6 +246,7 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
194
246
|
totalResponseSize: number,
|
|
195
247
|
printQueriesWithPlan: () => Promise<void>,
|
|
196
248
|
) => Promise<void> | void,
|
|
249
|
+
options?: MetadataQueryOptions,
|
|
197
250
|
): Promise<T> {
|
|
198
251
|
return metadataQueryContext.run(
|
|
199
252
|
{
|
|
@@ -204,6 +257,8 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
204
257
|
printQueriesWithPlan: async () => {
|
|
205
258
|
return;
|
|
206
259
|
},
|
|
260
|
+
options: options,
|
|
261
|
+
statistics: [],
|
|
207
262
|
},
|
|
208
263
|
async () => {
|
|
209
264
|
const result = await query();
|
|
@@ -886,7 +941,15 @@ class ForgeSQLORM implements ForgeSqlOperation {
|
|
|
886
941
|
* @param onMetadata - Callback function that receives aggregated execution metadata
|
|
887
942
|
* @param onMetadata.totalDbExecutionTime - Total database execution time across all operations in the query function (in milliseconds)
|
|
888
943
|
* @param onMetadata.totalResponseSize - Total response size across all operations (in bytes)
|
|
889
|
-
* @param onMetadata.
|
|
944
|
+
* @param onMetadata.printQueriesWithPlan - Function to analyze and print query execution plans. Supports two modes:
|
|
945
|
+
* - TopSlowest: Prints execution plans for the slowest queries from the current resolver (default)
|
|
946
|
+
* - SummaryTable: Uses CLUSTER_STATEMENTS_SUMMARY if within time window
|
|
947
|
+
* @param options - Optional configuration for query plan printing behavior
|
|
948
|
+
* @param options.mode - Query plan printing mode: 'TopSlowest' (default) or 'SummaryTable'
|
|
949
|
+
* @param options.summaryTableWindowTime - Time window in milliseconds for summary table queries (default: 15000ms). Only used when mode is 'SummaryTable'
|
|
950
|
+
* @param options.topQueries - Number of top slowest queries to analyze when mode is 'TopSlowest' (default: 1)
|
|
951
|
+
* @param options.showSlowestPlans - Whether to show execution plans for slowest queries in TopSlowest mode (default: true)
|
|
952
|
+
* @param options.normalizeQuery - Whether to normalize SQL queries by replacing parameter values with '?' placeholders (default: true). Set to false to disable normalization if it causes issues
|
|
890
953
|
* @returns Promise with the query result
|
|
891
954
|
*
|
|
892
955
|
* @example
|
|
@@ -898,12 +961,12 @@ class ForgeSQLORM implements ForgeSqlOperation {
|
|
|
898
961
|
* const orders = await forgeSQL.selectFrom(ordersTable).where(eq(ordersTable.userId, usersTable.id));
|
|
899
962
|
* return { users, orders };
|
|
900
963
|
* },
|
|
901
|
-
* (totalDbExecutionTime, totalResponseSize,
|
|
964
|
+
* (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
|
|
902
965
|
* const threshold = 500; // ms baseline for this resolver
|
|
903
966
|
*
|
|
904
967
|
* if (totalDbExecutionTime > threshold * 1.5) {
|
|
905
968
|
* console.warn(`[Performance Warning] Resolver exceeded DB time: ${totalDbExecutionTime} ms`);
|
|
906
|
-
* await
|
|
969
|
+
* await printQueriesWithPlan(); // Analyze and print query execution plans
|
|
907
970
|
* } else if (totalDbExecutionTime > threshold) {
|
|
908
971
|
* console.debug(`[Performance Debug] High DB time: ${totalDbExecutionTime} ms`);
|
|
909
972
|
* }
|
|
@@ -926,12 +989,12 @@ class ForgeSQLORM implements ForgeSqlOperation {
|
|
|
926
989
|
* .where(eq(demoOrders.userId, demoUsers.id));
|
|
927
990
|
* return { users, orders };
|
|
928
991
|
* },
|
|
929
|
-
* async (totalDbExecutionTime, totalResponseSize,
|
|
992
|
+
* async (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
|
|
930
993
|
* const threshold = 500; // ms baseline for this resolver
|
|
931
994
|
*
|
|
932
995
|
* if (totalDbExecutionTime > threshold * 1.5) {
|
|
933
996
|
* console.warn(`[Performance Warning fetch] Resolver exceeded DB time: ${totalDbExecutionTime} ms`);
|
|
934
|
-
* await
|
|
997
|
+
* await printQueriesWithPlan(); // Optionally log or capture diagnostics for further analysis
|
|
935
998
|
* } else if (totalDbExecutionTime > threshold) {
|
|
936
999
|
* console.debug(`[Performance Debug] High DB time: ${totalDbExecutionTime} ms`);
|
|
937
1000
|
* }
|
|
@@ -947,7 +1010,7 @@ class ForgeSQLORM implements ForgeSqlOperation {
|
|
|
947
1010
|
* });
|
|
948
1011
|
* ```
|
|
949
1012
|
*
|
|
950
|
-
* @note **Important**: When multiple resolvers are running concurrently, their query data may also appear in `
|
|
1013
|
+
* @note **Important**: When multiple resolvers are running concurrently, their query data may also appear in `printQueriesWithPlan()` analysis, as it queries the global `CLUSTER_STATEMENTS_SUMMARY` table.
|
|
951
1014
|
*/
|
|
952
1015
|
async executeWithMetadata<T>(
|
|
953
1016
|
query: () => Promise<T>,
|
|
@@ -956,8 +1019,9 @@ class ForgeSQLORM implements ForgeSqlOperation {
|
|
|
956
1019
|
totalResponseSize: number,
|
|
957
1020
|
printQueriesWithPlan: () => Promise<void>,
|
|
958
1021
|
) => Promise<void> | void,
|
|
1022
|
+
options?: MetadataQueryOptions,
|
|
959
1023
|
): Promise<T> {
|
|
960
|
-
return this.ormInstance.executeWithMetadata(query, onMetadata);
|
|
1024
|
+
return this.ormInstance.executeWithMetadata(query, onMetadata, options);
|
|
961
1025
|
}
|
|
962
1026
|
|
|
963
1027
|
selectCacheable<TSelection extends SelectedFields>(
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
customType,
|
|
7
7
|
MySqlSelectBuilder,
|
|
8
8
|
MySqlTable,
|
|
9
|
+
MySqlColumn,
|
|
9
10
|
} from "drizzle-orm/mysql-core";
|
|
10
11
|
import {
|
|
11
12
|
MySqlSelectDynamic,
|
|
@@ -56,7 +57,7 @@ import { SQLWrapper } from "drizzle-orm/sql/sql";
|
|
|
56
57
|
import type { MySqlQueryResultKind } from "drizzle-orm/mysql-core/session";
|
|
57
58
|
import type { WithBuilder } from "drizzle-orm/mysql-core/subquery";
|
|
58
59
|
import { WithSubquery } from "drizzle-orm/subquery";
|
|
59
|
-
import {
|
|
60
|
+
import { MetadataQueryOptions } from "../utils/metadataContextUtils";
|
|
60
61
|
|
|
61
62
|
/**
|
|
62
63
|
* Core interface for ForgeSQL operations.
|
|
@@ -585,7 +586,15 @@ export interface QueryBuilderForgeSql {
|
|
|
585
586
|
* @param onMetadata - Callback function that receives aggregated execution metadata
|
|
586
587
|
* @param onMetadata.totalDbExecutionTime - Total database execution time across all operations in the query function (in milliseconds)
|
|
587
588
|
* @param onMetadata.totalResponseSize - Total response size across all operations (in bytes)
|
|
588
|
-
* @param onMetadata.
|
|
589
|
+
* @param onMetadata.printQueriesWithPlan - Function to analyze and print query execution plans. Supports two modes:
|
|
590
|
+
* - TopSlowest: Prints execution plans for the slowest queries from the current resolver (default)
|
|
591
|
+
* - SummaryTable: Uses CLUSTER_STATEMENTS_SUMMARY if within time window
|
|
592
|
+
* @param options - Optional configuration for query plan printing behavior
|
|
593
|
+
* @param options.mode - Query plan printing mode: 'TopSlowest' (default) or 'SummaryTable'
|
|
594
|
+
* @param options.summaryTableWindowTime - Time window in milliseconds for summary table queries (default: 15000ms). Only used when mode is 'SummaryTable'
|
|
595
|
+
* @param options.topQueries - Number of top slowest queries to analyze when mode is 'TopSlowest' (default: 1)
|
|
596
|
+
* @param options.showSlowestPlans - Whether to show execution plans for slowest queries in TopSlowest mode (default: true)
|
|
597
|
+
* @param options.normalizeQuery - Whether to normalize SQL queries by replacing parameter values with '?' placeholders (default: true). Set to false to disable normalization if it causes issues
|
|
589
598
|
* @returns Promise with the query result
|
|
590
599
|
*
|
|
591
600
|
* @example
|
|
@@ -597,12 +606,12 @@ export interface QueryBuilderForgeSql {
|
|
|
597
606
|
* const orders = await forgeSQL.selectFrom(ordersTable).where(eq(ordersTable.userId, usersTable.id));
|
|
598
607
|
* return { users, orders };
|
|
599
608
|
* },
|
|
600
|
-
* (totalDbExecutionTime, totalResponseSize,
|
|
609
|
+
* (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
|
|
601
610
|
* const threshold = 500; // ms baseline for this resolver
|
|
602
611
|
*
|
|
603
612
|
* if (totalDbExecutionTime > threshold * 1.5) {
|
|
604
613
|
* console.warn(`[Performance Warning] Resolver exceeded DB time: ${totalDbExecutionTime} ms`);
|
|
605
|
-
* await
|
|
614
|
+
* await printQueriesWithPlan(); // Analyze and print query execution plans
|
|
606
615
|
* } else if (totalDbExecutionTime > threshold) {
|
|
607
616
|
* console.debug(`[Performance Debug] High DB time: ${totalDbExecutionTime} ms`);
|
|
608
617
|
* }
|
|
@@ -655,6 +664,7 @@ export interface QueryBuilderForgeSql {
|
|
|
655
664
|
totalResponseSize: number,
|
|
656
665
|
printQueriesWithPlan: () => Promise<void>,
|
|
657
666
|
) => Promise<void> | void,
|
|
667
|
+
options?: MetadataQueryOptions,
|
|
658
668
|
): Promise<T>;
|
|
659
669
|
/**
|
|
660
670
|
* Executes a raw SQL query with local cache support.
|
|
@@ -1015,7 +1025,7 @@ export interface SchemaSqlForgeSql {
|
|
|
1015
1025
|
* @returns {Promise<T[]>} A list of results as objects
|
|
1016
1026
|
* @throws {Error} If the query execution fails
|
|
1017
1027
|
*/
|
|
1018
|
-
executeRawSQL<T
|
|
1028
|
+
executeRawSQL<T>(query: string, params?: SqlParameters[]): Promise<T[]>;
|
|
1019
1029
|
|
|
1020
1030
|
/**
|
|
1021
1031
|
* Executes a raw SQL update query.
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
AnyMySqlSelectQueryBuilder,
|
|
5
5
|
MySqlSelectDynamic,
|
|
6
6
|
} from "drizzle-orm/mysql-core/query-builders/select.types";
|
|
7
|
+
import { SqlParameters } from "@forge/sql/out/sql-statement";
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Class implementing SQL select operations for ForgeSQL ORM.
|
|
@@ -55,7 +56,7 @@ export class ForgeSQLSelectOperations implements SchemaSqlForgeSql {
|
|
|
55
56
|
* @param {SqlParameters[]} [params] - Optional SQL parameters
|
|
56
57
|
* @returns {Promise<T[]>} A list of results as objects
|
|
57
58
|
*/
|
|
58
|
-
async executeRawSQL<T
|
|
59
|
+
async executeRawSQL<T>(query: string, params?: SqlParameters[]): Promise<T[]> {
|
|
59
60
|
if (this.options.logRawSqlQuery) {
|
|
60
61
|
const paramsStr = params ? `, with params: ${JSON.stringify(params)}` : "";
|
|
61
62
|
// eslint-disable-next-line no-console
|