@bytebase/dbhub 1.4.0 → 1.5.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.
- package/dist/{chunk-ABTVMHD6.js → chunk-55X2VY5D.js} +1 -1
- package/dist/chunk-5XSBOK3W.js +63 -0
- package/dist/{chunk-MJVIE3QY.js → chunk-PDKPK25P.js} +286 -81
- package/dist/chunk-SJ5BRPQA.js +500 -0
- package/dist/{chunk-YIGJHEU6.js → chunk-X5OCFRNL.js} +170 -27
- package/dist/index.js +116 -32
- package/dist/mariadb-RWOMZTA6.js +270 -0
- package/dist/mysql-ZXO4TWLG.js +312 -0
- package/dist/{oracle-OUKBU52X.js → oracle-UAVN3F4U.js} +2 -2
- package/dist/{postgres-DC5BDEMU.js → postgres-KCFNDQLG.js} +136 -30
- package/dist/{registry-C7X5G7PA.js → registry-ZIVIYCB2.js} +2 -1
- package/dist/{sqlite-AO2BKIC6.js → sqlite-WKY6543Q.js} +2 -2
- package/dist/{sqlserver-AJUK6L55.js → sqlserver-25MAE77Q.js} +312 -372
- package/package.json +1 -1
- package/dist/chunk-6SZKW6GD.js +0 -179
- package/dist/mariadb-L7Z55ROY.js +0 -551
- package/dist/mysql-XXIHWQGR.js +0 -601
package/package.json
CHANGED
package/dist/chunk-6SZKW6GD.js
DELETED
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
computeHitRatioPct,
|
|
3
|
-
toNullableNumber
|
|
4
|
-
} from "./chunk-FU2ZJE4E.js";
|
|
5
|
-
import {
|
|
6
|
-
obfuscateDSNPassword
|
|
7
|
-
} from "./chunk-IXC4NQGC.js";
|
|
8
|
-
|
|
9
|
-
// src/connectors/mysql-family-health-check.ts
|
|
10
|
-
async function getMySQLFamilyHealthCheck(query) {
|
|
11
|
-
const [processlistRows, maxConnRows, bufferPoolRows, trxOutcome] = await Promise.all([
|
|
12
|
-
query(`
|
|
13
|
-
SELECT
|
|
14
|
-
COUNT(*) AS total,
|
|
15
|
-
SUM(CASE WHEN COMMAND != 'Sleep' THEN 1 ELSE 0 END) AS active,
|
|
16
|
-
SUM(CASE WHEN COMMAND = 'Sleep' THEN 1 ELSE 0 END) AS idle,
|
|
17
|
-
MAX(CASE WHEN COMMAND != 'Sleep' THEN TIME ELSE NULL END) AS longest_active_query_seconds
|
|
18
|
-
FROM information_schema.PROCESSLIST
|
|
19
|
-
WHERE ID <> CONNECTION_ID()
|
|
20
|
-
`),
|
|
21
|
-
query(`SHOW VARIABLES LIKE 'max_connections'`),
|
|
22
|
-
query(`
|
|
23
|
-
SHOW GLOBAL STATUS WHERE Variable_name IN ('Innodb_buffer_pool_read_requests', 'Innodb_buffer_pool_reads')
|
|
24
|
-
`),
|
|
25
|
-
// Joining PROCESSLIST against INNODB_TRX to detect idle-in-transaction
|
|
26
|
-
// sessions requires the PROCESS privilege - unlike a plain PROCESSLIST
|
|
27
|
-
// select, which silently narrows to the caller's own session instead of
|
|
28
|
-
// erroring. Run concurrently with the other queries above, but resolve
|
|
29
|
-
// rather than reject on failure so it degrades instead of failing the
|
|
30
|
-
// whole health check.
|
|
31
|
-
query(`
|
|
32
|
-
SELECT
|
|
33
|
-
COUNT(*) AS idle_in_transaction,
|
|
34
|
-
MAX(TIMESTAMPDIFF(SECOND, t.trx_started, NOW())) AS longest_idle_in_transaction_seconds
|
|
35
|
-
FROM information_schema.INNODB_TRX t
|
|
36
|
-
JOIN information_schema.PROCESSLIST p ON p.ID = t.trx_mysql_thread_id
|
|
37
|
-
WHERE p.COMMAND = 'Sleep'
|
|
38
|
-
`).then(
|
|
39
|
-
(rows) => ({ ok: true, rows }),
|
|
40
|
-
() => ({ ok: false })
|
|
41
|
-
)
|
|
42
|
-
]);
|
|
43
|
-
const notes = [];
|
|
44
|
-
let idleInTransaction = 0;
|
|
45
|
-
let longestIdleInTransactionSeconds = null;
|
|
46
|
-
if (trxOutcome.ok) {
|
|
47
|
-
idleInTransaction = Number(trxOutcome.rows[0].idle_in_transaction);
|
|
48
|
-
longestIdleInTransactionSeconds = toNullableNumber(trxOutcome.rows[0].longest_idle_in_transaction_seconds);
|
|
49
|
-
} else {
|
|
50
|
-
notes.push(
|
|
51
|
-
"Connected user lacks the PROCESS privilege: PROCESSLIST visibility is restricted to the connecting user's own sessions, and this diagnostic session is excluded from the count, so connection counts and active-query duration may under-report (down to 0). Idle-in-transaction detection is unavailable."
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
const proc = processlistRows[0];
|
|
55
|
-
const bufferPoolStats = Object.fromEntries(bufferPoolRows.map((row) => [row.Variable_name, row.Value]));
|
|
56
|
-
const readRequests = Number(bufferPoolStats.Innodb_buffer_pool_read_requests ?? 0);
|
|
57
|
-
const reads = Number(bufferPoolStats.Innodb_buffer_pool_reads ?? 0);
|
|
58
|
-
return {
|
|
59
|
-
connections: {
|
|
60
|
-
total: Number(proc.total),
|
|
61
|
-
active: Number(proc.active),
|
|
62
|
-
idle: Number(proc.idle),
|
|
63
|
-
idleInTransaction,
|
|
64
|
-
// MySQL/MariaDB's InnoDB has no equivalent of Postgres's "idle in
|
|
65
|
-
// transaction (aborted)" state - a failed statement doesn't leave the
|
|
66
|
-
// session's transaction in a distinct aborted-but-open state the way
|
|
67
|
-
// Postgres does - so idleInTransactionAborted is left undefined.
|
|
68
|
-
maxConnections: maxConnRows.length > 0 ? Number(maxConnRows[0].Value) : null,
|
|
69
|
-
longestIdleInTransactionSeconds,
|
|
70
|
-
longestActiveQuerySeconds: toNullableNumber(proc.longest_active_query_seconds)
|
|
71
|
-
},
|
|
72
|
-
bufferCache: {
|
|
73
|
-
hitRatioPct: computeHitRatioPct(readRequests, reads),
|
|
74
|
-
blocksHit: readRequests - reads,
|
|
75
|
-
blocksRead: reads
|
|
76
|
-
},
|
|
77
|
-
...notes.length > 0 ? { notes } : {}
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// src/utils/dsn-database.ts
|
|
82
|
-
var MissingDatabaseError = class extends Error {
|
|
83
|
-
constructor(message) {
|
|
84
|
-
super(message);
|
|
85
|
-
this.name = "MissingDatabaseError";
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
function requireDatabaseInDSN(database, dsn, label) {
|
|
89
|
-
if (database) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
throw new MissingDatabaseError(
|
|
93
|
-
`${label} DSN must name a database.
|
|
94
|
-
Provided: ${obfuscateDSNPassword(dsn)}
|
|
95
|
-
Add the database to the DSN, e.g. ...:3306/mydb
|
|
96
|
-
To work with several databases, define one [[sources]] entry per database in a TOML config file: https://dbhub.ai/config/toml`
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// src/utils/multi-statement-result-parser.ts
|
|
101
|
-
function isMetadataObject(element) {
|
|
102
|
-
if (!element || typeof element !== "object" || Array.isArray(element)) {
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
return "affectedRows" in element || "insertId" in element || "fieldCount" in element || "warningStatus" in element;
|
|
106
|
-
}
|
|
107
|
-
function isMultiStatementResult(results) {
|
|
108
|
-
if (!Array.isArray(results) || results.length === 0) {
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
const firstElement = results[0];
|
|
112
|
-
return isMetadataObject(firstElement) || Array.isArray(firstElement);
|
|
113
|
-
}
|
|
114
|
-
function buildResultSetsFromMultiStatement(results, statementTexts) {
|
|
115
|
-
const sql = statementTexts?.length === results.length ? statementTexts : void 0;
|
|
116
|
-
return results.map((result, index) => {
|
|
117
|
-
if (Array.isArray(result)) {
|
|
118
|
-
return { sql: sql?.[index], rows: result, rowCount: result.length };
|
|
119
|
-
}
|
|
120
|
-
if (isMetadataObject(result)) {
|
|
121
|
-
return { sql: sql?.[index], rows: [], rowCount: result.affectedRows || 0 };
|
|
122
|
-
}
|
|
123
|
-
return { sql: sql?.[index], rows: [], rowCount: 0 };
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
function parseQueryResultSets(results, statementTexts) {
|
|
127
|
-
const singleStatementSql = statementTexts?.length === 1 ? statementTexts[0] : void 0;
|
|
128
|
-
if (isMetadataObject(results)) {
|
|
129
|
-
return [{ sql: singleStatementSql, rows: [], rowCount: results.affectedRows || 0 }];
|
|
130
|
-
}
|
|
131
|
-
if (!Array.isArray(results)) {
|
|
132
|
-
return [{ sql: singleStatementSql, rows: [], rowCount: 0 }];
|
|
133
|
-
}
|
|
134
|
-
if (isMultiStatementResult(results)) {
|
|
135
|
-
return buildResultSetsFromMultiStatement(results, statementTexts);
|
|
136
|
-
}
|
|
137
|
-
return [{ sql: singleStatementSql, rows: results, rowCount: results.length }];
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// src/utils/readonly-transaction.ts
|
|
141
|
-
function isClientSideTimeout(error) {
|
|
142
|
-
return typeof error === "object" && error !== null && error.code === "PROTOCOL_SEQUENCE_TIMEOUT";
|
|
143
|
-
}
|
|
144
|
-
async function withReadOnlyTransaction(conn, readonly, supportsReadOnlyTransaction, execute) {
|
|
145
|
-
if (!readonly) {
|
|
146
|
-
return execute();
|
|
147
|
-
}
|
|
148
|
-
try {
|
|
149
|
-
await conn.query(
|
|
150
|
-
supportsReadOnlyTransaction ? "START TRANSACTION READ ONLY" : "START TRANSACTION"
|
|
151
|
-
);
|
|
152
|
-
const result = await execute();
|
|
153
|
-
await conn.query(supportsReadOnlyTransaction ? "COMMIT" : "ROLLBACK");
|
|
154
|
-
return result;
|
|
155
|
-
} catch (error) {
|
|
156
|
-
if (!isClientSideTimeout(error)) {
|
|
157
|
-
try {
|
|
158
|
-
await conn.query("ROLLBACK");
|
|
159
|
-
} catch {
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
throw error;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// src/utils/server-flavor.ts
|
|
167
|
-
function isTiDBVersion(version) {
|
|
168
|
-
return typeof version === "string" && /tidb/i.test(version);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
export {
|
|
172
|
-
getMySQLFamilyHealthCheck,
|
|
173
|
-
MissingDatabaseError,
|
|
174
|
-
requireDatabaseInDSN,
|
|
175
|
-
parseQueryResultSets,
|
|
176
|
-
isClientSideTimeout,
|
|
177
|
-
withReadOnlyTransaction,
|
|
178
|
-
isTiDBVersion
|
|
179
|
-
};
|