@bytebase/dbhub 1.0.0 → 1.2.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/README.md +10 -52
- package/dist/{chunk-MQR6VX5F.js → chunk-CUBIR72I.js} +30 -5
- package/dist/chunk-FU2ZJE4E.js +16 -0
- package/dist/{chunk-JO7YQPBQ.js → chunk-PBN2UXB5.js} +25 -3
- package/dist/chunk-QEFMUQJ2.js +179 -0
- package/dist/{chunk-S2V6RZ3C.js → chunk-RSB7DPO2.js} +64 -3
- package/dist/{chunk-JEZZN2YZ.js → chunk-WIQ4DWGY.js} +16 -0
- package/dist/index.js +341 -57
- package/dist/{mariadb-72C2BNCG.js → mariadb-E33EXGJZ.js} +16 -9
- package/dist/{mysql-CDUKJMNN.js → mysql-RLDQI3SJ.js} +68 -11
- package/dist/{postgres-YAYHDXVD.js → postgres-6XY2GPQV.js} +80 -13
- package/dist/public/assets/{index-DBYlgGks.js → index-DOZ5HOZ9.js} +21 -20
- package/dist/public/index.html +1 -1
- package/dist/{registry-ZU6ZFNQ2.js → registry-XMEJF7WW.js} +2 -2
- package/dist/{sqlite-5M7SDAQZ.js → sqlite-CZE6Z36Y.js} +14 -13
- package/dist/{sqlserver-COKW7RIK.js → sqlserver-IIGRXGYK.js} +148 -13
- package/package.json +4 -2
- package/dist/chunk-DUCNPMNW.js +0 -113
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MissingDatabaseError,
|
|
3
|
-
|
|
3
|
+
getMySQLFamilyHealthCheck,
|
|
4
4
|
isTiDBVersion,
|
|
5
|
-
|
|
5
|
+
parseQueryResultSets,
|
|
6
6
|
requireDatabaseInDSN,
|
|
7
7
|
withReadOnlyTransaction
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-QEFMUQJ2.js";
|
|
9
|
+
import "./chunk-FU2ZJE4E.js";
|
|
9
10
|
import {
|
|
10
11
|
quoteIdentifier
|
|
11
12
|
} from "./chunk-JFWX35TB.js";
|
|
12
13
|
import {
|
|
13
14
|
SQLRowLimiter,
|
|
14
15
|
closeQuietly
|
|
15
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-RSB7DPO2.js";
|
|
16
17
|
import {
|
|
17
18
|
ConnectorRegistry,
|
|
18
19
|
SafeURL,
|
|
19
20
|
obfuscateDSNPassword,
|
|
20
21
|
splitSQLStatements
|
|
21
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-WIQ4DWGY.js";
|
|
22
23
|
|
|
23
24
|
// src/connectors/mariadb/index.ts
|
|
24
25
|
import * as mariadb from "mariadb";
|
|
@@ -338,6 +339,13 @@ var MariaDBConnector = class _MariaDBConnector {
|
|
|
338
339
|
return null;
|
|
339
340
|
}
|
|
340
341
|
}
|
|
342
|
+
async getHealthCheck() {
|
|
343
|
+
if (!this.pool) {
|
|
344
|
+
throw new Error("Not connected to database");
|
|
345
|
+
}
|
|
346
|
+
const pool = this.pool;
|
|
347
|
+
return getMySQLFamilyHealthCheck((sql) => pool.query(sql));
|
|
348
|
+
}
|
|
341
349
|
async getStoredProcedures(schema, routineType) {
|
|
342
350
|
if (!this.pool) {
|
|
343
351
|
throw new Error("Not connected to database");
|
|
@@ -496,9 +504,9 @@ var MariaDBConnector = class _MariaDBConnector {
|
|
|
496
504
|
options.readonly,
|
|
497
505
|
this.supportsReadOnlyTransaction,
|
|
498
506
|
async () => {
|
|
507
|
+
const statements = splitSQLStatements(sql, "mariadb");
|
|
499
508
|
let processedSQL = sql;
|
|
500
509
|
if (options.maxRows) {
|
|
501
|
-
const statements = splitSQLStatements(sql, "mariadb");
|
|
502
510
|
const processedStatements = statements.map(
|
|
503
511
|
(statement) => SQLRowLimiter.applyMaxRows(statement, options.maxRows)
|
|
504
512
|
);
|
|
@@ -513,9 +521,8 @@ var MariaDBConnector = class _MariaDBConnector {
|
|
|
513
521
|
} else {
|
|
514
522
|
results = await conn.query(processedSQL);
|
|
515
523
|
}
|
|
516
|
-
const
|
|
517
|
-
|
|
518
|
-
return { rows, rowCount };
|
|
524
|
+
const resultSets = parseQueryResultSets(results, statements);
|
|
525
|
+
return { resultSets };
|
|
519
526
|
}
|
|
520
527
|
);
|
|
521
528
|
} finally {
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MissingDatabaseError,
|
|
3
|
-
|
|
3
|
+
getMySQLFamilyHealthCheck,
|
|
4
|
+
isClientSideTimeout,
|
|
4
5
|
isTiDBVersion,
|
|
5
|
-
|
|
6
|
+
parseQueryResultSets,
|
|
6
7
|
requireDatabaseInDSN,
|
|
7
8
|
withReadOnlyTransaction
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-QEFMUQJ2.js";
|
|
10
|
+
import "./chunk-FU2ZJE4E.js";
|
|
9
11
|
import {
|
|
10
12
|
quoteIdentifier
|
|
11
13
|
} from "./chunk-JFWX35TB.js";
|
|
12
14
|
import {
|
|
13
15
|
SQLRowLimiter,
|
|
14
16
|
closeQuietly
|
|
15
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-RSB7DPO2.js";
|
|
16
18
|
import {
|
|
17
19
|
ConnectorRegistry,
|
|
18
20
|
SafeURL,
|
|
19
21
|
obfuscateDSNPassword,
|
|
20
22
|
splitSQLStatements
|
|
21
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-WIQ4DWGY.js";
|
|
22
24
|
|
|
23
25
|
// src/connectors/mysql/index.ts
|
|
24
26
|
import mysql from "mysql2/promise";
|
|
@@ -104,7 +106,7 @@ Expected: ${expectedFormat}`
|
|
|
104
106
|
}
|
|
105
107
|
}
|
|
106
108
|
};
|
|
107
|
-
var
|
|
109
|
+
var _MySQLConnector = class _MySQLConnector {
|
|
108
110
|
constructor() {
|
|
109
111
|
this.id = "mysql";
|
|
110
112
|
this.name = "MySQL";
|
|
@@ -343,6 +345,16 @@ var MySQLConnector = class _MySQLConnector {
|
|
|
343
345
|
return null;
|
|
344
346
|
}
|
|
345
347
|
}
|
|
348
|
+
async getHealthCheck() {
|
|
349
|
+
if (!this.pool) {
|
|
350
|
+
throw new Error("Not connected to database");
|
|
351
|
+
}
|
|
352
|
+
const pool = this.pool;
|
|
353
|
+
return getMySQLFamilyHealthCheck(async (sql) => {
|
|
354
|
+
const [rows] = await pool.query(sql);
|
|
355
|
+
return rows;
|
|
356
|
+
});
|
|
357
|
+
}
|
|
346
358
|
async getStoredProcedures(schema, routineType) {
|
|
347
359
|
if (!this.pool) {
|
|
348
360
|
throw new Error("Not connected to database");
|
|
@@ -495,15 +507,17 @@ var MySQLConnector = class _MySQLConnector {
|
|
|
495
507
|
throw new Error("Not connected to database");
|
|
496
508
|
}
|
|
497
509
|
const conn = await this.pool.getConnection();
|
|
510
|
+
const threadId = conn.threadId;
|
|
511
|
+
let isConnectionPoisoned = false;
|
|
498
512
|
try {
|
|
499
513
|
return await withReadOnlyTransaction(
|
|
500
514
|
conn,
|
|
501
515
|
options.readonly,
|
|
502
516
|
this.supportsReadOnlyTransaction,
|
|
503
517
|
async () => {
|
|
518
|
+
const statements = splitSQLStatements(sql, "mysql");
|
|
504
519
|
let processedSQL = sql;
|
|
505
520
|
if (options.maxRows) {
|
|
506
|
-
const statements = splitSQLStatements(sql, "mysql");
|
|
507
521
|
const processedStatements = statements.map(
|
|
508
522
|
(statement) => SQLRowLimiter.applyMaxRows(statement, options.maxRows)
|
|
509
523
|
);
|
|
@@ -519,16 +533,59 @@ var MySQLConnector = class _MySQLConnector {
|
|
|
519
533
|
results = await conn.query({ sql: processedSQL, timeout: this.queryTimeoutMs });
|
|
520
534
|
}
|
|
521
535
|
const [firstResult] = results;
|
|
522
|
-
const
|
|
523
|
-
|
|
524
|
-
return { rows, rowCount };
|
|
536
|
+
const resultSets = parseQueryResultSets(firstResult, statements);
|
|
537
|
+
return { resultSets };
|
|
525
538
|
}
|
|
526
539
|
);
|
|
540
|
+
} catch (error) {
|
|
541
|
+
if (isClientSideTimeout(error)) {
|
|
542
|
+
isConnectionPoisoned = true;
|
|
543
|
+
await this.killQuery(threadId);
|
|
544
|
+
}
|
|
545
|
+
throw error;
|
|
546
|
+
} finally {
|
|
547
|
+
if (isConnectionPoisoned) {
|
|
548
|
+
conn.destroy();
|
|
549
|
+
} else {
|
|
550
|
+
conn.release();
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Best-effort server-side kill for a query abandoned by mysql2's client-side
|
|
556
|
+
* timeout. Uses a separate connection: the original connection's command
|
|
557
|
+
* queue is stuck behind the abandoned statement (see isClientSideTimeout)
|
|
558
|
+
* and cannot itself be used to send KILL QUERY.
|
|
559
|
+
*
|
|
560
|
+
* Bounded by its own short timeout, independent of the user's (possibly
|
|
561
|
+
* long or unset) query_timeout — KILL QUERY is metadata-only and should
|
|
562
|
+
* return almost immediately on a healthy server, so cleanup must not stall
|
|
563
|
+
* indefinitely if it doesn't.
|
|
564
|
+
*/
|
|
565
|
+
async killQuery(threadId) {
|
|
566
|
+
if (!this.pool) return;
|
|
567
|
+
let killer;
|
|
568
|
+
let killerPoisoned = false;
|
|
569
|
+
try {
|
|
570
|
+
killer = await this.pool.getConnection();
|
|
571
|
+
await killer.query({ sql: `KILL QUERY ${threadId}`, timeout: _MySQLConnector.KILL_QUERY_TIMEOUT_MS });
|
|
572
|
+
} catch (error) {
|
|
573
|
+
killerPoisoned = isClientSideTimeout(error);
|
|
527
574
|
} finally {
|
|
528
|
-
|
|
575
|
+
if (killer) {
|
|
576
|
+
if (killerPoisoned) {
|
|
577
|
+
killer.destroy();
|
|
578
|
+
} else {
|
|
579
|
+
killer.release();
|
|
580
|
+
}
|
|
581
|
+
}
|
|
529
582
|
}
|
|
530
583
|
}
|
|
531
584
|
};
|
|
585
|
+
// Bounds the KILL QUERY cleanup call issued after a client-side query
|
|
586
|
+
// timeout; see killQuery.
|
|
587
|
+
_MySQLConnector.KILL_QUERY_TIMEOUT_MS = 5e3;
|
|
588
|
+
var MySQLConnector = _MySQLConnector;
|
|
532
589
|
var mysqlConnector = new MySQLConnector();
|
|
533
590
|
ConnectorRegistry.register(mysqlConnector);
|
|
534
591
|
export {
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
toNullableNumber
|
|
3
|
+
} from "./chunk-FU2ZJE4E.js";
|
|
1
4
|
import {
|
|
2
5
|
quoteIdentifier
|
|
3
6
|
} from "./chunk-JFWX35TB.js";
|
|
4
7
|
import {
|
|
5
8
|
SQLRowLimiter,
|
|
6
9
|
closeQuietly
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-RSB7DPO2.js";
|
|
8
11
|
import {
|
|
9
12
|
ConnectorRegistry,
|
|
10
13
|
SafeURL,
|
|
11
14
|
obfuscateDSNPassword,
|
|
12
15
|
splitSQLStatements
|
|
13
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-WIQ4DWGY.js";
|
|
14
17
|
|
|
15
18
|
// src/connectors/postgres/index.ts
|
|
16
19
|
import fs from "fs";
|
|
@@ -383,6 +386,64 @@ var PostgresConnector = class _PostgresConnector {
|
|
|
383
386
|
client.release();
|
|
384
387
|
}
|
|
385
388
|
}
|
|
389
|
+
async getHealthCheck() {
|
|
390
|
+
if (!this.pool) {
|
|
391
|
+
throw new Error("Not connected to database");
|
|
392
|
+
}
|
|
393
|
+
const client = await this.pool.connect();
|
|
394
|
+
try {
|
|
395
|
+
const [connectionsResult, maxConnectionsResult, bufferCacheResult] = await Promise.all([
|
|
396
|
+
client.query(`
|
|
397
|
+
SELECT
|
|
398
|
+
count(*) AS total,
|
|
399
|
+
count(*) FILTER (WHERE state = 'active') AS active,
|
|
400
|
+
count(*) FILTER (WHERE state = 'idle') AS idle,
|
|
401
|
+
count(*) FILTER (WHERE state = 'idle in transaction') AS idle_in_transaction,
|
|
402
|
+
count(*) FILTER (WHERE state = 'idle in transaction (aborted)') AS idle_in_transaction_aborted,
|
|
403
|
+
max(EXTRACT(EPOCH FROM (now() - state_change)))
|
|
404
|
+
FILTER (WHERE state = 'idle in transaction') AS longest_idle_in_transaction_seconds,
|
|
405
|
+
max(EXTRACT(EPOCH FROM (now() - query_start)))
|
|
406
|
+
FILTER (WHERE state = 'active') AS longest_active_query_seconds
|
|
407
|
+
FROM pg_stat_activity
|
|
408
|
+
WHERE pid <> pg_backend_pid()
|
|
409
|
+
`),
|
|
410
|
+
client.query(`SHOW max_connections`),
|
|
411
|
+
client.query(
|
|
412
|
+
`
|
|
413
|
+
SELECT
|
|
414
|
+
blks_hit,
|
|
415
|
+
blks_read,
|
|
416
|
+
CASE WHEN (blks_hit + blks_read) = 0 THEN NULL
|
|
417
|
+
ELSE round(100.0 * blks_hit / (blks_hit + blks_read), 2)
|
|
418
|
+
END AS hit_ratio_pct
|
|
419
|
+
FROM pg_stat_database
|
|
420
|
+
WHERE datname = current_database()
|
|
421
|
+
`
|
|
422
|
+
)
|
|
423
|
+
]);
|
|
424
|
+
const conn = connectionsResult.rows[0];
|
|
425
|
+
const cache = bufferCacheResult.rows[0];
|
|
426
|
+
return {
|
|
427
|
+
connections: {
|
|
428
|
+
total: Number(conn.total),
|
|
429
|
+
active: Number(conn.active),
|
|
430
|
+
idle: Number(conn.idle),
|
|
431
|
+
idleInTransaction: Number(conn.idle_in_transaction),
|
|
432
|
+
idleInTransactionAborted: Number(conn.idle_in_transaction_aborted),
|
|
433
|
+
maxConnections: Number(maxConnectionsResult.rows[0].max_connections),
|
|
434
|
+
longestIdleInTransactionSeconds: toNullableNumber(conn.longest_idle_in_transaction_seconds),
|
|
435
|
+
longestActiveQuerySeconds: toNullableNumber(conn.longest_active_query_seconds)
|
|
436
|
+
},
|
|
437
|
+
bufferCache: {
|
|
438
|
+
hitRatioPct: toNullableNumber(cache.hit_ratio_pct),
|
|
439
|
+
blocksHit: Number(cache.blks_hit),
|
|
440
|
+
blocksRead: Number(cache.blks_read)
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
} finally {
|
|
444
|
+
client.release();
|
|
445
|
+
}
|
|
446
|
+
}
|
|
386
447
|
async getStoredProcedures(schema, routineType) {
|
|
387
448
|
if (!this.pool) {
|
|
388
449
|
throw new Error("Not connected to database");
|
|
@@ -502,7 +563,11 @@ var PostgresConnector = class _PostgresConnector {
|
|
|
502
563
|
try {
|
|
503
564
|
const result2 = parameters && parameters.length > 0 ? await client.query(processedStatement, parameters) : await client.query(processedStatement);
|
|
504
565
|
await client.query("COMMIT");
|
|
505
|
-
return {
|
|
566
|
+
return {
|
|
567
|
+
resultSets: [
|
|
568
|
+
{ sql: statements[0], rows: result2.rows, rowCount: result2.rowCount ?? result2.rows.length }
|
|
569
|
+
]
|
|
570
|
+
};
|
|
506
571
|
} catch (error) {
|
|
507
572
|
try {
|
|
508
573
|
await client.query("ROLLBACK");
|
|
@@ -517,24 +582,26 @@ var PostgresConnector = class _PostgresConnector {
|
|
|
517
582
|
} else {
|
|
518
583
|
result = await client.query(processedStatement);
|
|
519
584
|
}
|
|
520
|
-
return {
|
|
585
|
+
return {
|
|
586
|
+
resultSets: [
|
|
587
|
+
{ sql: statements[0], rows: result.rows, rowCount: result.rowCount ?? result.rows.length }
|
|
588
|
+
]
|
|
589
|
+
};
|
|
521
590
|
} else {
|
|
522
591
|
if (parameters && parameters.length > 0) {
|
|
523
592
|
throw new Error("Parameters are not supported for multi-statement queries in PostgreSQL");
|
|
524
593
|
}
|
|
525
|
-
|
|
526
|
-
let totalRowCount = 0;
|
|
594
|
+
const resultSets = [];
|
|
527
595
|
await client.query(options.readonly ? "BEGIN READ ONLY" : "BEGIN");
|
|
528
596
|
try {
|
|
529
597
|
for (let statement of statements) {
|
|
530
598
|
const processedStatement = SQLRowLimiter.applyMaxRows(statement, options.maxRows);
|
|
531
599
|
const result = await client.query(processedStatement);
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
}
|
|
600
|
+
resultSets.push({
|
|
601
|
+
sql: statement,
|
|
602
|
+
rows: result.rows ?? [],
|
|
603
|
+
rowCount: result.rowCount ?? result.rows?.length ?? 0
|
|
604
|
+
});
|
|
538
605
|
}
|
|
539
606
|
await client.query("COMMIT");
|
|
540
607
|
} catch (error) {
|
|
@@ -544,7 +611,7 @@ var PostgresConnector = class _PostgresConnector {
|
|
|
544
611
|
}
|
|
545
612
|
throw error;
|
|
546
613
|
}
|
|
547
|
-
return {
|
|
614
|
+
return { resultSets };
|
|
548
615
|
}
|
|
549
616
|
} finally {
|
|
550
617
|
client.release();
|