Skip to content

Commit 1960fce

Browse files
committed
feat: get tables
1 parent 82408a2 commit 1960fce

File tree

7 files changed

+98
-33
lines changed

7 files changed

+98
-33
lines changed
Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,36 @@
11
from fastapi import APIRouter
2-
from ..crud.datasource import get_datasource_list, check_status, create_ds, update_ds, delete_ds
2+
from ..crud.datasource import get_datasource_list, check_status, create_ds, update_ds, delete_ds, getTables
33
from common.core.deps import SessionDep
44
from ..models.datasource import CoreDatasource
55

66
router = APIRouter(tags=["datasource"], prefix="/datasource")
77

8+
89
@router.get("/list")
910
async def datasource_list(session: SessionDep):
1011
return get_datasource_list(session=session)
1112

13+
1214
@router.post("/check")
1315
async def check(session: SessionDep, ds: CoreDatasource):
1416
return check_status(session, ds)
1517

18+
1619
@router.post("/add", response_model=CoreDatasource)
1720
async def add(session: SessionDep, ds: CoreDatasource):
1821
return create_ds(session, ds)
1922

23+
2024
@router.post("/update", response_model=CoreDatasource)
2125
async def update(session: SessionDep, ds: CoreDatasource):
2226
return update_ds(session, ds)
2327

28+
2429
@router.post("/delete/{id}", response_model=CoreDatasource)
2530
async def delete(session: SessionDep, id: int):
26-
return delete_ds(session, id)
31+
return delete_ds(session, id)
32+
33+
34+
@router.post("/getTables/{id}")
35+
async def get_tables(session: SessionDep, id: int):
36+
return getTables(session, id)

backend/apps/datasource/crud/datasource.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,29 @@
44
from common.core.deps import SessionDep
55
import json
66
from ..utils.utils import aes_decrypt
7-
from apps.db.db import get_connection
7+
from apps.db.db import get_session, get_tables
8+
from sqlalchemy import text
9+
810

911
def get_datasource_list(session: SessionDep) -> CoreDatasource:
1012
statement = select(CoreDatasource).order_by(CoreDatasource.create_time.desc())
1113
datasource_list = session.exec(statement).fetchall()
1214
return datasource_list
1315

16+
1417
def check_status(session: SessionDep, ds: CoreDatasource):
1518
conf = DatasourceConf(**json.loads(aes_decrypt(ds.configuration)))
16-
conn = get_connection(conf)
17-
if conn is not None:
19+
conn = get_session(conf, ds)
20+
try:
21+
conn.execute(text("SELECT 1")).scalar()
22+
print("success")
1823
return True
19-
else:
20-
return False
24+
except Exception as e:
25+
print("Fail:", e)
26+
raise e
27+
finally:
28+
conn.close()
29+
2130

2231
def create_ds(session: SessionDep, ds: CoreDatasource):
2332
ds.create_time = datetime.datetime.now()
@@ -27,6 +36,7 @@ def create_ds(session: SessionDep, ds: CoreDatasource):
2736
session.commit()
2837
return ds
2938

39+
3040
def update_ds(session: SessionDep, ds: CoreDatasource):
3141
ds.id = int(ds.id)
3242
record = session.exec(select(CoreDatasource).where(CoreDatasource.id == ds.id)).first()
@@ -37,10 +47,18 @@ def update_ds(session: SessionDep, ds: CoreDatasource):
3747
session.commit()
3848
return ds
3949

50+
4051
def delete_ds(session: SessionDep, id: int):
4152
term = session.exec(select(CoreDatasource).where(CoreDatasource.id == id)).first()
4253
session.delete(term)
4354
session.commit()
4455
return {
4556
"message": f"Datasource with ID {id} deleted successfully."
46-
}
57+
}
58+
59+
60+
def getTables(session: SessionDep, id: int):
61+
ds = session.exec(select(CoreDatasource).where(CoreDatasource.id == id)).first()
62+
conf = DatasourceConf(**json.loads(aes_decrypt(ds.configuration)))
63+
tables = get_tables(conf, ds)
64+
return tables

backend/apps/datasource/models/datasource.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from datetime import datetime
44
from pydantic import BaseModel
55

6+
67
class CoreDatasource(SQLModel, table=True):
78
__tablename__ = "core_datasource"
89
id: int = Field(sa_column=Column(Integer, Identity(always=True), nullable=False, primary_key=True))
@@ -14,10 +15,20 @@ class CoreDatasource(SQLModel, table=True):
1415
create_by: int = Field(sa_column=Column(BigInteger()))
1516
status: str = Field(max_length=64, nullable=True)
1617

