Skip to content

Commit aa2b7b7

Browse files
committed
default duckdb_api config
1 parent e22ace1 commit aa2b7b7

File tree

4 files changed

+103
-16
lines changed

4 files changed

+103
-16
lines changed

api/src/DuckDBInstance.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ export class DuckDBInstance {
1010
path?: string,
1111
options?: Record<string, string>
1212
): Promise<DuckDBInstance> {
13+
const config = duckdb.create_config();
14+
// Set the default duckdb_api value for the api. Can be overridden.
15+
duckdb.set_config(config, 'duckdb_api', 'node-neo-api');
1316
if (options) {
14-
const config = duckdb.create_config();
1517
for (const optionName in options) {
1618
const optionValue = String(options[optionName]);
1719
duckdb.set_config(config, optionName, optionValue);
1820
}
19-
return new DuckDBInstance(await duckdb.open(path, config));
20-
} else {
21-
return new DuckDBInstance(await duckdb.open(path));
2221
}
22+
return new DuckDBInstance(await duckdb.open(path, config));
2323
}
2424
public async connect(): Promise<DuckDBConnection> {
2525
return new DuckDBConnection(await duckdb.connect(this.db));

api/test/api.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -973,4 +973,34 @@ describe('api', () => {
973973
assert.deepEqual(rows[4999], [4999, 14999]);
974974
});
975975
});
976+
test('default duckdb_api without explicit options', async () => {
977+
const instance = await DuckDBInstance.create();
978+
const connection = await instance.connect();
979+
const result = await connection.run(`select current_setting('duckdb_api') as duckdb_api`);
980+
assertColumns(result, [{ name: 'duckdb_api', type: DuckDBVarCharType.instance }]);
981+
const chunk = await result.fetchChunk();
982+
assert.strictEqual(chunk.columnCount, 1);
983+
assert.strictEqual(chunk.rowCount, 1);
984+
assertValues<string, DuckDBVarCharVector>(chunk, 0, DuckDBVarCharVector, ['node-neo-api']);
985+
});
986+
test('default duckdb_api with explicit options', async () => {
987+
const instance = await DuckDBInstance.create(undefined, {});
988+
const connection = await instance.connect();
989+
const result = await connection.run(`select current_setting('duckdb_api') as duckdb_api`);
990+
assertColumns(result, [{ name: 'duckdb_api', type: DuckDBVarCharType.instance }]);
991+
const chunk = await result.fetchChunk();
992+
assert.strictEqual(chunk.columnCount, 1);
993+
assert.strictEqual(chunk.rowCount, 1);
994+
assertValues<string, DuckDBVarCharVector>(chunk, 0, DuckDBVarCharVector, ['node-neo-api']);
995+
});
996+
test('overriding duckdb_api', async () => {
997+
const instance = await DuckDBInstance.create(undefined, { 'duckdb_api': 'custom-duckdb-api' });
998+
const connection = await instance.connect();
999+
const result = await connection.run(`select current_setting('duckdb_api') as duckdb_api`);
1000+
assertColumns(result, [{ name: 'duckdb_api', type: DuckDBVarCharType.instance }]);
1001+
const chunk = await result.fetchChunk();
1002+
assert.strictEqual(chunk.columnCount, 1);
1003+
assert.strictEqual(chunk.rowCount, 1);
1004+
assertValues<string, DuckDBVarCharVector>(chunk, 0, DuckDBVarCharVector, ['custom-duckdb-api']);
1005+
});
9761006
});

bindings/src/duckdb_node_bindings.cpp

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#include "duckdb.h"
1111

12+
#define DEFAULT_DUCKDB_API "node-neo-bindings"
13+
1214
// Conversion betweeen structs and objects
1315

