forge-sql-orm 2.1.4 → 2.1.6

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 (52) hide show
  1. package/README.md +195 -27
  2. package/dist/ForgeSQLORM.js +632 -192
  3. package/dist/ForgeSQLORM.js.map +1 -1
  4. package/dist/ForgeSQLORM.mjs +632 -192
  5. package/dist/ForgeSQLORM.mjs.map +1 -1
  6. package/dist/core/ForgeSQLCrudOperations.d.ts.map +1 -1
  7. package/dist/core/ForgeSQLORM.d.ts +114 -3
  8. package/dist/core/ForgeSQLORM.d.ts.map +1 -1
  9. package/dist/core/ForgeSQLQueryBuilder.d.ts +125 -7
  10. package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
  11. package/dist/core/ForgeSQLSelectOperations.d.ts.map +1 -1
  12. package/dist/core/SystemTables.d.ts +3654 -0
  13. package/dist/core/SystemTables.d.ts.map +1 -1
  14. package/dist/lib/drizzle/extensions/additionalActions.d.ts +2 -2
  15. package/dist/lib/drizzle/extensions/additionalActions.d.ts.map +1 -1
  16. package/dist/utils/cacheContextUtils.d.ts.map +1 -1
  17. package/dist/utils/cacheUtils.d.ts.map +1 -1
  18. package/dist/utils/forgeDriver.d.ts +71 -3
  19. package/dist/utils/forgeDriver.d.ts.map +1 -1
  20. package/dist/utils/forgeDriverProxy.d.ts.map +1 -1
  21. package/dist/utils/metadataContextUtils.d.ts +11 -0
  22. package/dist/utils/metadataContextUtils.d.ts.map +1 -0
  23. package/dist/utils/requestTypeContextUtils.d.ts +8 -0
  24. package/dist/utils/requestTypeContextUtils.d.ts.map +1 -0
  25. package/dist/utils/sqlUtils.d.ts.map +1 -1
  26. package/dist/webtriggers/applyMigrationsWebTrigger.d.ts.map +1 -1
  27. package/dist/webtriggers/clearCacheSchedulerTrigger.d.ts.map +1 -1
  28. package/dist/webtriggers/dropMigrationWebTrigger.d.ts.map +1 -1
  29. package/dist/webtriggers/dropTablesMigrationWebTrigger.d.ts.map +1 -1
  30. package/dist/webtriggers/fetchSchemaWebTrigger.d.ts.map +1 -1
  31. package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts +85 -43
  32. package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts.map +1 -1
  33. package/package.json +9 -9
  34. package/src/core/ForgeSQLCrudOperations.ts +3 -0
  35. package/src/core/ForgeSQLORM.ts +287 -9
  36. package/src/core/ForgeSQLQueryBuilder.ts +138 -8
  37. package/src/core/ForgeSQLSelectOperations.ts +2 -0
  38. package/src/core/SystemTables.ts +16 -0
  39. package/src/lib/drizzle/extensions/additionalActions.ts +10 -12
  40. package/src/utils/cacheContextUtils.ts +4 -2
  41. package/src/utils/cacheUtils.ts +20 -8
  42. package/src/utils/forgeDriver.ts +223 -23
  43. package/src/utils/forgeDriverProxy.ts +2 -0
  44. package/src/utils/metadataContextUtils.ts +22 -0
  45. package/src/utils/requestTypeContextUtils.ts +11 -0
  46. package/src/utils/sqlUtils.ts +1 -0
  47. package/src/webtriggers/applyMigrationsWebTrigger.ts +9 -6
  48. package/src/webtriggers/clearCacheSchedulerTrigger.ts +1 -0
  49. package/src/webtriggers/dropMigrationWebTrigger.ts +2 -0
  50. package/src/webtriggers/dropTablesMigrationWebTrigger.ts +2 -0
  51. package/src/webtriggers/fetchSchemaWebTrigger.ts +1 -0
  52. package/src/webtriggers/topSlowestStatementLastHourTrigger.ts +515 -257
package/README.md CHANGED
@@ -19,11 +19,12 @@
19
19
  - ✅ **Custom Drizzle Driver** for direct integration with @forge/sql
20
20
  - ✅ **Local Cache System (Level 1)** for in-memory query optimization within single resolver invocation scope
