forge-sql-orm 2.1.2 → 2.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 +205 -0
- package/dist/ForgeSQLORM.js +677 -56
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +680 -59
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts +1 -2
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/core/SystemTables.d.ts +5039 -0
- package/dist/core/SystemTables.d.ts.map +1 -1
- package/dist/utils/cacheUtils.d.ts.map +1 -1
- package/dist/utils/forgeDriver.d.ts.map +1 -1
- package/dist/utils/forgeDriverProxy.d.ts.map +1 -1
- package/dist/utils/sqlUtils.d.ts +1 -1
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/dist/webtriggers/applyMigrationsWebTrigger.d.ts +1 -1
- package/dist/webtriggers/applyMigrationsWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/dropMigrationWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/dropTablesMigrationWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/fetchSchemaWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/index.d.ts +1 -0
- package/dist/webtriggers/index.d.ts.map +1 -1
- package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts +72 -0
- package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts.map +1 -0
- package/package.json +8 -7
- package/src/core/ForgeSQLQueryBuilder.ts +13 -9
- package/src/core/SystemTables.ts +313 -1
- package/src/lib/drizzle/extensions/additionalActions.ts +2 -2
- package/src/utils/cacheContextUtils.ts +2 -2
- package/src/utils/cacheUtils.ts +3 -1
- package/src/utils/forgeDriver.ts +16 -21
- package/src/utils/forgeDriverProxy.ts +10 -3
- package/src/utils/sqlUtils.ts +32 -7
- package/src/webtriggers/applyMigrationsWebTrigger.ts +21 -15
- package/src/webtriggers/dropMigrationWebTrigger.ts +8 -4
- package/src/webtriggers/dropTablesMigrationWebTrigger.ts +8 -4
- package/src/webtriggers/fetchSchemaWebTrigger.ts +7 -3
- package/src/webtriggers/index.ts +1 -0
- package/src/webtriggers/topSlowestStatementLastHourTrigger.ts +305 -0
package/dist/ForgeSQLORM.js
CHANGED
|
@@ -36,11 +36,16 @@ const parseDateTime = (value, format) => {
|
|
|
36
36
|
if (dt.isValid) {
|
|
37
37
|
result = dt.toJSDate();
|
|
38
38
|
} else {
|
|
39
|
-
const
|
|
40
|
-
if (
|
|
41
|
-
result =
|
|
39
|
+
const sqlDt = luxon.DateTime.fromSQL(value);
|
|
40
|
+
if (sqlDt.isValid) {
|
|
41
|
+
result = sqlDt.toJSDate();
|
|
42
42
|
} else {
|
|
43
|
-
|
|
43
|
+
const isoDt = luxon.DateTime.fromRFC2822(value);
|
|
44
|
+
if (isoDt.isValid) {
|
|
45
|
+
result = isoDt.toJSDate();
|
|
46
|
+
} else {
|
|
47
|
+
result = new Date(value);
|
|
48
|
+
}
|
|
44
49
|
}
|
|
45
50
|
}
|
|
46
51
|
}
|
|
@@ -49,7 +54,7 @@ const parseDateTime = (value, format) => {
|
|
|
49
54
|
}
|
|
50
55
|
return result;
|
|
51
56
|
};
|
|
52
|
-
function formatDateTime(value, format) {
|
|
57
|
+
function formatDateTime(value, format, isTimeStamp) {
|
|
53
58
|
let dt = null;
|
|
54
59
|
if (value instanceof Date) {
|
|
55
60
|
dt = luxon.DateTime.fromJSDate(value);
|
|
@@ -77,6 +82,20 @@ function formatDateTime(value, format) {
|
|
|
77
82
|
if (!dt?.isValid) {
|
|
78
83
|
throw new Error("Invalid Date");
|
|
79
84
|
}
|
|
85
|
+
const minDate = luxon.DateTime.fromSeconds(1);
|
|
86
|
+
const maxDate = luxon.DateTime.fromMillis(2147483647 * 1e3);
|
|
87
|
+
if (isTimeStamp) {
|
|
88
|
+
if (dt < minDate) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
"Atlassian Forge does not support zero or negative timestamps. Allowed range: from '1970-01-01 00:00:01.000000' to '2038-01-19 03:14:07.999999'."
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
if (dt > maxDate) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
"Atlassian Forge does not support timestamps beyond 2038-01-19 03:14:07.999999. Please use a smaller date within the supported range."
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
80
99
|
return dt.toFormat(format);
|
|
81
100
|
}
|
|
82
101
|
function getPrimaryKeys(table2) {
|
|
@@ -480,7 +499,9 @@ async function clearExpiredCache(options) {
|
|
|
480
499
|
);
|
|
481
500
|
} finally {
|
|
482
501
|
const duration = luxon.DateTime.now().toSeconds() - startTime.toSeconds();
|
|
483
|
-
|
|
502
|
+
if (options?.logRawSqlQuery) {
|
|
503
|
+
console.debug(`Cleared ${totalRecords} expired cache records in ${duration} seconds`);
|
|
504
|
+
}
|
|
484
505
|
}
|
|
485
506
|
}
|
|
486
507
|
async function getFromCache(query, options) {
|
|
@@ -567,7 +588,7 @@ async function saveQueryLocalCacheQuery(query, rows, options) {
|
|
|
567
588
|
};
|
|
568
589
|
if (options.logRawSqlQuery) {
|
|
569
590
|
const q = sql2.toSQL();
|
|
570
|
-
console.
|
|
591
|
+
console.debug(
|
|
571
592
|
`[forge-sql-orm][local-cache][SAVE] Stored result in cache. sql="${q.sql}", params=${JSON.stringify(q.params)}`
|
|
572
593
|
);
|
|
573
594
|
}
|
|
@@ -584,7 +605,7 @@ async function getQueryLocalCacheQuery(query, options) {
|
|
|
584
605
|
if (context.cache[key] && context.cache[key].sql === sql2.toSQL().sql.toLowerCase()) {
|
|
585
606
|
if (options.logRawSqlQuery) {
|
|
586
607
|
const q = sql2.toSQL();
|
|
587
|
-
console.
|
|
608
|
+
console.debug(
|
|
588
609
|
`[forge-sql-orm][local-cache][HIT] Returned cached result. sql="${q.sql}", params=${JSON.stringify(q.params)}`
|
|
589
610
|
);
|
|
590
611
|
}
|
|
@@ -1014,28 +1035,23 @@ class ForgeSQLSelectOperations {
|
|
|
1014
1035
|
}
|
|
1015
1036
|
}
|
|
1016
1037
|
const forgeDriver = async (query, params, method) => {
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
sqlStatement.bindParams(...params);
|
|
1022
|
-
}
|
|
1023
|
-
const updateQueryResponseResults = await sqlStatement.execute();
|
|
1024
|
-
let result = updateQueryResponseResults.rows;
|
|
1025
|
-
return { ...result, rows: [result] };
|
|
1026
|
-
} else {
|
|
1027
|
-
const sqlStatement = await sql$1.sql.prepare(query);
|
|
1028
|
-
if (params) {
|
|
1029
|
-
await sqlStatement.bindParams(...params);
|
|
1030
|
-
}
|
|
1031
|
-
const result = await sqlStatement.execute();
|
|
1032
|
-
let rows;
|
|
1033
|
-
rows = result.rows.map((r) => Object.values(r));
|
|
1034
|
-
return { rows };
|
|
1038
|
+
if (method == "execute") {
|
|
1039
|
+
const sqlStatement = sql$1.sql.prepare(query);
|
|
1040
|
+
if (params) {
|
|
1041
|
+
sqlStatement.bindParams(...params);
|
|
1035
1042
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1043
|
+
const updateQueryResponseResults = await sqlStatement.execute();
|
|
1044
|
+
let result = updateQueryResponseResults.rows;
|
|
1045
|
+
return { ...result, rows: [result] };
|
|
1046
|
+
} else {
|
|
1047
|
+
const sqlStatement = await sql$1.sql.prepare(query);
|
|
1048
|
+
if (params) {
|
|
1049
|
+
await sqlStatement.bindParams(...params);
|
|
1050
|
+
}
|
|
1051
|
+
const result = await sqlStatement.execute();
|
|
1052
|
+
let rows;
|
|
1053
|
+
rows = result.rows.map((r) => Object.values(r));
|
|
1054
|
+
return { rows };
|
|
1039
1055
|
}
|
|
1040
1056
|
};
|
|
1041
1057
|
function injectSqlHints(query, hints) {
|
|
@@ -1072,9 +1088,16 @@ function createForgeDriverProxy(options, logRawSqlQuery) {
|
|
|
1072
1088
|
return async (query, params, method) => {
|
|
1073
1089
|
const modifiedQuery = injectSqlHints(query, options);
|
|
1074
1090
|
if (options && logRawSqlQuery && modifiedQuery !== query) {
|
|
1075
|
-
console.
|
|
1091
|
+
console.debug("injected Hints: " + modifiedQuery);
|
|
1092
|
+
}
|
|
1093
|
+
try {
|
|
1094
|
+
return await forgeDriver(modifiedQuery, params, method);
|
|
1095
|
+
} catch (error) {
|
|
1096
|
+
if (logRawSqlQuery) {
|
|
1097
|
+
console.debug("SQL Error:", JSON.stringify(error));
|
|
1098
|
+
}
|
|
1099
|
+
throw error;
|
|
1076
1100
|
}
|
|
1077
|
-
return forgeDriver(modifiedQuery, params, method);
|
|
1078
1101
|
};
|
|
1079
1102
|
}
|
|
1080
1103
|
const NON_CACHE_CLEARING_ERROR_CODES = ["VALIDATION_ERROR", "CONSTRAINT_ERROR"];
|
|
@@ -1109,8 +1132,8 @@ async function handleSuccessfulExecution(rows, onfulfilled, table2, options, isC
|
|
|
1109
1132
|
if (shouldClearCacheOnError(error)) {
|
|
1110
1133
|
await evictLocalCacheQuery(table2, options);
|
|
1111
1134
|
if (isCached) {
|
|
1112
|
-
await clearCache(table2, options).catch(() => {
|
|
1113
|
-
console.warn("Ignore cache clear errors");
|
|
1135
|
+
await clearCache(table2, options).catch((e) => {
|
|
1136
|
+
console.warn("Ignore cache clear errors", e);
|
|
1114
1137
|
});
|
|
1115
1138
|
} else {
|
|
1116
1139
|
await saveTableIfInsideCacheContext(table2);
|
|
@@ -2572,10 +2595,10 @@ const forgeDateTimeString = mysqlCore.customType({
|
|
|
2572
2595
|
return "datetime";
|
|
2573
2596
|
},
|
|
2574
2597
|
toDriver(value) {
|
|
2575
|
-
return formatDateTime(value, "yyyy-
|
|
2598
|
+
return formatDateTime(value, "yyyy-MM-dd' 'HH:mm:ss.SSS", false);
|
|
2576
2599
|
},
|
|
2577
2600
|
fromDriver(value) {
|
|
2578
|
-
const format = "yyyy-
|
|
2601
|
+
const format = "yyyy-MM-dd' 'HH:mm:ss.SSS";
|
|
2579
2602
|
return parseDateTime(value, format);
|
|
2580
2603
|
}
|
|
2581
2604
|
});
|
|
@@ -2584,10 +2607,10 @@ const forgeTimestampString = mysqlCore.customType({
|
|
|
2584
2607
|
return "timestamp";
|
|
2585
2608
|
},
|
|
2586
2609
|
toDriver(value) {
|
|
2587
|
-
return formatDateTime(value, "yyyy-
|
|
2610
|
+
return formatDateTime(value, "yyyy-MM-dd' 'HH:mm:ss.SSS", true);
|
|
2588
2611
|
},
|
|
2589
2612
|
fromDriver(value) {
|
|
2590
|
-
const format = "yyyy-
|
|
2613
|
+
const format = "yyyy-MM-dd' 'HH:mm:ss.SSS";
|
|
2591
2614
|
return parseDateTime(value, format);
|
|
2592
2615
|
}
|
|
2593
2616
|
});
|
|
@@ -2596,10 +2619,10 @@ const forgeDateString = mysqlCore.customType({
|
|
|
2596
2619
|
return "date";
|
|
2597
2620
|
},
|
|
2598
2621
|
toDriver(value) {
|
|
2599
|
-
return formatDateTime(value, "yyyy-
|
|
2622
|
+
return formatDateTime(value, "yyyy-MM-dd", false);
|
|
2600
2623
|
},
|
|
2601
2624
|
fromDriver(value) {
|
|
2602
|
-
const format = "yyyy-
|
|
2625
|
+
const format = "yyyy-MM-dd";
|
|
2603
2626
|
return parseDateTime(value, format);
|
|
2604
2627
|
}
|
|
2605
2628
|
});
|
|
@@ -2608,7 +2631,7 @@ const forgeTimeString = mysqlCore.customType({
|
|
|
2608
2631
|
return "time";
|
|
2609
2632
|
},
|
|
2610
2633
|
toDriver(value) {
|
|
2611
|
-
return formatDateTime(value, "HH:mm:ss.SSS");
|
|
2634
|
+
return formatDateTime(value, "HH:mm:ss.SSS", false);
|
|
2612
2635
|
},
|
|
2613
2636
|
fromDriver(value) {
|
|
2614
2637
|
return parseDateTime(value, "HH:mm:ss.SSS");
|
|
@@ -2619,6 +2642,435 @@ const migrations = mysqlCore.mysqlTable("__migrations", {
|
|
|
2619
2642
|
name: mysqlCore.varchar("name", { length: 255 }).notNull(),
|
|
2620
2643
|
migratedAt: mysqlCore.timestamp("migratedAt").defaultNow().notNull()
|
|
2621
2644
|
});
|
|
2645
|
+
const informationSchema = mysqlCore.mysqlSchema("information_schema");
|
|
2646
|
+
const slowQuery = informationSchema.table("SLOW_QUERY", {
|
|
2647
|
+
time: mysqlCore.timestamp("Time", { fsp: 6, mode: "string" }).notNull(),
|
|
2648
|
+
// Timestamp when the slow query was recorded
|
|
2649
|
+
txnStartTs: mysqlCore.bigint("Txn_start_ts", { mode: "bigint", unsigned: true }),
|
|
2650
|
+
// Transaction start timestamp (TSO)
|
|
2651
|
+
user: mysqlCore.varchar("User", { length: 64 }),
|
|
2652
|
+
// User executing the query
|
|
2653
|
+
host: mysqlCore.varchar("Host", { length: 64 }),
|
|
2654
|
+
// Host from which the query originated
|
|
2655
|
+
connId: mysqlCore.bigint("Conn_ID", { mode: "bigint", unsigned: true }),
|
|
2656
|
+
// Connection ID
|
|
2657
|
+
sessionAlias: mysqlCore.varchar("Session_alias", { length: 64 }),
|
|
2658
|
+
// Session alias
|
|
2659
|
+
execRetryCount: mysqlCore.bigint("Exec_retry_count", { mode: "bigint", unsigned: true }),
|
|
2660
|
+
// Number of retries during execution
|
|
2661
|
+
execRetryTime: mysqlCore.double("Exec_retry_time"),
|
|
2662
|
+
// Time spent in retries
|
|
2663
|
+
queryTime: mysqlCore.double("Query_time"),
|
|
2664
|
+
// Total execution time
|
|
2665
|
+
parseTime: mysqlCore.double("Parse_time"),
|
|
2666
|
+
// Time spent parsing SQL
|
|
2667
|
+
compileTime: mysqlCore.double("Compile_time"),
|
|
2668
|
+
// Time spent compiling query plan
|
|
2669
|
+
rewriteTime: mysqlCore.double("Rewrite_time"),
|
|
2670
|
+
// Time spent rewriting query
|
|
2671
|
+
preprocSubqueries: mysqlCore.bigint("Preproc_subqueries", { mode: "bigint", unsigned: true }),
|
|
2672
|
+
// Number of subqueries preprocessed
|
|
2673
|
+
preprocSubqueriesTime: mysqlCore.double("Preproc_subqueries_time"),
|
|
2674
|
+
// Time spent preprocessing subqueries
|
|
2675
|
+
optimizeTime: mysqlCore.double("Optimize_time"),
|
|
2676
|
+
// Time spent in optimizer
|
|
2677
|
+
waitTs: mysqlCore.double("Wait_TS"),
|
|
2678
|
+
// Wait time for getting TSO
|
|
2679
|
+
prewriteTime: mysqlCore.double("Prewrite_time"),
|
|
2680
|
+
// Time spent in prewrite phase
|
|
2681
|
+
waitPrewriteBinlogTime: mysqlCore.double("Wait_prewrite_binlog_time"),
|
|
2682
|
+
// Time waiting for binlog prewrite
|
|
2683
|
+
commitTime: mysqlCore.double("Commit_time"),
|
|
2684
|
+
// Commit duration
|
|
2685
|
+
getCommitTsTime: mysqlCore.double("Get_commit_ts_time"),
|
|
2686
|
+
// Time waiting for commit TSO
|
|
2687
|
+
commitBackoffTime: mysqlCore.double("Commit_backoff_time"),
|
|
2688
|
+
// Backoff time during commit
|
|
2689
|
+
backoffTypes: mysqlCore.varchar("Backoff_types", { length: 64 }),
|
|
2690
|
+
// Types of backoff occurred
|
|
2691
|
+
resolveLockTime: mysqlCore.double("Resolve_lock_time"),
|
|
2692
|
+
// Time resolving locks
|
|
2693
|
+
localLatchWaitTime: mysqlCore.double("Local_latch_wait_time"),
|
|
2694
|
+
// Time waiting on local latch
|
|
2695
|
+
writeKeys: mysqlCore.bigint("Write_keys", { mode: "bigint" }),
|
|
2696
|
+
// Number of keys written
|
|
2697
|
+
writeSize: mysqlCore.bigint("Write_size", { mode: "bigint" }),
|
|
2698
|
+
// Amount of data written
|
|
2699
|
+
prewriteRegion: mysqlCore.bigint("Prewrite_region", { mode: "bigint" }),
|
|
2700
|
+
// Regions involved in prewrite
|
|
2701
|
+
txnRetry: mysqlCore.bigint("Txn_retry", { mode: "bigint" }),
|
|
2702
|
+
// Transaction retry count
|
|
2703
|
+
copTime: mysqlCore.double("Cop_time"),
|
|
2704
|
+
// Time spent in coprocessor
|
|
2705
|
+
processTime: mysqlCore.double("Process_time"),
|
|
2706
|
+
// Processing time
|
|
2707
|
+
waitTime: mysqlCore.double("Wait_time"),
|
|
2708
|
+
// Wait time in TiKV
|
|
2709
|
+
backoffTime: mysqlCore.double("Backoff_time"),
|
|
2710
|
+
// Backoff wait time
|
|
2711
|
+
lockKeysTime: mysqlCore.double("LockKeys_time"),
|
|
2712
|
+
// Time spent waiting for locks
|
|
2713
|
+
requestCount: mysqlCore.bigint("Request_count", { mode: "bigint", unsigned: true }),
|
|
2714
|
+
// Total number of requests
|
|
2715
|
+
totalKeys: mysqlCore.bigint("Total_keys", { mode: "bigint", unsigned: true }),
|
|
2716
|
+
// Total keys scanned
|
|
2717
|
+
processKeys: mysqlCore.bigint("Process_keys", { mode: "bigint", unsigned: true }),
|
|
2718
|
+
// Keys processed
|
|
2719
|
+
rocksdbDeleteSkippedCount: mysqlCore.bigint("Rocksdb_delete_skipped_count", {
|
|
2720
|
+
mode: "bigint",
|
|
2721
|
+
unsigned: true
|
|
2722
|
+
}),
|
|
2723
|
+
// RocksDB delete skips
|
|
2724
|
+
rocksdbKeySkippedCount: mysqlCore.bigint("Rocksdb_key_skipped_count", { mode: "bigint", unsigned: true }),
|
|
2725
|
+
// RocksDB key skips
|
|
2726
|
+
rocksdbBlockCacheHitCount: mysqlCore.bigint("Rocksdb_block_cache_hit_count", {
|
|
2727
|
+
mode: "bigint",
|
|
2728
|
+
unsigned: true
|
|
2729
|
+
}),
|
|
2730
|
+
// RocksDB block cache hits
|
|
2731
|
+
rocksdbBlockReadCount: mysqlCore.bigint("Rocksdb_block_read_count", { mode: "bigint", unsigned: true }),
|
|
2732
|
+
// RocksDB block reads
|
|
2733
|
+
rocksdbBlockReadByte: mysqlCore.bigint("Rocksdb_block_read_byte", { mode: "bigint", unsigned: true }),
|
|
2734
|
+
// RocksDB block read bytes
|
|
2735
|
+
db: mysqlCore.varchar("DB", { length: 64 }),
|
|
2736
|
+
// Database name
|
|
2737
|
+
indexNames: mysqlCore.varchar("Index_names", { length: 100 }),
|
|
2738
|
+
// Indexes used
|
|
2739
|
+
isInternal: mysqlCore.boolean("Is_internal"),
|
|
2740
|
+
// Whether the query is internal
|
|
2741
|
+
digest: mysqlCore.varchar("Digest", { length: 64 }),
|
|
2742
|
+
// SQL digest hash
|
|
2743
|
+
stats: mysqlCore.varchar("Stats", { length: 512 }),
|
|
2744
|
+
// Stats used during planning
|
|
2745
|
+
copProcAvg: mysqlCore.double("Cop_proc_avg"),
|
|
2746
|
+
// Coprocessor average processing time
|
|
2747
|
+
copProcP90: mysqlCore.double("Cop_proc_p90"),
|
|
2748
|
+
// Coprocessor 90th percentile processing time
|
|
2749
|
+
copProcMax: mysqlCore.double("Cop_proc_max"),
|
|
2750
|
+
// Coprocessor max processing time
|
|
2751
|
+
copProcAddr: mysqlCore.varchar("Cop_proc_addr", { length: 64 }),
|
|
2752
|
+
// Coprocessor address for processing
|
|
2753
|
+
copWaitAvg: mysqlCore.double("Cop_wait_avg"),
|
|
2754
|
+
// Coprocessor average wait time
|
|
2755
|
+
copWaitP90: mysqlCore.double("Cop_wait_p90"),
|
|
2756
|
+
// Coprocessor 90th percentile wait time
|
|
2757
|
+
copWaitMax: mysqlCore.double("Cop_wait_max"),
|
|
2758
|
+
// Coprocessor max wait time
|
|
2759
|
+
copWaitAddr: mysqlCore.varchar("Cop_wait_addr", { length: 64 }),
|
|
2760
|
+
// Coprocessor address for wait
|
|
2761
|
+
memMax: mysqlCore.bigint("Mem_max", { mode: "bigint" }),
|
|
2762
|
+
// Max memory usage
|
|
2763
|
+
diskMax: mysqlCore.bigint("Disk_max", { mode: "bigint" }),
|
|
2764
|
+
// Max disk usage
|
|
2765
|
+
kvTotal: mysqlCore.double("KV_total"),
|
|
2766
|
+
// Total KV request time
|
|
2767
|
+
pdTotal: mysqlCore.double("PD_total"),
|
|
2768
|
+
// Total PD request time
|
|
2769
|
+
backoffTotal: mysqlCore.double("Backoff_total"),
|
|
2770
|
+
// Total backoff time
|
|
2771
|
+
writeSqlResponseTotal: mysqlCore.double("Write_sql_response_total"),
|
|
2772
|
+
// SQL response write time
|
|
2773
|
+
resultRows: mysqlCore.bigint("Result_rows", { mode: "bigint" }),
|
|
2774
|
+
// Rows returned
|
|
2775
|
+
warnings: mysqlCore.longtext("Warnings"),
|
|
2776
|
+
// Warnings during execution
|
|
2777
|
+
backoffDetail: mysqlCore.varchar("Backoff_Detail", { length: 4096 }),
|
|
2778
|
+
// Detailed backoff info
|
|
2779
|
+
prepared: mysqlCore.boolean("Prepared"),
|
|
2780
|
+
// Whether query was prepared
|
|
2781
|
+
succ: mysqlCore.boolean("Succ"),
|
|
2782
|
+
// Success flag
|
|
2783
|
+
isExplicitTxn: mysqlCore.boolean("IsExplicitTxn"),
|
|
2784
|
+
// Whether explicit transaction
|
|
2785
|
+
isWriteCacheTable: mysqlCore.boolean("IsWriteCacheTable"),
|
|
2786
|
+
// Whether wrote to cache table
|
|
2787
|
+
planFromCache: mysqlCore.boolean("Plan_from_cache"),
|
|
2788
|
+
// Plan was from cache
|
|
2789
|
+
planFromBinding: mysqlCore.boolean("Plan_from_binding"),
|
|
2790
|
+
// Plan was from binding
|
|
2791
|
+
hasMoreResults: mysqlCore.boolean("Has_more_results"),
|
|
2792
|
+
// Query returned multiple results
|
|
2793
|
+
resourceGroup: mysqlCore.varchar("Resource_group", { length: 64 }),
|
|
2794
|
+
// Resource group name
|
|
2795
|
+
requestUnitRead: mysqlCore.double("Request_unit_read"),
|
|
2796
|
+
// RU consumed for read
|
|
2797
|
+
requestUnitWrite: mysqlCore.double("Request_unit_write"),
|
|
2798
|
+
// RU consumed for write
|
|
2799
|
+
timeQueuedByRc: mysqlCore.double("Time_queued_by_rc"),
|
|
2800
|
+
// Time queued by resource control
|
|
2801
|
+
tidbCpuTime: mysqlCore.double("Tidb_cpu_time"),
|
|
2802
|
+
// TiDB CPU time
|
|
2803
|
+
tikvCpuTime: mysqlCore.double("Tikv_cpu_time"),
|
|
2804
|
+
// TiKV CPU time
|
|
2805
|
+
plan: mysqlCore.longtext("Plan"),
|
|
2806
|
+
// Query execution plan
|
|
2807
|
+
planDigest: mysqlCore.varchar("Plan_digest", { length: 128 }),
|
|
2808
|
+
// Plan digest hash
|
|
2809
|
+
binaryPlan: mysqlCore.longtext("Binary_plan"),
|
|
2810
|
+
// Binary execution plan
|
|
2811
|
+
prevStmt: mysqlCore.longtext("Prev_stmt"),
|
|
2812
|
+
// Previous statement in session
|
|
2813
|
+
query: mysqlCore.longtext("Query")
|
|
2814
|
+
// Original SQL query
|
|
2815
|
+
});
|
|
2816
|
+
const createClusterStatementsSummarySchema = () => ({
|
|
2817
|
+
instance: mysqlCore.varchar("INSTANCE", { length: 64 }),
|
|
2818
|
+
// TiDB/TiKV instance address
|
|
2819
|
+
summaryBeginTime: mysqlCore.timestamp("SUMMARY_BEGIN_TIME", { mode: "string" }).notNull(),
|
|
2820
|
+
// Begin time of this summary window
|
|
2821
|
+
summaryEndTime: mysqlCore.timestamp("SUMMARY_END_TIME", { mode: "string" }).notNull(),
|
|
2822
|
+
// End time of this summary window
|
|
2823
|
+
stmtType: mysqlCore.varchar("STMT_TYPE", { length: 64 }).notNull(),
|
|
2824
|
+
// Statement type (e.g., Select/Insert/Update)
|
|
2825
|
+
schemaName: mysqlCore.varchar("SCHEMA_NAME", { length: 64 }),
|
|
2826
|
+
// Current schema name
|
|
2827
|
+
digest: mysqlCore.varchar("DIGEST", { length: 64 }),
|
|
2828
|
+
// SQL digest (normalized hash)
|
|
2829
|
+
digestText: mysqlCore.text("DIGEST_TEXT").notNull(),
|
|
2830
|
+
// Normalized SQL text
|
|
2831
|
+
tableNames: mysqlCore.text("TABLE_NAMES"),
|
|
2832
|
+
// Involved table names
|
|
2833
|
+
indexNames: mysqlCore.text("INDEX_NAMES"),
|
|
2834
|
+
// Used index names
|
|
2835
|
+
sampleUser: mysqlCore.varchar("SAMPLE_USER", { length: 64 }),
|
|
2836
|
+
// Sampled user who executed the statements
|
|
2837
|
+
execCount: mysqlCore.bigint("EXEC_COUNT", { mode: "bigint", unsigned: true }).notNull(),
|
|
2838
|
+
// Total executions
|
|
2839
|
+
sumErrors: mysqlCore.int("SUM_ERRORS", { unsigned: true }).notNull(),
|
|
2840
|
+
// Sum of errors
|
|
2841
|
+
sumWarnings: mysqlCore.int("SUM_WARNINGS", { unsigned: true }).notNull(),
|
|
2842
|
+
// Sum of warnings
|
|
2843
|
+
sumLatency: mysqlCore.bigint("SUM_LATENCY", { mode: "bigint", unsigned: true }).notNull(),
|
|
2844
|
+
// Sum of latency (ns)
|
|
2845
|
+
maxLatency: mysqlCore.bigint("MAX_LATENCY", { mode: "bigint", unsigned: true }).notNull(),
|
|
2846
|
+
// Max latency (ns)
|
|
2847
|
+
minLatency: mysqlCore.bigint("MIN_LATENCY", { mode: "bigint", unsigned: true }).notNull(),
|
|
2848
|
+
// Min latency (ns)
|
|
2849
|
+
avgLatency: mysqlCore.bigint("AVG_LATENCY", { mode: "bigint", unsigned: true }).notNull(),
|
|
2850
|
+
// Avg latency (ns)
|
|
2851
|
+
avgParseLatency: mysqlCore.bigint("AVG_PARSE_LATENCY", { mode: "bigint", unsigned: true }).notNull(),
|
|
2852
|
+
// Avg parse time (ns)
|
|
2853
|
+
maxParseLatency: mysqlCore.bigint("MAX_PARSE_LATENCY", { mode: "bigint", unsigned: true }).notNull(),
|
|
2854
|
+
// Max parse time (ns)
|
|
2855
|
+
avgCompileLatency: mysqlCore.bigint("AVG_COMPILE_LATENCY", { mode: "bigint", unsigned: true }).notNull(),
|
|
2856
|
+
// Avg compile time (ns)
|
|
2857
|
+
maxCompileLatency: mysqlCore.bigint("MAX_COMPILE_LATENCY", { mode: "bigint", unsigned: true }).notNull(),
|
|
2858
|
+
// Max compile time (ns)
|
|
2859
|
+
sumCopTaskNum: mysqlCore.bigint("SUM_COP_TASK_NUM", { mode: "bigint", unsigned: true }).notNull(),
|
|
2860
|
+
// Total number of cop tasks
|
|
2861
|
+
maxCopProcessTime: mysqlCore.bigint("MAX_COP_PROCESS_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2862
|
+
// Max TiKV coprocessor processing time (ns)
|
|
2863
|
+
maxCopProcessAddress: mysqlCore.varchar("MAX_COP_PROCESS_ADDRESS", { length: 256 }),
|
|
2864
|
+
// Address of cop task with max processing time
|
|
2865
|
+
maxCopWaitTime: mysqlCore.bigint("MAX_COP_WAIT_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2866
|
+
// Max TiKV coprocessor wait time (ns)
|
|
2867
|
+
maxCopWaitAddress: mysqlCore.varchar("MAX_COP_WAIT_ADDRESS", { length: 256 }),
|
|
2868
|
+
// Address of cop task with max wait time
|
|
2869
|
+
avgProcessTime: mysqlCore.bigint("AVG_PROCESS_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2870
|
+
// Avg TiKV processing time (ns)
|
|
2871
|
+
maxProcessTime: mysqlCore.bigint("MAX_PROCESS_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2872
|
+
// Max TiKV processing time (ns)
|
|
2873
|
+
avgWaitTime: mysqlCore.bigint("AVG_WAIT_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2874
|
+
// Avg TiKV wait time (ns)
|
|
2875
|
+
maxWaitTime: mysqlCore.bigint("MAX_WAIT_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2876
|
+
// Max TiKV wait time (ns)
|
|
2877
|
+
avgBackoffTime: mysqlCore.bigint("AVG_BACKOFF_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2878
|
+
// Avg backoff time before retry (ns)
|
|
2879
|
+
maxBackoffTime: mysqlCore.bigint("MAX_BACKOFF_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2880
|
+
// Max backoff time before retry (ns)
|
|
2881
|
+
avgTotalKeys: mysqlCore.bigint("AVG_TOTAL_KEYS", { mode: "bigint", unsigned: true }).notNull(),
|
|
2882
|
+
// Avg scanned keys
|
|
2883
|
+
maxTotalKeys: mysqlCore.bigint("MAX_TOTAL_KEYS", { mode: "bigint", unsigned: true }).notNull(),
|
|
2884
|
+
// Max scanned keys
|
|
2885
|
+
avgProcessedKeys: mysqlCore.bigint("AVG_PROCESSED_KEYS", { mode: "bigint", unsigned: true }).notNull(),
|
|
2886
|
+
// Avg processed keys
|
|
2887
|
+
maxProcessedKeys: mysqlCore.bigint("MAX_PROCESSED_KEYS", { mode: "bigint", unsigned: true }).notNull(),
|
|
2888
|
+
// Max processed keys
|
|
2889
|
+
avgRocksdbDeleteSkippedCount: mysqlCore.double("AVG_ROCKSDB_DELETE_SKIPPED_COUNT").notNull(),
|
|
2890
|
+
// Avg RocksDB deletes skipped
|
|
2891
|
+
maxRocksdbDeleteSkippedCount: mysqlCore.int("MAX_ROCKSDB_DELETE_SKIPPED_COUNT", {
|
|
2892
|
+
unsigned: true
|
|
2893
|
+
}).notNull(),
|
|
2894
|
+
// Max RocksDB deletes skipped
|
|
2895
|
+
avgRocksdbKeySkippedCount: mysqlCore.double("AVG_ROCKSDB_KEY_SKIPPED_COUNT").notNull(),
|
|
2896
|
+
// Avg RocksDB keys skipped
|
|
2897
|
+
maxRocksdbKeySkippedCount: mysqlCore.int("MAX_ROCKSDB_KEY_SKIPPED_COUNT", { unsigned: true }).notNull(),
|
|
2898
|
+
// Max RocksDB keys skipped
|
|
2899
|
+
avgRocksdbBlockCacheHitCount: mysqlCore.double("AVG_ROCKSDB_BLOCK_CACHE_HIT_COUNT").notNull(),
|
|
2900
|
+
// Avg RocksDB block cache hits
|
|
2901
|
+
maxRocksdbBlockCacheHitCount: mysqlCore.int("MAX_ROCKSDB_BLOCK_CACHE_HIT_COUNT", {
|
|
2902
|
+
unsigned: true
|
|
2903
|
+
}).notNull(),
|
|
2904
|
+
// Max RocksDB block cache hits
|
|
2905
|
+
avgRocksdbBlockReadCount: mysqlCore.double("AVG_ROCKSDB_BLOCK_READ_COUNT").notNull(),
|
|
2906
|
+
// Avg RocksDB block reads
|
|
2907
|
+
maxRocksdbBlockReadCount: mysqlCore.int("MAX_ROCKSDB_BLOCK_READ_COUNT", { unsigned: true }).notNull(),
|
|
2908
|
+
// Max RocksDB block reads
|
|
2909
|
+
avgRocksdbBlockReadByte: mysqlCore.double("AVG_ROCKSDB_BLOCK_READ_BYTE").notNull(),
|
|
2910
|
+
// Avg RocksDB block read bytes
|
|
2911
|
+
maxRocksdbBlockReadByte: mysqlCore.int("MAX_ROCKSDB_BLOCK_READ_BYTE", { unsigned: true }).notNull(),
|
|
2912
|
+
// Max RocksDB block read bytes
|
|
2913
|
+
avgPrewriteTime: mysqlCore.bigint("AVG_PREWRITE_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2914
|
+
// Avg prewrite phase time (ns)
|
|
2915
|
+
maxPrewriteTime: mysqlCore.bigint("MAX_PREWRITE_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2916
|
+
// Max prewrite phase time (ns)
|
|
2917
|
+
avgCommitTime: mysqlCore.bigint("AVG_COMMIT_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2918
|
+
// Avg commit phase time (ns)
|
|
2919
|
+
maxCommitTime: mysqlCore.bigint("MAX_COMMIT_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2920
|
+
// Max commit phase time (ns)
|
|
2921
|
+
avgGetCommitTsTime: mysqlCore.bigint("AVG_GET_COMMIT_TS_TIME", {
|
|
2922
|
+
mode: "bigint",
|
|
2923
|
+
unsigned: true
|
|
2924
|
+
}).notNull(),
|
|
2925
|
+
// Avg get commit_ts time (ns)
|
|
2926
|
+
maxGetCommitTsTime: mysqlCore.bigint("MAX_GET_COMMIT_TS_TIME", {
|
|
2927
|
+
mode: "bigint",
|
|
2928
|
+
unsigned: true
|
|
2929
|
+
}).notNull(),
|
|
2930
|
+
// Max get commit_ts time (ns)
|
|
2931
|
+
avgCommitBackoffTime: mysqlCore.bigint("AVG_COMMIT_BACKOFF_TIME", {
|
|
2932
|
+
mode: "bigint",
|
|
2933
|
+
unsigned: true
|
|
2934
|
+
}).notNull(),
|
|
2935
|
+
// Avg backoff during commit (ns)
|
|
2936
|
+
maxCommitBackoffTime: mysqlCore.bigint("MAX_COMMIT_BACKOFF_TIME", {
|
|
2937
|
+
mode: "bigint",
|
|
2938
|
+
unsigned: true
|
|
2939
|
+
}).notNull(),
|
|
2940
|
+
// Max backoff during commit (ns)
|
|
2941
|
+
avgResolveLockTime: mysqlCore.bigint("AVG_RESOLVE_LOCK_TIME", {
|
|
2942
|
+
mode: "bigint",
|
|
2943
|
+
unsigned: true
|
|
2944
|
+
}).notNull(),
|
|
2945
|
+
// Avg resolve lock time (ns)
|
|
2946
|
+
maxResolveLockTime: mysqlCore.bigint("MAX_RESOLVE_LOCK_TIME", {
|
|
2947
|
+
mode: "bigint",
|
|
2948
|
+
unsigned: true
|
|
2949
|
+
}).notNull(),
|
|
2950
|
+
// Max resolve lock time (ns)
|
|
2951
|
+
avgLocalLatchWaitTime: mysqlCore.bigint("AVG_LOCAL_LATCH_WAIT_TIME", {
|
|
2952
|
+
mode: "bigint",
|
|
2953
|
+
unsigned: true
|
|
2954
|
+
}).notNull(),
|
|
2955
|
+
// Avg local latch wait (ns)
|
|
2956
|
+
maxLocalLatchWaitTime: mysqlCore.bigint("MAX_LOCAL_LATCH_WAIT_TIME", {
|
|
2957
|
+
mode: "bigint",
|
|
2958
|
+
unsigned: true
|
|
2959
|
+
}).notNull(),
|
|
2960
|
+
// Max local latch wait (ns)
|
|
2961
|
+
avgWriteKeys: mysqlCore.double("AVG_WRITE_KEYS").notNull(),
|
|
2962
|
+
// Avg number of written keys
|
|
2963
|
+
maxWriteKeys: mysqlCore.bigint("MAX_WRITE_KEYS", { mode: "bigint", unsigned: true }).notNull(),
|
|
2964
|
+
// Max written keys
|
|
2965
|
+
avgWriteSize: mysqlCore.double("AVG_WRITE_SIZE").notNull(),
|
|
2966
|
+
// Avg written bytes
|
|
2967
|
+
maxWriteSize: mysqlCore.bigint("MAX_WRITE_SIZE", { mode: "bigint", unsigned: true }).notNull(),
|
|
2968
|
+
// Max written bytes
|
|
2969
|
+
avgPrewriteRegions: mysqlCore.double("AVG_PREWRITE_REGIONS").notNull(),
|
|
2970
|
+
// Avg regions in prewrite
|
|
2971
|
+
maxPrewriteRegions: mysqlCore.int("MAX_PREWRITE_REGIONS", { unsigned: true }).notNull(),
|
|
2972
|
+
// Max regions in prewrite
|
|
2973
|
+
avgTxnRetry: mysqlCore.double("AVG_TXN_RETRY").notNull(),
|
|
2974
|
+
// Avg transaction retry count
|
|
2975
|
+
maxTxnRetry: mysqlCore.int("MAX_TXN_RETRY", { unsigned: true }).notNull(),
|
|
2976
|
+
// Max transaction retry count
|
|
2977
|
+
sumExecRetry: mysqlCore.bigint("SUM_EXEC_RETRY", { mode: "bigint", unsigned: true }).notNull(),
|
|
2978
|
+
// Sum of execution retries (pessimistic)
|
|
2979
|
+
sumExecRetryTime: mysqlCore.bigint("SUM_EXEC_RETRY_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2980
|
+
// Sum time of execution retries (ns)
|
|
2981
|
+
sumBackoffTimes: mysqlCore.bigint("SUM_BACKOFF_TIMES", { mode: "bigint", unsigned: true }).notNull(),
|
|
2982
|
+
// Sum of backoff retries
|
|
2983
|
+
backoffTypes: mysqlCore.varchar("BACKOFF_TYPES", { length: 1024 }),
|
|
2984
|
+
// Backoff types with counts
|
|
2985
|
+
avgMem: mysqlCore.bigint("AVG_MEM", { mode: "bigint", unsigned: true }).notNull(),
|
|
2986
|
+
// Avg memory used (bytes)
|
|
2987
|
+
maxMem: mysqlCore.bigint("MAX_MEM", { mode: "bigint", unsigned: true }).notNull(),
|
|
2988
|
+
// Max memory used (bytes)
|
|
2989
|
+
avgDisk: mysqlCore.bigint("AVG_DISK", { mode: "bigint", unsigned: true }).notNull(),
|
|
2990
|
+
// Avg disk used (bytes)
|
|
2991
|
+
maxDisk: mysqlCore.bigint("MAX_DISK", { mode: "bigint", unsigned: true }).notNull(),
|
|
2992
|
+
// Max disk used (bytes)
|
|
2993
|
+
avgKvTime: mysqlCore.bigint("AVG_KV_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2994
|
+
// Avg time spent in TiKV (ns)
|
|
2995
|
+
avgPdTime: mysqlCore.bigint("AVG_PD_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
2996
|
+
// Avg time spent in PD (ns)
|
|
2997
|
+
avgBackoffTotalTime: mysqlCore.bigint("AVG_BACKOFF_TOTAL_TIME", {
|
|
2998
|
+
mode: "bigint",
|
|
2999
|
+
unsigned: true
|
|
3000
|
+
}).notNull(),
|
|
3001
|
+
// Avg total backoff time (ns)
|
|
3002
|
+
avgWriteSqlRespTime: mysqlCore.bigint("AVG_WRITE_SQL_RESP_TIME", {
|
|
3003
|
+
mode: "bigint",
|
|
3004
|
+
unsigned: true
|
|
3005
|
+
}).notNull(),
|
|
3006
|
+
// Avg write SQL response time (ns)
|
|
3007
|
+
avgTidbCpuTime: mysqlCore.bigint("AVG_TIDB_CPU_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
3008
|
+
// Avg TiDB CPU time (ns)
|
|
3009
|
+
avgTikvCpuTime: mysqlCore.bigint("AVG_TIKV_CPU_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
3010
|
+
// Avg TiKV CPU time (ns)
|
|
3011
|
+
maxResultRows: mysqlCore.bigint("MAX_RESULT_ROWS", { mode: "bigint" }).notNull(),
|
|
3012
|
+
// Max number of result rows
|
|
3013
|
+
minResultRows: mysqlCore.bigint("MIN_RESULT_ROWS", { mode: "bigint" }).notNull(),
|
|
3014
|
+
// Min number of result rows
|
|
3015
|
+
avgResultRows: mysqlCore.bigint("AVG_RESULT_ROWS", { mode: "bigint" }).notNull(),
|
|
3016
|
+
// Avg number of result rows
|
|
3017
|
+
prepared: mysqlCore.boolean("PREPARED").notNull(),
|
|
3018
|
+
// Whether statements are prepared
|
|
3019
|
+
avgAffectedRows: mysqlCore.double("AVG_AFFECTED_ROWS").notNull(),
|
|
3020
|
+
// Avg affected rows
|
|
3021
|
+
firstSeen: mysqlCore.timestamp("FIRST_SEEN", { mode: "string" }).notNull(),
|
|
3022
|
+
// First time statements observed
|
|
3023
|
+
lastSeen: mysqlCore.timestamp("LAST_SEEN", { mode: "string" }).notNull(),
|
|
3024
|
+
// Last time statements observed
|
|
3025
|
+
planInCache: mysqlCore.boolean("PLAN_IN_CACHE").notNull(),
|
|
3026
|
+
// Whether last stmt hit plan cache
|
|
3027
|
+
planCacheHits: mysqlCore.bigint("PLAN_CACHE_HITS", { mode: "bigint" }).notNull(),
|
|
3028
|
+
// Number of plan cache hits
|
|
3029
|
+
planInBinding: mysqlCore.boolean("PLAN_IN_BINDING").notNull(),
|
|
3030
|
+
// Whether matched bindings
|
|
3031
|
+
querySampleText: mysqlCore.text("QUERY_SAMPLE_TEXT"),
|
|
3032
|
+
// Sampled original SQL
|
|
3033
|
+
prevSampleText: mysqlCore.text("PREV_SAMPLE_TEXT"),
|
|
3034
|
+
// Sampled previous SQL before commit
|
|
3035
|
+
planDigest: mysqlCore.varchar("PLAN_DIGEST", { length: 64 }),
|
|
3036
|
+
// Plan digest hash
|
|
3037
|
+
plan: mysqlCore.text("PLAN"),
|
|
3038
|
+
// Sampled textual plan
|
|
3039
|
+
binaryPlan: mysqlCore.text("BINARY_PLAN"),
|
|
3040
|
+
// Sampled binary plan
|
|
3041
|
+
charset: mysqlCore.varchar("CHARSET", { length: 64 }),
|
|
3042
|
+
// Sampled charset
|
|
3043
|
+
collation: mysqlCore.varchar("COLLATION", { length: 64 }),
|
|
3044
|
+
// Sampled collation
|
|
3045
|
+
planHint: mysqlCore.varchar("PLAN_HINT", { length: 64 }),
|
|
3046
|
+
// Sampled plan hint
|
|
3047
|
+
maxRequestUnitRead: mysqlCore.double("MAX_REQUEST_UNIT_READ").notNull(),
|
|
3048
|
+
// Max RU cost (read)
|
|
3049
|
+
avgRequestUnitRead: mysqlCore.double("AVG_REQUEST_UNIT_READ").notNull(),
|
|
3050
|
+
// Avg RU cost (read)
|
|
3051
|
+
maxRequestUnitWrite: mysqlCore.double("MAX_REQUEST_UNIT_WRITE").notNull(),
|
|
3052
|
+
// Max RU cost (write)
|
|
3053
|
+
avgRequestUnitWrite: mysqlCore.double("AVG_REQUEST_UNIT_WRITE").notNull(),
|
|
3054
|
+
// Avg RU cost (write)
|
|
3055
|
+
maxQueuedRcTime: mysqlCore.bigint("MAX_QUEUED_RC_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
3056
|
+
// Max queued time waiting for RU (ns)
|
|
3057
|
+
avgQueuedRcTime: mysqlCore.bigint("AVG_QUEUED_RC_TIME", { mode: "bigint", unsigned: true }).notNull(),
|
|
3058
|
+
// Avg queued time waiting for RU (ns)
|
|
3059
|
+
resourceGroup: mysqlCore.varchar("RESOURCE_GROUP", { length: 64 }),
|
|
3060
|
+
// Bound resource group name
|
|
3061
|
+
planCacheUnqualified: mysqlCore.bigint("PLAN_CACHE_UNQUALIFIED", { mode: "bigint" }).notNull(),
|
|
3062
|
+
// Times not eligible for plan cache
|
|
3063
|
+
planCacheUnqualifiedLastReason: mysqlCore.text("PLAN_CACHE_UNQUALIFIED_LAST_REASON")
|
|
3064
|
+
// Last reason of plan cache ineligibility
|
|
3065
|
+
});
|
|
3066
|
+
const clusterStatementsSummaryHistory = informationSchema.table(
|
|
3067
|
+
"CLUSTER_STATEMENTS_SUMMARY_HISTORY",
|
|
3068
|
+
createClusterStatementsSummarySchema()
|
|
3069
|
+
);
|
|
3070
|
+
const clusterStatementsSummary = informationSchema.table(
|
|
3071
|
+
"CLUSTER_STATEMENTS_SUMMARY",
|
|
3072
|
+
createClusterStatementsSummarySchema()
|
|
3073
|
+
);
|
|
2622
3074
|
async function getTables() {
|
|
2623
3075
|
const tables = await sql$1.sql.executeDDL("SHOW TABLES");
|
|
2624
3076
|
return tables.rows.flatMap((tableInfo) => Object.values(tableInfo));
|
|
@@ -2629,7 +3081,7 @@ async function dropSchemaMigrations() {
|
|
|
2629
3081
|
const tables = await getTables();
|
|
2630
3082
|
const dropStatements = generateDropTableStatements(tables, { sequence: true, table: true });
|
|
2631
3083
|
for (const statement of dropStatements) {
|
|
2632
|
-
console.
|
|
3084
|
+
console.debug(`execute DDL: ${statement}`);
|
|
2633
3085
|
await sql$1.sql.executeDDL(statement);
|
|
2634
3086
|
}
|
|
2635
3087
|
return getHttpResponse(
|
|
@@ -2637,8 +3089,8 @@ async function dropSchemaMigrations() {
|
|
|
2637
3089
|
"⚠️ All data in these tables has been permanently deleted. This operation cannot be undone."
|
|
2638
3090
|
);
|
|
2639
3091
|
} catch (error) {
|
|
2640
|
-
|
|
2641
|
-
|
|
3092
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
3093
|
+
console.error(errorMessage);
|
|
2642
3094
|
return getHttpResponse(500, errorMessage);
|
|
2643
3095
|
}
|
|
2644
3096
|
}
|
|
@@ -2654,7 +3106,13 @@ const applySchemaMigrations = async (migration) => {
|
|
|
2654
3106
|
const successfulMigrations = await migrations2.run();
|
|
2655
3107
|
console.info("Migrations applied:", successfulMigrations);
|
|
2656
3108
|
const migrationList = await sql$1.migrationRunner.list();
|
|
2657
|
-
|
|
3109
|
+
let migrationHistory = "No migrations found";
|
|
3110
|
+
if (Array.isArray(migrationList) && migrationList.length > 0) {
|
|
3111
|
+
const sortedMigrations = migrationList.toSorted(
|
|
3112
|
+
(a, b) => a.migratedAt.getTime() - b.migratedAt.getTime()
|
|
3113
|
+
);
|
|
3114
|
+
migrationHistory = sortedMigrations.map((y) => `${y.id}, ${y.name}, ${y.migratedAt.toUTCString()}`).join("\n");
|
|
3115
|
+
}
|
|
2658
3116
|
console.info("Migrations history:\nid, name, migrated_at\n", migrationHistory);
|
|
2659
3117
|
return {
|
|
2660
3118
|
headers: { "Content-Type": ["application/json"] },
|
|
@@ -2663,17 +3121,13 @@ const applySchemaMigrations = async (migration) => {
|
|
|
2663
3121
|
body: "Migrations successfully executed"
|
|
2664
3122
|
};
|
|
2665
3123
|
} catch (error) {
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
} catch (e) {
|
|
2669
|
-
console.trace("Error stringify:", e);
|
|
2670
|
-
console.error("Error during migration:", error);
|
|
2671
|
-
}
|
|
3124
|
+
const errorMessage = error?.cause?.context?.debug?.sqlMessage ?? error?.cause?.context?.debug?.message ?? error?.debug?.context?.sqlMessage ?? error?.debug?.context?.message ?? error.message ?? "Unknown error occurred";
|
|
3125
|
+
console.error("Error during migration:", errorMessage);
|
|
2672
3126
|
return {
|
|
2673
3127
|
headers: { "Content-Type": ["application/json"] },
|
|
2674
3128
|
statusCode: 500,
|
|
2675
3129
|
statusText: "Internal Server Error",
|
|
2676
|
-
body: error instanceof Error ?
|
|
3130
|
+
body: error instanceof Error ? errorMessage : "Unknown error during migration"
|
|
2677
3131
|
};
|
|
2678
3132
|
}
|
|
2679
3133
|
};
|
|
@@ -2684,8 +3138,8 @@ async function fetchSchemaWebTrigger() {
|
|
|
2684
3138
|
const sqlStatements = wrapWithForeignKeyChecks(createTableStatements);
|
|
2685
3139
|
return getHttpResponse(200, sqlStatements.join(";\n"));
|
|
2686
3140
|
} catch (error) {
|
|
2687
|
-
|
|
2688
|
-
|
|
3141
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
3142
|
+
console.error(errorMessage);
|
|
2689
3143
|
return getHttpResponse(500, errorMessage);
|
|
2690
3144
|
}
|
|
2691
3145
|
}
|
|
@@ -2712,7 +3166,7 @@ async function dropTableSchemaMigrations() {
|
|
|
2712
3166
|
const tables = await getTables();
|
|
2713
3167
|
const dropStatements = generateDropTableStatements(tables, { sequence: false, table: true });
|
|
2714
3168
|
for (const statement of dropStatements) {
|
|
2715
|
-
console.
|
|
3169
|
+
console.debug(`execute DDL: ${statement}`);
|
|
2716
3170
|
await sql$1.sql.executeDDL(statement);
|
|
2717
3171
|
}
|
|
2718
3172
|
return getHttpResponse(
|
|
@@ -2720,8 +3174,8 @@ async function dropTableSchemaMigrations() {
|
|
|
2720
3174
|
"⚠️ All data in these tables has been permanently deleted. This operation cannot be undone."
|
|
2721
3175
|
);
|
|
2722
3176
|
} catch (error) {
|
|
2723
|
-
|
|
2724
|
-
|
|
3177
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
3178
|
+
console.error(errorMessage);
|
|
2725
3179
|
return getHttpResponse(500, errorMessage);
|
|
2726
3180
|
}
|
|
2727
3181
|
}
|
|
@@ -2764,6 +3218,169 @@ const clearCacheSchedulerTrigger = async (options) => {
|
|
|
2764
3218
|
};
|
|
2765
3219
|
}
|
|
2766
3220
|
};
|
|
3221
|
+
const topSlowestStatementLastHourTrigger = async (orm, warnThresholdMs = 300, memoryThresholdBytes = 8 * 1024 * 1024) => {
|
|
3222
|
+
const nsToMs = (v) => {
|
|
3223
|
+
const n = Number(v);
|
|
3224
|
+
return Number.isFinite(n) ? n / 1e6 : NaN;
|
|
3225
|
+
};
|
|
3226
|
+
const bytesToMB = (v) => {
|
|
3227
|
+
const n = Number(v);
|
|
3228
|
+
return Number.isFinite(n) ? n / (1024 * 1024) : NaN;
|
|
3229
|
+
};
|
|
3230
|
+
const jsonSafeStringify = (value) => JSON.stringify(value, (_k, v) => typeof v === "bigint" ? v.toString() : v);
|
|
3231
|
+
const TOP_N = 1;
|
|
3232
|
+
try {
|
|
3233
|
+
const summaryHistory = clusterStatementsSummaryHistory;
|
|
3234
|
+
const summary = clusterStatementsSummary;
|
|
3235
|
+
const selectShape = (t) => ({
|
|
3236
|
+
digest: t.digest,
|
|
3237
|
+
stmtType: t.stmtType,
|
|
3238
|
+
schemaName: t.schemaName,
|
|
3239
|
+
execCount: t.execCount,
|
|
3240
|
+
avgLatencyNs: t.avgLatency,
|
|
3241
|
+
maxLatencyNs: t.maxLatency,
|
|
3242
|
+
minLatencyNs: t.minLatency,
|
|
3243
|
+
avgProcessTimeNs: t.avgProcessTime,
|
|
3244
|
+
avgWaitTimeNs: t.avgWaitTime,
|
|
3245
|
+
avgBackoffTimeNs: t.avgBackoffTime,
|
|
3246
|
+
avgTotalKeys: t.avgTotalKeys,
|
|
3247
|
+
firstSeen: t.firstSeen,
|
|
3248
|
+
lastSeen: t.lastSeen,
|
|
3249
|
+
planInCache: t.planInCache,
|
|
3250
|
+
planCacheHits: t.planCacheHits,
|
|
3251
|
+
digestText: t.digestText,
|
|
3252
|
+
plan: t.plan,
|
|
3253
|
+
avgMemBytes: t.avgMem,
|
|
3254
|
+
maxMemBytes: t.maxMem
|
|
3255
|
+
});
|
|
3256
|
+
const lastHourFilterHistory = drizzleOrm.gte(
|
|
3257
|
+
summaryHistory.summaryEndTime,
|
|
3258
|
+
drizzleOrm.sql`DATE_SUB(NOW(), INTERVAL 1 HOUR)`
|
|
3259
|
+
);
|
|
3260
|
+
const lastHourFilterSummary = drizzleOrm.gte(
|
|
3261
|
+
summary.summaryEndTime,
|
|
3262
|
+
drizzleOrm.sql`DATE_SUB(NOW(), INTERVAL 1 HOUR)`
|
|
3263
|
+
);
|
|
3264
|
+
const qHistory = orm.getDrizzleQueryBuilder().select(selectShape(summaryHistory)).from(summaryHistory).where(lastHourFilterHistory);
|
|
3265
|
+
const qSummary = orm.getDrizzleQueryBuilder().select(selectShape(summary)).from(summary).where(lastHourFilterSummary);
|
|
3266
|
+
const combined = mysqlCore.unionAll(qHistory, qSummary).as("combined");
|
|
3267
|
+
const thresholdNs = Math.floor(warnThresholdMs * 1e6);
|
|
3268
|
+
const grouped = orm.getDrizzleQueryBuilder().select({
|
|
3269
|
+
digest: combined.digest,
|
|
3270
|
+
stmtType: combined.stmtType,
|
|
3271
|
+
schemaName: combined.schemaName,
|
|
3272
|
+
execCount: drizzleOrm.sql`SUM(${combined.execCount})`.as("execCount"),
|
|
3273
|
+
avgLatencyNs: drizzleOrm.sql`MAX(${combined.avgLatencyNs})`.as("avgLatencyNs"),
|
|
3274
|
+
maxLatencyNs: drizzleOrm.sql`MAX(${combined.maxLatencyNs})`.as("maxLatencyNs"),
|
|
3275
|
+
minLatencyNs: drizzleOrm.sql`MIN(${combined.minLatencyNs})`.as("minLatencyNs"),
|
|
3276
|
+
avgProcessTimeNs: drizzleOrm.sql`MAX(${combined.avgProcessTimeNs})`.as("avgProcessTimeNs"),
|
|
3277
|
+
avgWaitTimeNs: drizzleOrm.sql`MAX(${combined.avgWaitTimeNs})`.as("avgWaitTimeNs"),
|
|
3278
|
+
avgBackoffTimeNs: drizzleOrm.sql`MAX(${combined.avgBackoffTimeNs})`.as("avgBackoffTimeNs"),
|
|
3279
|
+
avgMemBytes: drizzleOrm.sql`MAX(${combined.avgMemBytes})`.as("avgMemBytes"),
|
|
3280
|
+
maxMemBytes: drizzleOrm.sql`MAX(${combined.maxMemBytes})`.as("maxMemBytes"),
|
|
3281
|
+
avgTotalKeys: drizzleOrm.sql`MAX(${combined.avgTotalKeys})`.as("avgTotalKeys"),
|
|
3282
|
+
firstSeen: drizzleOrm.sql`MIN(${combined.firstSeen})`.as("firstSeen"),
|
|
3283
|
+
lastSeen: drizzleOrm.sql`MAX(${combined.lastSeen})`.as("lastSeen"),
|
|
3284
|
+
planInCache: drizzleOrm.sql`MAX(${combined.planInCache})`.as("planInCache"),
|
|
3285
|
+
planCacheHits: drizzleOrm.sql`SUM(${combined.planCacheHits})`.as("planCacheHits"),
|
|
3286
|
+
// Prefer a non-empty sample text/plan via MAX; acceptable for de-dup
|
|
3287
|
+
digestText: drizzleOrm.sql`MAX(${combined.digestText})`.as("digestText"),
|
|
3288
|
+
plan: drizzleOrm.sql`MAX(${combined.plan})`.as("plan")
|
|
3289
|
+
}).from(combined).where(
|
|
3290
|
+
drizzleOrm.sql`COALESCE(${combined.digest}, '') <> '' AND COALESCE(${combined.digestText}, '') <> '' AND COALESCE(${combined.stmtType}, '') NOT IN ('Use','Set','Show')`
|
|
3291
|
+
).groupBy(combined.digest, combined.stmtType, combined.schemaName).as("grouped");
|
|
3292
|
+
const rows = await orm.getDrizzleQueryBuilder().select({
|
|
3293
|
+
digest: grouped.digest,
|
|
3294
|
+
stmtType: grouped.stmtType,
|
|
3295
|
+
schemaName: grouped.schemaName,
|
|
3296
|
+
execCount: grouped.execCount,
|
|
3297
|
+
avgLatencyNs: grouped.avgLatencyNs,
|
|
3298
|
+
maxLatencyNs: grouped.maxLatencyNs,
|
|
3299
|
+
minLatencyNs: grouped.minLatencyNs,
|
|
3300
|
+
avgProcessTimeNs: grouped.avgProcessTimeNs,
|
|
3301
|
+
avgWaitTimeNs: grouped.avgWaitTimeNs,
|
|
3302
|
+
avgBackoffTimeNs: grouped.avgBackoffTimeNs,
|
|
3303
|
+
avgMemBytes: grouped.avgMemBytes,
|
|
3304
|
+
maxMemBytes: grouped.maxMemBytes,
|
|
3305
|
+
avgTotalKeys: grouped.avgTotalKeys,
|
|
3306
|
+
firstSeen: grouped.firstSeen,
|
|
3307
|
+
lastSeen: grouped.lastSeen,
|
|
3308
|
+
planInCache: grouped.planInCache,
|
|
3309
|
+
planCacheHits: grouped.planCacheHits,
|
|
3310
|
+
digestText: grouped.digestText,
|
|
3311
|
+
plan: grouped.plan
|
|
3312
|
+
}).from(grouped).where(
|
|
3313
|
+
drizzleOrm.sql`${grouped.avgLatencyNs} > ${thresholdNs} OR ${grouped.avgMemBytes} > ${memoryThresholdBytes}`
|
|
3314
|
+
).orderBy(drizzleOrm.desc(grouped.avgLatencyNs)).limit(formatLimitOffset(TOP_N));
|
|
3315
|
+
const formatted = rows.map((r, i) => ({
|
|
3316
|
+
rank: i + 1,
|
|
3317
|
+
// 1-based rank in the top N
|
|
3318
|
+
digest: r.digest,
|
|
3319
|
+
stmtType: r.stmtType,
|
|
3320
|
+
schemaName: r.schemaName,
|
|
3321
|
+
execCount: r.execCount,
|
|
3322
|
+
avgLatencyMs: nsToMs(r.avgLatencyNs),
|
|
3323
|
+
// Convert ns to ms for readability
|
|
3324
|
+
maxLatencyMs: nsToMs(r.maxLatencyNs),
|
|
3325
|
+
minLatencyMs: nsToMs(r.minLatencyNs),
|
|
3326
|
+
avgProcessTimeMs: nsToMs(r.avgProcessTimeNs),
|
|
3327
|
+
avgWaitTimeMs: nsToMs(r.avgWaitTimeNs),
|
|
3328
|
+
avgBackoffTimeMs: nsToMs(r.avgBackoffTimeNs),
|
|
3329
|
+
avgMemMB: bytesToMB(r.avgMemBytes),
|
|
3330
|
+
maxMemMB: bytesToMB(r.maxMemBytes),
|
|
3331
|
+
avgMemBytes: r.avgMemBytes,
|
|
3332
|
+
maxMemBytes: r.maxMemBytes,
|
|
3333
|
+
avgTotalKeys: r.avgTotalKeys,
|
|
3334
|
+
firstSeen: r.firstSeen,
|
|
3335
|
+
lastSeen: r.lastSeen,
|
|
3336
|
+
planInCache: r.planInCache,
|
|
3337
|
+
planCacheHits: r.planCacheHits,
|
|
3338
|
+
digestText: r.digestText,
|
|
3339
|
+
plan: r.plan
|
|
3340
|
+
}));
|
|
3341
|
+
for (const f of formatted) {
|
|
3342
|
+
console.warn(
|
|
3343
|
+
`${f.rank}. ${f.stmtType} avg=${f.avgLatencyMs?.toFixed?.(2)}ms max=${f.maxLatencyMs?.toFixed?.(2)}ms mem≈${f.avgMemMB?.toFixed?.(2)}MB(max ${f.maxMemMB?.toFixed?.(2)}MB) exec=${f.execCount}
|
|
3344
|
+
digest=${f.digest}
|
|
3345
|
+
sql=${(f.digestText || "").slice(0, 300)}${f.digestText && f.digestText.length > 300 ? "…" : ""}`
|
|
3346
|
+
);
|
|
3347
|
+
if (f.plan) {
|
|
3348
|
+
console.warn(` full plan:
|
|
3349
|
+
${f.plan}`);
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
return {
|
|
3353
|
+
headers: { "Content-Type": ["application/json"] },
|
|
3354
|
+
statusCode: 200,
|
|
3355
|
+
statusText: "OK",
|
|
3356
|
+
body: jsonSafeStringify({
|
|
3357
|
+
success: true,
|
|
3358
|
+
window: "last_1h",
|
|
3359
|
+
top: TOP_N,
|
|
3360
|
+
warnThresholdMs,
|
|
3361
|
+
memoryThresholdBytes,
|
|
3362
|
+
rows: formatted,
|
|
3363
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3364
|
+
})
|
|
3365
|
+
};
|
|
3366
|
+
} catch (error) {
|
|
3367
|
+
console.error(
|
|
3368
|
+
"Error in topSlowestStatementLastHourTrigger:",
|
|
3369
|
+
error?.cause?.context?.debug?.sqlMessage ?? error?.cause ?? error
|
|
3370
|
+
);
|
|
3371
|
+
return {
|
|
3372
|
+
headers: { "Content-Type": ["application/json"] },
|
|
3373
|
+
statusCode: 500,
|
|
3374
|
+
statusText: "Internal Server Error",
|
|
3375
|
+
body: jsonSafeStringify({
|
|
3376
|
+
success: false,
|
|
3377
|
+
message: "Failed to fetch or log slow queries",
|
|
3378
|
+
error: error?.cause?.context?.debug?.sqlMessage ?? error?.cause?.message,
|
|
3379
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
3380
|
+
})
|
|
3381
|
+
};
|
|
3382
|
+
}
|
|
3383
|
+
};
|
|
2767
3384
|
const getHttpResponse = (statusCode, body) => {
|
|
2768
3385
|
let statusText = "";
|
|
2769
3386
|
if (statusCode === 200) {
|
|
@@ -2783,6 +3400,8 @@ exports.ForgeSQLSelectOperations = ForgeSQLSelectOperations;
|
|
|
2783
3400
|
exports.applyFromDriverTransform = applyFromDriverTransform;
|
|
2784
3401
|
exports.applySchemaMigrations = applySchemaMigrations;
|
|
2785
3402
|
exports.clearCacheSchedulerTrigger = clearCacheSchedulerTrigger;
|
|
3403
|
+
exports.clusterStatementsSummary = clusterStatementsSummary;
|
|
3404
|
+
exports.clusterStatementsSummaryHistory = clusterStatementsSummaryHistory;
|
|
2786
3405
|
exports.default = ForgeSQLORM;
|
|
2787
3406
|
exports.dropSchemaMigrations = dropSchemaMigrations;
|
|
2788
3407
|
exports.dropTableSchemaMigrations = dropTableSchemaMigrations;
|
|
@@ -2806,4 +3425,6 @@ exports.migrations = migrations;
|
|
|
2806
3425
|
exports.nextVal = nextVal;
|
|
2807
3426
|
exports.parseDateTime = parseDateTime;
|
|
2808
3427
|
exports.patchDbWithSelectAliased = patchDbWithSelectAliased;
|
|
3428
|
+
exports.slowQuery = slowQuery;
|
|
3429
|
+
exports.topSlowestStatementLastHourTrigger = topSlowestStatementLastHourTrigger;
|
|
2809
3430
|
//# sourceMappingURL=ForgeSQLORM.js.map
|