@bytebase/dbhub 0.22.5 → 0.22.6
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-BRXZ5ZQB.js → chunk-BXXHWEQS.js} +1 -1
- package/dist/{chunk-C7WEAPX4.js → chunk-JEZZN2YZ.js} +15 -1
- package/dist/{chunk-IOKERPF2.js → chunk-WPXPKRDU.js} +1 -4
- package/dist/index.js +24 -8
- package/dist/{mariadb-ERB4D3RP.js → mariadb-JPEKVFEW.js} +14 -2
- package/dist/{mysql-WG6UFALX.js → mysql-EK6TCER5.js} +14 -2
- package/dist/{postgres-EKVOBAH6.js → postgres-BKBCGDZS.js} +26 -4
- package/dist/{registry-L3ZIOUF2.js → registry-IPRZ55YC.js} +2 -2
- package/dist/{sqlite-2GBIF3MQ.js → sqlite-CQ4LCBB6.js} +18 -4
- package/dist/{sqlserver-5TFVBCMA.js → sqlserver-47APXMSF.js} +2 -2
- package/package.json +1 -1
|
@@ -267,6 +267,20 @@ function scanSingleLineComment(sql, i) {
|
|
|
267
267
|
}
|
|
268
268
|
return { type: TokenType.Comment, end: j };
|
|
269
269
|
}
|
|
270
|
+
function scanSingleLineCommentMySQL(sql, i) {
|
|
271
|
+
if (sql[i] !== "-" || sql[i + 1] !== "-") {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
const next = sql[i + 2];
|
|
275
|
+
if (next !== void 0 && next.charCodeAt(0) > 32 && next.charCodeAt(0) !== 127) {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
let j = i;
|
|
279
|
+
while (j < sql.length && sql[j] !== "\n") {
|
|
280
|
+
j++;
|
|
281
|
+
}
|
|
282
|
+
return { type: TokenType.Comment, end: j };
|
|
283
|
+
}
|
|
270
284
|
function scanMultiLineComment(sql, i) {
|
|
271
285
|
if (sql[i] !== "/" || sql[i + 1] !== "*") {
|
|
272
286
|
return null;
|
|
@@ -405,7 +419,7 @@ function scanTokenPostgres(sql, i) {
|
|
|
405
419
|
return scanSingleLineComment(sql, i) ?? scanNestedMultiLineComment(sql, i) ?? scanSingleQuotedString(sql, i) ?? scanDoubleQuotedString(sql, i) ?? scanDollarQuotedBlock(sql, i) ?? plainToken(i);
|
|
406
420
|
}
|
|
407
421
|
function scanTokenMySQL(sql, i) {
|
|
408
|
-
return
|
|
422
|
+
return scanSingleLineCommentMySQL(sql, i) ?? scanMultiLineCommentMySQL(sql, i) ?? scanSingleQuotedString(sql, i) ?? scanDoubleQuotedString(sql, i) ?? scanBacktickQuotedIdentifier(sql, i) ?? plainToken(i);
|
|
409
423
|
}
|
|
410
424
|
function scanTokenSQLite(sql, i) {
|
|
411
425
|
return scanSingleLineComment(sql, i) ?? scanMultiLineComment(sql, i) ?? scanSingleQuotedString(sql, i) ?? scanDoubleQuotedString(sql, i) ?? scanBacktickQuotedIdentifier(sql, i) ?? scanBracketQuotedIdentifier(sql, i) ?? plainToken(i);
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
getDefaultPortForType,
|
|
9
9
|
parseConnectionInfoFromDSN,
|
|
10
10
|
stripCommentsAndStrings
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-JEZZN2YZ.js";
|
|
12
12
|
|
|
13
13
|
// src/tools/builtin-tools.ts
|
|
14
14
|
var BUILTIN_TOOL_EXECUTE_SQL = "execute_sql";
|
|
@@ -1802,9 +1802,6 @@ var ConnectorManager = class {
|
|
|
1802
1802
|
if (source.query_timeout !== void 0 && connector.id !== "sqlite") {
|
|
1803
1803
|
config.queryTimeoutSeconds = source.query_timeout;
|
|
1804
1804
|
}
|
|
1805
|
-
if (source.readonly !== void 0) {
|
|
1806
|
-
config.readonly = source.readonly;
|
|
1807
|
-
}
|
|
1808
1805
|
if (source.search_path) {
|
|
1809
1806
|
config.searchPath = source.search_path;
|
|
1810
1807
|
}
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
resolveSourceConfigs,
|
|
16
16
|
resolveTomlConfigPath,
|
|
17
17
|
resolveTransport
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-WPXPKRDU.js";
|
|
19
19
|
import {
|
|
20
20
|
loadConnectors
|
|
21
21
|
} from "./chunk-WVVMH6FJ.js";
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
parseConnectionInfoFromDSN,
|
|
30
30
|
splitSQLStatements,
|
|
31
31
|
stripCommentsAndStrings
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-JEZZN2YZ.js";
|
|
33
33
|
|
|
34
34
|
// src/server.ts
|
|
35
35
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -134,6 +134,13 @@ var mutatingPatterns = {
|
|
|
134
134
|
sqlserver: mutatingPattern
|
|
135
135
|
};
|
|
136
136
|
var selectIntoPattern = /\bselect\b[\s\S]+\binto\b/i;
|
|
137
|
+
var sqliteReadOnlyArgPragmas = /* @__PURE__ */ new Set([
|
|
138
|
+
"table_info",
|
|
139
|
+
"index_info",
|
|
140
|
+
"index_list",
|
|
141
|
+
"foreign_key_list"
|
|
142
|
+
]);
|
|
143
|
+
var sqlitePragmaParenPattern = /^pragma\s+(?:[a-z0-9_]+\.)?([a-z0-9_]+)\s*\(/;
|
|
137
144
|
var explainAnalyzePattern = /^explain\s+(?:\([^)]*\banalyze\b(?!\s*(?:=\s*)?(?:false|off|0)\b)[^)]*\)|\banalyze\b(?!\s*(?:=\s*)?(?:false|off|0)\b)(?:\s+verbose\b)?)/i;
|
|
138
145
|
function isReadOnlySQL(sql, connectorType) {
|
|
139
146
|
return checkReadOnly(
|
|
@@ -156,6 +163,15 @@ function checkReadOnly(cleanedSQL, connectorType) {
|
|
|
156
163
|
return false;
|
|
157
164
|
}
|
|
158
165
|
}
|
|
166
|
+
if (firstWord === "pragma" && connectorType === "sqlite") {
|
|
167
|
+
if (cleanedSQL.includes("=")) {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
const parenMatch = cleanedSQL.match(sqlitePragmaParenPattern);
|
|
171
|
+
if (parenMatch && !sqliteReadOnlyArgPragmas.has(parenMatch[1])) {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
159
175
|
if ((firstWord === "select" || firstWord === "with") && selectIntoPattern.test(cleanedSQL)) {
|
|
160
176
|
return false;
|
|
161
177
|
}
|
|
@@ -1656,7 +1672,7 @@ See documentation for more details on configuring database connections.
|
|
|
1656
1672
|
const sources = sourceConfigsData.sources;
|
|
1657
1673
|
console.error(`Configuration source: ${sourceConfigsData.source}`);
|
|
1658
1674
|
await connectorManager.connectWithSources(sources);
|
|
1659
|
-
const { initializeToolRegistry: initializeToolRegistry2 } = await import("./registry-
|
|
1675
|
+
const { initializeToolRegistry: initializeToolRegistry2 } = await import("./registry-IPRZ55YC.js");
|
|
1660
1676
|
initializeToolRegistry2({
|
|
1661
1677
|
sources: sourceConfigsData.sources,
|
|
1662
1678
|
tools: sourceConfigsData.tools
|
|
@@ -1810,11 +1826,11 @@ See documentation for more details on configuring database connections.
|
|
|
1810
1826
|
|
|
1811
1827
|
// src/index.ts
|
|
1812
1828
|
var connectorModules = [
|
|
1813
|
-
{ load: () => import("./postgres-
|
|
1814
|
-
{ load: () => import("./sqlserver-
|
|
1815
|
-
{ load: () => import("./sqlite-
|
|
1816
|
-
{ load: () => import("./mysql-
|
|
1817
|
-
{ load: () => import("./mariadb-
|
|
1829
|
+
{ load: () => import("./postgres-BKBCGDZS.js"), name: "PostgreSQL", driver: "pg" },
|
|
1830
|
+
{ load: () => import("./sqlserver-47APXMSF.js"), name: "SQL Server", driver: "mssql" },
|
|
1831
|
+
{ load: () => import("./sqlite-CQ4LCBB6.js"), name: "SQLite", driver: "node:sqlite" },
|
|
1832
|
+
{ load: () => import("./mysql-EK6TCER5.js"), name: "MySQL", driver: "mysql2" },
|
|
1833
|
+
{ load: () => import("./mariadb-JPEKVFEW.js"), name: "MariaDB", driver: "mariadb" }
|
|
1818
1834
|
];
|
|
1819
1835
|
loadConnectors(connectorModules).then(() => main()).catch((error) => {
|
|
1820
1836
|
console.error("Fatal error:", error);
|
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
} from "./chunk-JFWX35TB.js";
|
|
8
8
|
import {
|
|
9
9
|
SQLRowLimiter
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-BXXHWEQS.js";
|
|
11
11
|
import {
|
|
12
12
|
ConnectorRegistry,
|
|
13
13
|
SafeURL,
|
|
14
14
|
obfuscateDSNPassword,
|
|
15
15
|
splitSQLStatements
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-JEZZN2YZ.js";
|
|
17
17
|
|
|
18
18
|
// src/connectors/mariadb/index.ts
|
|
19
19
|
import * as mariadb from "mariadb";
|
|
@@ -466,6 +466,9 @@ var MariaDBConnector = class _MariaDBConnector {
|
|
|
466
466
|
}
|
|
467
467
|
const conn = await this.pool.getConnection();
|
|
468
468
|
try {
|
|
469
|
+
if (options.readonly) {
|
|
470
|
+
await conn.query("START TRANSACTION READ ONLY");
|
|
471
|
+
}
|
|
469
472
|
let processedSQL = sql;
|
|
470
473
|
if (options.maxRows) {
|
|
471
474
|
const statements = splitSQLStatements(sql, "mariadb");
|
|
@@ -492,8 +495,17 @@ var MariaDBConnector = class _MariaDBConnector {
|
|
|
492
495
|
}
|
|
493
496
|
const rows = parseQueryResults(results);
|
|
494
497
|
const rowCount = extractAffectedRows(results);
|
|
498
|
+
if (options.readonly) {
|
|
499
|
+
await conn.query("COMMIT");
|
|
500
|
+
}
|
|
495
501
|
return { rows, rowCount };
|
|
496
502
|
} catch (error) {
|
|
503
|
+
if (options.readonly) {
|
|
504
|
+
try {
|
|
505
|
+
await conn.query("ROLLBACK");
|
|
506
|
+
} catch {
|
|
507
|
+
}
|
|
508
|
+
}
|
|
497
509
|
console.error("Error executing query:", error);
|
|
498
510
|
throw error;
|
|
499
511
|
} finally {
|
|
@@ -7,13 +7,13 @@ import {
|
|
|
7
7
|
} from "./chunk-JFWX35TB.js";
|
|
8
8
|
import {
|
|
9
9
|
SQLRowLimiter
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-BXXHWEQS.js";
|
|
11
11
|
import {
|
|
12
12
|
ConnectorRegistry,
|
|
13
13
|
SafeURL,
|
|
14
14
|
obfuscateDSNPassword,
|
|
15
15
|
splitSQLStatements
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-JEZZN2YZ.js";
|
|
17
17
|
|
|
18
18
|
// src/connectors/mysql/index.ts
|
|
19
19
|
import mysql from "mysql2/promise";
|
|
@@ -472,6 +472,9 @@ var MySQLConnector = class _MySQLConnector {
|
|
|
472
472
|
}
|
|
473
473
|
const conn = await this.pool.getConnection();
|
|
474
474
|
try {
|
|
475
|
+
if (options.readonly) {
|
|
476
|
+
await conn.query("START TRANSACTION READ ONLY");
|
|
477
|
+
}
|
|
475
478
|
let processedSQL = sql;
|
|
476
479
|
if (options.maxRows) {
|
|
477
480
|
const statements = splitSQLStatements(sql, "mysql");
|
|
@@ -499,8 +502,17 @@ var MySQLConnector = class _MySQLConnector {
|
|
|
499
502
|
const [firstResult] = results;
|
|
500
503
|
const rows = parseQueryResults(firstResult);
|
|
501
504
|
const rowCount = extractAffectedRows(firstResult);
|
|
505
|
+
if (options.readonly) {
|
|
506
|
+
await conn.query("COMMIT");
|
|
507
|
+
}
|
|
502
508
|
return { rows, rowCount };
|
|
503
509
|
} catch (error) {
|
|
510
|
+
if (options.readonly) {
|
|
511
|
+
try {
|
|
512
|
+
await conn.query("ROLLBACK");
|
|
513
|
+
} catch {
|
|
514
|
+
}
|
|
515
|
+
}
|
|
504
516
|
console.error("Error executing query:", error);
|
|
505
517
|
throw error;
|
|
506
518
|
} finally {
|
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
} from "./chunk-JFWX35TB.js";
|
|
4
4
|
import {
|
|
5
5
|
SQLRowLimiter
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-BXXHWEQS.js";
|
|
7
7
|
import {
|
|
8
8
|
ConnectorRegistry,
|
|
9
9
|
SafeURL,
|
|
10
10
|
obfuscateDSNPassword,
|
|
11
11
|
splitSQLStatements
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-JEZZN2YZ.js";
|
|
13
13
|
|
|
14
14
|
// src/connectors/postgres/index.ts
|
|
15
15
|
import fs from "fs";
|
|
@@ -491,6 +491,25 @@ var PostgresConnector = class _PostgresConnector {
|
|
|
491
491
|
const statements = splitSQLStatements(sql, "postgres");
|
|
492
492
|
if (statements.length === 1) {
|
|
493
493
|
const processedStatement = SQLRowLimiter.applyMaxRows(statements[0], options.maxRows);
|
|
494
|
+
if (options.readonly) {
|
|
495
|
+
await client.query("BEGIN READ ONLY");
|
|
496
|
+
try {
|
|
497
|
+
const result2 = parameters && parameters.length > 0 ? await client.query(processedStatement, parameters) : await client.query(processedStatement);
|
|
498
|
+
await client.query("COMMIT");
|
|
499
|
+
return { rows: result2.rows, rowCount: result2.rowCount ?? result2.rows.length };
|
|
500
|
+
} catch (error) {
|
|
501
|
+
try {
|
|
502
|
+
await client.query("ROLLBACK");
|
|
503
|
+
} catch {
|
|
504
|
+
}
|
|
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
|
+
throw error;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
494
513
|
let result;
|
|
495
514
|
if (parameters && parameters.length > 0) {
|
|
496
515
|
try {
|
|
@@ -511,7 +530,7 @@ var PostgresConnector = class _PostgresConnector {
|
|
|
511
530
|
}
|
|
512
531
|
let allRows = [];
|
|
513
532
|
let totalRowCount = 0;
|
|
514
|
-
await client.query("BEGIN");
|
|
533
|
+
await client.query(options.readonly ? "BEGIN READ ONLY" : "BEGIN");
|
|
515
534
|
try {
|
|
516
535
|
for (let statement of statements) {
|
|
517
536
|
const processedStatement = SQLRowLimiter.applyMaxRows(statement, options.maxRows);
|
|
@@ -525,7 +544,10 @@ var PostgresConnector = class _PostgresConnector {
|
|
|
525
544
|
}
|
|
526
545
|
await client.query("COMMIT");
|
|
527
546
|
} catch (error) {
|
|
528
|
-
|
|
547
|
+
try {
|
|
548
|
+
await client.query("ROLLBACK");
|
|
549
|
+
} catch {
|
|
550
|
+
}
|
|
529
551
|
throw error;
|
|
530
552
|
}
|
|
531
553
|
return { rows: allRows, rowCount: totalRowCount };
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
ToolRegistry,
|
|
3
3
|
getToolRegistry,
|
|
4
4
|
initializeToolRegistry
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-WPXPKRDU.js";
|
|
6
6
|
import "./chunk-WVVMH6FJ.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-JEZZN2YZ.js";
|
|
8
8
|
export {
|
|
9
9
|
ToolRegistry,
|
|
10
10
|
getToolRegistry,
|
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
} from "./chunk-JFWX35TB.js";
|
|
4
4
|
import {
|
|
5
5
|
SQLRowLimiter
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-BXXHWEQS.js";
|
|
7
7
|
import {
|
|
8
8
|
ConnectorRegistry,
|
|
9
9
|
SafeURL,
|
|
10
10
|
obfuscateDSNPassword,
|
|
11
11
|
splitSQLStatements
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-JEZZN2YZ.js";
|
|
13
13
|
|
|
14
14
|
// src/connectors/sqlite/suppress-experimental-warning.ts
|
|
15
15
|
var installed = false;
|
|
@@ -319,6 +319,9 @@ var SQLiteConnector = class _SQLiteConnector {
|
|
|
319
319
|
if (!this.db) {
|
|
320
320
|
throw new Error("Not connected to SQLite database");
|
|
321
321
|
}
|
|
322
|
+
if (options.readonly) {
|
|
323
|
+
this.db.exec("PRAGMA query_only = ON");
|
|
324
|
+
}
|
|
322
325
|
try {
|
|
323
326
|
const statements = splitSQLStatements(sql, "sqlite");
|
|
324
327
|
if (statements.length === 1) {
|
|
@@ -375,19 +378,30 @@ var SQLiteConnector = class _SQLiteConnector {
|
|
|
375
378
|
}
|
|
376
379
|
let totalChanges = 0;
|
|
377
380
|
for (const statement of writeStatements) {
|
|
381
|
+
if (options.readonly) {
|
|
382
|
+
this.db.exec("PRAGMA query_only = ON");
|
|
383
|
+
}
|
|
378
384
|
const result = this.prepare(statement).run();
|
|
379
385
|
totalChanges += Number(result.changes);
|
|
380
386
|
}
|
|
381
387
|
let allRows = [];
|
|
382
388
|
for (let statement of readStatements) {
|
|
389
|
+
if (options.readonly) {
|
|
390
|
+
this.db.exec("PRAGMA query_only = ON");
|
|
391
|
+
}
|
|
383
392
|
statement = SQLRowLimiter.applyMaxRows(statement, options.maxRows);
|
|
384
393
|
const result = this.prepare(statement).all();
|
|
385
394
|
allRows.push(...result);
|
|
386
395
|
}
|
|
387
396
|
return { rows: allRows, rowCount: totalChanges + allRows.length };
|
|
388
397
|
}
|
|
389
|
-
}
|
|
390
|
-
|
|
398
|
+
} finally {
|
|
399
|
+
if (options.readonly) {
|
|
400
|
+
try {
|
|
401
|
+
this.db.exec("PRAGMA query_only = OFF");
|
|
402
|
+
} catch {
|
|
403
|
+
}
|
|
404
|
+
}
|
|
391
405
|
}
|
|
392
406
|
}
|
|
393
407
|
};
|
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
} from "./chunk-WVVMH6FJ.js";
|
|
4
4
|
import {
|
|
5
5
|
SQLRowLimiter
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-BXXHWEQS.js";
|
|
7
7
|
import {
|
|
8
8
|
ConnectorRegistry,
|
|
9
9
|
SafeURL,
|
|
10
10
|
obfuscateDSNPassword,
|
|
11
11
|
stripCommentsAndStrings
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-JEZZN2YZ.js";
|
|
13
13
|
|
|
14
14
|
// src/connectors/sqlserver/index.ts
|
|
15
15
|
import sql from "mssql";
|
package/package.json
CHANGED