1416
Napi::Object MakeDateObject(Napi::Env env, duckdb_date date) {
@@ -495,18 +497,25 @@ class OpenWorker : public PromiseWorker {
495497
if (path_) {
496498
path = path_->c_str();
497499
}
498-
if (config_ != nullptr) {
499-
char *error = nullptr;
500-
if (duckdb_open_ext(path, &database_, config_, &error)) {
501-
if (error != nullptr) {
502-
SetError(error);
503-
duckdb_free(error);
504-
} else {
505-
SetError("Failed to open");
506-
}
500+
duckdb_config cfg = config_;
501+
// If no config was provided, create one with the default duckdb_api value.
502+
if (cfg == nullptr) {
503+
if (duckdb_create_config(&cfg)) {
504+
duckdb_destroy_config(&cfg);
505+
SetError("Failed to create config");
506+
return;
507+
}
508+
if (duckdb_set_config(cfg, "duckdb_api", DEFAULT_DUCKDB_API)) {
509+
SetError("Failed to set duckdb_api");
510+
return;
507511
}
508-
} else {
509-
if (duckdb_open(path, &database_)) {
512+
}
513+
char *error = nullptr;
514+
if (duckdb_open_ext(path, &database_, cfg, &error)) {
515+
if (error != nullptr) {
516+
SetError(error);
517+
duckdb_free(error);
518+
} else {
510519
SetError("Failed to open");
511520
}
512521
}
@@ -1170,6 +1179,10 @@ class DuckDBNodeAddon : public Napi::Addon<DuckDBNodeAddon> {
11701179
duckdb_destroy_config(&config);
11711180
throw Napi::Error::New(env, "Failed to create config");
11721181
}
1182+
// Set the default duckdb_api value for the bindings. Can be overridden.
1183+
if (duckdb_set_config(config, "duckdb_api", DEFAULT_DUCKDB_API)) {
1184+
throw Napi::Error::New(env, "Failed to set duckdb_api");
1185+
}
11731186
return CreateExternalForConfig(env, config);
11741187
}
11751188

bindings/test/config.test.ts

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import duckdb from '@duckdb/node-bindings';
22
import { expect, suite, test } from 'vitest';
3+
import { expectResult } from './utils/expectResult';
4+
import { data } from './utils/expectedVectors';
35

46
suite('config', () => {
57
test('config_count', () => {
@@ -13,8 +15,50 @@ suite('config', () => {
1315
expect(() => duckdb.get_config_flag(-1)).toThrowError(/^Config option not found$/);
1416
});
1517
test('create, set, and destroy', () => {
16-
const config = duckdb.create_config()
18+
const config = duckdb.create_config();
1719
expect(config).toBeTruthy();
1820
duckdb.set_config(config, 'custom_user_agent', 'my_user_agent');
1921
});
22+
test('default duckdb_api without explicit config', async () => {
23+
const db = await duckdb.open();
24+
const connection = await duckdb.connect(db);
25+
const result = await duckdb.query(connection, `select current_setting('duckdb_api') as duckdb_api`);
26+
await expectResult(result, {
27+
columns: [
28+
{ name: 'duckdb_api', logicalType: { typeId: duckdb.Type.VARCHAR } },
29+
],
30+
chunks: [
31+
{ rowCount: 1, vectors: [data(16, [true], ['node-neo-bindings'])]},
32+
],
33+
});
34+
});
35+
test('default duckdb_api with explicit config', async () => {
36+
const config = duckdb.create_config();
37+
const db = await duckdb.open(undefined, config);
38+
const connection = await duckdb.connect(db);
39+
const result = await duckdb.query(connection, `select current_setting('duckdb_api') as duckdb_api`);
40+
await expectResult(result, {
41+
columns: [
42+
{ name: 'duckdb_api', logicalType: { typeId: duckdb.Type.VARCHAR } },
43+
],
44+
chunks: [
45+
{ rowCount: 1, vectors: [data(16, [true], ['node-neo-bindings'])]},
46+
],
47+
});
48+
});
49+
test('overriding duckdb_api', async () => {
50+
const config = duckdb.create_config();
51+
duckdb.set_config(config, 'duckdb_api', 'custom-duckdb-api');
52+
const db = await duckdb.open(undefined, config);
53+
const connection = await duckdb.connect(db);
54+
const result = await duckdb.query(connection, `select current_setting('duckdb_api') as duckdb_api`);
55+
await expectResult(result, {
56+
columns: [
57+
{ name: 'duckdb_api', logicalType: { typeId: duckdb.Type.VARCHAR } },
58+
],
59+
chunks: [
60+
{ rowCount: 1, vectors: [data(16, [true], ['custom-duckdb-api'])]},
61+
],
62+
});
63+
});
2064
});

0 commit comments

Comments
 (0)