21
21
  - ✅ **Global Cache System (Level 2)** with cross-invocation caching, automatic cache invalidation and context-aware operations (using [@forge/kvs](https://developer.atlassian.com/platform/forge/storage-reference/storage-api-custom-entities/) )
22
- - ✅ **Memory Usage Monitoring**: Automated detection of memory-intensive queries with configurable thresholds (essential for Atlassian's 16 MiB per query limit)
22
+ - ✅ **Performance Monitoring**: Automated detection of memory-intensive queries with configurable thresholds (essential for Atlassian's 16 MiB per query limit)
23
23
  - ✅ **Type-Safe Query Building**: Write SQL queries with full TypeScript support
24
24
  - ✅ **Supports complex SQL queries** with joins and filtering using Drizzle ORM
25
25
  - ✅ **Advanced Query Methods**: `selectFrom()`, `selectDistinctFrom()`, `selectCacheableFrom()`, `selectDistinctCacheableFrom()` for all-column queries with field aliasing
26
- - ✅ **Raw SQL Execution**: `execute()` and `executeCacheable()` methods for direct SQL queries with local and global caching
26
+ - ✅ **Query Execution with Metadata**: `executeWithMetadata()` method for capturing detailed execution metrics including database execution time, response size, and Forge SQL metadata
27
+ - ✅ **Raw SQL Execution**: `execute()`, `executeCacheable()`, `executeDDL()`, and `executeDDLActions()` methods for direct SQL queries with local and global caching
27
28
  - ✅ **Common Table Expressions (CTEs)**: `with()` method for complex queries with subqueries
28
29
  - ✅ **Schema migration support**, allowing automatic schema evolution
29
30
  - ✅ **Automatic entity generation** from MySQL/tidb databases
@@ -64,7 +65,7 @@
64
65
  ### 🔒 Advanced Features
65
66
  - [Optimistic Locking](#optimistic-locking)
66
67
  - [Query Analysis and Performance Optimization](#query-analysis-and-performance-optimization)
67
- - [Memory Usage Monitoring](#memory-usage-monitoring)
68
+ - [Performance Monitoring](#performance-monitoring)
68
69
  - [Date and Time Types](#date-and-time-types)
69
70
 
70
71
  ### 🛠️ Development Tools
@@ -81,7 +82,7 @@
81
82
  - [Query Analysis Example](examples/forge-sql-orm-example-query-analyses)
82
83
  - [Organization Tracker Example](examples/forge-sql-orm-example-org-tracker)
83
84
  - [Checklist Example](examples/forge-sql-orm-example-checklist)
84
- - [Cache Example](examples/forge-sql-orm-example-cache) - Advanced caching capabilities with `topSlowestStatementLastHourTrigger` memory monitoring
85
+ - [Cache Example](examples/forge-sql-orm-example-cache) - Advanced caching capabilities with `topSlowestStatementLastHourTrigger` performance monitoring
85
86
 
86
87
  ### 📚 Reference
87
88
  - [ForgeSqlOrmOptions](#forgesqlormoptions)
@@ -333,6 +334,42 @@ const cachedRawUsers = await forgeSQL.executeCacheable(
333
334
  300
334
335
  );
335
336
 
337
+ // Raw SQL with execution metadata
338
+ const usersWithMetadata = await forgeSQL.executeWithMetadata(
339
+ async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
340
+ (totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
341
+ console.log(`DB execution time: ${totalDbExecutionTime}ms`);
342
+ console.log(`Response size: ${totalResponseSize} bytes`);
343
+ console.log('Forge metadata:', forgeMetadata);
344
+ }
345
+ );
346
+
347
+ // DDL operations for schema modifications
348
+ await forgeSQL.executeDDL(`
349
+ CREATE TABLE users (
350
+ id INT PRIMARY KEY AUTO_INCREMENT,
351
+ name VARCHAR(255) NOT NULL,
352
+ email VARCHAR(255) UNIQUE
353
+ )
354
+ `);
355
+
356
+ // Execute regular SQL queries in DDL context for performance monitoring
357
+ await forgeSQL.executeDDLActions(async () => {
358
+ // Execute regular SQL queries in DDL context for monitoring
359
+ const slowQueries = await forgeSQL.execute(`
360
+ SELECT * FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY
361
+ WHERE AVG_LATENCY > 1000000
362
+ `);
363
+
364
+ // Execute complex analysis queries in DDL context
365
+ const performanceData = await forgeSQL.execute(`
366
+ SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY_HISTORY
367
+ WHERE SUMMARY_END_TIME > DATE_SUB(NOW(), INTERVAL 1 HOUR)
368
+ `);
369
+
370
+ return { slowQueries, performanceData };
371
+ });
372
+
336
373
  // Common Table Expressions (CTEs)
337
374
  const userStats = await forgeSQL
338
375
  .with(
@@ -406,6 +443,16 @@ const cachedRawUsers = await forgeSQL.executeCacheable(
406
443
  [true],
407
444
  300
408
445
  );
446
+
447
+ // Raw SQL with execution metadata
448
+ const usersWithMetadata = await forgeSQL.executeWithMetadata(
449
+ async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
450
+ (totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
451
+ console.log(`DB execution time: ${totalDbExecutionTime}ms`);
452
+ console.log(`Response size: ${totalResponseSize} bytes`);
453
+ console.log('Forge metadata:', forgeMetadata);
454
+ }
455
+ );
409
456
  ```
410
457
 
411
458
  ## Setting Up Caching with @forge/kvs (Optional)
@@ -757,6 +804,8 @@ const optimizedData = await forgeSQL.executeWithLocalCacheContextAndReturnValue(
757
804
  | `selectDistinctCacheableFrom()` | Distinct all-column queries with field aliasing and caching | ❌ No | Local + Global Cache |
758
805
  | `execute()` | Raw SQL queries with local caching | ❌ No | Local Cache |
759
806
  | `executeCacheable()` | Raw SQL queries with local and global caching | ❌ No | Local + Global Cache |
807
+ | `executeDDL()` | DDL operations (CREATE, ALTER, DROP, etc.) | ❌ No | No Caching |
808
+ | `executeDDLActions()` | Execute regular SQL queries in DDL operation context | ❌ No | No Caching |
760
809
  | `with()` | Common Table Expressions (CTEs) | ❌ No | Local Cache |
761
810
 
762
811
 
@@ -777,6 +826,9 @@ const optimizedData = await forgeSQL.executeWithLocalCacheContextAndReturnValue(
777
826
  | `selectDistinctCacheableFrom()` | Distinct all-column queries with field aliasing and caching | ❌ No | Local + Global Cache |
778
827
  | `execute()` | Raw SQL queries with local caching | ❌ No | Local Cache |
779
828
  | `executeCacheable()` | Raw SQL queries with local and global caching | ❌ No | Local + Global Cache |
829
+ | `executeWithMetadata()` | Raw SQL queries with execution metrics capture | ❌ No | Local Cache |
830
+ | `executeDDL()` | DDL operations (CREATE, ALTER, DROP, etc.) | ❌ No | No Caching |
831
+ | `executeDDLActions()` | Execute regular SQL queries in DDL operation context | ❌ No | No Caching |
780
832
  | `with()` | Common Table Expressions (CTEs) | ❌ No | Local Cache |
781
833
  where Cache context - allows you to batch cache invalidation events and bypass cache reads for affected tables.
782
834
 
@@ -1163,6 +1215,51 @@ const users = await forgeSQL
1163
1215
  const users = await forgeSQL
1164
1216
  .executeCacheable("SELECT * FROM users WHERE active = ?", [true], 300);
1165
1217
 
1218
+ // Using executeWithMetadata() for capturing execution metrics
1219
+ const usersWithMetadata = await forgeSQL
1220
+ .executeWithMetadata(
1221
+ async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
1222
+ (totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
1223
+ console.log(`DB execution time: ${totalDbExecutionTime}ms`);
1224
+ console.log(`Response size: ${totalResponseSize} bytes`);
1225
+ console.log('Forge metadata:', forgeMetadata);
1226
+ }
1227
+ );
1228
+
1229
+ // Using executeDDL() for DDL operations (CREATE, ALTER, DROP, etc.)
1230
+ await forgeSQL.executeDDL(`
1231
+ CREATE TABLE users (
1232
+ id INT PRIMARY KEY AUTO_INCREMENT,
1233
+ name VARCHAR(255) NOT NULL,
1234
+ email VARCHAR(255) UNIQUE
1235
+ )
1236
+ `);
1237
+
1238
+ await forgeSQL.executeDDL(sql`
1239
+ ALTER TABLE users
1240
+ ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
1241
+ `);
1242
+
1243
+ await forgeSQL.executeDDL("DROP TABLE IF EXISTS old_users");
1244
+
1245
+ // Using executeDDLActions() for executing regular SQL queries in DDL context
1246
+ // This method executes a series of actions within a DDL operation context for monitoring
1247
+ await forgeSQL.executeDDLActions(async () => {
1248
+ // Execute regular SQL queries in DDL context for performance monitoring
1249
+ const slowQueries = await forgeSQL.execute(`
1250
+ SELECT * FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY
1251
+ WHERE AVG_LATENCY > 1000000
1252
+ `);
1253
+
1254
+ // Execute complex analysis queries in DDL context
1255
+ const performanceData = await forgeSQL.execute(`
1256
+ SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY_HISTORY
1257
+ WHERE SUMMARY_END_TIME > DATE_SUB(NOW(), INTERVAL 1 HOUR)
1258
+ `);
1259
+
1260
+ return { slowQueries, performanceData };
1261
+ });
1262
+
1166
1263
  // Using execute() with complex queries
1167
1264
  const userStats = await forgeSQL
1168
1265
  .execute(`
@@ -1478,6 +1575,16 @@ await forgeSQL.executeWithLocalContext(async () => {
1478
1575
  [true]
1479
1576
  );
1480
1577
 
1578
+ // Raw SQL with execution metadata and local caching
1579
+ const usersWithMetadata = await forgeSQL.executeWithMetadata(
1580
+ async () => await forgeSQL.execute("SELECT id, name FROM users WHERE active = ?", [true]),
1581
+ (totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
1582
+ console.log(`DB execution time: ${totalDbExecutionTime}ms`);
1583
+ console.log(`Response size: ${totalResponseSize} bytes`);
1584
+ console.log('Forge metadata:', forgeMetadata);
1585
+ }
1586
+ );
1587
+
1481
1588
  // Insert operation - evicts local cache for users table
1482
1589
  await forgeSQL.insert(users).values({ name: 'New User', active: true });
1483
1590
 
@@ -1646,6 +1753,16 @@ const userStats = await forgeSQL
1646
1753
  })
1647
1754
  .from(sql`activeUsers au`)
1648
1755
  .leftJoin(sql`completedOrders co`, eq(sql`au.id`, sql`co.userId`));
1756
+
1757
+ // Using executeWithMetadata() for capturing execution metrics with caching
1758
+ const usersWithMetadata = await forgeSQL.executeWithMetadata(
1759
+ async () => await forgeSQL.executeCacheable("SELECT * FROM users WHERE active = ?", [true], 300),
1760
+ (totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
1761
+ console.log(`DB execution time: ${totalDbExecutionTime}ms`);
1762
+ console.log(`Response size: ${totalResponseSize} bytes`);
1763
+ console.log('Forge metadata:', forgeMetadata);
1764
+ }
1765
+ );
1649
1766
  ```
1650
1767
 
1651
1768
  ### Manual Cache Management
@@ -1721,6 +1838,7 @@ The `ForgeSqlOrmOptions` object allows customization of ORM behavior:
1721
1838
  | Option | Type | Description |
1722
1839
  | -------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1723
1840
  | `logRawSqlQuery` | `boolean` | Enables logging of raw SQL queries in the Atlassian Forge Developer Console. Useful for debugging and monitoring. Defaults to `false`. |
1841
+ | `logCache` | `boolean` | Enables logging of cache operations (hits, misses, evictions) in the Atlassian Forge Developer Console. Useful for debugging caching issues. Defaults to `false`. |
1724
1842
  | `disableOptimisticLocking` | `boolean` | Disables optimistic locking. When set to `true`, no additional condition (e.g., a version check) is added during record updates, which can improve performance. However, this may lead to conflicts when multiple transactions attempt to update the same record concurrently. |
1725
1843
  | `additionalMetadata` | `object` | Allows adding custom metadata to all entities. This is useful for tracking common fields across all tables (e.g., `createdAt`, `updatedAt`, `createdBy`, etc.). The metadata will be automatically added to all generated entities. |
1726
1844
  | `cacheEntityName` | `string` | KVS Custom entity name for cache storage. Must match the `name` in your `manifest.yml` storage entities configuration. Required for caching functionality. Defaults to `"cache"`. |
@@ -2020,13 +2138,13 @@ This analysis provides insights into:
2020
2138
  - Resource usage at each step
2021
2139
  - Performance optimization opportunities
2022
2140
 
2023
- ## Memory Usage Monitoring
2141
+ ## Performance Monitoring
2024
2142
 
2025
2143
  [↑ Back to Top](#table-of-contents)
2026
2144
 
2027
- Forge-SQL-ORM provides automated memory usage monitoring capabilities to help you identify and track memory-intensive queries in your Forge SQL instance. This feature is **essential for Atlassian Forge applications** as it helps you stay within the **16 MiB per query memory limit** and provides detailed insights for optimization.
2145
+ Forge-SQL-ORM provides automated performance monitoring capabilities to help you identify and track memory-intensive queries in your Forge SQL instance. This feature is **essential for Atlassian Forge applications** as it helps you stay within the **16 MiB per query memory limit** and provides detailed insights for optimization.
2028
2146
 
2029
- ### Why Memory Monitoring is Critical
2147
+ ### Why Performance Monitoring is Critical
2030
2148
 
2031
2149
  Atlassian Forge SQL has a strict **16 MiB memory limit per query**. Unlike slow query detection (which is available in the Forge Developer Console), there's **no built-in way to monitor memory usage** of your queries. This monitoring system fills that gap by:
2032
2150
 
@@ -2038,7 +2156,7 @@ Atlassian Forge SQL has a strict **16 MiB memory limit per query**. Unlike slow
2038
2156
 
2039
2157
  ### Overview
2040
2158
 
2041
- The memory monitoring system:
2159
+ The performance monitoring system:
2042
2160
  - **Automatically detects memory-intensive queries** based on configurable memory thresholds
2043
2161
  - **Provides detailed memory metrics** including execution time, memory usage, and execution plans
2044
2162
  - **Logs memory issues** to the Forge Developer Console for easy debugging
@@ -2047,7 +2165,7 @@ The memory monitoring system:
2047
2165
 
2048
2166
  ### Key Features
2049
2167
 
2050
- - **Memory-Focused Monitoring**: Primary focus on memory usage with configurable thresholds
2168
+ - **Memory-Focused Performance Monitoring**: Primary focus on memory usage with configurable thresholds
2051
2169
  - **Atlassian 16 MiB Limit Awareness**: Designed specifically for Forge SQL's memory constraints
2052
2170
  - **Execution Plan Analysis**: Shows detailed query plans to help optimize memory consumption
2053
2171
  - **Configurable Thresholds**: Set custom memory usage thresholds (default: 4MB warning)
@@ -2071,56 +2189,60 @@ import ForgeSQL, { topSlowestStatementLastHourTrigger } from 'forge-sql-orm';
2071
2189
  const forgeSQL = new ForgeSQL();
2072
2190
 
2073
2191
  // Basic usage with default thresholds (300ms latency, 8MB memory warning)
2074
- export const memoryUsageTrigger = () =>
2192
+ export const performanceTrigger = () =>
2075
2193
  topSlowestStatementLastHourTrigger(forgeSQL);
2076
2194
 
2077
- // Conservative memory monitoring: 4MB warning (well below 16MB limit)
2195
+ // Conservative performance monitoring: 4MB warning (well below 16MB limit)
2078
2196
  export const conservativeMemoryTrigger = () =>
2079
- topSlowestStatementLastHourTrigger(forgeSQL, 300, 4 * 1024 * 1024);
2197
+ topSlowestStatementLastHourTrigger(forgeSQL, { memoryThresholdBytes: 4 * 1024 * 1024 });
2080
2198
 
2081
- // Aggressive memory monitoring: 12MB warning (75% of 16MB limit)
2199
+ // Aggressive performance monitoring: 12MB warning (75% of 16MB limit)
2082
2200
  export const aggressiveMemoryTrigger = () =>
2083
- topSlowestStatementLastHourTrigger(forgeSQL, 300, 12 * 1024 * 1024);
2201
+ topSlowestStatementLastHourTrigger(forgeSQL, { memoryThresholdBytes: 12 * 1024 * 1024 });
2084
2202
 
2085
- // Memory-only monitoring: Only trigger on memory usage (latency effectively disabled)
2203
+ // Memory-only performance monitoring: Only trigger on memory usage (latency effectively disabled)
2086
2204
  export const memoryOnlyTrigger = () =>
2087
- topSlowestStatementLastHourTrigger(forgeSQL, 10000, 4 * 1024 * 1024);
2205
+ topSlowestStatementLastHourTrigger(forgeSQL, { warnThresholdMs: 10000, memoryThresholdBytes: 4 * 1024 * 1024 });
2088
2206
 
2089
2207
  // Latency-only monitoring: Only trigger on slow queries (memory effectively disabled)
2090
2208
  export const latencyOnlyTrigger = () =>
2091
- topSlowestStatementLastHourTrigger(forgeSQL, 500, 16 * 1024 * 1024);
2209
+ topSlowestStatementLastHourTrigger(forgeSQL, { warnThresholdMs: 500, memoryThresholdBytes: 16 * 1024 * 1024 });
2092
2210
 
2211
+ // With execution plan in logs
2212
+ export const performanceWithPlanTrigger = () =>
2213
+ topSlowestStatementLastHourTrigger(forgeSQL, { showPlan: true });
2214
+ ```
2093
2215
 
2094
2216
  #### 3. Configure in manifest.yml
2095
2217
 
2096
2218
  **As Scheduler Trigger (Recommended for Production):**
2097
2219
  ```yaml
2098
2220
  scheduledTrigger:
2099
- - key: memory-usage-trigger
2100
- function: memoryUsageTrigger
2221
+ - key: performance-trigger
2222
+ function: perfTrigger
2101
2223
  interval: hour # Required: only hour interval is supported
2102
2224
 
2103
2225
  function:
2104
- - key: memoryUsageTrigger
2105
- handler: index.memoryUsageTrigger
2226
+ - key: perfTrigger
2227
+ handler: index.performanceTrigger
2106
2228
  ```
2107
2229
 
2108
2230
  **As Web Trigger (Development Only):**
2109
2231
  ```yaml
2110
2232
  webtrigger:
2111
2233
  - key: print-slowest-queries
2112
- function: memoryUsageTrigger
2234
+ function: perfTrigger
2113
2235
 
2114
2236
  function:
2115
- - key: memoryUsageTrigger
2116
- handler: index.memoryUsageTrigger
2237
+ - key: perfTrigger
2238
+ handler: index.performanceTrigger
2117
2239
  ```
2118
2240
 
2119
2241
  > **⚠️ Important**: Web triggers are not recommended for production as they violate the "run-on-atlassian" principle. Use scheduler triggers for production monitoring.
2120
2242
 
2121
2243
  ### How It Works
2122
2244
 
2123
- The memory monitoring trigger works differently depending on how it's configured:
2245
+ The performance monitoring trigger works differently depending on how it's configured:
2124
2246
 
2125
2247
  #### Scheduler Trigger Mode (Production)
2126
2248
 
@@ -2196,7 +2318,8 @@ When used as a **web trigger**, the system:
2196
2318
  |-----------|------|---------|-------------|
2197
2319
  | `warnThresholdMs` | `number` | `300` | Latency threshold in milliseconds (secondary) |
2198
2320
  | `memoryThresholdBytes` | `number` | `8 * 1024 * 1024` | **Memory usage threshold in bytes (primary focus)** |
2199
- | `options` | `ForgeSqlOrmOptions` | `undefined` | Optional ORM configuration |
2321
+ | `showPlan` | `boolean` | `false` | Whether to include execution plan in logs |
2322
+ | `logCache` | `boolean` | `false` | Whether to log cache operations |
2200
2323
 
2201
2324
  **⚠️ Important: OR Logic**
2202
2325
  The monitoring uses **OR logic** - if **either** threshold is exceeded, the query will be logged/returned:
@@ -2205,9 +2328,11 @@ The monitoring uses **OR logic** - if **either** threshold is exceeded, the quer
2205
2328
  - No need to exceed both thresholds simultaneously
2206
2329
 
2207
2330
  **💡 Pro Tips:**
2208
- - **Memory-only monitoring**: Set `warnThresholdMs` to a very high value (e.g., 10000ms) to trigger only on memory usage
2331
+ - **Memory-only performance monitoring**: Set `warnThresholdMs` to a very high value (e.g., 10000ms) to trigger only on memory usage
2209
2332
  - **Latency-only monitoring**: Set `memoryThresholdBytes` to 16MB (16 * 1024 * 1024) to trigger only on latency
2210
2333
  - **Combined monitoring**: Use both thresholds for comprehensive monitoring
2334
+ - **Execution plan analysis**: Set `showPlan: true` to include detailed execution plans in logs (useful for debugging)
2335
+ - **Cache debugging**: Set `logCache: true` to log cache operations and debug caching issues
2211
2336
 
2212
2337
  **Memory Threshold Guidelines:**
2213
2338
  - **Conservative**: 4MB (25% of 16MB limit)
@@ -2276,6 +2401,8 @@ This section covers the breaking changes introduced in version 2.1.x and how to
2276
2401
  - `forgeSQL.selectDistinctCacheableFrom()` - Distinct all-column queries with field aliasing and caching
2277
2402
  - `forgeSQL.execute()` - Raw SQL queries with local caching
2278
2403
  - `forgeSQL.executeCacheable()` - Raw SQL queries with local and global caching
2404
+ - `forgeSQL.executeDDL()` - DDL operations (CREATE, ALTER, DROP, etc.)
2405
+ - `forgeSQL.executeDDLActions()` - Execute actions within DDL operation context
2279
2406
  - `forgeSQL.with()` - Common Table Expressions (CTEs)
2280
2407
 
2281
2408
  **Optional Migration:**
@@ -2312,6 +2439,47 @@ const cachedRawUsers = await forgeSQL.executeCacheable(
2312
2439
  300
2313
2440
  );
2314
2441
 
2442
+ // ✅ Raw SQL execution with metadata capture
2443
+ const usersWithMetadata = await forgeSQL.executeWithMetadata(
2444
+ async () => await forgeSQL.execute("SELECT * FROM users WHERE active = ?", [true]),
2445
+ (totalDbExecutionTime, totalResponseSize, forgeMetadata) => {
2446
+ console.log(`DB execution time: ${totalDbExecutionTime}ms`);
2447
+ console.log(`Response size: ${totalResponseSize} bytes`);
2448
+ console.log('Forge metadata:', forgeMetadata);
2449
+ }
2450
+ );
2451
+
2452
+ // ✅ DDL operations for schema modifications
2453
+ await forgeSQL.executeDDL(`
2454
+ CREATE TABLE users (
2455
+ id INT PRIMARY KEY AUTO_INCREMENT,
2456
+ name VARCHAR(255) NOT NULL,
2457
+ email VARCHAR(255) UNIQUE
2458
+ )
2459
+ `);
2460
+
2461
+ await forgeSQL.executeDDL(sql`
2462
+ ALTER TABLE users
2463
+ ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
2464
+ `);
2465
+
2466
+ // ✅ Execute regular SQL queries in DDL context for performance monitoring
2467
+ await forgeSQL.executeDDLActions(async () => {
2468
+ // Execute regular SQL queries in DDL context for monitoring
2469
+ const slowQueries = await forgeSQL.execute(`
2470
+ SELECT * FROM INFORMATION_SCHEMA.STATEMENTS_SUMMARY
2471
+ WHERE AVG_LATENCY > 1000000
2472
+ `);
2473
+
2474
+ // Execute complex analysis queries in DDL context
2475
+ const performanceData = await forgeSQL.execute(`
2476
+ SELECT * FROM INFORMATION_SCHEMA.CLUSTER_STATEMENTS_SUMMARY_HISTORY
2477
+ WHERE SUMMARY_END_TIME > DATE_SUB(NOW(), INTERVAL 1 HOUR)
2478
+ `);
2479
+
2480
+ return { slowQueries, performanceData };
2481
+ });
2482
+
2315
2483
  // ✅ Common Table Expressions (CTEs)
2316
2484
  const userStats = await forgeSQL
2317
2485
  .with(