18+
1719
class DatasourceConf(BaseModel):
1820
host: str = ''
1921
port: int = 0
2022
username: str = ''
2123
password: str = ''
2224
database: str = ''
23-
driver: str = ''
25+
driver: str = ''
26+
27+
28+
class TableSchema:
29+
def __init__(self, attr1, attr2):
30+
self.tableName = attr1
31+
self.tableRemark = attr2
32+
33+
tableName: str
34+
tableRemark: str

backend/apps/db/db.py

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,41 @@
1-
import pyodbc
2-
from apps.datasource.models.datasource import DatasourceConf
1+
from sqlalchemy import create_engine, text, Result
2+
from sqlalchemy.orm import sessionmaker
3+
from apps.datasource.models.datasource import DatasourceConf, CoreDatasource, TableSchema
4+
import urllib.parse
5+
from typing import Any
36

4-
def get_connection(conf: DatasourceConf):
5-
conn_str = (
6-
"DRIVER={MySQL ODBC 9.3 Unicode Driver};" # todo driver config
7-
f"SERVER={conf.host};"
8-
f"DATABASE={conf.database};"
9-
f"UID={conf.username};"
10-
f"PWD={conf.password};"
11-
f"PORT={conf.port};"
12-
)
13-
conn = None
14-
try:
15-
conn = pyodbc.connect(conn_str)
16-
print("Connect Success")
17-
return conn
18-
except pyodbc.Error as e:
19-
print(f"Connect Fail:{e}")
20-
raise e
21-
finally:
22-
if conn is not None:
23-
conn.close()
7+
8+
def get_session(conf: DatasourceConf, ds: CoreDatasource):
9+
db_url: str
10+
if ds.type == "mysql":
11+
db_url = f"mysql+pymysql://{urllib.parse.quote(conf.username)}:{urllib.parse.quote(conf.password)}@{conf.host}:{conf.port}/{urllib.parse.quote(conf.database)}"
12+
else:
13+
raise 'The datasource type not support.'
14+
engine = create_engine(db_url)
15+
session_maker = sessionmaker(bind=engine)
16+
session = session_maker()
17+
return session
18+
19+
20+
def get_tables(conf: DatasourceConf, ds: CoreDatasource):
21+
session = get_session(conf, ds)
22+
result: Result[Any]
23+
if ds.type == "mysql":
24+
sql = f"""SELECT
25+
TABLE_NAME AS `Table Name`,
26+
TABLE_COMMENT AS `Table Comment`
27+
FROM
28+
information_schema.TABLES
29+
WHERE
30+
TABLE_SCHEMA = '{conf.database}';"""
31+
result = session.execute(text(sql))
32+
33+
res = result.fetchall()
34+
res_list = [TableSchema(*item) for item in res]
35+
return res_list
36+
37+
38+
def get_fields(conf: DatasourceConf, ds: CoreDatasource):
39+
session = get_session(conf, ds)
40+
result: Result[Any]
41+
pass

backend/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ dependencies = [
1818
"pydantic-settings<3.0.0,>=2.2.1",
1919
"sentry-sdk[fastapi]<2.0.0,>=1.40.6",
2020
"pyjwt<3.0.0,>=2.8.0",
21-
"pyodbc (>=5.2.0,<5.2.1)",
2221
"pycryptodome (>=3.22.0,<4.0.0)",
22+
"pymysql (>=1.1.1,<2.0.0)",
2323
]
2424
[[tool.uv.index]]
2525
url = "https://pypi.tuna.tsinghua.edu.cn/simple"

frontend/src/api/datasource.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ export const datasourceApi = {
55
add: (data: any) => request.post('/datasource/add', data),
66
list: () => request.get('/datasource/list'),
77
update: (data: any) => request.post('/datasource/update', data),
8-
delete: (id: Number) => request.post(`/datasource/delete/${id}`)
8+
delete: (id: Number) => request.post(`/datasource/delete/${id}`),
9+
getTables: (id: Number) => request.post(`/datasource/getTables/${id}`),
910
}

frontend/src/views/ds/index.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
</div>
3636
<div class="connection-status" :class="`${getStatus(ds.status)}`">{{ ds.status }}</div>
3737
<div class="connection-actions">
38+
<el-button class="action-btn" circle @click="getTables(ds.id)"/>
3839
<el-button type="primary" class="action-btn" circle @click="editDs(ds)" :icon="IconOpeEdit"/>
3940
<el-button type="danger" class="action-btn" circle @click="deleteDs(ds)" :icon="IconOpeDelete"/>
4041
</div>
@@ -114,6 +115,12 @@ const deleteDs = (item: any) => {
114115
})
115116
}
116117
118+
const getTables = (id: Number) => {
119+
datasourceApi.getTables(id).then((res) => {
120+
console.log(res)
121+
})
122+
}
123+
117124
onMounted(() => {
118125
list()
119126
})

0 commit comments

Comments
 (0)