@zz1996/dbhub-dameng 0.1.4 → 0.1.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.
@@ -11,8 +11,9 @@ import dmdb from "dmdb";
11
11
  var DEFAULT_OPERATION_TIMEOUT_MS = 11e4;
12
12
  var RESOURCE_CLEANUP_TIMEOUT_MS = 2e3;
13
13
  var DamengOperationTimeoutError = class extends Error {
14
- constructor(message) {
14
+ constructor(message, label) {
15
15
  super(message);
16
+ this.label = label;
16
17
  this.name = "DamengOperationTimeoutError";
17
18
  }
18
19
  };
@@ -102,6 +103,8 @@ var DamengConnector = class _DamengConnector {
102
103
  this.poolAlias = connectionConfig.poolAlias;
103
104
  this.connectionTimeoutMs = config?.connectionTimeoutSeconds !== void 0 ? config.connectionTimeoutSeconds * 1e3 : 5e3;
104
105
  this.operationTimeoutMs = config?.queryTimeoutSeconds !== void 0 ? config.queryTimeoutSeconds * 1e3 : DEFAULT_OPERATION_TIMEOUT_MS;
106
+ connectionConfig.connectTimeout ?? (connectionConfig.connectTimeout = this.connectionTimeoutMs);
107
+ connectionConfig.queueTimeout ?? (connectionConfig.queueTimeout = this.connectionTimeoutMs);
105
108
  await this.closeRegisteredPool(connectionConfig.poolAlias);
106
109
  await this.validateDirectConnection(connectionConfig);
107
110
  createdPool = await dmdb.createPool(connectionConfig);
@@ -217,6 +220,64 @@ var DamengConnector = class _DamengConnector {
217
220
  );
218
221
  return rows.map((row) => this.rowValue(row, "TABLE_NAME")).filter(this.isPresent).map((name) => ({ name, schema: owner }));
219
222
  }
223
+ async searchColumns(pattern, schema, table, limit = 100) {
224
+ const owner = await this.resolveSchema(schema);
225
+ const rowLimit = this.normalizeLimit(limit);
226
+ const bindValues = [
227
+ owner,
228
+ this.normalizeLikePattern(pattern),
229
+ ...table ? [this.normalizeIdentifier(table)] : []
230
+ ];
231
+ const tablePredicate = table ? "AND c.TABLE_NAME = :3" : "";
232
+ const rows = await this.queryRows(
233
+ `
234
+ SELECT COLUMN_NAME,
235
+ TABLE_NAME,
236
+ DATA_TYPE,
237
+ DATA_LENGTH,
238
+ DATA_PRECISION,
239
+ DATA_SCALE,
240
+ NULLABLE,
241
+ DATA_DEFAULT,
242
+ COMMENTS
243
+ FROM (
244
+ SELECT c.COLUMN_NAME,
245
+ c.TABLE_NAME,
246
+ c.DATA_TYPE,
247
+ c.DATA_LENGTH,
248
+ c.DATA_PRECISION,
249
+ c.DATA_SCALE,
250
+ c.NULLABLE,
251
+ c.DATA_DEFAULT,
252
+ cc.COMMENTS,
253
+ c.COLUMN_ID
254
+ FROM ALL_TAB_COLUMNS c
255
+ LEFT JOIN ALL_COL_COMMENTS cc
256
+ ON cc.OWNER = c.OWNER
257
+ AND cc.TABLE_NAME = c.TABLE_NAME
258
+ AND cc.COLUMN_NAME = c.COLUMN_NAME
259
+ WHERE c.OWNER = :1
260
+ AND c.COLUMN_NAME LIKE :2
261
+ ${tablePredicate}
262
+ ORDER BY c.TABLE_NAME, c.COLUMN_ID
263
+ )
264
+ WHERE ROWNUM <= ${rowLimit}
265
+ `,
266
+ bindValues
267
+ );
268
+ return rows.map((row) => {
269
+ const description = this.rowValue(row, "COMMENTS");
270
+ return {
271
+ name: this.rowValue(row, "COLUMN_NAME") ?? "",
272
+ table: this.rowValue(row, "TABLE_NAME") ?? "",
273
+ schema: owner,
274
+ type: this.formatDataType(row),
275
+ nullable: this.rowValue(row, "NULLABLE") === "Y",
276
+ default: this.rowValue(row, "DATA_DEFAULT") ?? null,
277
+ ...description ? { description } : {}
278
+ };
279
+ });
280
+ }
220
281
  async getViews(schema) {
221
282
  const owner = await this.resolveSchema(schema);
222
283
  const rows = await this.queryRows(
@@ -436,6 +497,20 @@ var DamengConnector = class _DamengConnector {
436
497
  });
437
498
  }
438
499
  async withConnection(fn) {
500
+ try {
501
+ return await this.withConnectionAttempt(fn);
502
+ } catch (error) {
503
+ if (!this.isConnectionAcquisitionFailure(error)) {
504
+ throw error;
505
+ }
506
+ console.error(
507
+ `Retrying Dameng source '${this.sourceId}' after connection acquisition failure: ${error instanceof Error ? error.message : String(error)}`
508
+ );
509
+ await this.ensurePool();
510
+ return this.withConnectionAttempt(fn);
511
+ }
512
+ }
513
+ async withConnectionAttempt(fn) {
439
514
  await this.ensurePool();
440
515
  const pool = this.pool;
441
516
  if (!pool) {
@@ -444,16 +519,15 @@ var DamengConnector = class _DamengConnector {
444
519
  let conn = null;
445
520
  let shouldRelease = true;
446
521
  try {
447
- conn = await this.withTimeout(
448
- pool.getConnection(),
449
- this.connectionTimeoutMs,
450
- "Dameng connection acquisition"
451
- );
522
+ conn = await this.acquireConnectionWithTimeout(pool);
452
523
  return await fn(conn);
453
524
  } catch (error) {
454
525
  if (error instanceof DamengOperationTimeoutError) {
455
526
  shouldRelease = false;
456
527
  this.markPoolUnhealthy(error.message);
528
+ } else if (!conn && this.isConnectionAcquisitionFailure(error)) {
529
+ shouldRelease = false;
530
+ this.markPoolUnhealthy(error instanceof Error ? error.message : String(error));
457
531
  }
458
532
  throw error;
459
533
  } finally {
@@ -462,6 +536,21 @@ var DamengConnector = class _DamengConnector {
462
536
  }
463
537
  }
464
538
  }
539
+ async acquireConnectionWithTimeout(pool) {
540
+ const acquisition = pool.getConnection();
541
+ try {
542
+ return await this.withTimeout(
543
+ acquisition,
544
+ this.connectionTimeoutMs,
545
+ "Dameng connection acquisition"
546
+ );
547
+ } catch (error) {
548
+ if (error instanceof DamengOperationTimeoutError) {
549
+ void acquisition.then((conn) => this.releaseConnectionQuietly(conn)).catch(() => void 0);
550
+ }
551
+ throw error;
552
+ }
553
+ }
465
554
  async ensurePool() {
466
555
  if (this.pool) {
467
556
  return;
@@ -523,7 +612,7 @@ var DamengConnector = class _DamengConnector {
523
612
  let timer;
524
613
  const timeout = new Promise((_, reject) => {
525
614
  timer = setTimeout(() => {
526
- reject(new DamengOperationTimeoutError(`${label} timed out after ${timeoutMs}ms`));
615
+ reject(new DamengOperationTimeoutError(`${label} timed out after ${timeoutMs}ms`, label));
527
616
  }, timeoutMs);
528
617
  });
529
618
  try {
@@ -556,6 +645,18 @@ var DamengConnector = class _DamengConnector {
556
645
  );
557
646
  }
558
647
  }
648
+ isConnectionAcquisitionFailure(error) {
649
+ if (error instanceof DamengOperationTimeoutError) {
650
+ return error.label === "Dameng connection acquisition";
651
+ }
652
+ const message = error instanceof Error ? error.message : String(error);
653
+ return [
654
+ "Connection request timeout in queue",
655
+ "Pool cannot open more connections",
656
+ "\u83B7\u53D6\u8FDE\u63A5\u8BF7\u6C42\u7B49\u5F85\u8D85\u65F6",
657
+ "\u8FDE\u63A5\u6C60\u5DF2\u8FBE\u5230\u6700\u5927\u8FDE\u63A5\u6570"
658
+ ].some((item) => message.includes(item));
659
+ }
559
660
  executeOptions(extra = {}) {
560
661
  return {
561
662
  outFormat: dmdb.OUT_FORMAT_OBJECT,
package/dist/index.js CHANGED
@@ -586,6 +586,36 @@ async function searchColumns(connector, pattern, schemaFilter, tableFilter, deta
586
586
  for (const schemaName of schemasToSearch) {
587
587
  if (results.length >= limit) break;
588
588
  try {
589
+ const searchableConnector = connector;
590
+ if (searchableConnector.searchColumns) {
591
+ const matchedColumns = await searchableConnector.searchColumns(
592
+ pattern,
593
+ schemaName,
594
+ tableFilter,
595
+ limit - results.length
596
+ );
597
+ for (const column of matchedColumns) {
598
+ if (results.length >= limit) break;
599
+ if (detailLevel === "names") {
600
+ results.push({
601
+ name: column.name,
602
+ table: column.table,
603
+ schema: column.schema
604
+ });
605
+ } else {
606
+ results.push({
607
+ name: column.name,
608
+ table: column.table,
609
+ schema: column.schema,
610
+ type: column.type,
611
+ nullable: column.nullable,
612
+ default: column.default,
613
+ ...column.description ? { description: column.description } : {}
614
+ });
615
+ }
616
+ }
617
+ continue;
618
+ }
589
619
  let tablesToSearch;
590
620
  if (tableFilter) {
591
621
  tablesToSearch = [tableFilter];
@@ -1835,7 +1865,7 @@ var connectorModules = [
1835
1865
  { load: () => import("./sqlite-IOUAYHGE.js"), name: "SQLite", driver: "node:sqlite" },
1836
1866
  { load: () => import("./mysql-A43SL7UM.js"), name: "MySQL", driver: "mysql2" },
1837
1867
  { load: () => import("./mariadb-7F72IRB4.js"), name: "MariaDB", driver: "mariadb" },
1838
- { load: () => import("./dameng-SOGGZUEW.js"), name: "Dameng", driver: "dmdb" }
1868
+ { load: () => import("./dameng-27LNS5MO.js"), name: "Dameng", driver: "dmdb" }
1839
1869
  ];
1840
1870
  loadConnectors(connectorModules).then(() => main()).catch((error) => {
1841
1871
  console.error("Fatal error:", error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zz1996/dbhub-dameng",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "mcpName": "io.github.zuozh11/dbhub-dameng",
5
5
  "description": "Local fork of DBHub with Dameng/DM8 database connector support",
6
6
  "repository": {