taurusdb-core 0.1.0

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 (170) hide show
  1. package/README.md +21 -0
  2. package/dist/auth/secret-resolver.d.ts +16 -0
  3. package/dist/auth/secret-resolver.js +64 -0
  4. package/dist/auth/sql-profile-loader/env-source.d.ts +3 -0
  5. package/dist/auth/sql-profile-loader/env-source.js +94 -0
  6. package/dist/auth/sql-profile-loader/file-source.d.ts +6 -0
  7. package/dist/auth/sql-profile-loader/file-source.js +40 -0
  8. package/dist/auth/sql-profile-loader/loader.d.ts +16 -0
  9. package/dist/auth/sql-profile-loader/loader.js +81 -0
  10. package/dist/auth/sql-profile-loader/parsing.d.ts +14 -0
  11. package/dist/auth/sql-profile-loader/parsing.js +216 -0
  12. package/dist/auth/sql-profile-loader/runtime-override.d.ts +14 -0
  13. package/dist/auth/sql-profile-loader/runtime-override.js +52 -0
  14. package/dist/auth/sql-profile-loader/types.d.ts +64 -0
  15. package/dist/auth/sql-profile-loader/types.js +1 -0
  16. package/dist/auth/sql-profile-loader.d.ts +4 -0
  17. package/dist/auth/sql-profile-loader.js +3 -0
  18. package/dist/capability/feature-matrix.d.ts +5 -0
  19. package/dist/capability/feature-matrix.js +237 -0
  20. package/dist/capability/probe.d.ts +19 -0
  21. package/dist/capability/probe.js +139 -0
  22. package/dist/capability/types.d.ts +49 -0
  23. package/dist/capability/types.js +16 -0
  24. package/dist/capability/version.d.ts +3 -0
  25. package/dist/capability/version.js +47 -0
  26. package/dist/cloud/auth.d.ts +26 -0
  27. package/dist/cloud/auth.js +198 -0
  28. package/dist/cloud/instances.d.ts +46 -0
  29. package/dist/cloud/instances.js +224 -0
  30. package/dist/config/env.d.ts +1 -0
  31. package/dist/config/env.js +194 -0
  32. package/dist/config/index.d.ts +6 -0
  33. package/dist/config/index.js +21 -0
  34. package/dist/config/redaction.d.ts +2 -0
  35. package/dist/config/redaction.js +19 -0
  36. package/dist/config/schema.d.ts +417 -0
  37. package/dist/config/schema.js +100 -0
  38. package/dist/context/datasource-resolver.d.ts +19 -0
  39. package/dist/context/datasource-resolver.js +71 -0
  40. package/dist/context/session-context.d.ts +26 -0
  41. package/dist/context/session-context.js +1 -0
  42. package/dist/diagnostics/metrics-source.d.ts +65 -0
  43. package/dist/diagnostics/metrics-source.js +280 -0
  44. package/dist/diagnostics/slow-sql-source/das-source.d.ts +43 -0
  45. package/dist/diagnostics/slow-sql-source/das-source.js +170 -0
  46. package/dist/diagnostics/slow-sql-source/factory.d.ts +5 -0
  47. package/dist/diagnostics/slow-sql-source/factory.js +87 -0
  48. package/dist/diagnostics/slow-sql-source/parsers.d.ts +7 -0
  49. package/dist/diagnostics/slow-sql-source/parsers.js +125 -0
  50. package/dist/diagnostics/slow-sql-source/taurus-api-source.d.ts +42 -0
  51. package/dist/diagnostics/slow-sql-source/taurus-api-source.js +149 -0
  52. package/dist/diagnostics/slow-sql-source/types.d.ts +40 -0
  53. package/dist/diagnostics/slow-sql-source/types.js +1 -0
  54. package/dist/diagnostics/slow-sql-source/utils.d.ts +20 -0
  55. package/dist/diagnostics/slow-sql-source/utils.js +170 -0
  56. package/dist/diagnostics/slow-sql-source.d.ts +4 -0
  57. package/dist/diagnostics/slow-sql-source.js +3 -0
  58. package/dist/diagnostics/types.d.ts +189 -0
  59. package/dist/diagnostics/types.js +39 -0
  60. package/dist/engine/data-access/locks.d.ts +8 -0
  61. package/dist/engine/data-access/locks.js +146 -0
  62. package/dist/engine/data-access/processlist.d.ts +4 -0
  63. package/dist/engine/data-access/processlist.js +56 -0
  64. package/dist/engine/data-access/statements.d.ts +10 -0
  65. package/dist/engine/data-access/statements.js +203 -0
  66. package/dist/engine/data-access/storage.d.ts +6 -0
  67. package/dist/engine/data-access/storage.js +96 -0
  68. package/dist/engine/data-access.d.ts +4 -0
  69. package/dist/engine/data-access.js +4 -0
  70. package/dist/engine/diagnostics.d.ts +7 -0
  71. package/dist/engine/diagnostics.js +7 -0
  72. package/dist/engine/helper-modules/diagnostics.d.ts +57 -0
  73. package/dist/engine/helper-modules/diagnostics.js +322 -0
  74. package/dist/engine/helper-modules/parsers.d.ts +13 -0
  75. package/dist/engine/helper-modules/parsers.js +283 -0
  76. package/dist/engine/helper-modules/sql.d.ts +12 -0
  77. package/dist/engine/helper-modules/sql.js +119 -0
  78. package/dist/engine/helper-modules/types.d.ts +103 -0
  79. package/dist/engine/helper-modules/types.js +1 -0
  80. package/dist/engine/helpers.d.ts +4 -0
  81. package/dist/engine/helpers.js +4 -0
  82. package/dist/engine/runtime.d.ts +20 -0
  83. package/dist/engine/runtime.js +385 -0
  84. package/dist/engine/types.d.ts +125 -0
  85. package/dist/engine/types.js +1 -0
  86. package/dist/engine/workflows/connection-spike.d.ts +4 -0
  87. package/dist/engine/workflows/connection-spike.js +316 -0
  88. package/dist/engine/workflows/db-hotspot.d.ts +4 -0
  89. package/dist/engine/workflows/db-hotspot.js +182 -0
  90. package/dist/engine/workflows/lock-contention-helpers/entities.d.ts +9 -0
  91. package/dist/engine/workflows/lock-contention-helpers/entities.js +58 -0
  92. package/dist/engine/workflows/lock-contention-helpers/no-match.d.ts +3 -0
  93. package/dist/engine/workflows/lock-contention-helpers/no-match.js +65 -0
  94. package/dist/engine/workflows/lock-contention-helpers/report.d.ts +21 -0
  95. package/dist/engine/workflows/lock-contention-helpers/report.js +104 -0
  96. package/dist/engine/workflows/lock-contention-helpers/root-cause.d.ts +4 -0
  97. package/dist/engine/workflows/lock-contention-helpers/root-cause.js +79 -0
  98. package/dist/engine/workflows/lock-contention-helpers/signals.d.ts +22 -0
  99. package/dist/engine/workflows/lock-contention-helpers/signals.js +34 -0
  100. package/dist/engine/workflows/lock-contention-helpers.d.ts +5 -0
  101. package/dist/engine/workflows/lock-contention-helpers.js +5 -0
  102. package/dist/engine/workflows/lock-contention.d.ts +4 -0
  103. package/dist/engine/workflows/lock-contention.js +67 -0
  104. package/dist/engine/workflows/service-latency.d.ts +4 -0
  105. package/dist/engine/workflows/service-latency.js +262 -0
  106. package/dist/engine/workflows/slow-query-helpers.d.ts +41 -0
  107. package/dist/engine/workflows/slow-query-helpers.js +253 -0
  108. package/dist/engine/workflows/slow-query.d.ts +4 -0
  109. package/dist/engine/workflows/slow-query.js +156 -0
  110. package/dist/engine/workflows/storage-pressure-helpers.d.ts +12 -0
  111. package/dist/engine/workflows/storage-pressure-helpers.js +281 -0
  112. package/dist/engine/workflows/storage-pressure.d.ts +4 -0
  113. package/dist/engine/workflows/storage-pressure.js +27 -0
  114. package/dist/engine/workflows/top-slow-sql.d.ts +4 -0
  115. package/dist/engine/workflows/top-slow-sql.js +222 -0
  116. package/dist/engine.d.ts +77 -0
  117. package/dist/engine.js +240 -0
  118. package/dist/executor/adapters/mysql.d.ts +2 -0
  119. package/dist/executor/adapters/mysql.js +114 -0
  120. package/dist/executor/connection-pool.d.ts +105 -0
  121. package/dist/executor/connection-pool.js +236 -0
  122. package/dist/executor/explain.d.ts +5 -0
  123. package/dist/executor/explain.js +119 -0
  124. package/dist/executor/query-tracker.d.ts +45 -0
  125. package/dist/executor/query-tracker.js +83 -0
  126. package/dist/executor/result-normalizer.d.ts +6 -0
  127. package/dist/executor/result-normalizer.js +47 -0
  128. package/dist/executor/sql-executor.d.ts +32 -0
  129. package/dist/executor/sql-executor.js +250 -0
  130. package/dist/executor/types.d.ts +70 -0
  131. package/dist/executor/types.js +1 -0
  132. package/dist/index.d.ts +40 -0
  133. package/dist/index.js +21 -0
  134. package/dist/safety/confirmation-store.d.ts +44 -0
  135. package/dist/safety/confirmation-store.js +130 -0
  136. package/dist/safety/guardrail.d.ts +39 -0
  137. package/dist/safety/guardrail.js +99 -0
  138. package/dist/safety/parser/adapter.d.ts +10 -0
  139. package/dist/safety/parser/adapter.js +72 -0
  140. package/dist/safety/parser/ast-utils.d.ts +10 -0
  141. package/dist/safety/parser/ast-utils.js +167 -0
  142. package/dist/safety/parser/features.d.ts +12 -0
  143. package/dist/safety/parser/features.js +113 -0
  144. package/dist/safety/parser/index.d.ts +2 -0
  145. package/dist/safety/parser/index.js +1 -0
  146. package/dist/safety/parser/types.d.ts +76 -0
  147. package/dist/safety/parser/types.js +1 -0
  148. package/dist/safety/redaction.d.ts +34 -0
  149. package/dist/safety/redaction.js +186 -0
  150. package/dist/safety/sql-classifier.d.ts +19 -0
  151. package/dist/safety/sql-classifier.js +43 -0
  152. package/dist/safety/sql-validator.d.ts +19 -0
  153. package/dist/safety/sql-validator.js +143 -0
  154. package/dist/schema/adapters/mysql.d.ts +16 -0
  155. package/dist/schema/adapters/mysql.js +287 -0
  156. package/dist/schema/introspector.d.ts +70 -0
  157. package/dist/schema/introspector.js +40 -0
  158. package/dist/taurus/flashback.d.ts +36 -0
  159. package/dist/taurus/flashback.js +149 -0
  160. package/dist/taurus/recycle-bin.d.ts +14 -0
  161. package/dist/taurus/recycle-bin.js +61 -0
  162. package/dist/utils/formatter.d.ts +70 -0
  163. package/dist/utils/formatter.js +60 -0
  164. package/dist/utils/hash.d.ts +2 -0
  165. package/dist/utils/hash.js +247 -0
  166. package/dist/utils/id.d.ts +2 -0
  167. package/dist/utils/id.js +11 -0
  168. package/dist/utils/logger.d.ts +9 -0
  169. package/dist/utils/logger.js +39 -0
  170. package/package.json +46 -0
