@zz1996/dbhub-dameng 0.1.7 → 1.2.5-dameng.621
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 +126 -137
- package/dbhub.dameng.toml.example +4 -11
- package/dist/{chunk-SQA2ISDE.js → chunk-2JL4KCP5.js} +21 -119
- package/dist/chunk-3RJRH3CN.js +121 -0
- package/dist/chunk-4276LPPU.js +179 -0
- package/dist/chunk-FU2ZJE4E.js +16 -0
- package/dist/chunk-HDPZAIDL.js +155 -0
- package/dist/{chunk-2A2QF3CS.js → chunk-HGU7ILEZ.js} +215 -68
- package/dist/{chunk-IPK7BYBL.js → chunk-JFWX35TB.js} +0 -1
- package/dist/chunk-O3PEWKBB.js +302 -0
- package/dist/dameng-NKF7NZKE.js +250 -0
- package/dist/index.js +461 -251
- package/dist/{mariadb-7F72IRB4.js → mariadb-MMC6WMEG.js} +86 -53
- package/dist/{mysql-A43SL7UM.js → mysql-TESH7KKV.js} +126 -50
- package/dist/{postgres-VFNLBWMF.js → postgres-C24SBQ4I.js} +154 -36
- package/dist/public/assets/index-BJ-1UrcV.css +1 -0
- package/dist/public/assets/index-BdBaFSHd.js +148 -0
- package/dist/public/assets/postgres-BpcazhJg.svg +22 -0
- package/dist/public/assets/sqlserver-ByfFYYpV.svg +11 -0
- package/dist/public/favicon.svg +57 -0
- package/dist/public/index.html +14 -0
- package/dist/public/logo-full-light.svg +58 -0
- package/dist/{registry-XSX2VZTD.js → registry-WVSFVS35.js} +3 -2
- package/dist/{sqlite-IOUAYHGE.js → sqlite-7BNGDMBZ.js} +57 -42
- package/dist/sqlserver-KZPPK67Q.js +1042 -0
- package/package.json +22 -65
- package/dist/chunk-RTB262PR.js +0 -60
- package/dist/chunk-ZNQTMARG.js +0 -127
- package/dist/dameng-5KYI5JBK.js +0 -898
- package/dist/sqlserver-OE4SFH4B.js +0 -587
- package/docs/README.md +0 -14
- package/docs/dameng-connector-plan.md +0 -143
package/dist/dameng-5KYI5JBK.js
DELETED
|
@@ -1,898 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ConnectorRegistry,
|
|
3
|
-
SafeURL,
|
|
4
|
-
obfuscateDSNPassword,
|
|
5
|
-
splitSQLStatements,
|
|
6
|
-
stripCommentsAndStrings
|
|
7
|
-
} from "./chunk-SQA2ISDE.js";
|
|
8
|
-
|
|
9
|
-
// src/connectors/dameng/index.ts
|
|
10
|
-
import dmdb from "dmdb";
|
|
11
|
-
var DEFAULT_OPERATION_TIMEOUT_MS = 11e4;
|
|
12
|
-
var RESOURCE_CLEANUP_TIMEOUT_MS = 2e3;
|
|
13
|
-
var CONNECT_RETRY_ATTEMPTS = 3;
|
|
14
|
-
var CONNECT_RETRY_DELAY_MS = 500;
|
|
15
|
-
var DamengOperationTimeoutError = class extends Error {
|
|
16
|
-
constructor(message, label) {
|
|
17
|
-
super(message);
|
|
18
|
-
this.label = label;
|
|
19
|
-
this.name = "DamengOperationTimeoutError";
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
var DamengDSNParser = class {
|
|
23
|
-
async parse(dsn, config) {
|
|
24
|
-
if (!this.isValidDSN(dsn)) {
|
|
25
|
-
const obfuscatedDSN = obfuscateDSNPassword(dsn);
|
|
26
|
-
const expectedFormat = this.getSampleDSN();
|
|
27
|
-
throw new Error(
|
|
28
|
-
`Invalid Dameng DSN format.
|
|
29
|
-
Provided: ${obfuscatedDSN}
|
|
30
|
-
Expected: ${expectedFormat}`
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
const url = new SafeURL(dsn);
|
|
35
|
-
const schema = url.pathname ? decodeURIComponent(url.pathname.substring(1)) : void 0;
|
|
36
|
-
const port = url.port ? parseInt(url.port, 10) : 5236;
|
|
37
|
-
const queryParams = {};
|
|
38
|
-
const queryStringParts = [];
|
|
39
|
-
url.forEachSearchParam((value, key) => {
|
|
40
|
-
queryParams[key] = value;
|
|
41
|
-
queryStringParts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
|
|
42
|
-
});
|
|
43
|
-
const connectionConfig = {
|
|
44
|
-
connectString: `dm://${encodeURIComponent(url.username)}:${encodeURIComponent(url.password)}@${url.hostname}:${port}${queryStringParts.length > 0 ? `?${queryStringParts.join("&")}` : ""}`,
|
|
45
|
-
directConnectString: `${url.hostname}:${port}`,
|
|
46
|
-
user: url.username,
|
|
47
|
-
password: url.password,
|
|
48
|
-
schema: schema || void 0,
|
|
49
|
-
poolMin: 0,
|
|
50
|
-
poolMax: 4,
|
|
51
|
-
...queryParams
|
|
52
|
-
};
|
|
53
|
-
if (config?.connectionTimeoutSeconds !== void 0) {
|
|
54
|
-
connectionConfig.connectTimeout = config.connectionTimeoutSeconds * 1e3;
|
|
55
|
-
connectionConfig.queueTimeout = config.connectionTimeoutSeconds * 1e3;
|
|
56
|
-
}
|
|
57
|
-
if (config?.queryTimeoutSeconds !== void 0) {
|
|
58
|
-
connectionConfig.sessionTimeout = config.queryTimeoutSeconds;
|
|
59
|
-
connectionConfig.socketTimeout = config.queryTimeoutSeconds * 1e3 + 1e3;
|
|
60
|
-
}
|
|
61
|
-
return connectionConfig;
|
|
62
|
-
} catch (error) {
|
|
63
|
-
throw new Error(
|
|
64
|
-
`Failed to parse Dameng DSN: ${error instanceof Error ? error.message : String(error)}`
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
getSampleDSN() {
|
|
69
|
-
return "dameng://SYSDBA:password@localhost:5236/SYSDBA";
|
|
70
|
-
}
|
|
71
|
-
isValidDSN(dsn) {
|
|
72
|
-
try {
|
|
73
|
-
return dsn.startsWith("dameng://") || dsn.startsWith("dm://");
|
|
74
|
-
} catch {
|
|
75
|
-
return false;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
var DamengConnector = class _DamengConnector {
|
|
80
|
-
constructor() {
|
|
81
|
-
this.id = "dameng";
|
|
82
|
-
this.name = "Dameng";
|
|
83
|
-
this.dsnParser = new DamengDSNParser();
|
|
84
|
-
this.pool = null;
|
|
85
|
-
this.sourceId = "default";
|
|
86
|
-
this.defaultSchema = null;
|
|
87
|
-
this.poolAlias = null;
|
|
88
|
-
this.connectionConfig = null;
|
|
89
|
-
this.connectionTimeoutMs = 5e3;
|
|
90
|
-
this.operationTimeoutMs = DEFAULT_OPERATION_TIMEOUT_MS;
|
|
91
|
-
this.reconnectingPool = null;
|
|
92
|
-
}
|
|
93
|
-
getId() {
|
|
94
|
-
return this.sourceId;
|
|
95
|
-
}
|
|
96
|
-
clone() {
|
|
97
|
-
return new _DamengConnector();
|
|
98
|
-
}
|
|
99
|
-
async connect(dsn, initScript, config) {
|
|
100
|
-
for (let attempt = 1; attempt <= CONNECT_RETRY_ATTEMPTS; attempt += 1) {
|
|
101
|
-
let createdPool = null;
|
|
102
|
-
try {
|
|
103
|
-
const connectionConfig = await this.dsnParser.parse(dsn, config);
|
|
104
|
-
connectionConfig.poolAlias = this.buildPoolAlias();
|
|
105
|
-
this.defaultSchema = connectionConfig.schema ?? null;
|
|
106
|
-
this.poolAlias = connectionConfig.poolAlias;
|
|
107
|
-
this.connectionTimeoutMs = config?.connectionTimeoutSeconds !== void 0 ? config.connectionTimeoutSeconds * 1e3 : 5e3;
|
|
108
|
-
this.operationTimeoutMs = config?.queryTimeoutSeconds !== void 0 ? config.queryTimeoutSeconds * 1e3 : DEFAULT_OPERATION_TIMEOUT_MS;
|
|
109
|
-
connectionConfig.connectTimeout ?? (connectionConfig.connectTimeout = this.connectionTimeoutMs);
|
|
110
|
-
connectionConfig.queueTimeout ?? (connectionConfig.queueTimeout = this.connectionTimeoutMs);
|
|
111
|
-
await this.closeRegisteredPool(connectionConfig.poolAlias);
|
|
112
|
-
await this.validateDirectConnection(connectionConfig);
|
|
113
|
-
createdPool = await dmdb.createPool(connectionConfig);
|
|
114
|
-
this.pool = createdPool;
|
|
115
|
-
await this.withConnection((conn) => this.initializeSession(conn, initScript));
|
|
116
|
-
this.connectionConfig = connectionConfig;
|
|
117
|
-
this.initScript = initScript;
|
|
118
|
-
return;
|
|
119
|
-
} catch (error) {
|
|
120
|
-
if (createdPool) {
|
|
121
|
-
await this.closePoolQuietly(createdPool);
|
|
122
|
-
} else if (this.poolAlias) {
|
|
123
|
-
await this.closeRegisteredPool(this.poolAlias);
|
|
124
|
-
}
|
|
125
|
-
this.pool = null;
|
|
126
|
-
this.poolAlias = null;
|
|
127
|
-
this.connectionConfig = null;
|
|
128
|
-
this.initScript = void 0;
|
|
129
|
-
if (attempt < CONNECT_RETRY_ATTEMPTS && this.isRetryableConnectFailure(error)) {
|
|
130
|
-
console.error(
|
|
131
|
-
`Retrying Dameng source '${this.sourceId}' connection after transient failure (${attempt}/${CONNECT_RETRY_ATTEMPTS}): ${error instanceof Error ? error.message : String(error)}`
|
|
132
|
-
);
|
|
133
|
-
await this.delay(CONNECT_RETRY_DELAY_MS * attempt);
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
console.error("Failed to connect to Dameng database:", error);
|
|
137
|
-
throw error;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
throw new Error("Failed to connect to Dameng database");
|
|
141
|
-
}
|
|
142
|
-
async initializeSession(conn, initScript) {
|
|
143
|
-
await this.executeWithTimeout(
|
|
144
|
-
conn,
|
|
145
|
-
"SELECT 1 AS OK",
|
|
146
|
-
[],
|
|
147
|
-
this.executeOptions()
|
|
148
|
-
);
|
|
149
|
-
if (!this.defaultSchema) {
|
|
150
|
-
const result = await this.executeWithTimeout(
|
|
151
|
-
conn,
|
|
152
|
-
"SELECT USER AS SCHEMA_NAME FROM DUAL",
|
|
153
|
-
[],
|
|
154
|
-
this.executeOptions()
|
|
155
|
-
);
|
|
156
|
-
this.defaultSchema = this.rowValue(result.rows?.[0], "SCHEMA_NAME") ?? null;
|
|
157
|
-
}
|
|
158
|
-
if (initScript) {
|
|
159
|
-
for (const statement of splitSQLStatements(initScript, "dameng")) {
|
|
160
|
-
await this.executeWithTimeout(
|
|
161
|
-
conn,
|
|
162
|
-
statement,
|
|
163
|
-
[],
|
|
164
|
-
this.executeOptions({ autoCommit: true })
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
async disconnect() {
|
|
170
|
-
if (this.pool) {
|
|
171
|
-
await this.closePoolQuietly(this.pool);
|
|
172
|
-
this.pool = null;
|
|
173
|
-
}
|
|
174
|
-
if (this.poolAlias) {
|
|
175
|
-
await this.closeRegisteredPool(this.poolAlias);
|
|
176
|
-
this.poolAlias = null;
|
|
177
|
-
}
|
|
178
|
-
this.connectionConfig = null;
|
|
179
|
-
this.initScript = void 0;
|
|
180
|
-
this.reconnectingPool = null;
|
|
181
|
-
}
|
|
182
|
-
async getSchemas() {
|
|
183
|
-
const rows = await this.queryRows(`
|
|
184
|
-
SELECT USERNAME AS SCHEMA_NAME
|
|
185
|
-
FROM ALL_USERS
|
|
186
|
-
WHERE USERNAME NOT IN ('SYS', 'SYSTEM', 'SYSAUDITOR', 'SYSSSO', 'CTISYS')
|
|
187
|
-
ORDER BY USERNAME
|
|
188
|
-
`);
|
|
189
|
-
return rows.map((row) => this.rowValue(row, "SCHEMA_NAME")).filter(this.isPresent);
|
|
190
|
-
}
|
|
191
|
-
async schemaExists(schema) {
|
|
192
|
-
const rows = await this.queryRows(
|
|
193
|
-
`
|
|
194
|
-
SELECT COUNT(*) AS CNT
|
|
195
|
-
FROM ALL_USERS
|
|
196
|
-
WHERE USERNAME = :1
|
|
197
|
-
`,
|
|
198
|
-
[this.normalizeIdentifier(schema)]
|
|
199
|
-
);
|
|
200
|
-
return Number(this.rowValue(rows[0], "CNT") ?? 0) > 0;
|
|
201
|
-
}
|
|
202
|
-
async getDefaultSchema() {
|
|
203
|
-
return this.defaultSchema;
|
|
204
|
-
}
|
|
205
|
-
async getTables(schema) {
|
|
206
|
-
const owner = await this.resolveSchema(schema);
|
|
207
|
-
const rows = await this.queryRows(
|
|
208
|
-
`
|
|
209
|
-
SELECT TABLE_NAME
|
|
210
|
-
FROM ALL_TABLES
|
|
211
|
-
WHERE OWNER = :1
|
|
212
|
-
ORDER BY TABLE_NAME
|
|
213
|
-
`,
|
|
214
|
-
[owner]
|
|
215
|
-
);
|
|
216
|
-
return rows.map((row) => this.rowValue(row, "TABLE_NAME")).filter(this.isPresent);
|
|
217
|
-
}
|
|
218
|
-
async searchTables(pattern, schema, limit = 100) {
|
|
219
|
-
const owner = await this.resolveSchema(schema);
|
|
220
|
-
const rowLimit = this.normalizeLimit(limit);
|
|
221
|
-
const rows = await this.queryRows(
|
|
222
|
-
`
|
|
223
|
-
SELECT TABLE_NAME
|
|
224
|
-
FROM (
|
|
225
|
-
SELECT TABLE_NAME
|
|
226
|
-
FROM ALL_TABLES
|
|
227
|
-
WHERE OWNER = :1
|
|
228
|
-
AND TABLE_NAME LIKE :2
|
|
229
|
-
ORDER BY TABLE_NAME
|
|
230
|
-
)
|
|
231
|
-
WHERE ROWNUM <= ${rowLimit}
|
|
232
|
-
`,
|
|
233
|
-
[owner, this.normalizeLikePattern(pattern)]
|
|
234
|
-
);
|
|
235
|
-
return rows.map((row) => this.rowValue(row, "TABLE_NAME")).filter(this.isPresent).map((name) => ({ name, schema: owner }));
|
|
236
|
-
}
|
|
237
|
-
async searchColumns(pattern, schema, table, limit = 100) {
|
|
238
|
-
const owner = await this.resolveSchema(schema);
|
|
239
|
-
const rowLimit = this.normalizeLimit(limit);
|
|
240
|
-
const bindValues = [
|
|
241
|
-
owner,
|
|
242
|
-
this.normalizeLikePattern(pattern),
|
|
243
|
-
...table ? [this.normalizeIdentifier(table)] : []
|
|
244
|
-
];
|
|
245
|
-
const tablePredicate = table ? "AND c.TABLE_NAME = :3" : "";
|
|
246
|
-
const rows = await this.queryRows(
|
|
247
|
-
`
|
|
248
|
-
SELECT COLUMN_NAME,
|
|
249
|
-
TABLE_NAME,
|
|
250
|
-
DATA_TYPE,
|
|
251
|
-
DATA_LENGTH,
|
|
252
|
-
DATA_PRECISION,
|
|
253
|
-
DATA_SCALE,
|
|
254
|
-
NULLABLE,
|
|
255
|
-
DATA_DEFAULT,
|
|
256
|
-
COMMENTS
|
|
257
|
-
FROM (
|
|
258
|
-
SELECT c.COLUMN_NAME,
|
|
259
|
-
c.TABLE_NAME,
|
|
260
|
-
c.DATA_TYPE,
|
|
261
|
-
c.DATA_LENGTH,
|
|
262
|
-
c.DATA_PRECISION,
|
|
263
|
-
c.DATA_SCALE,
|
|
264
|
-
c.NULLABLE,
|
|
265
|
-
c.DATA_DEFAULT,
|
|
266
|
-
cc.COMMENTS,
|
|
267
|
-
c.COLUMN_ID
|
|
268
|
-
FROM ALL_TAB_COLUMNS c
|
|
269
|
-
LEFT JOIN ALL_COL_COMMENTS cc
|
|
270
|
-
ON cc.OWNER = c.OWNER
|
|
271
|
-
AND cc.TABLE_NAME = c.TABLE_NAME
|
|
272
|
-
AND cc.COLUMN_NAME = c.COLUMN_NAME
|
|
273
|
-
WHERE c.OWNER = :1
|
|
274
|
-
AND c.COLUMN_NAME LIKE :2
|
|
275
|
-
${tablePredicate}
|
|
276
|
-
ORDER BY c.TABLE_NAME, c.COLUMN_ID
|
|
277
|
-
)
|
|
278
|
-
WHERE ROWNUM <= ${rowLimit}
|
|
279
|
-
`,
|
|
280
|
-
bindValues
|
|
281
|
-
);
|
|
282
|
-
return rows.map((row) => {
|
|
283
|
-
const description = this.rowValue(row, "COMMENTS");
|
|
284
|
-
return {
|
|
285
|
-
name: this.rowValue(row, "COLUMN_NAME") ?? "",
|
|
286
|
-
table: this.rowValue(row, "TABLE_NAME") ?? "",
|
|
287
|
-
schema: owner,
|
|
288
|
-
type: this.formatDataType(row),
|
|
289
|
-
nullable: this.rowValue(row, "NULLABLE") === "Y",
|
|
290
|
-
default: this.rowValue(row, "DATA_DEFAULT") ?? null,
|
|
291
|
-
...description ? { description } : {}
|
|
292
|
-
};
|
|
293
|
-
});
|
|
294
|
-
}
|
|
295
|
-
async getViews(schema) {
|
|
296
|
-
const owner = await this.resolveSchema(schema);
|
|
297
|
-
const rows = await this.queryRows(
|
|
298
|
-
`
|
|
299
|
-
SELECT VIEW_NAME
|
|
300
|
-
FROM ALL_VIEWS
|
|
301
|
-
WHERE OWNER = :1
|
|
302
|
-
ORDER BY VIEW_NAME
|
|
303
|
-
`,
|
|
304
|
-
[owner]
|
|
305
|
-
);
|
|
306
|
-
return rows.map((row) => this.rowValue(row, "VIEW_NAME")).filter(this.isPresent);
|
|
307
|
-
}
|
|
308
|
-
async tableExists(tableName, schema) {
|
|
309
|
-
const owner = await this.resolveSchema(schema);
|
|
310
|
-
const rows = await this.queryRows(
|
|
311
|
-
`
|
|
312
|
-
SELECT COUNT(*) AS CNT
|
|
313
|
-
FROM ALL_OBJECTS
|
|
314
|
-
WHERE OWNER = :1
|
|
315
|
-
AND OBJECT_NAME = :2
|
|
316
|
-
AND OBJECT_TYPE IN ('TABLE', 'VIEW')
|
|
317
|
-
`,
|
|
318
|
-
[owner, this.normalizeIdentifier(tableName)]
|
|
319
|
-
);
|
|
320
|
-
return Number(this.rowValue(rows[0], "CNT") ?? 0) > 0;
|
|
321
|
-
}
|
|
322
|
-
async getTableSchema(tableName, schema) {
|
|
323
|
-
const owner = await this.resolveSchema(schema);
|
|
324
|
-
const rows = await this.queryRows(
|
|
325
|
-
`
|
|
326
|
-
SELECT c.COLUMN_NAME,
|
|
327
|
-
c.DATA_TYPE,
|
|
328
|
-
c.DATA_LENGTH,
|
|
329
|
-
c.DATA_PRECISION,
|
|
330
|
-
c.DATA_SCALE,
|
|
331
|
-
c.NULLABLE,
|
|
332
|
-
c.DATA_DEFAULT,
|
|
333
|
-
cc.COMMENTS
|
|
334
|
-
FROM ALL_TAB_COLUMNS c
|
|
335
|
-
LEFT JOIN ALL_COL_COMMENTS cc
|
|
336
|
-
ON cc.OWNER = c.OWNER
|
|
337
|
-
AND cc.TABLE_NAME = c.TABLE_NAME
|
|
338
|
-
AND cc.COLUMN_NAME = c.COLUMN_NAME
|
|
339
|
-
WHERE c.OWNER = :1
|
|
340
|
-
AND c.TABLE_NAME = :2
|
|
341
|
-
ORDER BY c.COLUMN_ID
|
|
342
|
-
`,
|
|
343
|
-
[owner, this.normalizeIdentifier(tableName)]
|
|
344
|
-
);
|
|
345
|
-
return rows.map((row) => {
|
|
346
|
-
const dataType = this.formatDataType(row);
|
|
347
|
-
return {
|
|
348
|
-
column_name: this.rowValue(row, "COLUMN_NAME") ?? "",
|
|
349
|
-
data_type: dataType,
|
|
350
|
-
is_nullable: this.rowValue(row, "NULLABLE") === "Y" ? "YES" : "NO",
|
|
351
|
-
column_default: this.rowValue(row, "DATA_DEFAULT") ?? null,
|
|
352
|
-
description: this.rowValue(row, "COMMENTS") ?? null
|
|
353
|
-
};
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
async getTableIndexes(tableName, schema) {
|
|
357
|
-
const owner = await this.resolveSchema(schema);
|
|
358
|
-
const rows = await this.queryRows(
|
|
359
|
-
`
|
|
360
|
-
SELECT i.INDEX_NAME,
|
|
361
|
-
i.UNIQUENESS,
|
|
362
|
-
ic.COLUMN_NAME,
|
|
363
|
-
ic.COLUMN_POSITION,
|
|
364
|
-
CASE WHEN c.CONSTRAINT_TYPE = 'P' THEN 1 ELSE 0 END AS IS_PRIMARY
|
|
365
|
-
FROM ALL_INDEXES i
|
|
366
|
-
JOIN ALL_IND_COLUMNS ic
|
|
367
|
-
ON i.OWNER = ic.INDEX_OWNER
|
|
368
|
-
AND i.INDEX_NAME = ic.INDEX_NAME
|
|
369
|
-
LEFT JOIN ALL_CONSTRAINTS c
|
|
370
|
-
ON c.OWNER = i.TABLE_OWNER
|
|
371
|
-
AND c.TABLE_NAME = i.TABLE_NAME
|
|
372
|
-
AND c.INDEX_NAME = i.INDEX_NAME
|
|
373
|
-
AND c.CONSTRAINT_TYPE = 'P'
|
|
374
|
-
WHERE i.TABLE_OWNER = :1
|
|
375
|
-
AND i.TABLE_NAME = :2
|
|
376
|
-
ORDER BY i.INDEX_NAME, ic.COLUMN_POSITION
|
|
377
|
-
`,
|
|
378
|
-
[owner, this.normalizeIdentifier(tableName)]
|
|
379
|
-
);
|
|
380
|
-
const indexMap = /* @__PURE__ */ new Map();
|
|
381
|
-
for (const row of rows) {
|
|
382
|
-
const indexName = this.rowValue(row, "INDEX_NAME") ?? "";
|
|
383
|
-
if (!indexMap.has(indexName)) {
|
|
384
|
-
indexMap.set(indexName, {
|
|
385
|
-
index_name: indexName,
|
|
386
|
-
column_names: [],
|
|
387
|
-
is_unique: this.rowValue(row, "UNIQUENESS") === "UNIQUE",
|
|
388
|
-
is_primary: Number(this.rowValue(row, "IS_PRIMARY") ?? 0) === 1
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
const columnName = this.rowValue(row, "COLUMN_NAME");
|
|
392
|
-
if (columnName) {
|
|
393
|
-
indexMap.get(indexName).column_names.push(columnName);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
return Array.from(indexMap.values());
|
|
397
|
-
}
|
|
398
|
-
async getStoredProcedures(schema, routineType) {
|
|
399
|
-
const owner = await this.resolveSchema(schema);
|
|
400
|
-
const types = routineType ? [routineType === "procedure" ? "PROCEDURE" : "FUNCTION"] : ["PROCEDURE", "FUNCTION"];
|
|
401
|
-
const rows = await this.queryRows(
|
|
402
|
-
`
|
|
403
|
-
SELECT OBJECT_NAME
|
|
404
|
-
FROM ALL_OBJECTS
|
|
405
|
-
WHERE OWNER = :1
|
|
406
|
-
AND OBJECT_TYPE IN (${types.map((_, i) => `:${i + 2}`).join(", ")})
|
|
407
|
-
ORDER BY OBJECT_NAME
|
|
408
|
-
`,
|
|
409
|
-
[owner, ...types]
|
|
410
|
-
);
|
|
411
|
-
return rows.map((row) => this.rowValue(row, "OBJECT_NAME")).filter(this.isPresent);
|
|
412
|
-
}
|
|
413
|
-
async getStoredProcedureDetail(procedureName, schema) {
|
|
414
|
-
const owner = await this.resolveSchema(schema);
|
|
415
|
-
const name = this.normalizeIdentifier(procedureName);
|
|
416
|
-
const rows = await this.queryRows(
|
|
417
|
-
`
|
|
418
|
-
SELECT OBJECT_NAME, OBJECT_TYPE
|
|
419
|
-
FROM ALL_OBJECTS
|
|
420
|
-
WHERE OWNER = :1
|
|
421
|
-
AND OBJECT_NAME = :2
|
|
422
|
-
AND OBJECT_TYPE IN ('PROCEDURE', 'FUNCTION')
|
|
423
|
-
`,
|
|
424
|
-
[owner, name]
|
|
425
|
-
);
|
|
426
|
-
if (rows.length === 0) {
|
|
427
|
-
throw new Error(`Stored procedure '${procedureName}' not found in ${owner}`);
|
|
428
|
-
}
|
|
429
|
-
const sourceRows = await this.queryRows(
|
|
430
|
-
`
|
|
431
|
-
SELECT TEXT
|
|
432
|
-
FROM ALL_SOURCE
|
|
433
|
-
WHERE OWNER = :1
|
|
434
|
-
AND NAME = :2
|
|
435
|
-
ORDER BY LINE
|
|
436
|
-
`,
|
|
437
|
-
[owner, name]
|
|
438
|
-
);
|
|
439
|
-
const objectType = this.rowValue(rows[0], "OBJECT_TYPE") ?? "PROCEDURE";
|
|
440
|
-
return {
|
|
441
|
-
procedure_name: this.rowValue(rows[0], "OBJECT_NAME") ?? procedureName,
|
|
442
|
-
procedure_type: objectType === "FUNCTION" ? "function" : "procedure",
|
|
443
|
-
language: "sql",
|
|
444
|
-
parameter_list: "",
|
|
445
|
-
definition: sourceRows.map((row) => this.rowValue(row, "TEXT") ?? "").join("")
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
async getTableRowCount(tableName, schema) {
|
|
449
|
-
const owner = await this.resolveSchema(schema);
|
|
450
|
-
const rows = await this.queryRows(
|
|
451
|
-
`
|
|
452
|
-
SELECT NUM_ROWS
|
|
453
|
-
FROM ALL_TABLES
|
|
454
|
-
WHERE OWNER = :1
|
|
455
|
-
AND TABLE_NAME = :2
|
|
456
|
-
`,
|
|
457
|
-
[owner, this.normalizeIdentifier(tableName)]
|
|
458
|
-
);
|
|
459
|
-
const value = this.rowValue(rows[0], "NUM_ROWS");
|
|
460
|
-
return value === null || value === void 0 ? null : Number(value);
|
|
461
|
-
}
|
|
462
|
-
async getTableComment(tableName, schema) {
|
|
463
|
-
const owner = await this.resolveSchema(schema);
|
|
464
|
-
const rows = await this.queryRows(
|
|
465
|
-
`
|
|
466
|
-
SELECT COMMENTS
|
|
467
|
-
FROM ALL_TAB_COMMENTS
|
|
468
|
-
WHERE OWNER = :1
|
|
469
|
-
AND TABLE_NAME = :2
|
|
470
|
-
`,
|
|
471
|
-
[owner, this.normalizeIdentifier(tableName)]
|
|
472
|
-
);
|
|
473
|
-
return this.rowValue(rows[0], "COMMENTS") ?? null;
|
|
474
|
-
}
|
|
475
|
-
async executeSQL(sql, options, parameters) {
|
|
476
|
-
if (!this.pool) {
|
|
477
|
-
throw new Error("Not connected to Dameng database");
|
|
478
|
-
}
|
|
479
|
-
return this.withConnection(async (conn) => {
|
|
480
|
-
const statements = splitSQLStatements(sql, "dameng");
|
|
481
|
-
const allRows = [];
|
|
482
|
-
let rowCount = 0;
|
|
483
|
-
for (const [index, statement] of statements.entries()) {
|
|
484
|
-
const processedSQL = this.applyMaxRows(statement, options.maxRows);
|
|
485
|
-
const { sql: boundSQL, bindValues } = this.replacePositionalParameters(
|
|
486
|
-
processedSQL,
|
|
487
|
-
index === 0 ? parameters ?? [] : []
|
|
488
|
-
);
|
|
489
|
-
const result = await this.executeWithTimeout(
|
|
490
|
-
conn,
|
|
491
|
-
boundSQL,
|
|
492
|
-
this.toBindParams(bindValues),
|
|
493
|
-
this.executeOptions({ autoCommit: true, maxRows: options.maxRows })
|
|
494
|
-
);
|
|
495
|
-
const rows = this.normalizeRows(result.rows ?? []);
|
|
496
|
-
allRows.push(...rows);
|
|
497
|
-
rowCount += Number(result.rowsAffected ?? rows.length ?? 0);
|
|
498
|
-
}
|
|
499
|
-
return { rows: allRows, rowCount };
|
|
500
|
-
});
|
|
501
|
-
}
|
|
502
|
-
async queryRows(sql, bindValues = []) {
|
|
503
|
-
return this.withConnection(async (conn) => {
|
|
504
|
-
const result = await this.executeWithTimeout(
|
|
505
|
-
conn,
|
|
506
|
-
sql,
|
|
507
|
-
this.toBindParams(bindValues),
|
|
508
|
-
this.executeOptions()
|
|
509
|
-
);
|
|
510
|
-
return this.normalizeRows(result.rows ?? []);
|
|
511
|
-
});
|
|
512
|
-
}
|
|
513
|
-
async withConnection(fn) {
|
|
514
|
-
try {
|
|
515
|
-
return await this.withConnectionAttempt(fn);
|
|
516
|
-
} catch (error) {
|
|
517
|
-
if (!this.isConnectionAcquisitionFailure(error)) {
|
|
518
|
-
throw error;
|
|
519
|
-
}
|
|
520
|
-
console.error(
|
|
521
|
-
`Retrying Dameng source '${this.sourceId}' after connection acquisition failure: ${error instanceof Error ? error.message : String(error)}`
|
|
522
|
-
);
|
|
523
|
-
await this.ensurePool();
|
|
524
|
-
return this.withConnectionAttempt(fn);
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
async withConnectionAttempt(fn) {
|
|
528
|
-
await this.ensurePool();
|
|
529
|
-
const pool = this.pool;
|
|
530
|
-
if (!pool) {
|
|
531
|
-
throw new Error("Not connected to Dameng database");
|
|
532
|
-
}
|
|
533
|
-
let conn = null;
|
|
534
|
-
let shouldRelease = true;
|
|
535
|
-
try {
|
|
536
|
-
conn = await this.acquireConnectionWithTimeout(pool);
|
|
537
|
-
return await fn(conn);
|
|
538
|
-
} catch (error) {
|
|
539
|
-
if (error instanceof DamengOperationTimeoutError) {
|
|
540
|
-
shouldRelease = false;
|
|
541
|
-
this.markPoolUnhealthy(error.message);
|
|
542
|
-
} else if (!conn && this.isConnectionAcquisitionFailure(error)) {
|
|
543
|
-
shouldRelease = false;
|
|
544
|
-
this.markPoolUnhealthy(error instanceof Error ? error.message : String(error));
|
|
545
|
-
}
|
|
546
|
-
throw error;
|
|
547
|
-
} finally {
|
|
548
|
-
if (conn && shouldRelease) {
|
|
549
|
-
await this.releaseConnectionQuietly(conn);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
async acquireConnectionWithTimeout(pool) {
|
|
554
|
-
const acquisition = pool.getConnection();
|
|
555
|
-
try {
|
|
556
|
-
return await this.withTimeout(
|
|
557
|
-
acquisition,
|
|
558
|
-
this.connectionTimeoutMs,
|
|
559
|
-
"Dameng connection acquisition"
|
|
560
|
-
);
|
|
561
|
-
} catch (error) {
|
|
562
|
-
if (error instanceof DamengOperationTimeoutError) {
|
|
563
|
-
void acquisition.then((conn) => this.releaseConnectionQuietly(conn)).catch(() => void 0);
|
|
564
|
-
}
|
|
565
|
-
throw error;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
async ensurePool() {
|
|
569
|
-
if (this.pool) {
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
572
|
-
if (!this.connectionConfig) {
|
|
573
|
-
throw new Error("Not connected to Dameng database");
|
|
574
|
-
}
|
|
575
|
-
if (!this.reconnectingPool) {
|
|
576
|
-
this.reconnectingPool = this.reconnectPool();
|
|
577
|
-
}
|
|
578
|
-
try {
|
|
579
|
-
await this.reconnectingPool;
|
|
580
|
-
} finally {
|
|
581
|
-
this.reconnectingPool = null;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
async reconnectPool() {
|
|
585
|
-
const config = this.connectionConfig;
|
|
586
|
-
if (!config) {
|
|
587
|
-
throw new Error("Not connected to Dameng database");
|
|
588
|
-
}
|
|
589
|
-
console.error(`Reconnecting Dameng source '${this.sourceId}' after pool reset...`);
|
|
590
|
-
await this.closeRegisteredPool(config.poolAlias ?? this.buildPoolAlias());
|
|
591
|
-
await this.validateDirectConnection(config);
|
|
592
|
-
const createdPool = await dmdb.createPool(config);
|
|
593
|
-
this.pool = createdPool;
|
|
594
|
-
this.poolAlias = config.poolAlias ?? null;
|
|
595
|
-
try {
|
|
596
|
-
await this.withConnection(async (conn) => {
|
|
597
|
-
await this.executeWithTimeout(conn, "SELECT 1 AS OK", [], this.executeOptions());
|
|
598
|
-
if (this.initScript) {
|
|
599
|
-
for (const statement of splitSQLStatements(this.initScript, "dameng")) {
|
|
600
|
-
await this.executeWithTimeout(
|
|
601
|
-
conn,
|
|
602
|
-
statement,
|
|
603
|
-
[],
|
|
604
|
-
this.executeOptions({ autoCommit: true })
|
|
605
|
-
);
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
});
|
|
609
|
-
} catch (error) {
|
|
610
|
-
await this.closePoolQuietly(createdPool);
|
|
611
|
-
this.pool = null;
|
|
612
|
-
throw error;
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
executeWithTimeout(conn, sql, bindParams, options) {
|
|
616
|
-
return this.withTimeout(
|
|
617
|
-
conn.execute(sql, bindParams, options),
|
|
618
|
-
this.operationTimeoutMs,
|
|
619
|
-
"Dameng SQL execution"
|
|
620
|
-
);
|
|
621
|
-
}
|
|
622
|
-
async withTimeout(promise, timeoutMs, label) {
|
|
623
|
-
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
624
|
-
return promise;
|
|
625
|
-
}
|
|
626
|
-
let timer;
|
|
627
|
-
const timeout = new Promise((_, reject) => {
|
|
628
|
-
timer = setTimeout(() => {
|
|
629
|
-
reject(new DamengOperationTimeoutError(`${label} timed out after ${timeoutMs}ms`, label));
|
|
630
|
-
}, timeoutMs);
|
|
631
|
-
});
|
|
632
|
-
try {
|
|
633
|
-
return await Promise.race([promise, timeout]);
|
|
634
|
-
} finally {
|
|
635
|
-
if (timer) {
|
|
636
|
-
clearTimeout(timer);
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
markPoolUnhealthy(reason) {
|
|
641
|
-
const pool = this.pool;
|
|
642
|
-
this.pool = null;
|
|
643
|
-
console.error(`Resetting Dameng source '${this.sourceId}' pool: ${reason}`);
|
|
644
|
-
if (pool) {
|
|
645
|
-
void this.closePoolQuietly(pool);
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
async releaseConnectionQuietly(conn) {
|
|
649
|
-
try {
|
|
650
|
-
const release = conn.release ? conn.release() : conn.close();
|
|
651
|
-
await this.withTimeout(
|
|
652
|
-
release,
|
|
653
|
-
RESOURCE_CLEANUP_TIMEOUT_MS,
|
|
654
|
-
"Dameng connection release"
|
|
655
|
-
);
|
|
656
|
-
} catch (error) {
|
|
657
|
-
this.markPoolUnhealthy(
|
|
658
|
-
`failed to release connection: ${error instanceof Error ? error.message : String(error)}`
|
|
659
|
-
);
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
isConnectionAcquisitionFailure(error) {
|
|
663
|
-
if (error instanceof DamengOperationTimeoutError) {
|
|
664
|
-
return error.label === "Dameng connection acquisition";
|
|
665
|
-
}
|
|
666
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
667
|
-
return [
|
|
668
|
-
"Connection request timeout in queue",
|
|
669
|
-
"Pool cannot open more connections",
|
|
670
|
-
"\u83B7\u53D6\u8FDE\u63A5\u8BF7\u6C42\u7B49\u5F85\u8D85\u65F6",
|
|
671
|
-
"\u8FDE\u63A5\u6C60\u5DF2\u8FBE\u5230\u6700\u5927\u8FDE\u63A5\u6570"
|
|
672
|
-
].some((item) => message.includes(item));
|
|
673
|
-
}
|
|
674
|
-
isRetryableConnectFailure(error) {
|
|
675
|
-
if (error instanceof DamengOperationTimeoutError) {
|
|
676
|
-
return [
|
|
677
|
-
"Dameng direct connection",
|
|
678
|
-
"Dameng connection acquisition",
|
|
679
|
-
"Dameng SQL execution"
|
|
680
|
-
].includes(error.label);
|
|
681
|
-
}
|
|
682
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
683
|
-
return [
|
|
684
|
-
"ECONNRESET",
|
|
685
|
-
"ETIMEDOUT",
|
|
686
|
-
"ECONNREFUSED",
|
|
687
|
-
"socket hang up",
|
|
688
|
-
"Socket timeout",
|
|
689
|
-
"connect timeout",
|
|
690
|
-
"Connection request timeout in queue",
|
|
691
|
-
"Pool cannot open more connections",
|
|
692
|
-
"\u7F51\u7EDC\u901A\u8BAF\u8D85\u65F6",
|
|
693
|
-
"\u7F51\u7EDC\u901A\u4FE1\u5F02\u5E38",
|
|
694
|
-
"\u8FDE\u63A5\u8D85\u65F6",
|
|
695
|
-
"\u83B7\u53D6\u8FDE\u63A5\u8BF7\u6C42\u7B49\u5F85\u8D85\u65F6",
|
|
696
|
-
"\u8FDE\u63A5\u6C60\u5DF2\u8FBE\u5230\u6700\u5927\u8FDE\u63A5\u6570"
|
|
697
|
-
].some((item) => message.includes(item));
|
|
698
|
-
}
|
|
699
|
-
delay(ms) {
|
|
700
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
701
|
-
}
|
|
702
|
-
executeOptions(extra = {}) {
|
|
703
|
-
return {
|
|
704
|
-
outFormat: dmdb.OUT_FORMAT_OBJECT,
|
|
705
|
-
...extra
|
|
706
|
-
};
|
|
707
|
-
}
|
|
708
|
-
async validateDirectConnection(config) {
|
|
709
|
-
let conn = null;
|
|
710
|
-
try {
|
|
711
|
-
const {
|
|
712
|
-
directConnectString,
|
|
713
|
-
poolAlias,
|
|
714
|
-
poolMin,
|
|
715
|
-
poolMax,
|
|
716
|
-
queueRequests,
|
|
717
|
-
queueTimeout,
|
|
718
|
-
...directConfig
|
|
719
|
-
} = config;
|
|
720
|
-
const directConn = await this.withTimeout(
|
|
721
|
-
dmdb.getConnection({
|
|
722
|
-
...directConfig,
|
|
723
|
-
connectString: directConnectString ?? config.connectString
|
|
724
|
-
}),
|
|
725
|
-
this.connectionTimeoutMs,
|
|
726
|
-
"Dameng direct connection"
|
|
727
|
-
);
|
|
728
|
-
conn = directConn;
|
|
729
|
-
await this.executeWithTimeout(conn, "SELECT 1 AS OK", [], this.executeOptions());
|
|
730
|
-
} finally {
|
|
731
|
-
if (conn) {
|
|
732
|
-
await this.releaseConnectionQuietly(conn);
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
buildPoolAlias() {
|
|
737
|
-
const safeSourceId = this.sourceId.replace(/[^a-zA-Z0-9_-]/g, "_") || "default";
|
|
738
|
-
return `dbhub_dameng_${safeSourceId}`;
|
|
739
|
-
}
|
|
740
|
-
async closeRegisteredPool(poolAlias) {
|
|
741
|
-
if (!dmdb.pools?.has?.(poolAlias)) {
|
|
742
|
-
return;
|
|
743
|
-
}
|
|
744
|
-
const pool = dmdb.pools.get(poolAlias);
|
|
745
|
-
await this.closePoolQuietly(pool);
|
|
746
|
-
dmdb.pools?.delete?.(poolAlias);
|
|
747
|
-
}
|
|
748
|
-
async closePoolQuietly(pool) {
|
|
749
|
-
try {
|
|
750
|
-
await this.withTimeout(pool.close(0), RESOURCE_CLEANUP_TIMEOUT_MS, "Dameng pool close");
|
|
751
|
-
} catch {
|
|
752
|
-
if (pool.poolAlias) {
|
|
753
|
-
dmdb.pools?.delete?.(pool.poolAlias);
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
async resolveSchema(schema) {
|
|
758
|
-
const resolved = schema || this.defaultSchema || await this.getDefaultSchema();
|
|
759
|
-
if (!resolved) {
|
|
760
|
-
throw new Error("No Dameng schema specified and current schema could not be resolved");
|
|
761
|
-
}
|
|
762
|
-
return this.normalizeIdentifier(resolved);
|
|
763
|
-
}
|
|
764
|
-
normalizeIdentifier(identifier) {
|
|
765
|
-
return /[a-z]/.test(identifier) ? identifier.toUpperCase() : identifier;
|
|
766
|
-
}
|
|
767
|
-
normalizeLikePattern(pattern) {
|
|
768
|
-
return /[a-z]/.test(pattern) ? pattern.toUpperCase() : pattern;
|
|
769
|
-
}
|
|
770
|
-
normalizeLimit(limit) {
|
|
771
|
-
return Math.max(1, Math.min(1e3, Math.floor(limit)));
|
|
772
|
-
}
|
|
773
|
-
normalizeRows(rows) {
|
|
774
|
-
return rows.map((row) => {
|
|
775
|
-
if (!Array.isArray(row)) {
|
|
776
|
-
return row;
|
|
777
|
-
}
|
|
778
|
-
return row;
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
rowValue(row, key) {
|
|
782
|
-
if (!row) {
|
|
783
|
-
return null;
|
|
784
|
-
}
|
|
785
|
-
return row[key] ?? row[key.toLowerCase()] ?? row[key.toUpperCase()] ?? null;
|
|
786
|
-
}
|
|
787
|
-
isPresent(value) {
|
|
788
|
-
return value !== null && value !== "";
|
|
789
|
-
}
|
|
790
|
-
formatDataType(row) {
|
|
791
|
-
const dataType = this.rowValue(row, "DATA_TYPE") ?? "";
|
|
792
|
-
const precision = this.rowValue(row, "DATA_PRECISION");
|
|
793
|
-
const scale = this.rowValue(row, "DATA_SCALE");
|
|
794
|
-
const length = this.rowValue(row, "DATA_LENGTH");
|
|
795
|
-
if (precision !== null && precision !== void 0) {
|
|
796
|
-
return scale !== null && scale !== void 0 ? `${dataType}(${precision},${scale})` : `${dataType}(${precision})`;
|
|
797
|
-
}
|
|
798
|
-
if (length !== null && length !== void 0 && /CHAR|VARCHAR|BINARY/i.test(dataType)) {
|
|
799
|
-
return `${dataType}(${length})`;
|
|
800
|
-
}
|
|
801
|
-
return dataType;
|
|
802
|
-
}
|
|
803
|
-
toBindParams(values) {
|
|
804
|
-
return values.map((value) => ({ val: value }));
|
|
805
|
-
}
|
|
806
|
-
applyMaxRows(sql, maxRows) {
|
|
807
|
-
if (!maxRows) {
|
|
808
|
-
return sql;
|
|
809
|
-
}
|
|
810
|
-
const cleaned = stripCommentsAndStrings(sql, "dameng").trim().toLowerCase();
|
|
811
|
-
if (!cleaned.startsWith("select")) {
|
|
812
|
-
return sql;
|
|
813
|
-
}
|
|
814
|
-
const trimmed = sql.trim();
|
|
815
|
-
const withoutSemicolon = trimmed.endsWith(";") ? trimmed.slice(0, -1) : trimmed;
|
|
816
|
-
return `SELECT * FROM (${withoutSemicolon}) WHERE ROWNUM <= ${maxRows}`;
|
|
817
|
-
}
|
|
818
|
-
replacePositionalParameters(sql, parameters) {
|
|
819
|
-
if (!parameters.length) {
|
|
820
|
-
return { sql, bindValues: [] };
|
|
821
|
-
}
|
|
822
|
-
let index = 0;
|
|
823
|
-
let result = "";
|
|
824
|
-
let i = 0;
|
|
825
|
-
while (i < sql.length) {
|
|
826
|
-
const char = sql[i];
|
|
827
|
-
const next = sql[i + 1];
|
|
828
|
-
if (char === "'") {
|
|
829
|
-
const start = i++;
|
|
830
|
-
while (i < sql.length) {
|
|
831
|
-
if (sql[i] === "'" && sql[i + 1] === "'") {
|
|
832
|
-
i += 2;
|
|
833
|
-
} else if (sql[i] === "'") {
|
|
834
|
-
i++;
|
|
835
|
-
break;
|
|
836
|
-
} else {
|
|
837
|
-
i++;
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
result += sql.slice(start, i);
|
|
841
|
-
continue;
|
|
842
|
-
}
|
|
843
|
-
if (char === '"') {
|
|
844
|
-
const start = i++;
|
|
845
|
-
while (i < sql.length) {
|
|
846
|
-
if (sql[i] === '"' && sql[i + 1] === '"') {
|
|
847
|
-
i += 2;
|
|
848
|
-
} else if (sql[i] === '"') {
|
|
849
|
-
i++;
|
|
850
|
-
break;
|
|
851
|
-
} else {
|
|
852
|
-
i++;
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
result += sql.slice(start, i);
|
|
856
|
-
continue;
|
|
857
|
-
}
|
|
858
|
-
if (char === "-" && next === "-") {
|
|
859
|
-
const start = i;
|
|
860
|
-
i += 2;
|
|
861
|
-
while (i < sql.length && sql[i] !== "\n") {
|
|
862
|
-
i++;
|
|
863
|
-
}
|
|
864
|
-
result += sql.slice(start, i);
|
|
865
|
-
continue;
|
|
866
|
-
}
|
|
867
|
-
if (char === "/" && next === "*") {
|
|
868
|
-
const start = i;
|
|
869
|
-
i += 2;
|
|
870
|
-
while (i < sql.length && !(sql[i] === "*" && sql[i + 1] === "/")) {
|
|
871
|
-
i++;
|
|
872
|
-
}
|
|
873
|
-
i = i < sql.length ? i + 2 : i;
|
|
874
|
-
result += sql.slice(start, i);
|
|
875
|
-
continue;
|
|
876
|
-
}
|
|
877
|
-
if (char === "?") {
|
|
878
|
-
index += 1;
|
|
879
|
-
result += `:${index}`;
|
|
880
|
-
i++;
|
|
881
|
-
continue;
|
|
882
|
-
}
|
|
883
|
-
result += char;
|
|
884
|
-
i++;
|
|
885
|
-
}
|
|
886
|
-
if (index !== parameters.length) {
|
|
887
|
-
throw new Error(
|
|
888
|
-
`Parameter count mismatch: SQL statement has ${index} parameter(s), but ${parameters.length} value(s) were provided.`
|
|
889
|
-
);
|
|
890
|
-
}
|
|
891
|
-
return { sql: result, bindValues: parameters };
|
|
892
|
-
}
|
|
893
|
-
};
|
|
894
|
-
var damengConnector = new DamengConnector();
|
|
895
|
-
ConnectorRegistry.register(damengConnector);
|
|
896
|
-
export {
|
|
897
|
-
DamengConnector
|
|
898
|
-
};
|