Skip to content

Commit 541bcfa

Browse files
authored
Merge pull request #319 from Canner/fix/duckdb-connection-pool-initialization-issue
Fix DuckDB Connection Pool Initialization Issue
2 parents 10ca6f7 + dda3aa8 commit 541bcfa

File tree

3 files changed

+61
-35
lines changed

3 files changed

+61
-35
lines changed

packages/extension-driver-duckdb/src/lib/duckdbDataSource.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,13 @@ export class DuckDBDataSource extends DataSource<any, DuckDBOptions> {
104104
// create new connection for each query
105105
const parameters = Array.from(bindParams.values());
106106
this.logRequest(firstDataSQL, parameters, options);
107-
const connection = db.connect();
108-
await this.loadExtensions(connection, configurationParameters);
109-
await this.setExecConfig(connection);
110107
if (restDataSQL) this.logRequest(restDataSQL, parameters, options);
111108
const [firstData, restDataStream] = await this.acquireData(
112109
firstDataSQL,
113110
restDataSQL,
114111
parameters,
115-
db
112+
db,
113+
configurationParameters
116114
);
117115
const readable = this.createReadableStream(firstData, restDataStream);
118116
return {
@@ -168,15 +166,24 @@ export class DuckDBDataSource extends DataSource<any, DuckDBOptions> {
168166
firstDataSql: string,
169167
restDataSql: string | undefined,
170168
parameters: any[],
171-
db: duckdb.Database
169+
db: duckdb.Database,
170+
configurationParameters: ConfigurationParameters
172171
) {
173172
// conn.all() is faster then stream.checkChunk().
174173
// For the small size data we use conn.all() to get the data at once
175174
// To limit memory use and prevent server crashes, we will use conn.all() to acquire the initial chunk of data, then conn.stream() to receive the remainder of the data.
175+
const c1 = db.connect();
176+
const c2 = db.connect();
177+
await Promise.all([
178+
await this.loadExtensions(c1, configurationParameters),
179+
await this.setExecConfig(c1),
180+
await this.loadExtensions(c2, configurationParameters),
181+
await this.setExecConfig(c2),
182+
]);
183+
176184
return await Promise.all([
177185
new Promise<duckdb.TableData>((resolve, reject) => {
178-
const c = db.connect();
179-
c.all(
186+
c1.all(
180187
firstDataSql,
181188
...parameters,
182189
(err: duckdb.DuckDbError | null, res: duckdb.TableData) => {
@@ -190,8 +197,7 @@ export class DuckDBDataSource extends DataSource<any, DuckDBOptions> {
190197
new Promise<duckdb.QueryResult | undefined>((resolve, reject) => {
191198
if (!restDataSql) resolve(undefined);
192199
try {
193-
const c = db.connect();
194-
const result = c.stream(restDataSql, ...parameters);
200+
const result = c2.stream(restDataSql, ...parameters);
195201
resolve(result);
196202
} catch (err: any) {
197203
reject(err);

packages/extension-driver-duckdb/src/lib/duckdbExtensionLoader.ts

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -37,36 +37,51 @@ export class DuckDBExtensionLoader {
3737
return;
3838
}
3939
try {
40-
conn.run(`LOAD ${extensionName}`);
40+
await new Promise<void>((resolve, reject) => {
41+
conn.run(`LOAD ${extensionName}`, (err: any) => {
42+
if (err) reject(err);
43+
this.logger.debug('Extension loaded');
44+
resolve();
45+
});
46+
});
4147
} catch (error) {
4248
this.logger.debug(`Error when loading extension:${extensionName}`);
4349
throw error;
4450
}
51+
await Promise.all(
52+
Object.entries(extensionConfigurations).map(
53+
async ([dbParameterName, configurationKey]) => {
54+
const configurationValue =
55+
this.configurations[
56+
configurationKey as keyof ConfigurationParameters
57+
];
58+
// if configuration is not undefined
59+
if (configurationValue !== undefined) {
60+
return await new Promise<void>((resolve, reject) => {
61+
conn.run(
62+
`SET ${dbParameterName}='${configurationValue}'`,
63+
(err: any) => {
64+
if (err) {
65+
this.logger.debug(
66+
`Configuration error "${dbParameterName}": ${err}`
67+
);
68+
reject(err);
69+
}
4570

46-
Object.entries(extensionConfigurations).forEach(
47-
([dbParameterName, configurationKey]) => {
48-
const configurationValue =
49-
this.configurations[
50-
configurationKey as keyof ConfigurationParameters
51-
];
52-
// if configuration is not undefined
53-
if (configurationValue !== undefined) {
54-
conn.run(
55-
`SET ${dbParameterName}='${configurationValue}'`,
56-
(err: any) => {
57-
if (err) throw err;
58-
this.logger.debug(
59-
`Configuration error "${dbParameterName}": ${err}`
71+
this.logger.debug(
72+
`Configuration parameter "${dbParameterName}" set`
73+
);
74+
resolve();
75+
}
6076
);
61-
}
62-
);
63-
this.logger.debug(`Configuration parameter "${dbParameterName}" set`);
64-
} else {
65-
this.logger.debug(
66-
`Configuration "${dbParameterName}" has not been set`
67-
);
77+
});
78+
} else {
79+
this.logger.debug(
80+
`Configuration "${dbParameterName}" has not been set`
81+
);
82+
}
6883
}
69-
}
84+
)
7085
);
7186
}
7287
}

packages/extension-driver-duckdb/tests/duckdbDataSource.spec.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,9 @@ it('Should print queries without binding when log-queries = true', async () => {
316316
profileName: 'mocked-profile',
317317
});
318318
// Assert
319-
expect(/select \$1::INTEGER as test/.test(logs.slice(-1)[0][0])).toBe(true);
319+
expect(
320+
logs.flat(2).find((log) => /select \$1::INTEGER as test/.test(log))
321+
).not.toBe(undefined);
320322
});
321323

322324
it('Should print queries with binding when log-queries = true and log-parameters = true', async () => {
@@ -357,8 +359,11 @@ it('Should print queries with binding when log-queries = true and log-parameters
357359
profileName: 'mocked-profile',
358360
});
359361
// Assert
360-
expect(/select \$1::INTEGER as test/.test(logs.slice(-1)[0][0])).toBe(true);
361-
expect(logs.slice(-1)[0][1]).toEqual([1234]);
362+
expect(
363+
logs.flat(2).find((log) => /select \$1::INTEGER as test/.test(log))
364+
).not.toBe(undefined);
365+
366+
expect(logs.flat(2)).toContain(1234);
362367
});
363368

364369
it('Should share db instances for same path besides in-memory only db', async () => {

0 commit comments

Comments
 (0)