@@ -0,0 +1,189 @@
1
+ export type DiagnosticToolName = "diagnose_service_latency" | "diagnose_db_hotspot" | "find_top_slow_sql" | "diagnose_slow_query" | "diagnose_connection_spike" | "diagnose_lock_contention" | "diagnose_storage_pressure";
2
+ export type DiagnosticStatus = "ok" | "inconclusive" | "not_applicable";
3
+ export type DiagnosticSeverity = "info" | "warning" | "high" | "critical";
4
+ export type DiagnosticEvidenceLevel = "basic" | "standard" | "full";
5
+ export type DiagnosticConfidence = "low" | "medium" | "high";
6
+ export interface DiagnosisWindow {
7
+ from?: string;
8
+ to?: string;
9
+ relative?: string;
10
+ }
11
+ export interface DiagnosticBaseInput {
12
+ datasource?: string;
13
+ database?: string;
14
+ timeRange?: DiagnosisWindow;
15
+ evidenceLevel?: DiagnosticEvidenceLevel;
16
+ includeRawEvidence?: boolean;
17
+ maxCandidates?: number;
18
+ }
19
+ export interface DiagnoseSlowQueryInput extends DiagnosticBaseInput {
20
+ sql?: string;
21
+ sqlHash?: string;
22
+ digestText?: string;
23
+ }
24
+ export interface DiagnoseServiceLatencyInput extends DiagnosticBaseInput {
25
+ user?: string;
26
+ clientHost?: string;
27
+ symptom?: "latency" | "timeout" | "cpu" | "connection_growth";
28
+ }
29
+ export interface DiagnoseDbHotspotInput extends DiagnosticBaseInput {
30
+ scope?: "sql" | "table" | "session";
31
+ }
32
+ export interface FindTopSlowSqlInput extends DiagnosticBaseInput {
33
+ topN?: number;
34
+ sortBy?: "avg_latency" | "total_latency" | "exec_count" | "lock_time";
35
+ }
36
+ export interface DiagnoseConnectionSpikeInput extends DiagnosticBaseInput {
37
+ user?: string;
38
+ clientHost?: string;
39
+ compareBaseline?: boolean;
40
+ }
41
+ export interface DiagnoseLockContentionInput extends DiagnosticBaseInput {
42
+ table?: string;
43
+ blockerSessionId?: string;
44
+ }
45
+ export interface DiagnoseStoragePressureInput extends DiagnosticBaseInput {
46
+ scope?: "instance" | "database" | "table";
47
+ table?: string;
48
+ }
49
+ export interface DiagnosticRootCauseCandidate {
50
+ code: string;
51
+ title: string;
52
+ confidence: DiagnosticConfidence;
53
+ rationale: string;
54
+ }
55
+ export interface DiagnosticSuspiciousSql {
56
+ sqlHash?: string;
57
+ digestText?: string;
58
+ reason: string;
59
+ }
60
+ export interface DiagnosticSuspiciousSession {
61
+ sessionId?: string;
62
+ user?: string;
63
+ state?: string;
64
+ reason: string;
65
+ }
66
+ export interface DiagnosticSuspiciousTable {
67
+ table: string;
68
+ reason: string;
69
+ }
70
+ export interface DiagnosticSuspiciousUser {
71
+ user: string;
72
+ clientHost?: string;
73
+ reason: string;
74
+ }
75
+ export interface DiagnosticSuspiciousEntities {
76
+ sqls?: DiagnosticSuspiciousSql[];
77
+ sessions?: DiagnosticSuspiciousSession[];
78
+ tables?: DiagnosticSuspiciousTable[];
79
+ users?: DiagnosticSuspiciousUser[];
80
+ }
81
+ export interface DiagnosticEvidenceItem {
82
+ source: string;
83
+ title: string;
84
+ summary: string;
85
+ rawRef?: string;
86
+ }
87
+ export interface TopSlowSqlItem {
88
+ sqlHash?: string;
89
+ digestText?: string;
90
+ sampleSql?: string;
91
+ avgLatencyMs?: number;
92
+ totalLatencyMs?: number;
93
+ execCount?: number;
94
+ avgLockTimeMs?: number;
95
+ avgRowsExamined?: number;
96
+ evidenceSources: string[];
97
+ recommendation?: string;
98
+ }
99
+ export interface DiagnosticNextToolInput {
100
+ tool: DiagnosticToolName | "show_processlist";
101
+ input: Record<string, unknown>;
102
+ rationale: string;
103
+ }
104
+ export type ServiceLatencySuspectedCategory = "slow_sql" | "lock_contention" | "connection_spike" | "resource_pressure" | "mixed";
105
+ export interface ServiceLatencyCandidate {
106
+ type: "sql" | "session" | "table";
107
+ title: string;
108
+ confidence: DiagnosticConfidence;
109
+ sqlHash?: string;
110
+ digestText?: string;
111
+ sampleSql?: string;
112
+ sessionId?: string;
113
+ table?: string;
114
+ rationale: string;
115
+ }
116
+ export interface DbHotspotItem {
117
+ type: "sql" | "session" | "table";
118
+ title: string;
119
+ confidence: DiagnosticConfidence;
120
+ sqlHash?: string;
121
+ digestText?: string;
122
+ sampleSql?: string;
123
+ sessionId?: string;
124
+ table?: string;
125
+ rationale: string;
126
+ evidenceSources: string[];
127
+ recommendation?: string;
128
+ }
129
+ export interface DiagnosticResult {
130
+ tool: DiagnosticToolName;
131
+ status: DiagnosticStatus;
132
+ severity: DiagnosticSeverity;
133
+ summary: string;
134
+ diagnosisWindow: DiagnosisWindow;
135
+ rootCauseCandidates: DiagnosticRootCauseCandidate[];
136
+ keyFindings: string[];
137
+ suspiciousEntities?: DiagnosticSuspiciousEntities;
138
+ evidence: DiagnosticEvidenceItem[];
139
+ recommendedActions: string[];
140
+ recommendedNextTools?: string[];
141
+ nextToolInputs?: DiagnosticNextToolInput[];
142
+ limitations?: string[];
143
+ }
144
+ export interface ServiceLatencyResult {
145
+ tool: "diagnose_service_latency";
146
+ status: DiagnosticStatus;
147
+ summary: string;
148
+ diagnosisWindow: DiagnosisWindow;
149
+ suspectedCategory: ServiceLatencySuspectedCategory;
150
+ topCandidates: ServiceLatencyCandidate[];
151
+ evidence: DiagnosticEvidenceItem[];
152
+ recommendedNextTools: string[];
153
+ nextToolInputs: DiagnosticNextToolInput[];
154
+ limitations?: string[];
155
+ }
156
+ export interface DbHotspotResult {
157
+ tool: "diagnose_db_hotspot";
158
+ status: DiagnosticStatus;
159
+ summary: string;
160
+ diagnosisWindow: DiagnosisWindow;
161
+ scope: "sql" | "table" | "session" | "all";
162
+ hotspots: DbHotspotItem[];
163
+ evidence: DiagnosticEvidenceItem[];
164
+ recommendedNextTools: string[];
165
+ nextToolInputs: DiagnosticNextToolInput[];
166
+ limitations?: string[];
167
+ }
168
+ export interface FindTopSlowSqlResult {
169
+ tool: "find_top_slow_sql";
170
+ status: DiagnosticStatus;
171
+ summary: string;
172
+ diagnosisWindow: DiagnosisWindow;
173
+ topSqls: TopSlowSqlItem[];
174
+ evidence: DiagnosticEvidenceItem[];
175
+ limitations?: string[];
176
+ }
177
+ export interface PlaceholderDiagnosticOptions {
178
+ summary: string;
179
+ candidateTitle: string;
180
+ candidateRationale: string;
181
+ keyFindings?: string[];
182
+ suspiciousEntities?: DiagnosticSuspiciousEntities;
183
+ recommendedActions?: string[];
184
+ limitations?: string[];
185
+ evidence?: DiagnosticEvidenceItem[];
186
+ status?: DiagnosticStatus;
187
+ severity?: DiagnosticSeverity;
188
+ }
189
+ export declare function createPlaceholderDiagnosticResult(tool: DiagnosticToolName, input: DiagnosticBaseInput, options: PlaceholderDiagnosticOptions): DiagnosticResult;
@@ -0,0 +1,39 @@
1
+ export function createPlaceholderDiagnosticResult(tool, input, options) {
2
+ return {
3
+ tool,
4
+ status: options.status ?? "inconclusive",
5
+ severity: options.severity ?? "info",
6
+ summary: options.summary,
7
+ diagnosisWindow: {
8
+ from: input.timeRange?.from,
9
+ to: input.timeRange?.to,
10
+ relative: input.timeRange?.relative,
11
+ },
12
+ rootCauseCandidates: [
13
+ {
14
+ code: `${tool}_pending`,
15
+ title: options.candidateTitle,
16
+ confidence: "low",
17
+ rationale: options.candidateRationale,
18
+ },
19
+ ],
20
+ keyFindings: options.keyFindings ?? [
21
+ "The diagnostic contract is available, but evidence collectors have not been wired yet.",
22
+ "No live control-plane or data-plane evidence was collected in this run.",
23
+ ],
24
+ suspiciousEntities: options.suspiciousEntities,
25
+ evidence: options.evidence ?? [
26
+ {
27
+ source: "diagnostics_scaffold",
28
+ title: "Diagnostic scaffold active",
29
+ summary: "Typed inputs, outputs, and engine entrypoints are in place, but collectors and analyzers are pending.",
30
+ },
31
+ ],
32
+ recommendedActions: options.recommendedActions ?? [
33
+ "Implement the required collectors before relying on this tool for production diagnosis.",
34
+ ],
35
+ limitations: options.limitations ?? [
36
+ "This diagnostic currently returns a scaffolded result instead of live evidence-backed analysis.",
37
+ ],
38
+ };
39
+ }
@@ -0,0 +1,8 @@
1
+ import type { SessionContext } from "../../context/session-context.js";
2
+ import type { DiagnoseLockContentionInput } from "../../diagnostics/types.js";
3
+ import type { QueryResult } from "../../executor/sql-executor.js";
4
+ import type { ShowLockWaitsInput, TaurusDBEngine } from "../../engine.js";
5
+ import { type DeadlockSummary, type MetadataLockRow } from "../helpers.js";
6
+ export declare function showLockWaits(engine: TaurusDBEngine, input: ShowLockWaitsInput, ctx: SessionContext): Promise<QueryResult>;
7
+ export declare function findMetadataLockWaits(engine: TaurusDBEngine, input: DiagnoseLockContentionInput, ctx: SessionContext): Promise<MetadataLockRow[]>;
8
+ export declare function findLatestDeadlock(engine: TaurusDBEngine, ctx: SessionContext): Promise<DeadlockSummary | undefined>;
@@ -0,0 +1,146 @@
1
+ import { clampInteger, lockEvidenceRowLimit, parseDeadlockSummary, parseMetadataLockRows, quoteLiteral, } from "../helpers.js";
2
+ export async function showLockWaits(engine, input, ctx) {
3
+ const maxRows = clampInteger(input.maxRows, 20, 1, 100);
4
+ const includeSql = input.includeSql === true;
5
+ const sqlMaxChars = clampInteger(input.sqlMaxChars, 256, 32, 2048);
6
+ const selectedColumns = [
7
+ "CAST(waiting_thread.PROCESSLIST_ID AS CHAR) AS waiting_session_id",
8
+ "waiting_thread.PROCESSLIST_USER AS waiting_user",
9
+ "waiting_thread.PROCESSLIST_STATE AS waiting_state",
10
+ "waiting_trx.TRX_STATE AS waiting_trx_state",
11
+ "TIMESTAMPDIFF(SECOND, waiting_trx.TRX_WAIT_STARTED, CURRENT_TIMESTAMP) AS wait_age_seconds",
12
+ "CAST(blocking_thread.PROCESSLIST_ID AS CHAR) AS blocking_session_id",
13
+ "blocking_thread.PROCESSLIST_USER AS blocking_user",
14
+ "blocking_thread.PROCESSLIST_STATE AS blocking_state",
15
+ "blocking_trx.TRX_STATE AS blocking_trx_state",
16
+ "TIMESTAMPDIFF(SECOND, blocking_trx.TRX_STARTED, CURRENT_TIMESTAMP) AS blocking_trx_age_seconds",
17
+ "requesting_lock.OBJECT_SCHEMA AS locked_schema",
18
+ "requesting_lock.OBJECT_NAME AS locked_table",
19
+ "requesting_lock.INDEX_NAME AS locked_index",
20
+ "requesting_lock.LOCK_TYPE AS waiting_lock_type",
21
+ "requesting_lock.LOCK_MODE AS waiting_lock_mode",
22
+ "blocking_lock.LOCK_TYPE AS blocking_lock_type",
23
+ "blocking_lock.LOCK_MODE AS blocking_lock_mode",
24
+ ];
25
+ if (includeSql) {
26
+ selectedColumns.push("waiting_thread.PROCESSLIST_INFO AS waiting_query", "blocking_thread.PROCESSLIST_INFO AS blocking_query");
27
+ }
28
+ const whereClauses = ["waits.ENGINE = 'INNODB'"];
29
+ const targetSchema = ctx.database;
30
+ if (targetSchema) {
31
+ whereClauses.push(`requesting_lock.OBJECT_SCHEMA = ${quoteLiteral(targetSchema)}`);
32
+ }
33
+ if (input.table) {
34
+ whereClauses.push(`requesting_lock.OBJECT_NAME = ${quoteLiteral(input.table)}`);
35
+ }
36
+ if (input.blockerSessionId) {
37
+ whereClauses.push(`CAST(blocking_thread.PROCESSLIST_ID AS CHAR) = ${quoteLiteral(input.blockerSessionId)}`);
38
+ }
39
+ const sql = `
40
+ SELECT ${selectedColumns.join(", ")}
41
+ FROM performance_schema.data_lock_waits AS waits
42
+ INNER JOIN performance_schema.data_locks AS requesting_lock
43
+ ON requesting_lock.ENGINE = waits.ENGINE
44
+ AND requesting_lock.ENGINE_LOCK_ID = waits.REQUESTING_ENGINE_LOCK_ID
45
+ INNER JOIN performance_schema.data_locks AS blocking_lock
46
+ ON blocking_lock.ENGINE = waits.ENGINE
47
+ AND blocking_lock.ENGINE_LOCK_ID = waits.BLOCKING_ENGINE_LOCK_ID
48
+ LEFT JOIN information_schema.INNODB_TRX AS waiting_trx
49
+ ON waiting_trx.TRX_ID = waits.REQUESTING_ENGINE_TRANSACTION_ID
50
+ LEFT JOIN information_schema.INNODB_TRX AS blocking_trx
51
+ ON blocking_trx.TRX_ID = waits.BLOCKING_ENGINE_TRANSACTION_ID
52
+ LEFT JOIN performance_schema.threads AS waiting_thread
53
+ ON waiting_thread.THREAD_ID = waits.REQUESTING_THREAD_ID
54
+ LEFT JOIN performance_schema.threads AS blocking_thread
55
+ ON blocking_thread.THREAD_ID = waits.BLOCKING_THREAD_ID
56
+ WHERE ${whereClauses.join(" AND ")}
57
+ ORDER BY wait_age_seconds DESC, blocking_trx_age_seconds DESC, blocking_session_id DESC
58
+ LIMIT ${maxRows}
59
+ `.trim();
60
+ return engine.executor.executeReadonly(sql, ctx, {
61
+ maxRows,
62
+ maxColumns: selectedColumns.length,
63
+ maxFieldChars: includeSql ? sqlMaxChars : 256,
64
+ timeoutMs: ctx.limits.timeoutMs,
65
+ });
66
+ }
67
+ export async function findMetadataLockWaits(engine, input, ctx) {
68
+ const maxRows = lockEvidenceRowLimit(input.evidenceLevel);
69
+ const whereClauses = [
70
+ "waiting.LOCK_STATUS = 'PENDING'",
71
+ "blocking.LOCK_STATUS = 'GRANTED'",
72
+ "waiting.OWNER_THREAD_ID <> blocking.OWNER_THREAD_ID",
73
+ ];
74
+ const focusedTable = input.table?.includes(".")
75
+ ? {
76
+ schema: input.table.split(".")[0],
77
+ table: input.table.split(".").slice(1).join("."),
78
+ }
79
+ : {
80
+ schema: ctx.database,
81
+ table: input.table,
82
+ };
83
+ if (focusedTable.schema) {
84
+ whereClauses.push(`waiting.OBJECT_SCHEMA = ${quoteLiteral(focusedTable.schema)}`);
85
+ }
86
+ if (focusedTable.table) {
87
+ whereClauses.push(`waiting.OBJECT_NAME = ${quoteLiteral(focusedTable.table)}`);
88
+ }
89
+ if (input.blockerSessionId) {
90
+ whereClauses.push(`blocking_threads.PROCESSLIST_ID = ${quoteLiteral(input.blockerSessionId)}`);
91
+ }
92
+ const sql = `
93
+ SELECT
94
+ waiting_threads.PROCESSLIST_ID AS waiting_session_id,
95
+ waiting_threads.PROCESSLIST_USER AS waiting_user,
96
+ waiting_threads.PROCESSLIST_STATE AS waiting_state,
97
+ blocking_threads.PROCESSLIST_ID AS blocking_session_id,
98
+ blocking_threads.PROCESSLIST_USER AS blocking_user,
99
+ blocking_threads.PROCESSLIST_STATE AS blocking_state,
100
+ waiting.OBJECT_TYPE AS object_type,
101
+ waiting.OBJECT_SCHEMA AS object_schema,
102
+ waiting.OBJECT_NAME AS object_name,
103
+ waiting.LOCK_TYPE AS waiting_lock_type,
104
+ waiting.LOCK_DURATION AS waiting_lock_duration,
105
+ blocking.LOCK_TYPE AS blocking_lock_type,
106
+ blocking.LOCK_DURATION AS blocking_lock_duration
107
+ FROM performance_schema.metadata_locks AS waiting
108
+ INNER JOIN performance_schema.threads AS waiting_threads
109
+ ON waiting_threads.THREAD_ID = waiting.OWNER_THREAD_ID
110
+ INNER JOIN performance_schema.metadata_locks AS blocking
111
+ ON blocking.OBJECT_TYPE = waiting.OBJECT_TYPE
112
+ AND COALESCE(blocking.OBJECT_SCHEMA, '') = COALESCE(waiting.OBJECT_SCHEMA, '')
113
+ AND COALESCE(blocking.OBJECT_NAME, '') = COALESCE(waiting.OBJECT_NAME, '')
114
+ INNER JOIN performance_schema.threads AS blocking_threads
115
+ ON blocking_threads.THREAD_ID = blocking.OWNER_THREAD_ID
116
+ WHERE ${whereClauses.join(" AND ")}
117
+ ORDER BY waiting.OBJECT_SCHEMA ASC, waiting.OBJECT_NAME ASC, blocking_threads.PROCESSLIST_ID ASC
118
+ LIMIT ${maxRows}
119
+ `.trim();
120
+ try {
121
+ const result = await engine.executor.executeReadonly(sql, ctx, {
122
+ maxRows,
123
+ maxColumns: 13,
124
+ maxFieldChars: 512,
125
+ timeoutMs: ctx.limits.timeoutMs,
126
+ });
127
+ return parseMetadataLockRows(result);
128
+ }
129
+ catch {
130
+ return [];
131
+ }
132
+ }
133
+ export async function findLatestDeadlock(engine, ctx) {
134
+ try {
135
+ const result = await engine.executor.executeReadonly("SHOW ENGINE INNODB STATUS", ctx, {
136
+ maxRows: 1,
137
+ maxColumns: 3,
138
+ maxFieldChars: 32768,
139
+ timeoutMs: ctx.limits.timeoutMs,
140
+ });
141
+ return parseDeadlockSummary(result);
142
+ }
143
+ catch {
144
+ return undefined;
145
+ }
146
+ }
@@ -0,0 +1,4 @@
1
+ import type { SessionContext } from "../../context/session-context.js";
2
+ import type { QueryResult } from "../../executor/sql-executor.js";
3
+ import type { ShowProcesslistInput, TaurusDBEngine } from "../../engine.js";
4
+ export declare function showProcesslist(engine: TaurusDBEngine, input: ShowProcesslistInput, ctx: SessionContext): Promise<QueryResult>;
@@ -0,0 +1,56 @@
1
+ import { clampInteger, escapeLikePrefix, quoteLiteral, } from "../helpers.js";
2
+ export async function showProcesslist(engine, input, ctx) {
3
+ const maxRows = clampInteger(input.maxRows, 20, 1, 100);
4
+ const minTimeSeconds = clampInteger(input.minTimeSeconds, 0, 0, 86_400);
5
+ const includeIdle = input.includeIdle === true;
6
+ const includeSystem = input.includeSystem === true;
7
+ const includeInfo = input.includeInfo === true;
8
+ const infoMaxChars = clampInteger(input.infoMaxChars, 256, 32, 2048);
9
+ const selectedColumns = [
10
+ "ID AS session_id",
11
+ "USER AS user",
12
+ "HOST AS host",
13
+ "DB AS database_name",
14
+ "COMMAND AS command",
15
+ "TIME AS time_seconds",
16
+ "STATE AS state",
17
+ ];
18
+ if (includeInfo) {
19
+ selectedColumns.push("INFO AS info_preview");
20
+ }
21
+ const whereClauses = [];
22
+ if (!includeIdle) {
23
+ whereClauses.push("COMMAND <> 'Sleep'");
24
+ }
25
+ if (!includeSystem) {
26
+ whereClauses.push("USER <> 'system user'");
27
+ }
28
+ if (input.user) {
29
+ whereClauses.push(`USER = ${quoteLiteral(input.user)}`);
30
+ }
31
+ if (input.host) {
32
+ whereClauses.push(`HOST LIKE ${quoteLiteral(`${escapeLikePrefix(input.host)}%`)} ESCAPE '\\'`);
33
+ }
34
+ if (input.sessionDatabase) {
35
+ whereClauses.push(`DB = ${quoteLiteral(input.sessionDatabase)}`);
36
+ }
37
+ if (input.command) {
38
+ whereClauses.push(`COMMAND = ${quoteLiteral(input.command)}`);
39
+ }
40
+ if (minTimeSeconds > 0) {
41
+ whereClauses.push(`TIME >= ${minTimeSeconds}`);
42
+ }
43
+ const sql = `
44
+ SELECT ${selectedColumns.join(", ")}
45
+ FROM information_schema.PROCESSLIST
46
+ ${whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : ""}
47
+ ORDER BY TIME DESC, ID DESC
48
+ LIMIT ${maxRows}
49
+ `.trim();
50
+ return engine.executor.executeReadonly(sql, ctx, {
51
+ maxRows,
52
+ maxColumns: selectedColumns.length,
53
+ maxFieldChars: includeInfo ? infoMaxChars : 256,
54
+ timeoutMs: ctx.limits.timeoutMs,
55
+ });
56
+ }
@@ -0,0 +1,10 @@
1
+ import type { SessionContext } from "../../context/session-context.js";
2
+ import type { FindTopSlowSqlInput } from "../../diagnostics/types.js";
3
+ import type { TaurusDBEngine } from "../../engine.js";
4
+ import { type StatementDigestRow, type StatementWaitEventRow } from "../helpers.js";
5
+ export declare function findStatementDigestSample(engine: TaurusDBEngine, digestText: string, ctx: SessionContext): Promise<StatementDigestRow | undefined>;
6
+ export declare function findStatementDigestSampleForSql(engine: TaurusDBEngine, sql: string, ctx: SessionContext): Promise<StatementDigestRow | undefined>;
7
+ export declare function findStatementDigestCandidatesForSqlHints(engine: TaurusDBEngine, sqlText: string, ctx: SessionContext): Promise<StatementDigestRow[]>;
8
+ export declare function findTopStatementDigests(engine: TaurusDBEngine, input: FindTopSlowSqlInput, ctx: SessionContext): Promise<StatementDigestRow[]>;
9
+ export declare function isPerformanceSchemaEnabled(engine: TaurusDBEngine, ctx: SessionContext): Promise<boolean | undefined>;
10
+ export declare function findStatementWaitEvents(engine: TaurusDBEngine, digestText: string, ctx: SessionContext): Promise<StatementWaitEventRow[]>;
@@ -0,0 +1,203 @@
1
+ import { clampInteger, digestMatchScore, escapeLikePrefix, extractSqlTableNameHints, parseStatementDigestRows, parseStatementWaitEventRows, quoteLiteral, topSlowSqlOrderBy, } from "../helpers.js";
2
+ export async function findStatementDigestSample(engine, digestText, ctx) {
3
+ const whereClauses = [`DIGEST_TEXT = ${quoteLiteral(digestText)}`];
4
+ if (ctx.database) {
5
+ whereClauses.push(`SCHEMA_NAME = ${quoteLiteral(ctx.database)}`);
6
+ }
7
+ const sql = `
8
+ SELECT
9
+ SCHEMA_NAME AS schema_name,
10
+ DIGEST AS digest,
11
+ DIGEST_TEXT AS digest_text,
12
+ QUERY_SAMPLE_TEXT AS query_sample_text,
13
+ COUNT_STAR AS exec_count,
14
+ ROUND(AVG_TIMER_WAIT / 1000000000, 3) AS avg_latency_ms,
15
+ ROUND(SUM_TIMER_WAIT / 1000000000, 3) AS total_latency_ms,
16
+ ROUND(MAX_TIMER_WAIT / 1000000000, 3) AS max_latency_ms,
17
+ ROUND(SUM_LOCK_TIME / 1000000000 / NULLIF(COUNT_STAR, 0), 3) AS avg_lock_time_ms,
18
+ ROUND(SUM_ROWS_EXAMINED / NULLIF(COUNT_STAR, 0), 3) AS avg_rows_examined,
19
+ ROUND(SUM_SORT_ROWS / NULLIF(COUNT_STAR, 0), 3) AS avg_sort_rows,
20
+ ROUND(SUM_CREATED_TMP_TABLES / NULLIF(COUNT_STAR, 0), 3) AS avg_tmp_tables,
21
+ ROUND(SUM_CREATED_TMP_DISK_TABLES / NULLIF(COUNT_STAR, 0), 3) AS avg_tmp_disk_tables,
22
+ SUM_SELECT_SCAN AS select_scan_count,
23
+ SUM_NO_INDEX_USED AS no_index_used_count
24
+ FROM performance_schema.events_statements_summary_by_digest
25
+ WHERE ${whereClauses.join(" AND ")}
26
+ ORDER BY SUM_TIMER_WAIT DESC, COUNT_STAR DESC
27
+ LIMIT 1
28
+ `.trim();
29
+ const result = await engine.executor.executeReadonly(sql, ctx, {
30
+ maxRows: 1,
31
+ maxColumns: 15,
32
+ maxFieldChars: 2048,
33
+ timeoutMs: ctx.limits.timeoutMs,
34
+ });
35
+ return parseStatementDigestRows(result)[0];
36
+ }
37
+ export async function findStatementDigestSampleForSql(engine, sql, ctx) {
38
+ const candidates = await engine.findTopStatementDigests({
39
+ database: ctx.database,
40
+ topN: 20,
41
+ sortBy: "total_latency",
42
+ }, ctx);
43
+ const ranked = candidates
44
+ .map((candidate) => ({
45
+ candidate,
46
+ score: digestMatchScore(sql, candidate),
47
+ }))
48
+ .filter((item) => item.score > 0)
49
+ .sort((left, right) => right.score - left.score ||
50
+ (right.candidate.totalLatencyMs ?? 0) -
51
+ (left.candidate.totalLatencyMs ?? 0) ||
52
+ (right.candidate.execCount ?? 0) - (left.candidate.execCount ?? 0));
53
+ if (ranked[0]?.candidate) {
54
+ return ranked[0].candidate;
55
+ }
56
+ const hintCandidates = await engine.findStatementDigestCandidatesForSqlHints(sql, ctx).catch(() => []);
57
+ return hintCandidates
58
+ .map((candidate) => ({
59
+ candidate,
60
+ score: digestMatchScore(sql, candidate),
61
+ }))
62
+ .filter((item) => item.score > 0)
63
+ .sort((left, right) => right.score - left.score ||
64
+ (right.candidate.totalLatencyMs ?? 0) -
65
+ (left.candidate.totalLatencyMs ?? 0) ||
66
+ (right.candidate.execCount ?? 0) - (left.candidate.execCount ?? 0))[0]?.candidate;
67
+ }
68
+ export async function findStatementDigestCandidatesForSqlHints(engine, sqlText, ctx) {
69
+ const tableHints = extractSqlTableNameHints(sqlText).slice(0, 3);
70
+ if (tableHints.length === 0) {
71
+ return [];
72
+ }
73
+ const whereClauses = ["DIGEST_TEXT IS NOT NULL", "DIGEST_TEXT <> 'NULL'"];
74
+ if (ctx.database) {
75
+ whereClauses.push(`SCHEMA_NAME = ${quoteLiteral(ctx.database)}`);
76
+ }
77
+ const tableClauses = tableHints.map((table) => {
78
+ const tableLike = quoteLiteral(`%${escapeLikePrefix(table)}%`);
79
+ return `(DIGEST_TEXT LIKE ${tableLike} ESCAPE '\\\\' OR QUERY_SAMPLE_TEXT LIKE ${tableLike} ESCAPE '\\\\')`;
80
+ });
81
+ whereClauses.push(`(${tableClauses.join(" OR ")})`);
82
+ const sql = `
83
+ SELECT
84
+ SCHEMA_NAME AS schema_name,
85
+ DIGEST AS digest,
86
+ DIGEST_TEXT AS digest_text,
87
+ QUERY_SAMPLE_TEXT AS query_sample_text,
88
+ COUNT_STAR AS exec_count,
89
+ ROUND(AVG_TIMER_WAIT / 1000000000, 3) AS avg_latency_ms,
90
+ ROUND(SUM_TIMER_WAIT / 1000000000, 3) AS total_latency_ms,
91
+ ROUND(MAX_TIMER_WAIT / 1000000000, 3) AS max_latency_ms,
92
+ ROUND(SUM_LOCK_TIME / 1000000000 / NULLIF(COUNT_STAR, 0), 3) AS avg_lock_time_ms,
93
+ ROUND(SUM_ROWS_EXAMINED / NULLIF(COUNT_STAR, 0), 3) AS avg_rows_examined,
94
+ ROUND(SUM_SORT_ROWS / NULLIF(COUNT_STAR, 0), 3) AS avg_sort_rows,
95
+ ROUND(SUM_CREATED_TMP_TABLES / NULLIF(COUNT_STAR, 0), 3) AS avg_tmp_tables,
96
+ ROUND(SUM_CREATED_TMP_DISK_TABLES / NULLIF(COUNT_STAR, 0), 3) AS avg_tmp_disk_tables,
97
+ SUM_SELECT_SCAN AS select_scan_count,
98
+ SUM_NO_INDEX_USED AS no_index_used_count
99
+ FROM performance_schema.events_statements_summary_by_digest
100
+ WHERE ${whereClauses.join(" AND ")}
101
+ ORDER BY SUM_TIMER_WAIT DESC, AVG_TIMER_WAIT DESC, COUNT_STAR DESC
102
+ LIMIT 50
103
+ `.trim();
104
+ const result = await engine.executor.executeReadonly(sql, ctx, {
105
+ maxRows: 50,
106
+ maxColumns: 15,
107
+ maxFieldChars: 4096,
108
+ timeoutMs: ctx.limits.timeoutMs,
109
+ });
110
+ return parseStatementDigestRows(result);
111
+ }
112
+ export async function findTopStatementDigests(engine, input, ctx) {
113
+ const maxRows = clampInteger(input.topN, 5, 1, 20);
114
+ const whereClauses = ["DIGEST_TEXT IS NOT NULL", "DIGEST_TEXT <> 'NULL'"];
115
+ if (ctx.database) {
116
+ whereClauses.push(`SCHEMA_NAME = ${quoteLiteral(ctx.database)}`);
117
+ }
118
+ const sql = `
119
+ SELECT
120
+ SCHEMA_NAME AS schema_name,
121
+ DIGEST AS digest,
122
+ DIGEST_TEXT AS digest_text,
123
+ QUERY_SAMPLE_TEXT AS query_sample_text,
124
+ COUNT_STAR AS exec_count,
125
+ ROUND(AVG_TIMER_WAIT / 1000000000, 3) AS avg_latency_ms,
126
+ ROUND(SUM_TIMER_WAIT / 1000000000, 3) AS total_latency_ms,
127
+ ROUND(MAX_TIMER_WAIT / 1000000000, 3) AS max_latency_ms,
128
+ ROUND(SUM_LOCK_TIME / 1000000000 / NULLIF(COUNT_STAR, 0), 3) AS avg_lock_time_ms,
129
+ ROUND(SUM_ROWS_EXAMINED / NULLIF(COUNT_STAR, 0), 3) AS avg_rows_examined,
130
+ ROUND(SUM_SORT_ROWS / NULLIF(COUNT_STAR, 0), 3) AS avg_sort_rows,
131
+ ROUND(SUM_CREATED_TMP_TABLES / NULLIF(COUNT_STAR, 0), 3) AS avg_tmp_tables,
132
+ ROUND(SUM_CREATED_TMP_DISK_TABLES / NULLIF(COUNT_STAR, 0), 3) AS avg_tmp_disk_tables,
133
+ SUM_SELECT_SCAN AS select_scan_count,
134
+ SUM_NO_INDEX_USED AS no_index_used_count
135
+ FROM performance_schema.events_statements_summary_by_digest
136
+ WHERE ${whereClauses.join(" AND ")}
137
+ ORDER BY ${topSlowSqlOrderBy(input.sortBy)}
138
+ LIMIT ${maxRows}
139
+ `.trim();
140
+ const result = await engine.executor.executeReadonly(sql, ctx, {
141
+ maxRows,
142
+ maxColumns: 15,
143
+ maxFieldChars: 4096,
144
+ timeoutMs: ctx.limits.timeoutMs,
145
+ });
146
+ return parseStatementDigestRows(result);
147
+ }
148
+ export async function isPerformanceSchemaEnabled(engine, ctx) {
149
+ try {
150
+ const result = await engine.executor.executeReadonly("SELECT @@performance_schema AS performance_schema_enabled", ctx, {
151
+ maxRows: 1,
152
+ maxColumns: 1,
153
+ maxFieldChars: 64,
154
+ timeoutMs: ctx.limits.timeoutMs,
155
+ });
156
+ const value = result.rows?.[0]?.[0];
157
+ if (typeof value === "number") {
158
+ return value === 1;
159
+ }
160
+ if (typeof value === "string") {
161
+ return value === "1" || value.toLowerCase() === "on";
162
+ }
163
+ return undefined;
164
+ }
165
+ catch {
166
+ return undefined;
167
+ }
168
+ }
169
+ export async function findStatementWaitEvents(engine, digestText, ctx) {
170
+ const whereClauses = [`stmt.DIGEST_TEXT = ${quoteLiteral(digestText)}`];
171
+ if (ctx.database) {
172
+ whereClauses.push(`stmt.CURRENT_SCHEMA = ${quoteLiteral(ctx.database)}`);
173
+ }
174
+ const sql = `
175
+ SELECT
176
+ waits.EVENT_NAME AS event_name,
177
+ COUNT(*) AS sample_count,
178
+ COUNT(DISTINCT CONCAT(stmt.THREAD_ID, ':', stmt.EVENT_ID)) AS statement_count,
179
+ ROUND(SUM(waits.TIMER_WAIT) / 1000000000, 3) AS total_wait_ms,
180
+ ROUND(AVG(waits.TIMER_WAIT) / 1000000000, 3) AS avg_wait_ms
181
+ FROM performance_schema.events_statements_history_long AS stmt
182
+ INNER JOIN performance_schema.events_waits_history_long AS waits
183
+ ON waits.THREAD_ID = stmt.THREAD_ID
184
+ AND waits.NESTING_EVENT_ID = stmt.EVENT_ID
185
+ AND waits.NESTING_EVENT_TYPE = 'STATEMENT'
186
+ WHERE ${whereClauses.join(" AND ")}
187
+ GROUP BY waits.EVENT_NAME
188
+ ORDER BY total_wait_ms DESC, sample_count DESC, event_name ASC
189
+ LIMIT 3
190
+ `.trim();
191
+ try {
192
+ const result = await engine.executor.executeReadonly(sql, ctx, {
193
+ maxRows: 3,
194
+ maxColumns: 5,
195
+ maxFieldChars: 256,
196
+ timeoutMs: ctx.limits.timeoutMs,
197
+ });
198
+ return parseStatementWaitEventRows(result);
199
+ }
200
+ catch {
201
+ return [];
202
+ }
203
+ }
@@ -0,0 +1,6 @@
1
+ import type { SessionContext } from "../../context/session-context.js";
2
+ import type { DiagnoseStoragePressureInput } from "../../diagnostics/types.js";
3
+ import type { TaurusDBEngine } from "../../engine.js";
4
+ import { type StatementDigestRow, type TableStorageRow } from "../helpers.js";
5
+ export declare function findStorageStatementDigests(engine: TaurusDBEngine, input: DiagnoseStoragePressureInput, ctx: SessionContext): Promise<StatementDigestRow[]>;
6
+ export declare function findTableStorageStats(engine: TaurusDBEngine, input: DiagnoseStoragePressureInput, ctx: SessionContext): Promise<TableStorageRow[]>;