mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 01:06:59 +08:00
feat: datasource
This commit is contained in:
@@ -20,15 +20,20 @@ def check_status(session: SessionDep, ds: CoreDatasource):
|
||||
return True
|
||||
except Exception as e:
|
||||
print("Fail:", e)
|
||||
raise e
|
||||
return False
|
||||
finally:
|
||||
conn.close()
|
||||
return False
|
||||
|
||||
|
||||
def create_ds(session: SessionDep, ds: CoreDatasource):
|
||||
ds.create_time = datetime.datetime.now()
|
||||
ds.status = "Success" # todo check status
|
||||
status = check_status(session, ds)
|
||||
ds.status = "Success" if status is True else "Fail"
|
||||
record = CoreDatasource(**ds.model_dump())
|
||||
# get tables and fields
|
||||
if status:
|
||||
pass
|
||||
session.add(record)
|
||||
session.commit()
|
||||
return ds
|
||||
|
||||
@@ -2,6 +2,7 @@ from sqlmodel import SQLModel, Field
|
||||
from sqlalchemy import Column, Text, BigInteger, DateTime, Integer, Identity
|
||||
from datetime import datetime
|
||||
from pydantic import BaseModel
|
||||
from typing import List
|
||||
|
||||
|
||||
class CoreDatasource(SQLModel, table=True):
|
||||
@@ -16,6 +17,22 @@ class CoreDatasource(SQLModel, table=True):
|
||||
status: str = Field(max_length=64, nullable=True)
|
||||
|
||||
|
||||
class TableSchema(BaseModel):
|
||||
checked: str = True
|
||||
table_name: str = ''
|
||||
table_comment: str = ''
|
||||
custom_comment: str = ''
|
||||
table_fields: List = []
|
||||
|
||||
|
||||
class FieldSchema(BaseModel):
|
||||
checked: str = True
|
||||
field_name: str = ''
|
||||
field_type: str = ''
|
||||
field_comment: str = ''
|
||||
custom_comment: str = ''
|
||||
|
||||
|
||||
class DatasourceConf(BaseModel):
|
||||
host: str = ''
|
||||
port: int = 0
|
||||
@@ -28,18 +45,18 @@ class DatasourceConf(BaseModel):
|
||||
class TableSchema:
|
||||
def __init__(self, attr1, attr2):
|
||||
self.tableName = attr1
|
||||
self.tableRemark = attr2
|
||||
self.tableComment = attr2
|
||||
|
||||
tableName: str
|
||||
tableRemark: str
|
||||
tableComment: str
|
||||
|
||||
|
||||
class ColumnSchema:
|
||||
def __init__(self, attr1, attr2, attr3):
|
||||
self.fieldName = attr1
|
||||
self.fieldType = attr2
|
||||
self.fieldRemark = attr3
|
||||
self.fieldComment = attr3
|
||||
|
||||
fieldName: str
|
||||
fieldType: str
|
||||
fieldRemark: str
|
||||
fieldComment: str
|
||||
|
||||
+6
-21
@@ -17,6 +17,7 @@ def get_uri(ds: CoreDatasource):
|
||||
raise 'The datasource type not support.'
|
||||
return db_url
|
||||
|
||||
|
||||
def get_session(ds: CoreDatasource):
|
||||
conf = DatasourceConf(**json.loads(aes_decrypt(ds.configuration)))
|
||||
db_url: str
|
||||
@@ -55,21 +56,22 @@ def get_tables(ds: CoreDatasource):
|
||||
session.close()
|
||||
|
||||
|
||||
def get_fields(ds: CoreDatasource, table_name: str):
|
||||
def get_fields(ds: CoreDatasource, table_name: str = None):
|
||||
conf = DatasourceConf(**json.loads(aes_decrypt(ds.configuration)))
|
||||
session = get_session(ds)
|
||||
result: Result[Any]
|
||||
try:
|
||||
if ds.type == "mysql":
|
||||
sql = f"""SELECT
|
||||
sql1 = f"""SELECT
|
||||
COLUMN_NAME,
|
||||
DATA_TYPE,
|
||||
COLUMN_COMMENT
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_SCHEMA = '{conf.database}' AND
|
||||
TABLE_NAME = '{table_name}';"""
|
||||
TABLE_SCHEMA = '{conf.database}'"""
|
||||
sql2 = f""" AND TABLE_NAME = '{table_name}';""" if table_name is not None and table_name != "" else ";"
|
||||
sql = sql1 + sql2
|
||||
result = session.execute(text(sql))
|
||||
|
||||
res = result.fetchall()
|
||||
@@ -99,20 +101,3 @@ def exec_sql(ds: CoreDatasource, sql: str):
|
||||
if session is not None:
|
||||
session.close()
|
||||
|
||||
def exec_sql(ds: CoreDatasource, sql: str):
|
||||
ds = session.get(CoreDatasource, id)
|
||||
session = get_session(ds)
|
||||
result = session.execute(text(sql))
|
||||
try:
|
||||
columns = result.keys()._keys
|
||||
res = result.fetchall()
|
||||
result_list = [
|
||||
{columns[i]: value for i, value in enumerate(tuple_item)}
|
||||
for tuple_item in res
|
||||
]
|
||||
return {"fields": columns, "data": result_list}
|
||||
finally:
|
||||
if result is not None:
|
||||
result.close()
|
||||
if session is not None:
|
||||
session.close()
|
||||
@@ -38,6 +38,13 @@ const router = createRouter({
|
||||
name: 'ds',
|
||||
component: ds,
|
||||
meta: { title: 'Data Connections', icon: 'ds' }
|
||||
},
|
||||
{
|
||||
path: 'dsTable/:dsId/:dsName',
|
||||
name: 'dsTable',
|
||||
component: () => import('@/views/ds/TableList.vue'),
|
||||
meta: { title: 'Data Connections', icon: 'ds' },
|
||||
props: true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
<template>
|
||||
<el-drawer
|
||||
<div class="layout">
|
||||
<el-row class="header">
|
||||
<div class="title">
|
||||
<el-button text :icon="ArrowLeft" @click="back()" />
|
||||
{{ props.dsName }}
|
||||
</div>
|
||||
<el-button type="primary" @click="save()">
|
||||
Save
|
||||
</el-button>
|
||||
</el-row>
|
||||
<el-row class="data">
|
||||
<el-table-v2
|
||||
:columns="tableColumns"
|
||||
:data="tableData"
|
||||
:width="1000"
|
||||
:height="800"
|
||||
fixed
|
||||
/>
|
||||
</el-row>
|
||||
<el-drawer
|
||||
v-model="drawer"
|
||||
direction="btt"
|
||||
:destroy-on-close="true"
|
||||
@@ -11,33 +30,23 @@
|
||||
</template>
|
||||
<template #default>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-table-v2
|
||||
:columns="tableColumns"
|
||||
:data="tableData"
|
||||
:width="700"
|
||||
:height="400"
|
||||
fixed
|
||||
/>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-table-v2
|
||||
:columns="fieldColumns"
|
||||
:data="fieldData"
|
||||
:width="700"
|
||||
:height="400"
|
||||
fixed
|
||||
/>
|
||||
</el-col>
|
||||
<el-table-v2
|
||||
:columns="fieldColumns"
|
||||
:data="fieldData"
|
||||
:width="1000"
|
||||
:height="800"
|
||||
fixed
|
||||
/>
|
||||
</el-row>
|
||||
</template>
|
||||
<template #footer>
|
||||
<div style="flex: auto">
|
||||
<el-button @click="cancelClick">cancel</el-button>
|
||||
<el-button type="primary" @click="confirmClick">confirm</el-button>
|
||||
<el-button @click="cancelClick">Cancel</el-button>
|
||||
<el-button type="primary" @click="confirmClick">Confirm</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="tsx" setup>
|
||||
@@ -45,6 +54,13 @@ import { ref } from 'vue'
|
||||
import { datasourceApi } from '@/api/datasource'
|
||||
import { ElButton } from 'element-plus'
|
||||
import { h } from 'vue'
|
||||
import { onMounted } from 'vue'
|
||||
import { ArrowLeft } from '@element-plus/icons-vue'
|
||||
|
||||
const props = defineProps({
|
||||
dsId: { type: [Number], required: true },
|
||||
dsName: { type: [String], required: true }
|
||||
})
|
||||
|
||||
const drawer = ref<boolean>(false)
|
||||
const tableColumns = ref<any>([
|
||||
@@ -55,9 +71,9 @@ const tableColumns = ref<any>([
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
key:"tableRemark",
|
||||
dataKey:"tableRemark",
|
||||
title: 'Table Remark',
|
||||
key:"tableComment",
|
||||
dataKey:"tableComment",
|
||||
title: 'Table Comment',
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
@@ -87,24 +103,25 @@ const fieldColumns = ref<any>([
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
key:"fieldRemark",
|
||||
dataKey:"fieldRemark",
|
||||
title: 'Field Remark',
|
||||
key:"fieldComment",
|
||||
dataKey:"fieldComment",
|
||||
title: 'Field Comment',
|
||||
width: 300,
|
||||
}
|
||||
])
|
||||
const fieldData = ref<any>([])
|
||||
const dsId = ref<Number>(0)
|
||||
|
||||
const open = (id: Number) => {
|
||||
drawer.value = true
|
||||
dsId.value = id
|
||||
datasourceApi.getTables(id).then((res) => {
|
||||
tableData.value = res
|
||||
})
|
||||
const back = () => {
|
||||
history.back()
|
||||
}
|
||||
|
||||
const save = () => {
|
||||
|
||||
}
|
||||
|
||||
const showFields = (tableName: string) =>{
|
||||
drawer.value = true
|
||||
datasourceApi.getFields(dsId.value, tableName).then((res) => {
|
||||
fieldData.value = res
|
||||
})
|
||||
@@ -119,9 +136,27 @@ const confirmClick = () => {
|
||||
cancelClick()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
dsId.value = props.dsId
|
||||
datasourceApi.getTables(props.dsId).then((res) => {
|
||||
tableData.value = res
|
||||
})
|
||||
})
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.layout{
|
||||
padding: 20px 40px;
|
||||
.header{
|
||||
padding: 20px 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.title{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -35,7 +35,7 @@
|
||||
</div>
|
||||
<div class="connection-status" :class="`${getStatus(ds.status)}`">{{ ds.status }}</div>
|
||||
<div class="connection-actions">
|
||||
<el-button class="action-btn" circle @click="getTables(ds.id)" :icon="List" />
|
||||
<el-button class="action-btn" circle @click="getTables(ds.id, ds.name)" :icon="List" />
|
||||
<el-button type="primary" class="action-btn" circle @click="editDs(ds)" :icon="IconOpeEdit"/>
|
||||
<el-button type="danger" class="action-btn" circle @click="deleteDs(ds)" :icon="IconOpeDelete"/>
|
||||
</div>
|
||||
@@ -43,7 +43,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<DsForm ref="dsForm" @refresh="refresh"/>
|
||||
<TableList ref="tableList" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import IconOpeAdd from '@/assets/svg/operate/ope-add.svg'
|
||||
@@ -55,13 +54,13 @@ import DsForm from './form.vue'
|
||||
import { datasourceApi } from '@/api/datasource'
|
||||
import { datetimeFormat } from '@/utils/utils'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import TableList from './TableList.vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const searchValue = ref<string>('')
|
||||
const dsForm = ref()
|
||||
const tableList = ref()
|
||||
const dsList = ref<any>([])// show ds list
|
||||
const allDsList = ref<any>([])// all ds list
|
||||
const router = useRouter()
|
||||
|
||||
const getStatus = (status: string) => {
|
||||
if (status === 'Success') {
|
||||
@@ -118,7 +117,7 @@ const deleteDs = (item: any) => {
|
||||
})
|
||||
}
|
||||
|
||||
const getTables = (id: Number) => {
|
||||
const getTables = (id: number, name: string) => {
|
||||
// datasourceApi.getTables(id).then((res) => {
|
||||
// console.log(res)
|
||||
// })
|
||||
@@ -130,7 +129,7 @@ const getTables = (id: Number) => {
|
||||
// datasourceApi.execSql(id,'select id,name,table_name from core_dataset_table limit 10').then((res) => {
|
||||
// console.log(res)
|
||||
// })
|
||||
tableList.value.open(id)
|
||||
router.push(`/ds/dsTable/${id}/${name}`)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
Reference in New Issue
Block a user