@xcr1234/dbhub-fork 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.
Files changed (34) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +139 -0
  3. package/dist/chunk-6O5I6UAW.js +2150 -0
  4. package/dist/chunk-BRXZ5ZQB.js +127 -0
  5. package/dist/chunk-C7WEAPX4.js +485 -0
  6. package/dist/chunk-FAIJPBT5.js +40 -0
  7. package/dist/chunk-JFWX35TB.js +34 -0
  8. package/dist/chunk-RTB262PR.js +60 -0
  9. package/dist/chunk-WVVMH6FJ.js +49 -0
  10. package/dist/demo/employee-sqlite/employee.sql +117 -0
  11. package/dist/demo/employee-sqlite/load_department.sql +10 -0
  12. package/dist/demo/employee-sqlite/load_dept_emp.sql +1103 -0
  13. package/dist/demo/employee-sqlite/load_dept_manager.sql +17 -0
  14. package/dist/demo/employee-sqlite/load_employee.sql +1000 -0
  15. package/dist/demo/employee-sqlite/load_salary1.sql +9488 -0
  16. package/dist/demo/employee-sqlite/load_title.sql +1470 -0
  17. package/dist/demo-loader-WKQAEFSX.js +48 -0
  18. package/dist/index.d.ts +1 -0
  19. package/dist/index.js +1584 -0
  20. package/dist/mariadb-QHRMVK47.js +468 -0
  21. package/dist/mysql-GOLPG2Q6.js +475 -0
  22. package/dist/oracle-3V2T7ZWF.js +27739 -0
  23. package/dist/postgres-CK6N5BXI.js +520 -0
  24. package/dist/public/assets/index-BiTHVJQj.js +144 -0
  25. package/dist/public/assets/index-CfPYb3wl.css +1 -0
  26. package/dist/public/assets/postgres-BpcazhJg.svg +22 -0
  27. package/dist/public/assets/sqlserver-ByfFYYpV.svg +11 -0
  28. package/dist/public/favicon.svg +57 -0
  29. package/dist/public/index.html +14 -0
  30. package/dist/public/logo-full-light.svg +58 -0
  31. package/dist/registry-KI3KJMRY.js +13 -0
  32. package/dist/sqlite-P6NXTMYE.js +2473 -0
  33. package/dist/sqlserver-5RM44GWI.js +493 -0
  34. package/package.json +99 -0
