@bytebase/dbhub 0.23.0 → 1.0.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.
@@ -1,13 +1,18 @@
1
1
  import {
2
+ MissingDatabaseError,
2
3
  extractAffectedRows,
3
- parseQueryResults
4
- } from "./chunk-RTB262PR.js";
4
+ isTiDBVersion,
5
+ parseQueryResults,
6
+ requireDatabaseInDSN,
7
+ withReadOnlyTransaction
8
+ } from "./chunk-DUCNPMNW.js";
5
9
  import {
6
10
  quoteIdentifier
7
11
  } from "./chunk-JFWX35TB.js";
8
12
  import {
9
- SQLRowLimiter
10
- } from "./chunk-BXXHWEQS.js";
13
+ SQLRowLimiter,
14
+ closeQuietly
15
+ } from "./chunk-S2V6RZ3C.js";
11
16
  import {
12
17
  ConnectorRegistry,
13
18
  SafeURL,
@@ -34,11 +39,12 @@ Expected: ${expectedFormat}`
34
39
  }
35
40
  try {
36
41
  const url = new SafeURL(dsn);
42
+ const database = url.pathname ? url.pathname.substring(1) : "";
43
+ requireDatabaseInDSN(database, dsn, "MySQL");
37
44
  const config2 = {
38
45
  host: url.hostname,
39
46
  port: url.port ? parseInt(url.port) : 3306,
40
- database: url.pathname ? url.pathname.substring(1) : "",
41
- // Remove leading '/' if exists
47
+ database,
42
48
  user: url.username,
43
49
  password: url.password,
44
50
  multipleStatements: true,
@@ -79,6 +85,9 @@ Expected: ${expectedFormat}`
79
85
  }
80
86
  return config2;
