Skip to content

Commit 224129a

Browse files
mat02ludomikula
authored andcommitted
Add FirebirdSQL data source
1 parent 875bfa9 commit 224129a

File tree

9 files changed

+233
-0
lines changed

9 files changed

+233
-0
lines changed

server/node-service/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
"@types/node-fetch": "^2.6.2",
4949
"axios": "^1.2.0",
5050
"base64-arraybuffer": "^1.0.2",
51+
"bluebird": "^3.7.2",
52+
"duckdb-async": "^0.10.0",
5153
"dynamodb-data-types": "^4.0.1",
5254
"express": "^4.18.2",
5355
"express-async-errors": "^3.1.1",
@@ -62,6 +64,7 @@
6264
"lowcoder-sdk": "0.0.41",
6365
"morgan": "^1.10.0",
6466
"node-fetch": "2",
67+
"node-firebird": "^1.1.9",
6568
"openapi-types": "^12.1.0",
6669
"pino": "^8.14.1",
6770
"prom-client": "^14.2.0",
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { ConfigToType } from "lowcoder-sdk/dataSource";
2+
import { FirebirdI18nTranslator } from "./i18n";
3+
4+
const getDataSourceConfig = (i18n: FirebirdI18nTranslator) => {
5+
const dataSourceConfig = {
6+
type: "dataSource",
7+
params: [
8+
{
9+
key: "host",
10+
label: "Host Address",
11+
type: "textInput",
12+
placeholder: "<FQDN or IP address>",
13+
rules: [{ required: true, message: i18n.trans("hostRequiredMessage") }],
14+
},
15+
{
16+
key: "database",
17+
label: "Database name",
18+
type: "textInput",
19+
placeholder: "database.fdb",
20+
rules: [{ required: true, message: i18n.trans("dbnameRequiredMessage") }],
21+
},
22+
{
23+
key: "port",
24+
label: i18n.trans("port"),
25+
type: "numberInput",
26+
defaultValue: 3050,
27+
rules: [{ required: true, message: i18n.trans("portRequiredMessage") }],
28+
},
29+
{
30+
key: "username",
31+
label: i18n.trans("username"),
32+
type: "textInput",
33+
defaultValue: "SYSDBA",
34+
rules: [{ required: true, message: i18n.trans("usernameRequiredMessage") }],
35+
},
36+
{
37+
key: "password",
38+
label: i18n.trans("password"),
39+
type: "password",
40+
defaultValue: "masterkey",
41+
},
42+
{
43+
key: "role",
44+
label: i18n.trans("role"),
45+
type: "textInput",
46+
defaultValue: "",
47+
},
48+
{
49+
key: "lowercaseKeys",
50+
label: i18n.trans("lowercaseKeys"),
51+
type: "checkbox",
52+
defaultValue: true,
53+
},
54+
{
55+
key: "blobAsText",
56+
label: i18n.trans("blobAsText"),
57+
type: "checkbox",
58+
defaultValue: true,
59+
},
60+
],
61+
} as const;
62+
return dataSourceConfig;
63+
};
64+
65+
export default getDataSourceConfig;
66+
67+
export type DataSourceDataType = ConfigToType<ReturnType<typeof getDataSourceConfig>>;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export const en = {
2+
name: "FirebirdSQL",
3+
description: "Support for FirebirdSQL database",
4+
dbnameRequiredMessage: "Please input the database name and/or path",
5+
hostRequiredMessage: "Please input the Host address",
6+
usernameRequiredMessage: "Please input the Username",
7+
portRequiredMessage: "Please specify the Port number",
8+
username: "Username",
9+
password: "Password",
10+
role: "Connection Role",
11+
port: "Port",
12+
lowercaseKeys: "User lowerkeys keys",
13+
blobAsText: "Get blob as text, only affects blob subtype 1",
14+
15+
actions: "Actions",
16+
actionName: "SQL Query",
17+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { en } from "./en";
2+
import { I18n } from "../../../common/i18n";
3+
4+
export default function getI18nTranslator(languages: string[]) {
5+
return new I18n<typeof en>({ en }, languages);
6+
}
7+
8+
export type FirebirdI18nTranslator = ReturnType<typeof getI18nTranslator>;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { DataSourcePluginFactory, PluginContext } from "lowcoder-sdk/dataSource";
2+
import getDataSourceConfig, { DataSourceDataType } from "./dataSourceConfig";
3+
import getQueryConfig, { ActionDataType } from "./queryConfig";
4+
import getI18nTranslator from "./i18n";
5+
import run, { validateDataSourceConfig } from "./run";
6+
7+
const firebirdsqlPlugin: DataSourcePluginFactory = (context: PluginContext) => {
8+
const i18n = getI18nTranslator(context.languages);
9+
return {
10+
id: "firebird",
11+
name: i18n.trans("name"),
12+
icon: "firebirdsql.svg",
13+
description: i18n.trans("description"),
14+
category: "database",
15+
dataSourceConfig: getDataSourceConfig(i18n),
16+
queryConfig: getQueryConfig(i18n),
17+
18+
validateDataSourceConfig: async (dataSourceConfig: DataSourceDataType) => {
19+
return validateDataSourceConfig(dataSourceConfig);
20+
},
21+
22+
run: async (
23+
action: ActionDataType,
24+
dataSourceConfig: DataSourceDataType,
25+
ctx: PluginContext
26+
) => {
27+
const i18n = getI18nTranslator(ctx.languages);
28+
try {
29+
return await run(action, dataSourceConfig, i18n);
30+
} catch (e) {
31+
throw e;
32+
}
33+
},
34+
};
35+
};
36+
37+
export default firebirdsqlPlugin;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { ConfigToType } from "lowcoder-sdk/dataSource";
2+
import { FirebirdI18nTranslator } from "./i18n";
3+
4+
function getQueryConfig(i18n: FirebirdI18nTranslator) {
5+
const queryConfig = {
6+
type: "query",
7+
label: i18n.trans("actions"),
8+
actions: [
9+
{
10+
actionName: "Query",
11+
label: "Query",
12+
params: [
13+
{
14+
label: i18n.trans("actionName"),
15+
key: "sql",
16+
type: "sqlInput",
17+
},
18+
],
19+
},
20+
],
21+
} as const;
22+
return queryConfig;
23+
}
24+
25+
export type ActionDataType = ConfigToType<ReturnType<typeof getQueryConfig>>;
26+
27+
export default getQueryConfig;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { DataSourceDataType } from "./dataSourceConfig";
2+
import { ActionDataType } from "./queryConfig";
3+
import { FirebirdI18nTranslator } from "./i18n";
4+
import _ from "lodash";
5+
import Firebird from "node-firebird";
6+
7+
// @ts-ignore
8+
import { promisifyAll } from 'bluebird';
9+
const fbdAsync: any = promisifyAll(Firebird);
10+
11+
function getFirebirdOptions(params: DataSourceDataType) {
12+
const options = {
13+
host: params.host.trim(),
14+
port: params.port,
15+
database: params.database.trim(),
16+
user: params.username.trim(),
17+
password: params.password,
18+
lowercase_keys: params.lowercaseKeys, // set to true to lowercase keys
19+
role: _.isEmpty(_.isString(params.role) ? params.role.trim() : null) ? null : params.role.trim(),
20+
pageSize: 4096, // default when creating database
21+
retryConnectionInterval: 1000, // reconnect interval in case of connection drop
22+
blobAsText: params.blobAsText, // set to true to get blob as text, only affects blob subtype 1
23+
encoding: 'UTF8', // default encoding for connection is UTF-8
24+
};
25+
return options;
26+
}
27+
28+
export async function validateDataSourceConfig(dataSourceConfig: DataSourceDataType) {
29+
try {
30+
let db = await fbdAsync.attachAsync(getFirebirdOptions(dataSourceConfig));
31+
promisifyAll(db);
32+
let result = await db.queryAsync("SELECT 1 FROM RDB$DATABASE;");
33+
db.detachAsync();
34+
return {
35+
success: true,
36+
};
37+
} catch (e) {
38+
throw e;
39+
}
40+
}
41+
42+
export default async function run(action: ActionDataType, dataSourceConfig: DataSourceDataType, i18n: FirebirdI18nTranslator) {
43+
if (action.actionName === "Query") {
44+
let db = await fbdAsync.attachAsync(getFirebirdOptions(dataSourceConfig));
45+
promisifyAll(db);
46+
const results = await db.queryAsync(action.sql);
47+
db.detachAsync();
48+
return results;
49+
}
50+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import tursoPlugin from "./turso";
3737
import postmanEchoPlugin from "./postmanEcho";
3838
import lowcoderPlugin from "./lowcoder";
3939
import supabaseApiPlugin from "./supabaseApi";
40+
import firebirdsqlPlugin from "./firebirdsql";
4041

4142
let plugins: (DataSourcePlugin | DataSourcePluginFactory)[] = [
4243

@@ -46,6 +47,7 @@ let plugins: (DataSourcePlugin | DataSourcePluginFactory)[] = [
4647
// duckdbPlugin,
4748
faunaPlugin,
4849
tursoPlugin,
50+
firebirdsqlPlugin,
4951

5052
// Big Data
5153
athenaPlugin,
Lines changed: 22 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)