Skip to content

Commit 134087b

Browse files
committed
feat: support Apache Doris datasource
1 parent 5f513eb commit 134087b

File tree

7 files changed

+60
-6
lines changed

7 files changed

+60
-6
lines changed

backend/apps/datasource/crud/datasource.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ def preview(session: SessionDep, current_user: CurrentUser, id: int, data: Table
267267

268268
conf = DatasourceConf(**json.loads(aes_decrypt(ds.configuration))) if ds.type != "excel" else get_engine_config()
269269
sql: str = ""
270-
if ds.type == "mysql":
270+
if ds.type == "mysql" or ds.type == "doris":
271271
sql = f"""SELECT `{"`, `".join(fields)}` FROM `{data.table.table_name}`
272272
{where}
273273
LIMIT 100"""

backend/apps/db/constant.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class DB(Enum):
2020
oracle = ('oracle', '"', '"', ConnectType.sqlalchemy)
2121
ck = ('ck', '"', '"', ConnectType.sqlalchemy)
2222
dm = ('dm', '"', '"', ConnectType.py_driver)
23+
doris = ('doris', '`', '`', ConnectType.py_driver)
2324

2425
def __init__(self, type, prefix, suffix, connect_type: ConnectType):
2526
self.type = type

backend/apps/db/db.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
if platform.system() != "Darwin":
1010
import dmPython
11+
import pymysql
1112
from sqlalchemy import create_engine, text, Engine
1213
from sqlalchemy.orm import sessionmaker
1314

@@ -125,6 +126,19 @@ def check_connection(trans: Trans, ds: CoreDatasource, is_raise: bool = False):
125126
if is_raise:
126127
raise HTTPException(status_code=500, detail=trans('i18n_ds_invalid') + f': {e.args}')
127128
return False
129+
elif ds.type == 'doris':
130+
with pymysql.connect(user=conf.username, passwd=conf.password, host=conf.host,
131+
port=conf.port, db=conf.database, connect_timeout=10,
132+
read_timeout=10) as conn, conn.cursor() as cursor:
133+
try:
134+
cursor.execute('select 1')
135+
SQLBotLogUtil.info("success")
136+
return True
137+
except Exception as e:
138+
SQLBotLogUtil.error(f"Datasource {ds.id} connection failed: {e}")
139+
if is_raise:
140+
raise HTTPException(status_code=500, detail=trans('i18n_ds_invalid') + f': {e.args}')
141+
return False
128142

129143

130144
def get_schema(ds: CoreDatasource):
@@ -171,6 +185,14 @@ def get_tables(ds: CoreDatasource):
171185
res = cursor.fetchall()
172186
res_list = [TableSchema(*item) for item in res]
173187
return res_list
188+
elif ds.type == 'doris':
189+
with pymysql.connect(user=conf.username, passwd=conf.password, host=conf.host,
190+
port=conf.port, db=conf.database, connect_timeout=conf.timeout,
191+
read_timeout=conf.timeout) as conn, conn.cursor() as cursor:
192+
cursor.execute(sql)
193+
res = cursor.fetchall()
194+
res_list = [TableSchema(*item) for item in res]
195+
return res_list
174196

175197

176198
def get_fields(ds: CoreDatasource, table_name: str = None):
@@ -191,6 +213,14 @@ def get_fields(ds: CoreDatasource, table_name: str = None):
191213
res = cursor.fetchall()
192214
res_list = [ColumnSchema(*item) for item in res]
193215
return res_list
216+
elif ds.type == 'doris':
217+
with pymysql.connect(user=conf.username, passwd=conf.password, host=conf.host,
218+
port=conf.port, db=conf.database, connect_timeout=conf.timeout,
219+
read_timeout=conf.timeout) as conn, conn.cursor() as cursor:
220+
cursor.execute(sql)
221+
res = cursor.fetchall()
222+
res_list = [ColumnSchema(*item) for item in res]
223+
return res_list
194224

195225

196226
def exec_sql(ds: CoreDatasource | AssistantOutDsSchema, sql: str, origin_column=False):
@@ -233,3 +263,22 @@ def exec_sql(ds: CoreDatasource | AssistantOutDsSchema, sql: str, origin_column=
233263
"sql": bytes.decode(base64.b64encode(bytes(sql, 'utf-8')))}
234264
except Exception as ex:
235265
raise ex
266+
elif ds.type == 'doris':
267+
with pymysql.connect(user=conf.username, passwd=conf.password, host=conf.host,
268+
port=conf.port, db=conf.database, connect_timeout=conf.timeout,
269+
read_timeout=conf.timeout) as conn, conn.cursor() as cursor:
270+
try:
271+
cursor.execute(sql)
272+
res = cursor.fetchall()
273+
columns = [field[0] for field in cursor.description] if origin_column else [field[0].lower() for
274+
field in
275+
cursor.description]
276+
result_list = [
277+
{str(columns[i]): float(value) if isinstance(value, Decimal) else value for i, value in
278+
enumerate(tuple_item)}
279+
for tuple_item in res
280+
]
281+
return {"fields": columns, "data": result_list,
282+
"sql": bytes.decode(base64.b64encode(bytes(sql, 'utf-8')))}
283+
except Exception as ex:
284+
raise ex

backend/apps/db/db_sql.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55

66
def get_table_sql(ds: CoreDatasource, conf: DatasourceConf):
7-
if ds.type == "mysql":
7+
if ds.type == "mysql" or ds.type == "doris":
88
return f"""
99
SELECT
1010
TABLE_NAME,
@@ -31,15 +31,15 @@ def get_table_sql(ds: CoreDatasource, conf: DatasourceConf):
3131
AND t.TABLE_SCHEMA = '{conf.dbSchema}'
3232
"""
3333
elif ds.type == "pg" or ds.type == "excel":
34-
return """
34+
return f"""
3535
SELECT c.relname AS TABLE_NAME,
3636
COALESCE(d.description, obj_description(c.oid)) AS TABLE_COMMENT
3737
FROM pg_class c
3838
LEFT JOIN
3939
pg_namespace n ON n.oid = c.relnamespace
4040
LEFT JOIN
4141
pg_description d ON d.objoid = c.oid AND d.objsubid = 0
42-
WHERE n.nspname = current_schema()
42+
WHERE n.nspname = '{conf.dbSchema}'
4343
AND c.relkind IN ('r', 'v', 'p', 'm')
4444
AND c.relname NOT LIKE 'pg_%'
4545
AND c.relname NOT LIKE 'sql_%'
@@ -83,7 +83,7 @@ def get_table_sql(ds: CoreDatasource, conf: DatasourceConf):
8383

8484

8585
def get_field_sql(ds: CoreDatasource, conf: DatasourceConf, table_name: str = None):
86-
if ds.type == "mysql":
86+
if ds.type == "mysql" or ds.type == "doris":
8787
sql1 = f"""
8888
SELECT
8989
COLUMN_NAME,

backend/apps/db/type.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ def db_type_relation() -> Dict:
1111
"excel": "Excel/CSV",
1212
"oracle": "Oracle",
1313
"ck": "ClickHouse",
14-
"dm": "达梦"
14+
"dm": "达梦",
15+
"doris": "Apache Doris"
1516
}
597 Bytes
Loading

frontend/src/views/ds/js/ds-type.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import pg from '@/assets/datasource/icon_PostgreSQL.png'
55
import sqlServer from '@/assets/datasource/icon_SQL_Server.png'
66
import ck from '@/assets/datasource/icon_ck.png'
77
import dm from '@/assets/datasource/icon_dm.png'
8+
import doris from '@/assets/datasource/icon_doris.png'
89
import { i18n } from '@/i18n'
910

1011
const t = i18n.global.t
@@ -16,6 +17,7 @@ export const dsType = [
1617
{ label: 'SQL Server', value: 'sqlServer' },
1718
{ label: 'ClickHouse', value: 'ck' },
1819
{ label: '达梦', value: 'dm' },
20+
{ label: 'Apache Doris', value: 'doris' },
1921
]
2022

2123
export const dsTypeWithImg = [
@@ -26,6 +28,7 @@ export const dsTypeWithImg = [
2628
{ name: 'SQL Server', type: 'sqlServer', img: sqlServer },
2729
{ name: 'ClickHouse', type: 'ck', img: ck },
2830
{ name: '达梦', type: 'dm', img: dm },
31+
{ name: 'Apache Doris', type: 'doris', img: doris },
2932
]
3033

3134
export const haveSchema = ['sqlServer', 'pg', 'oracle', 'dm']

0 commit comments

Comments
 (0)