81
87
  } catch (error) {
88
+ if (error instanceof MissingDatabaseError) {
89
+ throw error;
90
+ }
82
91
  throw new Error(
83
92
  `Failed to parse MySQL DSN: ${error instanceof Error ? error.message : String(error)}`
84
93
  );
@@ -103,6 +112,9 @@ var MySQLConnector = class _MySQLConnector {
103
112
  this.pool = null;
104
113
  // Source ID is set by ConnectorManager after cloning
105
114
  this.sourceId = "default";
115
+ // TiDB speaks the MySQL protocol but rejects `START TRANSACTION READ ONLY`
116
+ // unless tidb_enable_noop_functions is on. Detected once at connect time.
117
+ this.supportsReadOnlyTransaction = true;
106
118
  }
107
119
  getId() {
108
120
  return this.sourceId;
@@ -117,8 +129,14 @@ var MySQLConnector = class _MySQLConnector {
117
129
  if (config?.queryTimeoutSeconds !== void 0) {
118
130
  this.queryTimeoutMs = config.queryTimeoutSeconds * 1e3;
119
131
  }
120
- const [rows] = await this.pool.query("SELECT 1");
132
+ const [rows] = await this.pool.query("SELECT VERSION() AS version");
133
+ this.supportsReadOnlyTransaction = !isTiDBVersion(rows[0]?.version);
121
134
  } catch (err) {
135
+ if (this.pool) {
136
+ const pool = this.pool;
137
+ this.pool = null;
138
+ await closeQuietly(() => pool.end());
139
+ }
122
140
  console.error("Failed to connect to MySQL database:", err);
123
141
  throw err;
124
142
  }
@@ -478,49 +496,34 @@ var MySQLConnector = class _MySQLConnector {
478
496
  }
479
497
  const conn = await this.pool.getConnection();
480
498
  try {
481
- if (options.readonly) {
482
- await conn.query("START TRANSACTION READ ONLY");
483
- }
484
- let processedSQL = sql;
485
- if (options.maxRows) {
486
- const statements = splitSQLStatements(sql, "mysql");
487
- const processedStatements = statements.map(
488
- (statement) => SQLRowLimiter.applyMaxRows(statement, options.maxRows)
489
- );
490
- processedSQL = processedStatements.join("; ");
491
- if (sql.trim().endsWith(";")) {
492
- processedSQL += ";";
493
- }
494
- }
495
- let results;
496
- if (parameters && parameters.length > 0) {
497
- try {
498
- results = await conn.query({ sql: processedSQL, timeout: this.queryTimeoutMs }, parameters);
499
- } catch (error) {
500
- console.error(`[MySQL executeSQL] ERROR: ${error.message}`);
501
- console.error(`[MySQL executeSQL] SQL: ${processedSQL}`);
502
- console.error(`[MySQL executeSQL] Parameters: ${JSON.stringify(parameters)}`);
503
- throw error;
504
- }
505
- } else {
506
- results = await conn.query({ sql: processedSQL, timeout: this.queryTimeoutMs });
507
- }
508
- const [firstResult] = results;
509
- const rows = parseQueryResults(firstResult);
510
- const rowCount = extractAffectedRows(firstResult);
511
- if (options.readonly) {
512
- await conn.query("COMMIT");
513
- }
514
- return { rows, rowCount };
515
- } catch (error) {
516
- if (options.readonly) {
517
- try {
518
- await conn.query("ROLLBACK");
519
- } catch {
499
+ return await withReadOnlyTransaction(
500
+ conn,
501
+ options.readonly,
502
+ this.supportsReadOnlyTransaction,
503
+ async () => {
504
+ let processedSQL = sql;
505
+ if (options.maxRows) {
506
+ const statements = splitSQLStatements(sql, "mysql");
507
+ const processedStatements = statements.map(
508
+ (statement) => SQLRowLimiter.applyMaxRows(statement, options.maxRows)
509
+ );
510
+ processedSQL = processedStatements.join("; ");
511
+ if (sql.trim().endsWith(";")) {
512
+ processedSQL += ";";
513
+ }
514
+ }
515
+ let results;
516
+ if (parameters && parameters.length > 0) {
517
+ results = await conn.query({ sql: processedSQL, timeout: this.queryTimeoutMs }, parameters);
518
+ } else {
519
+ results = await conn.query({ sql: processedSQL, timeout: this.queryTimeoutMs });
520
+ }
521
+ const [firstResult] = results;
522
+ const rows = parseQueryResults(firstResult);
523
+ const rowCount = extractAffectedRows(firstResult);
524
+ return { rows, rowCount };
520
525
  }
521
- }
522
- console.error("Error executing query:", error);
523
- throw error;
526
+ );
524
527
  } finally {
525
528
  conn.release();
526
529
  }
@@ -2,8 +2,9 @@ import {
2
2
  quoteIdentifier
3
3
  } from "./chunk-JFWX35TB.js";
4
4
  import {
5
- SQLRowLimiter
6
- } from "./chunk-BXXHWEQS.js";
5
+ SQLRowLimiter,
6
+ closeQuietly
7
+ } from "./chunk-S2V6RZ3C.js";
7
8
  import {
8
9
  ConnectorRegistry,
9
10
  SafeURL,
@@ -148,6 +149,11 @@ var PostgresConnector = class _PostgresConnector {
148
149
  const client = await this.pool.connect();
149
150
  client.release();
150
151
  } catch (err) {
152
+ if (this.pool) {
153
+ const pool = this.pool;
154
+ this.pool = null;
155
+ await closeQuietly(() => pool.end());
156
+ }
151
157
  console.error("Failed to connect to PostgreSQL database:", err);
152
158
  throw err;
153
159
  }
@@ -502,24 +508,12 @@ var PostgresConnector = class _PostgresConnector {
502
508
  await client.query("ROLLBACK");
503
509
  } catch {
504
510
  }
505
- console.error(`[PostgreSQL executeSQL] ERROR: ${error.message}`);
506
- console.error(`[PostgreSQL executeSQL] SQL: ${processedStatement}`);
507
- if (parameters && parameters.length > 0) {
508
- console.error(`[PostgreSQL executeSQL] Parameters: ${JSON.stringify(parameters)}`);
509
- }
510
511
  throw error;
511
512
  }
512
513
  }
513
514
  let result;
514
515
  if (parameters && parameters.length > 0) {
515
- try {
516
- result = await client.query(processedStatement, parameters);
517
- } catch (error) {
518
- console.error(`[PostgreSQL executeSQL] ERROR: ${error.message}`);
519
- console.error(`[PostgreSQL executeSQL] SQL: ${processedStatement}`);
520
- console.error(`[PostgreSQL executeSQL] Parameters: ${JSON.stringify(parameters)}`);
521
- throw error;
522
- }
516
+ result = await client.query(processedStatement, parameters);
523
517
  } else {
524
518
  result = await client.query(processedStatement);
525
519
  }
@@ -2,7 +2,7 @@ import {
2
2
  ToolRegistry,
3
3
  getToolRegistry,
4
4
  initializeToolRegistry
5
- } from "./chunk-COEDRFSK.js";
5
+ } from "./chunk-MQR6VX5F.js";
6
6
  import "./chunk-WVVMH6FJ.js";
