Skip to content

Commit 1a7bbf0

Browse files
authored
Merge pull request #808 from Youssef-Harby/plugin-duckdb
Plugin-duckdb
2 parents 3ecf1ac + a1cc052 commit 1a7bbf0

File tree

7 files changed

+266
-5
lines changed

7 files changed

+266
-5
lines changed

server/node-service/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"@types/node-fetch": "^2.6.2",
4949
"axios": "^1.2.0",
5050
"base64-arraybuffer": "^1.0.2",
51+
"duckdb-async": "^0.10.0",
5152
"dynamodb-data-types": "^4.0.1",
5253
"express": "^4.18.2",
5354
"express-async-errors": "^3.1.1",
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// @server/node-service/src/plugins/duckdb/dataSourceConfig.ts
2+
import { ConfigToType } from "lowcoder-sdk/dataSource";
3+
4+
const dataSourceConfig = {
5+
type: "dataSource",
6+
params: [
7+
{
8+
key: "databaseFile",
9+
type: "textInput",
10+
label: "Database File",
11+
rules: [{ required: true, message: "Please provide a database file path 'db.duckdb' or ':memory:' for an in-memory database" }],
12+
tooltip: "Please provide a database file path 'db.duckdb' or ':memory:' for an in-memory database",
13+
defaultValue: ":memory:",
14+
},
15+
{
16+
key: "options",
17+
type: "textInput",
18+
label: "Database Options",
19+
tooltip: "Additional options to pass to the DuckDB constructor (in JSON format)",
20+
defaultValue: `{"access_mode": "READ_WRITE","max_memory": "512MB","threads": "4"}`,
21+
},
22+
],
23+
} as const;
24+
25+
export default dataSourceConfig;
26+
27+
export type DataSourceDataType = ConfigToType<typeof dataSourceConfig>;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { DataSourcePlugin } from "lowcoder-sdk/dataSource";
2+
import dataSourceConfig, { DataSourceDataType } from "./dataSourceConfig";
3+
import queryConfig, { ActionDataType } from "./queryConfig";
4+
import { Database } from "duckdb-async";
5+
import { ServiceError } from "../../common/error";
6+
7+
// Helper function to handle BigInt serialization
8+
function serializeBigInts(row: any): any {
9+
const newRow: { [key: string]: any } = {}; // Add index signature
10+
for (const [key, value] of Object.entries(row)) {
11+
newRow[key] = typeof value === 'bigint' ? value.toString() : value;
12+
}
13+
return newRow;
14+
}
15+
16+
const duckdbPlugin: DataSourcePlugin<ActionDataType, DataSourceDataType> = {
17+
id: "duckdb",
18+
name: "DuckDB",
19+
category: "database",
20+
icon: "duckdb.svg",
21+
dataSourceConfig,
22+
queryConfig,
23+
run: async function (actionData, dataSourceConfig): Promise<any> {
24+
const { databaseFile, options } = dataSourceConfig;
25+
const parsedOptions = JSON.parse(options);
26+
const db = await Database.create(databaseFile, parsedOptions);
27+
28+
if (actionData.actionName === "Query") {
29+
try {
30+
const result = await db.all(actionData.queryString);
31+
// Apply BigInt serialization to each row
32+
return result.map(serializeBigInts);
33+
} catch (error) {
34+
throw new ServiceError((error as Error).message);
35+
} finally {
36+
await db.close();
37+
}
38+
}
39+
},
40+
};
41+
42+
export default duckdbPlugin;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// @server/node-service/src/plugins/duckdb/queryConfig.ts
2+
import { ConfigToType } from "lowcoder-sdk/dataSource";
3+
4+
const queryConfig = {
5+
type: "query",
6+
label: "Action",
7+
actions: [
8+
{
9+
actionName: "Query",
10+
label: "Query",
11+
params: [
12+
{
13+
label: "Query String",
14+
key: "queryString",
15+
type: "sqlInput",
16+
},
17+
],
18+
},
19+
],
20+
} as const;
21+
22+
export type ActionDataType = ConfigToType<typeof queryConfig>;
23+
24+
export default queryConfig;

server/node-service/src/plugins/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import couchdbPlugin from "./couchdb";
88
import wooCommercePlugin from "./woocommerce";
99
import openAiPlugin from "./openAi";
1010
import athenaPlugin from "./athena";
11+
import duckdbPlugin from "./duckdb";
1112
import lambdaPlugin from "./lambda";
1213
import googleCloudStorage from "./googleCloudStorage";
1314
import stripePlugin from "./stripe";
@@ -43,6 +44,7 @@ let plugins: (DataSourcePlugin | DataSourcePluginFactory)[] = [
4344
wooCommercePlugin,
4445
openAiPlugin,
4546
athenaPlugin,
47+
duckdbPlugin,
4648
lambdaPlugin,
4749
googleCloudStorage,
4850
stripePlugin,
@@ -72,6 +74,6 @@ let plugins: (DataSourcePlugin | DataSourcePluginFactory)[] = [
7274
try {
7375
plugins = require("../ee/plugins").default;
7476
console.info("using ee plugins");
75-
} catch {}
77+
} catch { }
7678

7779
export default plugins;
Lines changed: 31 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)