@@ -0,0 +1,468 @@
1
+ import {
2
+ extractAffectedRows,
3
+ parseQueryResults
4
+ } from "./chunk-RTB262PR.js";
5
+ import {
6
+ quoteIdentifier
7
+ } from "./chunk-JFWX35TB.js";
8
+ import {
9
+ SQLRowLimiter
10
+ } from "./chunk-BRXZ5ZQB.js";
11
+ import {
12
+ ConnectorRegistry,
13
+ SafeURL,
14
+ obfuscateDSNPassword,
15
+ splitSQLStatements
16
+ } from "./chunk-C7WEAPX4.js";
17
+ import "./chunk-FAIJPBT5.js";
18
+
19
+ // src/connectors/mariadb/index.ts
20
+ import * as mariadb from "mariadb";
21
+ var MariadbDSNParser = class {
22
+ async parse(dsn, config) {
23
+ const connectionTimeoutSeconds = config?.connectionTimeoutSeconds;
24
+ const queryTimeoutSeconds = config?.queryTimeoutSeconds;
25
+ if (!this.isValidDSN(dsn)) {
26
+ const obfuscatedDSN = obfuscateDSNPassword(dsn);
27
+ const expectedFormat = this.getSampleDSN();
28
+ throw new Error(
29
+ `Invalid MariaDB DSN format.
30
+ Provided: ${obfuscatedDSN}
31
+ Expected: ${expectedFormat}`
32
+ );
33
+ }
34
+ try {
35
+ const url = new SafeURL(dsn);
36
+ const connectionConfig = {
37
+ host: url.hostname,
38
+ port: url.port ? parseInt(url.port) : 3306,
39
+ database: url.pathname ? url.pathname.substring(1) : "",
40
+ // Remove leading '/' if exists
41
+ user: url.username,
42
+ password: url.password,
43
+ multipleStatements: true,
44
+ // Enable native multi-statement support
45
+ ...connectionTimeoutSeconds !== void 0 && {
46
+ connectTimeout: connectionTimeoutSeconds * 1e3
47
+ },
48
+ ...queryTimeoutSeconds !== void 0 && {
49
+ queryTimeout: queryTimeoutSeconds * 1e3
50
+ }
51
+ };
52
+ url.forEachSearchParam((value, key) => {
53
+ if (key === "sslmode") {
54
+ if (value === "disable") {
55
+ connectionConfig.ssl = void 0;
56
+ } else if (value === "require") {
57
+ connectionConfig.ssl = { rejectUnauthorized: false };
58
+ } else {
59
+ connectionConfig.ssl = {};
60
+ }
61
+ }
62
+ });
63
+ if (url.password && url.password.includes("X-Amz-Credential")) {
64
+ if (connectionConfig.ssl === void 0) {
65
+ connectionConfig.ssl = { rejectUnauthorized: false };
66
+ }
67
+ }
68
+ return connectionConfig;
69
+ } catch (error) {
70
+ throw new Error(
71
+ `Failed to parse MariaDB DSN: ${error instanceof Error ? error.message : String(error)}`
72
+ );
73
+ }
74
+ }
75
+ getSampleDSN() {
76
+ return "mariadb://root:password@localhost:3306/db?sslmode=require";
77
+ }
78
+ isValidDSN(dsn) {
79
+ try {
80
+ return dsn.startsWith("mariadb://");
81
+ } catch (error) {
82
+ return false;
83
+ }
84
+ }
85
+ };
86
+ var MariaDBConnector = class _MariaDBConnector {
87
+ constructor() {
88
+ this.id = "mariadb";
89
+ this.name = "MariaDB";
90
+ this.dsnParser = new MariadbDSNParser();
91
+ this.pool = null;
92
+ // Source ID is set by ConnectorManager after cloning
93
+ this.sourceId = "default";
94
+ }
95
+ getId() {
96
+ return this.sourceId;
97
+ }
98
+ clone() {
99
+ return new _MariaDBConnector();
100
+ }
101
+ async connect(dsn, initScript, config) {
102
+ try {
103
+ const connectionConfig = await this.dsnParser.parse(dsn, config);
104
+ this.pool = mariadb.createPool(connectionConfig);
105
+ await this.pool.query("SELECT 1");
106
+ } catch (err) {
107
+ console.error("Failed to connect to MariaDB database:", err);
108
+ throw err;
109
+ }
110
+ }
111
+ async disconnect() {
112
+ if (this.pool) {
113
+ await this.pool.end();
114
+ this.pool = null;
115
+ }
116
+ }
117
+ async getSchemas() {
118
+ if (!this.pool) {
119
+ throw new Error("Not connected to database");
120
+ }
121
+ try {
122
+ const rows = await this.pool.query(`
123
+ SELECT SCHEMA_NAME
124
+ FROM INFORMATION_SCHEMA.SCHEMATA
125
+ ORDER BY SCHEMA_NAME
126
+ `);
127
+ return rows.map((row) => row.SCHEMA_NAME);
128
+ } catch (error) {
129
+ console.error("Error getting schemas:", error);
130
+ throw error;
131
+ }
132
+ }
133
+ async getTables(schema) {
134
+ if (!this.pool) {
135
+ throw new Error("Not connected to database");
136
+ }
137
+ try {
138
+ const schemaClause = schema ? "WHERE TABLE_SCHEMA = ?" : "WHERE TABLE_SCHEMA = DATABASE()";
139
+ const queryParams = schema ? [schema] : [];
140
+ const rows = await this.pool.query(
141
+ `
142
+ SELECT TABLE_NAME
143
+ FROM INFORMATION_SCHEMA.TABLES
144
+ ${schemaClause}
145
+ ORDER BY TABLE_NAME
146
+ `,
147
+ queryParams
148
+ );
149
+ return rows.map((row) => row.TABLE_NAME);
150
+ } catch (error) {
151
+ console.error("Error getting tables:", error);
152
+ throw error;
153
+ }
154
+ }
155
+ async tableExists(tableName, schema) {
156
+ if (!this.pool) {
157
+ throw new Error("Not connected to database");
158
+ }
159
+ try {
160
+ const schemaClause = schema ? "WHERE TABLE_SCHEMA = ?" : "WHERE TABLE_SCHEMA = DATABASE()";
161
+ const queryParams = schema ? [schema, tableName] : [tableName];
162
+ const rows = await this.pool.query(
163
+ `
164
+ SELECT COUNT(*) AS COUNT
165
+ FROM INFORMATION_SCHEMA.TABLES
166
+ ${schemaClause}
167
+ AND TABLE_NAME = ?
168
+ `,
169
+ queryParams
170
+ );
171
+ return rows[0].COUNT > 0;
172
+ } catch (error) {
173
+ console.error("Error checking if table exists:", error);
174
+ throw error;
175
+ }
176
+ }
177
+ async getTableIndexes(tableName, schema) {
178
+ if (!this.pool) {
179
+ throw new Error("Not connected to database");
180
+ }
181
+ try {
182
+ const schemaClause = schema ? "TABLE_SCHEMA = ?" : "TABLE_SCHEMA = DATABASE()";
183
+ const queryParams = schema ? [schema, tableName] : [tableName];
184
+ const indexRows = await this.pool.query(
185
+ `
186
+ SELECT
187
+ INDEX_NAME,
188
+ COLUMN_NAME,
189
+ NON_UNIQUE,
190
+ SEQ_IN_INDEX
191
+ FROM
192
+ INFORMATION_SCHEMA.STATISTICS
193
+ WHERE
194
+ ${schemaClause}
195
+ AND TABLE_NAME = ?
196
+ ORDER BY
197
+ INDEX_NAME,
198
+ SEQ_IN_INDEX
199
+ `,
200
+ queryParams
201
+ );
202
+ const indexMap = /* @__PURE__ */ new Map();
203
+ for (const row of indexRows) {
204
+ const indexName = row.INDEX_NAME;
205
+ const columnName = row.COLUMN_NAME;
206
+ const isUnique = row.NON_UNIQUE === 0;
207
+ const isPrimary = indexName === "PRIMARY";
208
+ if (!indexMap.has(indexName)) {
209
+ indexMap.set(indexName, {
210
+ columns: [],
211
+ is_unique: isUnique,
212
+ is_primary: isPrimary
213
+ });
214
+ }
215
+ const indexInfo = indexMap.get(indexName);
216
+ indexInfo.columns.push(columnName);
217
+ }
218
+ const results = [];
219
+ indexMap.forEach((indexInfo, indexName) => {
220
+ results.push({
221
+ index_name: indexName,
222
+ column_names: indexInfo.columns,
223
+ is_unique: indexInfo.is_unique,
224
+ is_primary: indexInfo.is_primary
225
+ });
226
+ });
227
+ return results;
228
+ } catch (error) {
229
+ console.error("Error getting table indexes:", error);
230
+ throw error;
231
+ }
232
+ }
233
+ async getTableSchema(tableName, schema) {
234
+ if (!this.pool) {
235
+ throw new Error("Not connected to database");
236
+ }
237
+ try {
238
+ const schemaClause = schema ? "WHERE TABLE_SCHEMA = ?" : "WHERE TABLE_SCHEMA = DATABASE()";
239
+ const queryParams = schema ? [schema, tableName] : [tableName];
240
+ const rows = await this.pool.query(
241
+ `
242
+ SELECT
243
+ COLUMN_NAME as column_name,
244
+ DATA_TYPE as data_type,
245
+ IS_NULLABLE as is_nullable,
246
+ COLUMN_DEFAULT as column_default,
247
+ COLUMN_COMMENT as description
248
+ FROM INFORMATION_SCHEMA.COLUMNS
249
+ ${schemaClause}
250
+ AND TABLE_NAME = ?
251
+ ORDER BY ORDINAL_POSITION
252
+ `,
253
+ queryParams
254
+ );
255
+ return rows.map((row) => ({
256
+ ...row,
257
+ description: row.description || null
258
+ }));
259
+ } catch (error) {
260
+ console.error("Error getting table schema:", error);
261
+ throw error;
262
+ }
263
+ }
264
+ async getTableComment(tableName, schema) {
265
+ if (!this.pool) {
266
+ throw new Error("Not connected to database");
267
+ }
268
+ try {
269
+ const schemaClause = schema ? "WHERE TABLE_SCHEMA = ?" : "WHERE TABLE_SCHEMA = DATABASE()";
270
+ const queryParams = schema ? [schema, tableName] : [tableName];
271
+ const rows = await this.pool.query(
272
+ `
273
+ SELECT TABLE_COMMENT
274
+ FROM INFORMATION_SCHEMA.TABLES
275
+ ${schemaClause}
276
+ AND TABLE_NAME = ?
277
+ `,
278
+ queryParams
279
+ );
280
+ if (rows.length > 0) {
281
+ return rows[0].TABLE_COMMENT || null;
282
+ }
283
+ return null;
284
+ } catch (error) {
285
+ return null;
286
+ }
287
+ }
288
+ async getStoredProcedures(schema, routineType) {
289
+ if (!this.pool) {
290
+ throw new Error("Not connected to database");
291
+ }
292
+ try {
293
+ const schemaClause = schema ? "WHERE ROUTINE_SCHEMA = ?" : "WHERE ROUTINE_SCHEMA = DATABASE()";
294
+ const queryParams = schema ? [schema] : [];
295
+ let typeFilter = "";
296
+ if (routineType === "function") {
297
+ typeFilter = " AND ROUTINE_TYPE = 'FUNCTION'";
298
+ } else if (routineType === "procedure") {
299
+ typeFilter = " AND ROUTINE_TYPE = 'PROCEDURE'";
300
+ }
301
+ const rows = await this.pool.query(
302
+ `
303
+ SELECT ROUTINE_NAME
304
+ FROM INFORMATION_SCHEMA.ROUTINES
305
+ ${schemaClause}${typeFilter}
306
+ ORDER BY ROUTINE_NAME
307
+ `,
308
+ queryParams
309
+ );
310
+ return rows.map((row) => row.ROUTINE_NAME);
311
+ } catch (error) {
312
+ console.error("Error getting stored procedures:", error);
313
+ throw error;
314
+ }
315
+ }
316
+ async getStoredProcedureDetail(procedureName, schema) {
317
+ if (!this.pool) {
318
+ throw new Error("Not connected to database");
319
+ }
320
+ try {
321
+ const schemaClause = schema ? "WHERE r.ROUTINE_SCHEMA = ?" : "WHERE r.ROUTINE_SCHEMA = DATABASE()";
322
+ const queryParams = schema ? [schema, procedureName] : [procedureName];
323
+ const rows = await this.pool.query(
324
+ `
325
+ SELECT
326
+ r.ROUTINE_NAME AS procedure_name,
327
+ CASE
328
+ WHEN r.ROUTINE_TYPE = 'PROCEDURE' THEN 'procedure'
329
+ ELSE 'function'
330
+ END AS procedure_type,
331
+ LOWER(r.ROUTINE_TYPE) AS routine_type,
332
+ r.ROUTINE_DEFINITION,
333
+ r.DTD_IDENTIFIER AS return_type,
334
+ (
335
+ SELECT GROUP_CONCAT(
336
+ CONCAT(p.PARAMETER_NAME, ' ', p.PARAMETER_MODE, ' ', p.DATA_TYPE)
337
+ ORDER BY p.ORDINAL_POSITION
338
+ SEPARATOR ', '
339
+ )
340
+ FROM INFORMATION_SCHEMA.PARAMETERS p
341
+ WHERE p.SPECIFIC_SCHEMA = r.ROUTINE_SCHEMA
342
+ AND p.SPECIFIC_NAME = r.ROUTINE_NAME
343
+ AND p.PARAMETER_NAME IS NOT NULL
344
+ ) AS parameter_list
345
+ FROM INFORMATION_SCHEMA.ROUTINES r
346
+ ${schemaClause}
347
+ AND r.ROUTINE_NAME = ?
348
+ `,
349
+ queryParams
350
+ );
351
+ if (rows.length === 0) {
352
+ const schemaName = schema || "current schema";
353
+ throw new Error(`Stored procedure '${procedureName}' not found in ${schemaName}`);
354
+ }
355
+ const procedure = rows[0];
356
+ let definition = procedure.ROUTINE_DEFINITION;
357
+ try {
358
+ const schemaValue = schema || await this.getCurrentSchema();
359
+ const quotedSchema = quoteIdentifier(schemaValue, "mariadb");
360
+ const quotedProcName = quoteIdentifier(procedureName, "mariadb");
361
+ if (procedure.procedure_type === "procedure") {
362
+ try {
363
+ const defRows = await this.pool.query(`
364
+ SHOW CREATE PROCEDURE ${quotedSchema}.${quotedProcName}
365
+ `);
366
+ if (defRows && defRows.length > 0) {
367
+ definition = defRows[0]["Create Procedure"];
368
+ }
369
+ } catch (err) {
370
+ console.error(`Error getting procedure definition with SHOW CREATE: ${err}`);
371
+ }
372
+ } else {
373
+ try {
374
+ const defRows = await this.pool.query(`
375
+ SHOW CREATE FUNCTION ${quotedSchema}.${quotedProcName}
376
+ `);
377
+ if (defRows && defRows.length > 0) {
378
+ definition = defRows[0]["Create Function"];
379
+ }
380
+ } catch (innerErr) {
381
+ console.error(`Error getting function definition with SHOW CREATE: ${innerErr}`);
382
+ }
383
+ }
384
+ if (!definition) {
385
+ const bodyRows = await this.pool.query(
386
+ `
387
+ SELECT ROUTINE_DEFINITION, ROUTINE_BODY
388
+ FROM INFORMATION_SCHEMA.ROUTINES
389
+ WHERE ROUTINE_SCHEMA = ? AND ROUTINE_NAME = ?
390
+ `,
391
+ [schemaValue, procedureName]
392
+ );
393
+ if (bodyRows && bodyRows.length > 0) {
394
+ if (bodyRows[0].ROUTINE_DEFINITION) {
395
+ definition = bodyRows[0].ROUTINE_DEFINITION;
396
+ } else if (bodyRows[0].ROUTINE_BODY) {
397
+ definition = bodyRows[0].ROUTINE_BODY;
398
+ }
399
+ }
400
+ }
401
+ } catch (error) {
402
+ console.error(`Error getting procedure/function details: ${error}`);
403
+ }
404
+ return {
405
+ procedure_name: procedure.procedure_name,
406
+ procedure_type: procedure.procedure_type,
407
+ language: "sql",
408
+ // MariaDB procedures are generally in SQL
409
+ parameter_list: procedure.parameter_list || "",
410
+ return_type: procedure.routine_type === "function" ? procedure.return_type : void 0,
411
+ definition: definition || void 0
412
+ };
413
+ } catch (error) {
414
+ console.error("Error getting stored procedure detail:", error);
415
+ throw error;
416
+ }
417
+ }
418
+ // Helper method to get current schema (database) name
419
+ async getCurrentSchema() {
420
+ const rows = await this.pool.query("SELECT DATABASE() AS DB");
421
+ return rows[0].DB;
422
+ }
423
+ async executeSQL(sql, options, parameters) {
424
+ if (!this.pool) {
425
+ throw new Error("Not connected to database");
426
+ }
427
+ const conn = await this.pool.getConnection();
428
+ try {
429
+ let processedSQL = sql;
430
+ if (options.maxRows) {
431
+ const statements = splitSQLStatements(sql, "mariadb");
432
+ const processedStatements = statements.map(
433
+ (statement) => SQLRowLimiter.applyMaxRows(statement, options.maxRows)
434
+ );
435
+ processedSQL = processedStatements.join("; ");
436
+ if (sql.trim().endsWith(";")) {
437
+ processedSQL += ";";
438
+ }
439
+ }
440
+ let results;
441
+ if (parameters && parameters.length > 0) {
442
+ try {
443
+ results = await conn.query(processedSQL, parameters);
444
+ } catch (error) {
445
+ console.error(`[MariaDB executeSQL] ERROR: ${error.message}`);
446
+ console.error(`[MariaDB executeSQL] SQL: ${processedSQL}`);
447
+ console.error(`[MariaDB executeSQL] Parameters: ${JSON.stringify(parameters)}`);
448
+ throw error;
449
+ }
450
+ } else {
451
+ results = await conn.query(processedSQL);
452
+ }
453
+ const rows = parseQueryResults(results);
454
+ const rowCount = extractAffectedRows(results);
455
+ return { rows, rowCount };
456
+ } catch (error) {
457
+ console.error("Error executing query:", error);
458
+ throw error;
459
+ } finally {
460
+ conn.release();
461
+ }
462
+ }
463
+ };
464
+ var mariadbConnector = new MariaDBConnector();
465
+ ConnectorRegistry.register(mariadbConnector);
466
+ export {
467
+ MariaDBConnector
468
+ };