7
7
  import "./chunk-JEZZN2YZ.js";
8
8
  export {
@@ -2,8 +2,9 @@ import {
2
2
  quoteIdentifier
3
3
  } from "./chunk-JFWX35TB.js";
4
4
  import {
5
- SQLRowLimiter
6
- } from "./chunk-BXXHWEQS.js";
5
+ SQLRowLimiter,
6
+ closeQuietly
7
+ } from "./chunk-S2V6RZ3C.js";
7
8
  import {
8
9
  ConnectorRegistry,
9
10
  SafeURL,
@@ -150,6 +151,11 @@ var SQLiteConnector = class _SQLiteConnector {
150
151
  this.db.exec(initScript);
151
152
  }
152
153
  } catch (error) {
154
+ if (this.db) {
155
+ const db = this.db;
156
+ this.db = null;
157
+ await closeQuietly(() => db.close());
158
+ }
153
159
  console.error("Failed to connect to SQLite database:", error);
154
160
  throw error;
155
161
  }
@@ -333,15 +339,8 @@ var SQLiteConnector = class _SQLiteConnector {
333
339
  }
334
340
  if (isReadStatement) {
335
341
  if (parameters && parameters.length > 0) {
336
- try {
337
- const rows = this.prepare(processedStatement).all(...parameters);
338
- return { rows, rowCount: rows.length };
339
- } catch (error) {
340
- console.error(`[SQLite executeSQL] ERROR: ${error.message}`);
341
- console.error(`[SQLite executeSQL] SQL: ${processedStatement}`);
342
- console.error(`[SQLite executeSQL] Parameters: ${JSON.stringify(parameters)}`);
343
- throw error;
344
- }
342
+ const rows = this.prepare(processedStatement).all(...parameters);
343
+ return { rows, rowCount: rows.length };
345
344
  } else {
346
345
  const rows = this.prepare(processedStatement).all();
347
346
  return { rows, rowCount: rows.length };
@@ -349,14 +348,7 @@ var SQLiteConnector = class _SQLiteConnector {
349
348
  } else {
350
349
  let result;
351
350
  if (parameters && parameters.length > 0) {
352
- try {
353
- result = this.prepare(processedStatement).run(...parameters);
354
- } catch (error) {
355
- console.error(`[SQLite executeSQL] ERROR: ${error.message}`);
356
- console.error(`[SQLite executeSQL] SQL: ${processedStatement}`);
357
- console.error(`[SQLite executeSQL] Parameters: ${JSON.stringify(parameters)}`);
358
- throw error;
359
- }
351
+ result = this.prepare(processedStatement).run(...parameters);
360
352
  } else {
361
353
  result = this.prepare(processedStatement).run();
362
354
  }