mirror of
https://gitee.com/dromara/dbswitch.git
synced 2025-08-29 00:44:19 +00:00
!226 优化及添加tdengine
* 修改默认端口 * 更新dist * 添加tdengine * 优化任务详情 * 优化任务详情 * 添加tdengine * 添加tdengine * 优化任务详情 * Merge remote-tracking branch 'remote/master' * 模式名超出部分截断问题 * 优化任务详情 * 优化任务详情 * Merge remote-tracking branch 'remote/master' * 任务详情优化 * 回滚配置信息 * 回滚配置信息 * 任务列表优化 * 代码优化 * 代码优化 * Merge remote-tracking branch 'upstream/master' * Merge remote-tracking branch 'upstream/master' * 任务管理 同步数据,增加指定SQL * 任务管理 同步数据,增加指定SQL * Merge remote-tracking branch 'upstream/master' * 任务管理优化 10% * Merge remote-tracking branch 'upstream/master' * 优化任务管理详情 * 优化 * 优化 * Merge remote-tracking branch 'remote/master' * 左侧列表优化 * 优化数据导航 * 优化样式 * Merge remote-tracking branch 'remote/master' * 任务管理优化 10% * 任务管理优化 10% * Merge remote-tracking branch 'origin/master' * Merge remote-tracking branch 'origin/master' * Merge remote-tracking branch 'remote/master' * Merge remote-tracking branch 'upstream/master' * 数据导航优化 * 数据导航优化 * 删除数据源ID * 驱动配置类型展示优化 * sync remote * 删除任务详情展示限制 * 调度时间 添加默认值 * Merge remote-tracking branch 'remote/master' * 更新dbswitch-admin/resources静态资源文件 * Merge remote-tracking branch 'origin/master' * 解决 【npm run build】 打包报错问题
This commit is contained in:
Binary file not shown.
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 2.7 KiB |
BIN
dbswitch-admin-ui/src/assets/icons/TDengine.png
Normal file
BIN
dbswitch-admin-ui/src/assets/icons/TDengine.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
@@ -119,6 +119,12 @@ const constantRouter = new Router({
|
||||
hidden: true,
|
||||
component: () => import('@/views/task/detail')
|
||||
},
|
||||
{
|
||||
path: '/task/detail_old',
|
||||
name: '查看任务(原)',
|
||||
hidden: true,
|
||||
component: () => import('@/views/task/detail_old')
|
||||
},
|
||||
{
|
||||
path: '/connection/list/addDataSource1',
|
||||
name: '数据源创建步骤1',
|
||||
|
@@ -49,33 +49,15 @@
|
||||
min-width="10%"></el-table-column>
|
||||
<el-table-column label="操作"
|
||||
min-width="35%">
|
||||
|
||||
<template slot-scope="scope">
|
||||
<el-button-group>
|
||||
<el-button size="small"
|
||||
type="danger"
|
||||
icon="el-icon-video-play"
|
||||
@click="handleTest(scope.$index, scope.row)"
|
||||
round>测试
|
||||
</el-button>
|
||||
<el-button size="small"
|
||||
type="primary"
|
||||
icon="el-icon-document"
|
||||
@click="handleMore(scope.$index, scope.row)"
|
||||
round>详情
|
||||
</el-button>
|
||||
<el-button size="small"
|
||||
type="warning"
|
||||
icon="el-icon-edit"
|
||||
@click="handleUpdate(scope.$index, scope.row)"
|
||||
round>编辑
|
||||
</el-button>
|
||||
<el-button size="small"
|
||||
type="success"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.$index, scope.row)"
|
||||
round>删除
|
||||
</el-button>
|
||||
</el-button-group>
|
||||
<el-link class="btn-text" type="primary" @click="handleTest(scope.$index, scope.row)">测试</el-link>
|
||||
<label class="btn-style"> | </label>
|
||||
<el-link class="btn-text" type="primary" @click="handleUpdate(scope.$index, scope.row)">编辑</el-link>
|
||||
<label class="btn-style"> | </label>
|
||||
<el-link class="btn-text" type="primary" @click="handleMore(scope.$index, scope.row)">详情</el-link>
|
||||
<label class="btn-style"> | </label>
|
||||
<el-link class="btn-text" type="primary" @click="handleDelete(scope.$index, scope.row)">删除</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -347,4 +329,13 @@ export default {
|
||||
margin-left: auto;
|
||||
margin: 10px 5px;
|
||||
}
|
||||
|
||||
.btn-style {
|
||||
color: #e9e9f3;
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 12px;
|
||||
color: #6873ce;
|
||||
}
|
||||
</style>
|
||||
|
@@ -22,7 +22,7 @@
|
||||
type="primary"
|
||||
size="mini"
|
||||
icon="el-icon-document-add"
|
||||
@click="handleCreate">创建
|
||||
@click="handleCreate">创建任务
|
||||
</el-button>
|
||||
</el-row>
|
||||
<div class="assignment-list-top">
|
||||
@@ -73,7 +73,7 @@
|
||||
<p>源端模式名:{{ scope.row.sourceSchema }}</p>
|
||||
<div slot="reference"
|
||||
class="name-wrapper">
|
||||
<el-tag size="medium">{{ scope.row.sourceSchema }}</el-tag>
|
||||
<el-tag size="medium" class="name-wrapper-tag">{{ scope.row.sourceSchema }}</el-tag>
|
||||
</div>
|
||||
</el-popover>
|
||||
</template>
|
||||
@@ -87,7 +87,7 @@
|
||||
<p>目标端模式名:{{ scope.row.targetSchema }}</p>
|
||||
<div slot="reference"
|
||||
class="name-wrapper">
|
||||
<el-tag size="medium">{{ scope.row.targetSchema }}</el-tag>
|
||||
<el-tag size="medium" class="name-wrapper-tag">{{ scope.row.targetSchema }}</el-tag>
|
||||
</div>
|
||||
</el-popover>
|
||||
</template>
|
||||
@@ -125,62 +125,85 @@
|
||||
<el-table-column label="操作"
|
||||
min-width="35%">
|
||||
<template slot-scope="scope">
|
||||
<el-button-group>
|
||||
<el-tooltip content="跳转到调度监控"
|
||||
placement="top">
|
||||
<el-button size="small"
|
||||
type="primary"
|
||||
icon="el-icon-timer"
|
||||
v-if="scope.row.isPublished===true"
|
||||
@click="schedulingLog(scope.$index, scope.row)"
|
||||
round>日志
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-button size="small"
|
||||
type="primary"
|
||||
icon="el-icon-timer"
|
||||
v-if="scope.row.isPublished===false"
|
||||
@click="handlePublish(scope.$index, scope.row)"
|
||||
round>启动
|
||||
</el-button>
|
||||
<el-button size="small"
|
||||
type="info"
|
||||
icon="el-icon-delete-location"
|
||||
v-if="scope.row.isPublished===true"
|
||||
@click="handleRetireTask(scope.$index, scope.row)"
|
||||
round>停用
|
||||
</el-button>
|
||||
<el-tooltip content="人工触发调度执行"
|
||||
placement="top">
|
||||
<el-button size="small"
|
||||
type="danger"
|
||||
icon="el-icon-video-play"
|
||||
v-if="scope.row.isPublished===true"
|
||||
@click="handleRunTask(scope.$index, scope.row)"
|
||||
round>执行
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-button size="small"
|
||||
type="warning"
|
||||
icon="el-icon-edit"
|
||||
v-if="scope.row.isPublished===false"
|
||||
@click="handleUpdate(scope.$index, scope.row)"
|
||||
round>修改
|
||||
</el-button>
|
||||
<el-button size="small"
|
||||
type="success"
|
||||
icon="el-icon-document"
|
||||
@click="handleDetail(scope.$index, scope.row)"
|
||||
round>详情
|
||||
</el-button>
|
||||
<el-button size="small"
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
v-if="scope.row.isPublished===false"
|
||||
@click="handleDelete(scope.$index, scope.row)"
|
||||
round>删除
|
||||
</el-button>
|
||||
</el-button-group>
|
||||
<el-tooltip content="跳转到监控调度" placement="top">
|
||||
<el-link class="btn-text" type="primary" @click="schedulingLog(scope.$index, scope.row)">日志</el-link>
|
||||
</el-tooltip>
|
||||
<label class="btn-style"> | </label>
|
||||
<el-link class="btn-text" type="primary" v-if="scope.row.isPublished===false"
|
||||
@click="handlePublish(scope.$index, scope.row)">启动</el-link>
|
||||
<el-link class="btn-text" type="primary" v-if="scope.row.isPublished===true"
|
||||
@click="handleRetireTask(scope.$index, scope.row)">停止</el-link>
|
||||
<label v-if="scope.row.isPublished===true" class="btn-style"> | </label>
|
||||
<el-link class="btn-text" type="primary" v-if="scope.row.isPublished===true"
|
||||
@click="handleRunTask(scope.$index, scope.row)">执行</el-link>
|
||||
<label v-if="scope.row.isPublished===false" class="btn-style"> | </label>
|
||||
<el-link class="btn-text" type="primary" v-if="scope.row.isPublished===false"
|
||||
@click="handleUpdate(scope.$index, scope.row)">修改</el-link>
|
||||
<label class="btn-style"> | </label>
|
||||
<el-link class="btn-text" type="primary"
|
||||
@click="handleDetail(scope.$index, scope.row)">详情</el-link>
|
||||
<label v-if="scope.row.isPublished===false" class="btn-style"> | </label>
|
||||
<el-link class="btn-text" type="primary" v-if="scope.row.isPublished===false"
|
||||
@click="handleDelete(scope.$index, scope.row)">删除</el-link>
|
||||
<!-- <label class="btn-style"> | </label>-->
|
||||
<!-- <el-link class="btn-text" type="primary"-->
|
||||
<!-- @click="handleDetailOld(scope.$index, scope.row)">老详情</el-link>-->
|
||||
|
||||
<!-- <el-button-group>-->
|
||||
<!-- <el-button size="small"-->
|
||||
<!-- type="primary"-->
|
||||
<!-- icon="el-icon-timer"-->
|
||||
<!-- v-if="scope.row.isPublished===false"-->
|
||||
<!-- @click="handlePublish(scope.$index, scope.row)"-->
|
||||
<!-- round>启动-->
|
||||
<!-- </el-button>-->
|
||||
<!-- <el-button size="small"-->
|
||||
<!-- type="info"-->
|
||||
<!-- icon="el-icon-delete-location"-->
|
||||
<!-- v-if="scope.row.isPublished===true"-->
|
||||
<!-- @click="handleRetireTask(scope.$index, scope.row)"-->
|
||||
<!-- round>停用-->
|
||||
<!-- </el-button>-->
|
||||
<!-- <el-tooltip content="人工触发调度执行"-->
|
||||
<!-- placement="top">-->
|
||||
<!-- <el-button size="small"-->
|
||||
<!-- type="danger"-->
|
||||
<!-- icon="el-icon-video-play"-->
|
||||
<!-- v-if="scope.row.isPublished===true"-->
|
||||
<!-- @click="handleRunTask(scope.$index, scope.row)"-->
|
||||
<!-- round>执行-->
|
||||
<!-- </el-button>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- <el-button size="small"-->
|
||||
<!-- type="warning"-->
|
||||
<!-- icon="el-icon-edit"-->
|
||||
<!-- v-if="scope.row.isPublished===false"-->
|
||||
<!-- @click="handleUpdate(scope.$index, scope.row)"-->
|
||||
<!-- round>修改-->
|
||||
<!-- </el-button>-->
|
||||
<!-- <el-button size="small"-->
|
||||
<!-- type="success"-->
|
||||
<!-- icon="el-icon-document"-->
|
||||
<!-- @click="handleDetail(scope.$index, scope.row)"-->
|
||||
<!-- round>详情-->
|
||||
<!-- </el-button>-->
|
||||
<!-- <el-button size="small"-->
|
||||
<!-- type="danger"-->
|
||||
<!-- icon="el-icon-delete"-->
|
||||
<!-- v-if="scope.row.isPublished===false"-->
|
||||
<!-- @click="handleDelete(scope.$index, scope.row)"-->
|
||||
<!-- round>删除-->
|
||||
<!-- </el-button>-->
|
||||
<!-- <el-tooltip content="跳转到调度监控"-->
|
||||
<!-- placement="top">-->
|
||||
<!-- <el-button size="small"-->
|
||||
<!-- type="primary"-->
|
||||
<!-- icon="el-icon-timer"-->
|
||||
<!-- @click="schedulingLog(scope.$index, scope.row)"-->
|
||||
<!-- round>日志-->
|
||||
<!-- </el-button>-->
|
||||
<!-- </el-tooltip>-->
|
||||
<!-- </el-button-group>-->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -247,9 +270,9 @@ export default {
|
||||
},
|
||||
boolFormatPublish (row, column) {
|
||||
if (row.isPublished === true) {
|
||||
return "已启动";
|
||||
return "启动";
|
||||
} else {
|
||||
return "已停止";
|
||||
return "停止";
|
||||
}
|
||||
},
|
||||
scheduleTimeFormat (row, column) {
|
||||
@@ -382,7 +405,10 @@ export default {
|
||||
this.$router.push('/task/create')
|
||||
},
|
||||
handleDetail: function (index, row) {
|
||||
this.$router.push({ path: '/task/detail', query: { id: row.id } })
|
||||
this.$router.push({ path: '/task/detail', query: { id: row.id, record: row } })
|
||||
},
|
||||
handleDetailOld: function (index, row) {
|
||||
this.$router.push({ path: '/task/detail_old', query: { id: row.id } })
|
||||
},
|
||||
handleUpdate: function (index, row) {
|
||||
this.$router.push({ path: '/task/update', query: { id: row.id } })
|
||||
@@ -592,4 +618,19 @@ export default {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.btn-style {
|
||||
color: #e9e9f3;
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 12px;
|
||||
color: #6873ce;
|
||||
}
|
||||
|
||||
.name-wrapper-tag {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,168 +1,386 @@
|
||||
<template>
|
||||
<el-card>
|
||||
<el-form :model="updateform"
|
||||
status-icon
|
||||
ref="updateform">
|
||||
<el-descriptions size="small"
|
||||
:column="1"
|
||||
label-class-name="el-descriptions-item-label-class"
|
||||
border>
|
||||
<el-descriptions-item label="任务名称">{{ updateform.name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="任务描述">{{ updateform.description }}</el-descriptions-item>
|
||||
<el-descriptions-item label="集成模式">
|
||||
<span v-if="updateform.scheduleMode == 'MANUAL'">
|
||||
<div class="app-container">
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
|
||||
<el-tab-pane label="基本信息" name="first">
|
||||
|
||||
<el-card class="box-card">
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="2">
|
||||
<label class="key-text">任务ID</label>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<label class="value-text">{{ infoform.id }}</label>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<label class="key-text">任务名称</label>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<label class="value-text">{{ infoform.name }}</label>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<label class="key-text">任务类型</label>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<label class="value-text">
|
||||
普通任务
|
||||
</label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="2">
|
||||
<label class="key-text">任务状态</label>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<label class="value-text">
|
||||
{{ $route.query.record.runStatus }}
|
||||
</label>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<label class="key-text">运行状态</label>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<label class="value-text">
|
||||
{{ $route.query.record.isPublished === true ? '启动' : '停止' }}
|
||||
</label>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<label class="key-text">集成模式</label>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<label class="value-text"><span v-if="infoform.scheduleMode == 'MANUAL'">
|
||||
手动
|
||||
</span>
|
||||
<span v-if="updateform.scheduleMode == 'SYSTEM_SCHEDULED'">
|
||||
<span v-if="infoform.scheduleMode == 'SYSTEM_SCHEDULED'">
|
||||
定时
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="updateform.scheduleMode == 'SYSTEM_SCHEDULED'"
|
||||
label="CRON表达式">{{ updateform.cronExpression }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="源端数据源">[{{ updateform.sourceConnectionId }}]
|
||||
{{ updateform.sourceConnectionName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="源端schema">{{ updateform.sourceSchema }}</el-descriptions-item>
|
||||
<el-descriptions-item label="源端表类型">{{ updateform.tableType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="源端表选择方式">
|
||||
<span v-if="updateform.includeOrExclude == 'INCLUDE'">
|
||||
包含表
|
||||
</span>
|
||||
<span v-if="updateform.includeOrExclude == 'EXCLUDE'">
|
||||
排除表
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="源端表名列表">
|
||||
<span
|
||||
v-show="updateform.includeOrExclude == 'INCLUDE' && (!updateform.sourceTables || updateform.sourceTables.length==0)"><b>所有物理表</b></span>
|
||||
<p v-for="item in updateform.sourceTables"
|
||||
v-bind:key="item">{{ item }}</p>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="目地端数据源">[{{ updateform.targetConnectionId }}]
|
||||
{{ updateform.targetConnectionName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="目地端schema">{{ updateform.targetSchema }}</el-descriptions-item>
|
||||
<el-descriptions-item label="自动同步模式">
|
||||
<span v-if="updateform.autoSyncMode == 2">
|
||||
目标端建表并同步数据
|
||||
</span>
|
||||
<span v-if="updateform.autoSyncMode == 1">
|
||||
目标端只创建物理表
|
||||
</span>
|
||||
<span v-if="updateform.autoSyncMode == 0">
|
||||
目标端只同步表里数据
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="建表字段自增"
|
||||
v-if=" updateform.autoSyncMode!==0 ">{{ updateform.targetAutoIncrement }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="表名转换方法"
|
||||
v-if=" updateform.autoSyncMode!==0 ">
|
||||
<span v-if="updateform.tableNameCase == 'NONE'">
|
||||
无转换
|
||||
</span>
|
||||
<span v-if="updateform.tableNameCase == 'UPPER'">
|
||||
转大写
|
||||
</span>
|
||||
<span v-if="updateform.tableNameCase == 'LOWER'">
|
||||
转小写
|
||||
</span>
|
||||
<span v-if="updateform.tableNameCase == 'CAMEL'">
|
||||
下划线转驼峰
|
||||
</span>
|
||||
<span v-if="updateform.tableNameCase == 'SNAKE'">
|
||||
驼峰转下换线
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="列名转换方法"
|
||||
v-if=" updateform.autoSyncMode!==0 ">
|
||||
<span v-if="updateform.columnNameCase == 'NONE'">
|
||||
无转换
|
||||
</span>
|
||||
<span v-if="updateform.columnNameCase == 'UPPER'">
|
||||
转大写
|
||||
</span>
|
||||
<span v-if="updateform.columnNameCase == 'LOWER'">
|
||||
转小写
|
||||
</span>
|
||||
<span v-if="updateform.columnNameCase == 'CAMEL'">
|
||||
下划线转驼峰
|
||||
</span>
|
||||
<span v-if="updateform.columnNameCase == 'SNAKE'">
|
||||
驼峰转下换线
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="数据批次大小"
|
||||
v-if=" updateform.autoSyncMode!==1 ">{{ updateform.batchSize }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="通道队列大小"
|
||||
v-if=" updateform.autoSyncMode!==1 ">{{ updateform.channelSize }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="同步操作方法"
|
||||
v-if=" updateform.autoSyncMode!==1 ">{{ updateform.targetSyncOption }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="同步前置执行SQL脚本"
|
||||
v-if=" updateform.autoSyncMode!==1 ">
|
||||
<span v-show="!updateform.beforeSqlScripts || updateform.beforeSqlScripts.length==0">[SQL脚本内容为空]</span>
|
||||
<span
|
||||
v-show="updateform.beforeSqlScripts && updateform.beforeSqlScripts.length>0">{{ updateform.beforeSqlScripts }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="同步后置执行SQL脚本"
|
||||
v-if=" updateform.autoSyncMode!==1 ">
|
||||
<span v-show="!updateform.afterSqlScripts || updateform.afterSqlScripts.length==0">[SQL脚本内容为空]</span>
|
||||
<span
|
||||
v-show="updateform.afterSqlScripts && updateform.afterSqlScripts.length>0">{{ updateform.afterSqlScripts }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="表名映射规则">
|
||||
<span v-show="!updateform.tableNameMapper || updateform.tableNameMapper.length==0">[映射关系为空]</span>
|
||||
<table v-if="updateform.tableNameMapper && updateform.tableNameMapper.length>0"
|
||||
class="name-mapper-table">
|
||||
<tr>
|
||||
<th>表名匹配的正则名</th>
|
||||
<th>替换的目标值</th>
|
||||
</tr>
|
||||
<tr v-for='(item,index) in updateform.tableNameMapper'
|
||||
:key="index">
|
||||
<td>{{ item['fromPattern'] }}</td>
|
||||
<td>{{ item['toValue'] }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="字段名映射规则">
|
||||
<span v-show="!updateform.columnNameMapper || updateform.columnNameMapper.length==0">[映射关系为空]</span>
|
||||
<table v-if="updateform.columnNameMapper && updateform.columnNameMapper.length>0"
|
||||
class="name-mapper-table">
|
||||
<tr>
|
||||
<th>字段名匹配的正则名</th>
|
||||
<th>替换的目标值</th>
|
||||
</tr>
|
||||
<tr v-for='(item,index) in updateform.columnNameMapper'
|
||||
:key="index">
|
||||
<td>{{ item['fromPattern'] }}</td>
|
||||
<td>{{ item['toValue'] }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</span></label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="2">
|
||||
<label class="key-text">调度计划</label>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<label class="value-text">
|
||||
<span v-if="infoform.scheduleMode == 'MANUAL'">
|
||||
--
|
||||
</span>
|
||||
<span v-if="infoform.scheduleMode == 'SYSTEM_SCHEDULED'">
|
||||
{{ infoform.cronExpression }}
|
||||
</span>
|
||||
</label>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<label class="key-text">开始调度时间</label>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<label class="value-text">{{ $route.query.record.scheduleTime }}</label>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<label class="key-text">创建时间</label>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<label class="value-text">{{ $route.query.record.createTime }}</label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="2">
|
||||
<label class="key-text">描述</label>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<label class="value-text">{{ infoform.description }}</label>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<label class="key-text">任务标签</label>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<label class="value-text">--</label>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<div class="common-box">
|
||||
<div class="datainfo">
|
||||
<div class="source">
|
||||
<div class="head">
|
||||
<div class="head-img">
|
||||
<el-image
|
||||
style="width: 60px; height: 60px"
|
||||
:src="require('@/assets/icons/' + $route.query.record.sourceType +'.png')"
|
||||
:fit="fit"></el-image>
|
||||
</div>
|
||||
<div class="head-text">
|
||||
<div class="title">{{ infoform.sourceConnectionName }}</div>
|
||||
<div class="sub-title">源端数据源</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="body">
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">源端schema</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<label class="value-text">{{ infoform.sourceSchema }}</label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">源端表类型</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<label class="value-text">{{ infoform.tableType }}</label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">源端表选择方式</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<label class="value-text">{{
|
||||
infoform.includeOrExclude === 'INCLUDE' ? '包含表' : '排除表'
|
||||
}}</label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">源端表名列表</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<label class="value-text" v-for="item in infoform.sourceTables"
|
||||
v-bind:key="item">{{ item }}</label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="target">
|
||||
<div class="head">
|
||||
<div class="head-img">
|
||||
<el-image
|
||||
style="width: 60px; height: 60px"
|
||||
:src="require('@/assets/icons/' + $route.query.record.targetType +'.png')"
|
||||
:fit="fit"></el-image>
|
||||
</div>
|
||||
<div class="head-text">
|
||||
<div class="title">{{ infoform.targetConnectionName }}</div>
|
||||
<div class="sub-title">目标端数据源</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="body">
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">目地端schema</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<label class="value-text">{{ infoform.targetSchema }}</label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">自动同步模式</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<span class="value-text" v-if="infoform.autoSyncMode == 2">
|
||||
目标端建表并同步数据
|
||||
</span>
|
||||
<span class="value-text" v-if="infoform.autoSyncMode == 1">
|
||||
目标端只创建物理表
|
||||
</span>
|
||||
<span class="value-text" v-if="infoform.autoSyncMode == 0">
|
||||
目标端只同步表里数据
|
||||
</span>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">建表字段自增</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<label class="value-text"
|
||||
v-if=" infoform.autoSyncMode!==0 ">{{ infoform.targetAutoIncrement }}
|
||||
</label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">表名转换方法</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<label class="value-text" v-if=" infoform.autoSyncMode!==0 ">
|
||||
<span v-if="infoform.tableNameCase == 'NONE'">
|
||||
无转换
|
||||
</span>
|
||||
<span v-if="infoform.tableNameCase == 'UPPER'">
|
||||
转大写
|
||||
</span>
|
||||
<span v-if="infoform.tableNameCase == 'LOWER'">
|
||||
转小写
|
||||
</span>
|
||||
<span v-if="infoform.tableNameCase == 'CAMEL'">
|
||||
下划线转驼峰
|
||||
</span>
|
||||
<span v-if="infoform.tableNameCase == 'SNAKE'">
|
||||
驼峰转下换线
|
||||
</span>
|
||||
</label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">列名转换方法</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
|
||||
|
||||
<label class="value-text" v-if=" infoform.autoSyncMode!==0 ">
|
||||
<span v-if="infoform.columnNameCase == 'NONE'">
|
||||
无转换
|
||||
</span>
|
||||
<span v-if="infoform.columnNameCase == 'UPPER'">
|
||||
转大写
|
||||
</span>
|
||||
<span v-if="infoform.columnNameCase == 'LOWER'">
|
||||
转小写
|
||||
</span>
|
||||
<span v-if="infoform.columnNameCase == 'CAMEL'">
|
||||
下划线转驼峰
|
||||
</span>
|
||||
<span v-if="infoform.columnNameCase == 'SNAKE'">
|
||||
驼峰转下换线
|
||||
</span>
|
||||
</label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">数据批次大小</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<label class="value-text"
|
||||
v-if=" infoform.autoSyncMode!==1 ">{{ infoform.batchSize }}
|
||||
</label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">通道队列大小</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<label class="value-text"
|
||||
v-if=" infoform.autoSyncMode!==1 ">{{ infoform.channelSize }}
|
||||
</label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">同步操作方法</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<label class="value-text"
|
||||
v-if="infoform.autoSyncMode!==1 ">{{ infoform.targetSyncOption }}
|
||||
</label>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">同步前置执行SQL脚本</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<label class="value-text"
|
||||
v-if=" infoform.autoSyncMode!==1 ">
|
||||
<span
|
||||
v-show="!infoform.beforeSqlScripts || infoform.beforeSqlScripts.length==0">[SQL脚本内容为空]</span>
|
||||
<span
|
||||
v-show="infoform.beforeSqlScripts && infoform.beforeSqlScripts.length>0">{{
|
||||
infoform.beforeSqlScripts
|
||||
}}</span>
|
||||
</label>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="row-gutter">
|
||||
<el-col :span="8">
|
||||
<label class="key-text">同步后置执行SQL脚本</label>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<label class="value-text"
|
||||
v-if=" infoform.autoSyncMode!==1 ">
|
||||
<span
|
||||
v-show="!infoform.afterSqlScripts || infoform.afterSqlScripts.length==0">[SQL脚本内容为空]</span>
|
||||
<span
|
||||
v-show="infoform.afterSqlScripts && infoform.afterSqlScripts.length>0">{{
|
||||
infoform.afterSqlScripts
|
||||
}}</span>
|
||||
</label>
|
||||
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mapper">
|
||||
<div class="table-left">
|
||||
<div>表名映射规则</div>
|
||||
<div>
|
||||
<el-table
|
||||
:data="infoform.tableNameMapper"
|
||||
style="width: 100%"
|
||||
:row-class-name="tableRowClassName">
|
||||
<el-table-column
|
||||
prop="fromPattern"
|
||||
label="表名匹配的正则名">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="toValue"
|
||||
label="替换的目标值">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-right">
|
||||
<div>字段名映射规则</div>
|
||||
<div>
|
||||
<el-table
|
||||
:data="infoform.columnNameMapper"
|
||||
style="width: 100%"
|
||||
:row-class-name="tableRowClassName">
|
||||
<el-table-column
|
||||
prop="fromPattern"
|
||||
label="表名匹配的正则名">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="toValue"
|
||||
label="替换的目标值">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-tab-pane>
|
||||
<!-- <el-tab-pane label="调度日志" name="second">调度日志22</el-tab-pane>-->
|
||||
<!-- <el-tab-pane label="操作日志" name="third">操作日志33</el-tab-pane>-->
|
||||
</el-tabs>
|
||||
</div>
|
||||
|
||||
</el-form>
|
||||
<el-button type="primary"
|
||||
size="mini"
|
||||
icon="el-icon-arrow-left"
|
||||
@click="handleGoBack"
|
||||
style="margin: 12px 0px 20px;float: right">
|
||||
返回
|
||||
</el-button>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
updateform: {
|
||||
activeName: 'first',
|
||||
infoform: {
|
||||
id: 0,
|
||||
name: "",
|
||||
description: "",
|
||||
@@ -170,6 +388,7 @@ export default {
|
||||
cronExpression: "",
|
||||
sourceConnectionId: '请选择',
|
||||
sourceSchema: "",
|
||||
runStatus: "",
|
||||
tableType: "TABLE",
|
||||
includeOrExclude: "",
|
||||
sourceTables: [],
|
||||
@@ -210,7 +429,8 @@ export default {
|
||||
} else {
|
||||
varAutoSyncMode = 2;
|
||||
}
|
||||
this.updateform = {
|
||||
debugger
|
||||
this.infoform = {
|
||||
id: detail.id,
|
||||
name: detail.name,
|
||||
description: detail.description,
|
||||
@@ -239,9 +459,9 @@ export default {
|
||||
beforeSqlScripts: detail.configuration.beforeSqlScripts,
|
||||
afterSqlScripts: detail.configuration.afterSqlScripts,
|
||||
}
|
||||
this.selectChangedSourceConnection(this.updateform.sourceConnectionId)
|
||||
this.selectUpdateChangedSourceSchema(this.updateform.sourceSchema)
|
||||
this.selectChangedTargetConnection(this.updateform.targetConnectionId)
|
||||
this.selectChangedSourceConnection(this.infoform.sourceConnectionId)
|
||||
this.selectUpdateChangedSourceSchema(this.infoform.sourceSchema)
|
||||
this.selectChangedTargetConnection(this.infoform.targetConnectionId)
|
||||
} else {
|
||||
if (res.data.message) {
|
||||
alert("查询任务失败," + res.data.message);
|
||||
@@ -269,9 +489,9 @@ export default {
|
||||
},
|
||||
selectUpdateChangedSourceSchema: function (value) {
|
||||
this.sourceSchemaTables = [];
|
||||
if ('TABLE' === this.updateform.tableType) {
|
||||
if ('TABLE' === this.infoform.tableType) {
|
||||
this.$http.get(
|
||||
"/dbswitch/admin/api/v1/connection/tables/get/" + this.updateform.sourceConnectionId + "?schema=" + value
|
||||
"/dbswitch/admin/api/v1/connection/tables/get/" + this.infoform.sourceConnectionId + "?schema=" + value
|
||||
).then(res => {
|
||||
if (0 === res.data.code) {
|
||||
this.sourceSchemaTables = res.data.data;
|
||||
@@ -282,7 +502,7 @@ export default {
|
||||
});
|
||||
} else {
|
||||
this.$http.get(
|
||||
"/dbswitch/admin/api/v1/connection/views/get/" + this.updateform.sourceConnectionId + "?schema=" + value
|
||||
"/dbswitch/admin/api/v1/connection/views/get/" + this.infoform.sourceConnectionId + "?schema=" + value
|
||||
).then(res => {
|
||||
if (0 === res.data.code) {
|
||||
this.sourceSchemaTables = res.data.data;
|
||||
@@ -314,25 +534,163 @@ export default {
|
||||
handleGoBack() {
|
||||
this.$router.go(-1);
|
||||
},
|
||||
handleClick(tab, event) {
|
||||
if (tab.index !== 0) {
|
||||
this.$message({
|
||||
message: '功能暂未开放,敬请期待!',
|
||||
center: true
|
||||
});
|
||||
}
|
||||
},
|
||||
tableRowClassName({row, rowIndex}) {
|
||||
if (rowIndex === 1) {
|
||||
return 'warning-row';
|
||||
} else if (rowIndex === 3) {
|
||||
return 'success-row';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadAssignmentDetail();
|
||||
console.log(this.$route.query.record)
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-card {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
.app-container {
|
||||
background-color: white;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.el-descriptions__body
|
||||
.el-descriptions__table
|
||||
.el-descriptions-row
|
||||
.el-descriptions-item__label {
|
||||
min-width: 20px;
|
||||
max-width: 60px;
|
||||
/deep/ .el-tabs {
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
/deep/ .el-tabs__content {
|
||||
width: 98.5%;
|
||||
}
|
||||
|
||||
/deep/ .el-tabs__nav-wrap:after {
|
||||
width: 270px;
|
||||
}
|
||||
|
||||
.box-card {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.row-gutter {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.common-box {
|
||||
margin-top: 16px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 16px;
|
||||
padding-bottom: 24px;
|
||||
|
||||
.datainfo {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
gap: 24px;
|
||||
|
||||
.source {
|
||||
flex: 1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.target {
|
||||
flex: 1;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.head {
|
||||
display: flex;
|
||||
height: 72px;
|
||||
align-items: center;
|
||||
background-color: #F7FBFF;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
|
||||
.head-img {
|
||||
width: 40px;
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
.head-text {
|
||||
flex-grow: 1;
|
||||
padding-left: 48px;
|
||||
|
||||
.title {
|
||||
font-size: 14px;
|
||||
color: #0051FF;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sub-title {
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
color: #7D7D7D;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
background-color: white;
|
||||
padding: 24px;
|
||||
min-height: 328px;
|
||||
}
|
||||
}
|
||||
|
||||
.mapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
gap: 24px;
|
||||
|
||||
.table-left {
|
||||
background-color: white;
|
||||
width: 100%;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.table-right {
|
||||
background-color: white;
|
||||
width: 100%;
|
||||
padding: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.viewer-container {
|
||||
background-color: white;
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
.key-text {
|
||||
color: #7D7D7D;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.value-text {
|
||||
margin-left: 8px;
|
||||
font-size: 12px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.el-table .warning-row {
|
||||
background: oldlace;
|
||||
}
|
||||
|
||||
.el-table .success-row {
|
||||
background: #f0f9eb;
|
||||
}
|
||||
</style>
|
338
dbswitch-admin-ui/src/views/task/detail_old.vue
Normal file
338
dbswitch-admin-ui/src/views/task/detail_old.vue
Normal file
@@ -0,0 +1,338 @@
|
||||
<template>
|
||||
<el-card>
|
||||
<el-form :model="updateform"
|
||||
status-icon
|
||||
ref="updateform">
|
||||
<el-descriptions size="small"
|
||||
:column="1"
|
||||
label-class-name="el-descriptions-item-label-class"
|
||||
border>
|
||||
<el-descriptions-item label="任务名称">{{ updateform.name }}</el-descriptions-item>
|
||||
<el-descriptions-item label="任务描述">{{ updateform.description }}</el-descriptions-item>
|
||||
<el-descriptions-item label="集成模式">
|
||||
<span v-if="updateform.scheduleMode == 'MANUAL'">
|
||||
手动
|
||||
</span>
|
||||
<span v-if="updateform.scheduleMode == 'SYSTEM_SCHEDULED'">
|
||||
定时
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="updateform.scheduleMode == 'SYSTEM_SCHEDULED'"
|
||||
label="CRON表达式">{{ updateform.cronExpression }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="源端数据源">[{{ updateform.sourceConnectionId }}]
|
||||
{{ updateform.sourceConnectionName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="源端schema">{{ updateform.sourceSchema }}</el-descriptions-item>
|
||||
<el-descriptions-item label="源端表类型">{{ updateform.tableType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="源端表选择方式">
|
||||
<span v-if="updateform.includeOrExclude == 'INCLUDE'">
|
||||
包含表
|
||||
</span>
|
||||
<span v-if="updateform.includeOrExclude == 'EXCLUDE'">
|
||||
排除表
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="源端表名列表">
|
||||
<span
|
||||
v-show="updateform.includeOrExclude == 'INCLUDE' && (!updateform.sourceTables || updateform.sourceTables.length==0)"><b>所有物理表</b></span>
|
||||
<p v-for="item in updateform.sourceTables"
|
||||
v-bind:key="item">{{ item }}</p>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="目地端数据源">[{{ updateform.targetConnectionId }}]
|
||||
{{ updateform.targetConnectionName }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="目地端schema">{{ updateform.targetSchema }}</el-descriptions-item>
|
||||
<el-descriptions-item label="自动同步模式">
|
||||
<span v-if="updateform.autoSyncMode == 2">
|
||||
目标端建表并同步数据
|
||||
</span>
|
||||
<span v-if="updateform.autoSyncMode == 1">
|
||||
目标端只创建物理表
|
||||
</span>
|
||||
<span v-if="updateform.autoSyncMode == 0">
|
||||
目标端只同步表里数据
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="建表字段自增"
|
||||
v-if=" updateform.autoSyncMode!==0 ">{{ updateform.targetAutoIncrement }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="表名转换方法"
|
||||
v-if=" updateform.autoSyncMode!==0 ">
|
||||
<span v-if="updateform.tableNameCase == 'NONE'">
|
||||
无转换
|
||||
</span>
|
||||
<span v-if="updateform.tableNameCase == 'UPPER'">
|
||||
转大写
|
||||
</span>
|
||||
<span v-if="updateform.tableNameCase == 'LOWER'">
|
||||
转小写
|
||||
</span>
|
||||
<span v-if="updateform.tableNameCase == 'CAMEL'">
|
||||
下划线转驼峰
|
||||
</span>
|
||||
<span v-if="updateform.tableNameCase == 'SNAKE'">
|
||||
驼峰转下换线
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="列名转换方法"
|
||||
v-if=" updateform.autoSyncMode!==0 ">
|
||||
<span v-if="updateform.columnNameCase == 'NONE'">
|
||||
无转换
|
||||
</span>
|
||||
<span v-if="updateform.columnNameCase == 'UPPER'">
|
||||
转大写
|
||||
</span>
|
||||
<span v-if="updateform.columnNameCase == 'LOWER'">
|
||||
转小写
|
||||
</span>
|
||||
<span v-if="updateform.columnNameCase == 'CAMEL'">
|
||||
下划线转驼峰
|
||||
</span>
|
||||
<span v-if="updateform.columnNameCase == 'SNAKE'">
|
||||
驼峰转下换线
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="数据批次大小"
|
||||
v-if=" updateform.autoSyncMode!==1 ">{{ updateform.batchSize }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="通道队列大小"
|
||||
v-if=" updateform.autoSyncMode!==1 ">{{ updateform.channelSize }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="同步操作方法"
|
||||
v-if=" updateform.autoSyncMode!==1 ">{{ updateform.targetSyncOption }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="同步前置执行SQL脚本"
|
||||
v-if=" updateform.autoSyncMode!==1 ">
|
||||
<span v-show="!updateform.beforeSqlScripts || updateform.beforeSqlScripts.length==0">[SQL脚本内容为空]</span>
|
||||
<span
|
||||
v-show="updateform.beforeSqlScripts && updateform.beforeSqlScripts.length>0">{{ updateform.beforeSqlScripts }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="同步后置执行SQL脚本"
|
||||
v-if=" updateform.autoSyncMode!==1 ">
|
||||
<span v-show="!updateform.afterSqlScripts || updateform.afterSqlScripts.length==0">[SQL脚本内容为空]</span>
|
||||
<span
|
||||
v-show="updateform.afterSqlScripts && updateform.afterSqlScripts.length>0">{{ updateform.afterSqlScripts }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="表名映射规则">
|
||||
<span v-show="!updateform.tableNameMapper || updateform.tableNameMapper.length==0">[映射关系为空]</span>
|
||||
<table v-if="updateform.tableNameMapper && updateform.tableNameMapper.length>0"
|
||||
class="name-mapper-table">
|
||||
<tr>
|
||||
<th>表名匹配的正则名</th>
|
||||
<th>替换的目标值</th>
|
||||
</tr>
|
||||
<tr v-for='(item,index) in updateform.tableNameMapper'
|
||||
:key="index">
|
||||
<td>{{ item['fromPattern'] }}</td>
|
||||
<td>{{ item['toValue'] }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="字段名映射规则">
|
||||
<span v-show="!updateform.columnNameMapper || updateform.columnNameMapper.length==0">[映射关系为空]</span>
|
||||
<table v-if="updateform.columnNameMapper && updateform.columnNameMapper.length>0"
|
||||
class="name-mapper-table">
|
||||
<tr>
|
||||
<th>字段名匹配的正则名</th>
|
||||
<th>替换的目标值</th>
|
||||
</tr>
|
||||
<tr v-for='(item,index) in updateform.columnNameMapper'
|
||||
:key="index">
|
||||
<td>{{ item['fromPattern'] }}</td>
|
||||
<td>{{ item['toValue'] }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
</el-form>
|
||||
<el-button type="primary"
|
||||
size="mini"
|
||||
icon="el-icon-arrow-left"
|
||||
@click="handleGoBack"
|
||||
style="margin: 12px 0px 20px;float: right">
|
||||
返回
|
||||
</el-button>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
updateform: {
|
||||
id: 0,
|
||||
name: "",
|
||||
description: "",
|
||||
scheduleMode: "MANUAL",
|
||||
cronExpression: "",
|
||||
sourceConnectionId: '请选择',
|
||||
sourceSchema: "",
|
||||
tableType: "TABLE",
|
||||
includeOrExclude: "",
|
||||
sourceTables: [],
|
||||
tableNameMapper: [],
|
||||
columnNameMapper: [],
|
||||
tableNameCase: 'NONE',
|
||||
columnNameCase: 'NONE',
|
||||
targetConnectionId: '请选择',
|
||||
targetDropTable: true,
|
||||
targetOnlyCreate: false,
|
||||
autoSyncMode: 2,
|
||||
targetSchema: "",
|
||||
batchSize: 5000,
|
||||
channelSize: 100,
|
||||
targetSyncOption: 'INSERT_UPDATE_DELETE',
|
||||
beforeSqlScripts: '',
|
||||
afterSqlScripts: '',
|
||||
},
|
||||
sourceConnection: {},
|
||||
targetConnection: {},
|
||||
sourceConnectionSchemas: [],
|
||||
sourceSchemaTables: [],
|
||||
targetConnectionSchemas: [],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadAssignmentDetail: function () {
|
||||
this.$http.get(
|
||||
"/dbswitch/admin/api/v1/assignment/detail/id/" + this.$route.query.id
|
||||
).then(res => {
|
||||
if (0 === res.data.code) {
|
||||
let detail = res.data.data;
|
||||
let varAutoSyncMode = 2;
|
||||
if (detail.configuration.targetDropTable && detail.configuration.targetOnlyCreate) {
|
||||
varAutoSyncMode = 1;
|
||||
} else if (!detail.configuration.targetDropTable && !detail.configuration.targetOnlyCreate) {
|
||||
varAutoSyncMode = 0;
|
||||
} else {
|
||||
varAutoSyncMode = 2;
|
||||
}
|
||||
this.updateform = {
|
||||
id: detail.id,
|
||||
name: detail.name,
|
||||
description: detail.description,
|
||||
scheduleMode: detail.scheduleMode,
|
||||
cronExpression: detail.cronExpression,
|
||||
sourceConnectionId: detail.configuration.sourceConnectionId,
|
||||
sourceConnectionName: detail.configuration.sourceConnectionName,
|
||||
sourceSchema: detail.configuration.sourceSchema,
|
||||
tableType: detail.configuration.tableType,
|
||||
includeOrExclude: detail.configuration.includeOrExclude,
|
||||
sourceTables: detail.configuration.sourceTables,
|
||||
tableNameMapper: detail.configuration.tableNameMapper,
|
||||
columnNameMapper: detail.configuration.columnNameMapper,
|
||||
tableNameCase: detail.configuration.tableNameCase,
|
||||
columnNameCase: detail.configuration.columnNameCase,
|
||||
targetConnectionId: detail.configuration.targetConnectionId,
|
||||
targetConnectionName: detail.configuration.targetConnectionName,
|
||||
targetDropTable: detail.configuration.targetDropTable,
|
||||
targetOnlyCreate: detail.configuration.targetOnlyCreate,
|
||||
targetAutoIncrement: detail.configuration.targetAutoIncrement,
|
||||
autoSyncMode: varAutoSyncMode,
|
||||
targetSchema: detail.configuration.targetSchema,
|
||||
batchSize: detail.configuration.batchSize,
|
||||
channelSize: detail.configuration.channelSize,
|
||||
targetSyncOption: detail.configuration.targetSyncOption,
|
||||
beforeSqlScripts: detail.configuration.beforeSqlScripts,
|
||||
afterSqlScripts: detail.configuration.afterSqlScripts,
|
||||
}
|
||||
this.selectChangedSourceConnection(this.updateform.sourceConnectionId)
|
||||
this.selectUpdateChangedSourceSchema(this.updateform.sourceSchema)
|
||||
this.selectChangedTargetConnection(this.updateform.targetConnectionId)
|
||||
} else {
|
||||
if (res.data.message) {
|
||||
alert("查询任务失败," + res.data.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
selectChangedSourceConnection: function (value) {
|
||||
this.sourceConnection = this.connectionNameList.find(
|
||||
(item) => {
|
||||
return item.id === value;
|
||||
});
|
||||
|
||||
this.sourceConnectionSchemas = [];
|
||||
this.$http.get(
|
||||
"/dbswitch/admin/api/v1/connection/schemas/get/" + value
|
||||
).then(res => {
|
||||
if (0 === res.data.code) {
|
||||
this.sourceConnectionSchemas = res.data.data;
|
||||
} else {
|
||||
this.$message.error("查询来源端数据库的Schema失败," + res.data.message);
|
||||
this.sourceConnectionSchemas = [];
|
||||
}
|
||||
});
|
||||
},
|
||||
selectUpdateChangedSourceSchema: function (value) {
|
||||
this.sourceSchemaTables = [];
|
||||
if ('TABLE' === this.updateform.tableType) {
|
||||
this.$http.get(
|
||||
"/dbswitch/admin/api/v1/connection/tables/get/" + this.updateform.sourceConnectionId + "?schema=" + value
|
||||
).then(res => {
|
||||
if (0 === res.data.code) {
|
||||
this.sourceSchemaTables = res.data.data;
|
||||
} else {
|
||||
this.$message.error("查询来源端数据库在指定Schema下的物理表列表失败," + res.data.message);
|
||||
this.sourceSchemaTables = [];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.$http.get(
|
||||
"/dbswitch/admin/api/v1/connection/views/get/" + this.updateform.sourceConnectionId + "?schema=" + value
|
||||
).then(res => {
|
||||
if (0 === res.data.code) {
|
||||
this.sourceSchemaTables = res.data.data;
|
||||
} else {
|
||||
this.$message.error("查询来源端数据库在指定Schema下的视图表列表失败," + res.data.message);
|
||||
this.sourceSchemaTables = [];
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
selectChangedTargetConnection: function (value) {
|
||||
this.targetConnection = this.connectionNameList.find(
|
||||
(item) => {
|
||||
return item.id === value;
|
||||
});
|
||||
|
||||
this.targetConnectionSchemas = [];
|
||||
this.$http.get(
|
||||
"/dbswitch/admin/api/v1/connection/schemas/get/" + value
|
||||
).then(res => {
|
||||
if (0 === res.data.code) {
|
||||
this.targetConnectionSchemas = res.data.data;
|
||||
} else {
|
||||
this.$message.error("查询目的端数据库的Schema失败," + res.data.message);
|
||||
this.targetConnectionSchemas = [];
|
||||
}
|
||||
});
|
||||
},
|
||||
handleGoBack() {
|
||||
this.$router.go(-1);
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.loadAssignmentDetail();
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-card {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.el-descriptions__body
|
||||
.el-descriptions__table
|
||||
.el-descriptions-row
|
||||
.el-descriptions-item__label {
|
||||
min-width: 20px;
|
||||
max-width: 60px;
|
||||
}
|
||||
</style>
|
@@ -23,4 +23,4 @@ mybatis:
|
||||
|
||||
dbswitch:
|
||||
configuration:
|
||||
drivers-base-path: ${APP_DRIVERS_PATH}
|
||||
drivers-base-path: ${APP_DRIVERS_PATH:D:\lzm\otherproject\dbswitch\drivers}
|
||||
|
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>异构数据迁移工具</title><link href=/static/css/app.b7354ab5f63d44a80b8f75636e1e0abc.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.78b2138895a8f35eeff6.js></script><script type=text/javascript src=/static/js/vendor.8200341f98478c8f7552.js></script><script type=text/javascript src=/static/js/app.df5c26834a81c347a509.js></script></body></html>
|
||||
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>异构数据迁移工具</title><link href=/static/css/app.41fc9337aa8988f4a077ab190bbfa780.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.9eb26c1e5b920ae4f10a.js></script><script type=text/javascript src=/static/js/vendor.f606e4b64a7e8691aabf.js></script><script type=text/javascript src=/static/js/app.5fea471d29a49cd53a96.js></script></body></html>
|
@@ -223,6 +223,15 @@ public enum ProductTypeEnum {
|
||||
new String[]{"jdbc:oceanbase://{host}[:{port}]/[{database}][\\?{params}]"},
|
||||
"jdbc:oceanbase://127.0.0.1:2881/test?pool=false&useUnicode=true&characterEncoding=utf-8&useSSL=false"),
|
||||
|
||||
/**
|
||||
* TDengine 数据库类型
|
||||
*/
|
||||
TDENGINE(23, "", "TDengine", "com.taosdata.jdbc.rs.RestfulDriver", 6041,
|
||||
"/* ping */ SELECT 1",
|
||||
"jdbc:TAOS-RS://",
|
||||
new String[]{"jdbc:TAOS-RS://{host}[:{port}]/[{database}][\\?{params}]"},
|
||||
"jdbc:TAOS-RS://127.0.0.1:6041/test?charset=UTF-8&locale=en_US.UTF-8&timezone=UTC+8"),
|
||||
|
||||
;
|
||||
|
||||
private int id;
|
||||
|
28
dbswitch-product/dbswitch-product-tdengine/pom.xml
Normal file
28
dbswitch-product/dbswitch-product-tdengine/pom.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>dbswitch-product</artifactId>
|
||||
<groupId>org.dromara.dbswitch</groupId>
|
||||
<version>2.0.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>dbswitch-product-tdengine</artifactId>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara.dbswitch</groupId>
|
||||
<artifactId>dbswitch-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara.dbswitch</groupId>
|
||||
<artifactId>dbswitch-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
@@ -0,0 +1,29 @@
|
||||
// Copyright tang. All rights reserved.
|
||||
// https://gitee.com/inrgihc/dbswitch
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
//
|
||||
// Author: Li ZeMin (2413957313@qq.com)
|
||||
// Date : 2024/12/16
|
||||
// Location: nanjing , china
|
||||
/////////////////////////////////////////////////////////////
|
||||
package org.dromara.dbswitch.product.tdengine;
|
||||
|
||||
import org.dromara.dbswitch.core.provider.ProductFactoryProvider;
|
||||
import org.dromara.dbswitch.core.provider.write.AutoCastTableDataWriteProvider;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
|
||||
public class TDengineTableDataWriteProvider extends AutoCastTableDataWriteProvider {
|
||||
|
||||
public TDengineTableDataWriteProvider(ProductFactoryProvider factoryProvider) {
|
||||
super(factoryProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TransactionDefinition getDefaultTransactionDefinition() {
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
return definition;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
// Copyright tang. All rights reserved.
|
||||
// https://gitee.com/inrgihc/dbswitch
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
//
|
||||
// Author: Li ZeMin (2413957313@qq.com)
|
||||
// Date : 2024/12/16
|
||||
// Location: nanjing , china
|
||||
/////////////////////////////////////////////////////////////
|
||||
package org.dromara.dbswitch.product.tdengine;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import org.dromara.dbswitch.common.type.ProductTypeEnum;
|
||||
import org.dromara.dbswitch.core.annotation.Product;
|
||||
import org.dromara.dbswitch.core.features.ProductFeatures;
|
||||
import org.dromara.dbswitch.core.provider.AbstractFactoryProvider;
|
||||
import org.dromara.dbswitch.core.provider.manage.TableManageProvider;
|
||||
import org.dromara.dbswitch.core.provider.meta.MetadataProvider;
|
||||
import org.dromara.dbswitch.core.provider.query.TableDataQueryProvider;
|
||||
import org.dromara.dbswitch.core.provider.sync.TableDataSynchronizeProvider;
|
||||
import org.dromara.dbswitch.core.provider.write.TableDataWriteProvider;
|
||||
|
||||
@Product(ProductTypeEnum.TDENGINE)
|
||||
public class TdengineFactoryProvider extends AbstractFactoryProvider {
|
||||
|
||||
public TdengineFactoryProvider(DataSource dataSource) {
|
||||
super(dataSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProductFeatures getProductFeatures() {
|
||||
return new TdengineFeatures();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetadataProvider createMetadataQueryProvider() {
|
||||
return new TdengineMetadataQueryProvider(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDataWriteProvider createTableDataWriteProvider(boolean useInsert) {
|
||||
return new TDengineTableDataWriteProvider(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDataSynchronizeProvider createTableDataSynchronizeProvider() {
|
||||
return new TdengineTableSynchronizer(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDataQueryProvider createTableDataQueryProvider() {
|
||||
return new TdengineTableDataQueryProvider(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableManageProvider createTableManageProvider() {
|
||||
return new TdengineTableManageProvider(this);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
// Copyright tang. All rights reserved.
|
||||
// https://gitee.com/inrgihc/dbswitch
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
//
|
||||
// Author: Li ZeMin (2413957313@qq.com)
|
||||
// Date : 2024/12/16
|
||||
// Location: nanjing , china
|
||||
/////////////////////////////////////////////////////////////
|
||||
package org.dromara.dbswitch.product.tdengine;
|
||||
|
||||
import org.dromara.dbswitch.core.features.ProductFeatures;
|
||||
|
||||
public class TdengineFeatures implements ProductFeatures {
|
||||
|
||||
@Override
|
||||
public int convertFetchSize(int fetchSize) {
|
||||
return fetchSize;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,403 @@
|
||||
// Copyright tang. All rights reserved.
|
||||
// https://gitee.com/inrgihc/dbswitch
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
//
|
||||
// Author: Li ZeMin (2413957313@qq.com)
|
||||
// Date : 2024/12/16
|
||||
// Location: nanjing , china
|
||||
/////////////////////////////////////////////////////////////
|
||||
package org.dromara.dbswitch.product.tdengine;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dromara.dbswitch.common.consts.Constants;
|
||||
import org.dromara.dbswitch.core.provider.ProductFactoryProvider;
|
||||
import org.dromara.dbswitch.core.provider.meta.AbstractMetadataProvider;
|
||||
import org.dromara.dbswitch.core.schema.ColumnDescription;
|
||||
import org.dromara.dbswitch.core.schema.ColumnMetaData;
|
||||
import org.dromara.dbswitch.core.schema.IndexDescription;
|
||||
import org.dromara.dbswitch.core.schema.SourceProperties;
|
||||
import org.dromara.dbswitch.core.schema.TableDescription;
|
||||
|
||||
@Slf4j
|
||||
public class TdengineMetadataQueryProvider extends AbstractMetadataProvider {
|
||||
|
||||
private static final String SHOW_CREATE_TABLE_SQL = "SHOW CREATE TABLE `%s`.`%s` ";
|
||||
private static final String SHOW_CREATE_VIEW_SQL = "SHOW CREATE VIEW `%s`.`%s` ";
|
||||
private static final String QUERY_STABLE_LIST_SQL =
|
||||
"SELECT `db_name`,`stable_name` as table_name,'TABLE' as `type`,`table_comment` "
|
||||
+ "FROM `information_schema`.`ins_stables` WHERE `db_name`= ? ";
|
||||
|
||||
private static final String QUERY_TABLE_LIST_SQL =
|
||||
"SELECT `db_name`,`table_name`,`type`,`table_comment` "
|
||||
+ "FROM `information_schema`.`ins_tables` WHERE `db_name`= ? ";
|
||||
private static final String QUERY_TABLE_METADATA_SQL =
|
||||
"SELECT `table_comment`,`type` FROM `information_schema`.`ins_tables` "
|
||||
+ "WHERE `db_name` = ? AND `table_name` = ?";
|
||||
|
||||
public TdengineMetadataQueryProvider(ProductFactoryProvider factoryProvider) {
|
||||
super(factoryProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> querySchemaList(Connection connection) {
|
||||
List<String> result = new ArrayList<>();
|
||||
try (ResultSet rs = connection.getMetaData().getCatalogs()) {
|
||||
while (rs.next()) {
|
||||
Optional.ofNullable(rs.getString(1)).ifPresent(result::add);
|
||||
}
|
||||
return result.stream().distinct().collect(Collectors.toList());
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TableDescription> queryTableList(Connection connection, String schemaName) {
|
||||
List<TableDescription> result = new ArrayList<>();
|
||||
try (PreparedStatement ps = connection.prepareStatement(QUERY_STABLE_LIST_SQL)) {
|
||||
ps.setString(1, schemaName);
|
||||
try (ResultSet rs = ps.executeQuery();) {
|
||||
while (rs.next()) {
|
||||
TableDescription td = new TableDescription();
|
||||
td.setSchemaName(rs.getString("db_name"));
|
||||
td.setTableName(rs.getString("table_name"));
|
||||
td.setRemarks(rs.getString("table_comment"));
|
||||
String tableType = rs.getString("type");
|
||||
if (tableType.equalsIgnoreCase("VIEW")) {
|
||||
td.setTableType("VIEW");
|
||||
} else {
|
||||
td.setTableType("TABLE");
|
||||
}
|
||||
|
||||
result.add(td);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
try (PreparedStatement ps = connection.prepareStatement(QUERY_TABLE_LIST_SQL)) {
|
||||
ps.setString(1, schemaName);
|
||||
try (ResultSet rs = ps.executeQuery();) {
|
||||
while (rs.next()) {
|
||||
TableDescription td = new TableDescription();
|
||||
td.setSchemaName(rs.getString("db_name"));
|
||||
td.setTableName(rs.getString("table_name"));
|
||||
td.setRemarks(rs.getString("table_comment"));
|
||||
String tableType = rs.getString("type");
|
||||
if (tableType.equalsIgnoreCase("VIEW")) {
|
||||
td.setTableType("VIEW");
|
||||
} else {
|
||||
td.setTableType("TABLE");
|
||||
}
|
||||
|
||||
result.add(td);
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableDescription queryTableMeta(Connection connection, String schemaName, String tableName) {
|
||||
try (PreparedStatement ps = connection.prepareStatement(QUERY_TABLE_METADATA_SQL)) {
|
||||
ps.setString(1, schemaName);
|
||||
ps.setString(2, tableName);
|
||||
try (ResultSet rs = ps.executeQuery();) {
|
||||
while (rs.next()) {
|
||||
TableDescription td = new TableDescription();
|
||||
td.setSchemaName(schemaName);
|
||||
td.setTableName(tableName);
|
||||
td.setRemarks(rs.getString(1));
|
||||
|
||||
String tableType = rs.getString(2);
|
||||
if (tableType.equalsIgnoreCase("VIEW")) {
|
||||
td.setTableType("VIEW");
|
||||
} else {
|
||||
td.setTableType("TABLE");
|
||||
}
|
||||
|
||||
return td;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> queryTableColumnName(Connection connection, String schemaName, String tableName) {
|
||||
List<String> columns = new ArrayList<>();
|
||||
try (ResultSet rs = connection.getMetaData()
|
||||
.getColumns(schemaName, null, tableName, null)) {
|
||||
while (rs.next()) {
|
||||
columns.add(rs.getString("COLUMN_NAME"));
|
||||
}
|
||||
return columns.stream().distinct().collect(Collectors.toList());
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<ColumnDescription> queryTableColumnMeta(Connection connection, String schemaName,
|
||||
String tableName) {
|
||||
String sql = this.getTableFieldsQuerySQL(schemaName, tableName);
|
||||
List<ColumnDescription> ret = this.querySelectSqlColumnMeta(connection, sql);
|
||||
|
||||
// 补充一下注释信息
|
||||
try (ResultSet columns = connection.getMetaData()
|
||||
.getColumns(schemaName, null, tableName, null)) {
|
||||
while (columns.next()) {
|
||||
String columnName = columns.getString("COLUMN_NAME");
|
||||
String remarks = columns.getString("REMARKS");
|
||||
String columnDefault = columns.getString("COLUMN_DEF");
|
||||
for (ColumnDescription cd : ret) {
|
||||
if (columnName.equals(cd.getFieldName())) {
|
||||
cd.setRemarks(remarks);
|
||||
// 补充默认值信息
|
||||
cd.setDefaultValue(columnDefault);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> queryTablePrimaryKeys(Connection connection, String schemaName, String tableName) {
|
||||
List<String> ret = new ArrayList<>();
|
||||
try (ResultSet primaryKeys = connection.getMetaData()
|
||||
.getPrimaryKeys(schemaName, null, tableName)) {
|
||||
while (primaryKeys.next()) {
|
||||
ret.add(primaryKeys.getString("COLUMN_NAME"));
|
||||
}
|
||||
return ret.stream().distinct().collect(Collectors.toList());
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<IndexDescription> queryTableIndexes(Connection connection, String schemaName,
|
||||
String tableName) {
|
||||
setCatalogName(schemaName);
|
||||
return super.queryTableIndexes(connection, schemaName, tableName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableDDL(Connection connection, String schemaName, String tableName) {
|
||||
List<String> result = new ArrayList<>();
|
||||
try (Statement st = connection.createStatement()) {
|
||||
if (st.execute(String.format(SHOW_CREATE_TABLE_SQL, schemaName, tableName))) {
|
||||
try (ResultSet rs = st.getResultSet()) {
|
||||
if (rs != null) {
|
||||
while (rs.next()) {
|
||||
String value = rs.getString(2);
|
||||
Optional.ofNullable(value).ifPresent(result::add);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return result.stream().findAny().orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getViewDDL(Connection connection, String schemaName, String tableName) {
|
||||
List<String> result = new ArrayList<>();
|
||||
try (Statement st = connection.createStatement()) {
|
||||
if (st.execute(String.format(SHOW_CREATE_VIEW_SQL, schemaName, tableName))) {
|
||||
try (ResultSet rs = st.getResultSet()) {
|
||||
if (rs != null) {
|
||||
while (rs.next()) {
|
||||
String value = rs.getString(2);
|
||||
Optional.ofNullable(value).ifPresent(result::add);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return result.stream().findAny().orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ColumnDescription> querySelectSqlColumnMeta(Connection connection, String sql) {
|
||||
String querySQL = String.format(" %s LIMIT 0,1", sql.replace(";", ""));
|
||||
return this.getSelectSqlColumnMeta(connection, querySQL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testQuerySQL(Connection connection, String sql) {
|
||||
String testQuerySql = String.format("explain %s", sql.replace(";", ""));
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Execute sql :{}", testQuerySql);
|
||||
}
|
||||
try (Statement st = connection.createStatement()) {
|
||||
st.execute(testQuerySql);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFieldDefinition(ColumnMetaData v, List<String> pks, boolean useAutoInc,
|
||||
boolean addCr, boolean withRemarks) {
|
||||
String fieldname = v.getName();
|
||||
int length = v.getLength();
|
||||
int precision = v.getPrecision();
|
||||
int type = v.getType();
|
||||
|
||||
String retval = " `" + fieldname + "` ";
|
||||
|
||||
switch (type) {
|
||||
case ColumnMetaData.TYPE_TIMESTAMP:
|
||||
retval += "TIMESTAMP";
|
||||
break;
|
||||
case ColumnMetaData.TYPE_TIME:
|
||||
retval += "TIME";
|
||||
break;
|
||||
case ColumnMetaData.TYPE_DATE:
|
||||
retval += "DATE";
|
||||
break;
|
||||
case ColumnMetaData.TYPE_BOOLEAN:
|
||||
retval += "TINYINT";
|
||||
break;
|
||||
case ColumnMetaData.TYPE_NUMBER:
|
||||
case ColumnMetaData.TYPE_INTEGER:
|
||||
case ColumnMetaData.TYPE_BIGNUMBER:
|
||||
if (null != pks && !pks.isEmpty() && pks.contains(fieldname)) {
|
||||
if (useAutoInc) {
|
||||
retval += "BIGINT AUTO_INCREMENT NOT NULL";
|
||||
} else {
|
||||
retval += "BIGINT NOT NULL";
|
||||
}
|
||||
} else {
|
||||
// Integer values...
|
||||
if (precision == 0) {
|
||||
if (length > 9) {
|
||||
if (length < 19) {
|
||||
// can hold signed values between -9223372036854775808 and 9223372036854775807
|
||||
// 18 significant digits
|
||||
retval += "BIGINT";
|
||||
} else {
|
||||
retval += "DECIMAL(" + length + ")";
|
||||
}
|
||||
} else {
|
||||
retval += "INT";
|
||||
}
|
||||
} else {
|
||||
// Floating point values...
|
||||
if (length > 65) {
|
||||
length = 65;
|
||||
}
|
||||
if (length > 15) {
|
||||
retval += "DECIMAL(" + length;
|
||||
if (precision > 0) {
|
||||
retval += ", " + precision;
|
||||
}
|
||||
retval += ")";
|
||||
} else {
|
||||
// A double-precision floating-point number is accurate to approximately 15
|
||||
// decimal places.
|
||||
// http://mysql.mirrors-r-us.net/doc/refman/5.1/en/numeric-type-overview.html
|
||||
retval += "DOUBLE";
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ColumnMetaData.TYPE_STRING:
|
||||
if (length > 0) {
|
||||
if (length == 1) {
|
||||
retval += "CHAR(1)";
|
||||
} else if (length < 256) {
|
||||
retval += "VARCHAR(" + length + ")";
|
||||
} else if (null != pks && !pks.isEmpty() && pks.contains(fieldname)) {
|
||||
/*
|
||||
* MySQL5.6中varchar字段为主键时最大长度为254,例如如下的建表语句在MySQL5.7下能通过,但在MySQL5.6下无法通过:
|
||||
* create table `t_test`(
|
||||
* `key` varchar(1024) binary,
|
||||
* `val` varchar(1024) binary,
|
||||
* primary key(`key`)
|
||||
* );
|
||||
*/
|
||||
retval += "VARCHAR(254) BINARY";
|
||||
} else if (length < 65536) {
|
||||
retval += "TEXT";
|
||||
} else if (length < 16777216) {
|
||||
retval += "MEDIUMTEXT";
|
||||
} else {
|
||||
retval += "LONGTEXT";
|
||||
}
|
||||
} else {
|
||||
retval += "TINYTEXT";
|
||||
}
|
||||
break;
|
||||
case ColumnMetaData.TYPE_BINARY:
|
||||
retval += "LONGBLOB";
|
||||
break;
|
||||
default:
|
||||
retval += "LONGTEXT";
|
||||
break;
|
||||
}
|
||||
|
||||
if (withRemarks && StringUtils.isNotBlank(v.getRemarks())) {
|
||||
retval += String.format(" COMMENT '%s' ", v.getRemarks().replace("'", "\\'"));
|
||||
}
|
||||
|
||||
if (addCr) {
|
||||
retval += Constants.CR;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTableColumnCommentDefinition(TableDescription td, List<ColumnDescription> cds) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preAppendCreateTableSql(StringBuilder builder) {
|
||||
// builder.append( Const.IF_NOT_EXISTS );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postAppendCreateTableSql(StringBuilder builder, String tblComment, List<String> primaryKeys,
|
||||
SourceProperties tblProperties) {
|
||||
if (StringUtils.isNotBlank(tblComment)) {
|
||||
builder.append(String.format(" COMMENT='%s' ", tblComment.replace("'", "\\'")));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendPrimaryKeyForCreateTableSql(StringBuilder builder, List<String> primaryKeys) {
|
||||
// Tdengine默认第一个字段为主键
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
// Copyright tang. All rights reserved.
|
||||
// https://gitee.com/inrgihc/dbswitch
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
//
|
||||
// Author: Li ZeMin (2413957313@qq.com)
|
||||
// Date : 2024/12/16
|
||||
// Location: nanjing , china
|
||||
/////////////////////////////////////////////////////////////
|
||||
package org.dromara.dbswitch.product.tdengine;
|
||||
|
||||
import cn.hutool.core.util.HexUtil;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.dromara.dbswitch.common.util.ObjectCastUtils;
|
||||
import org.dromara.dbswitch.core.provider.ProductFactoryProvider;
|
||||
import org.dromara.dbswitch.core.provider.query.DefaultTableDataQueryProvider;
|
||||
import org.dromara.dbswitch.core.schema.SchemaTableData;
|
||||
|
||||
public class TdengineTableDataQueryProvider extends DefaultTableDataQueryProvider {
|
||||
|
||||
public TdengineTableDataQueryProvider(ProductFactoryProvider factoryProvider) {
|
||||
super(factoryProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchemaTableData queryTableData(Connection connection, String schemaName, String tableName, int rowCount) {
|
||||
String fullTableName = quoteSchemaTableName(schemaName, tableName);
|
||||
String querySQL = String.format("SELECT * FROM %s limit %s", fullTableName, rowCount);
|
||||
SchemaTableData data = new SchemaTableData();
|
||||
data.setSchemaName(schemaName);
|
||||
data.setTableName(tableName);
|
||||
data.setColumns(new ArrayList<>());
|
||||
data.setRows(new ArrayList<>());
|
||||
try (Statement st = connection.createStatement()) {
|
||||
beforeExecuteQuery(connection, schemaName, tableName);
|
||||
try (ResultSet rs = st.executeQuery(querySQL)) {
|
||||
ResultSetMetaData m = rs.getMetaData();
|
||||
int count = m.getColumnCount();
|
||||
for (int i = 1; i <= count; i++) {
|
||||
data.getColumns().add(m.getColumnLabel(i));
|
||||
}
|
||||
|
||||
int counter = 0;
|
||||
while (rs.next() && counter++ < rowCount) {
|
||||
List<Object> row = new ArrayList<>(count);
|
||||
for (int i = 1; i <= count; i++) {
|
||||
Object value = rs.getObject(i);
|
||||
if (value instanceof byte[]) {
|
||||
row.add(HexUtil.encodeHexStr((byte[]) value));
|
||||
} else if (value instanceof java.sql.Clob) {
|
||||
row.add(ObjectCastUtils.castToString(value));
|
||||
} else if (value instanceof java.sql.Blob) {
|
||||
byte[] bytes = ObjectCastUtils.castToByteArray(value);
|
||||
row.add(HexUtil.encodeHexStr(bytes));
|
||||
} else {
|
||||
row.add(null == value ? null : value.toString());
|
||||
}
|
||||
}
|
||||
data.getRows().add(row);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
// Copyright tang. All rights reserved.
|
||||
// https://gitee.com/inrgihc/dbswitch
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
//
|
||||
// Author: Li ZeMin (2413957313@qq.com)
|
||||
// Date : 2024/12/16
|
||||
// Location: nanjing , china
|
||||
/////////////////////////////////////////////////////////////
|
||||
package org.dromara.dbswitch.product.tdengine;
|
||||
|
||||
import org.dromara.dbswitch.core.provider.ProductFactoryProvider;
|
||||
import org.dromara.dbswitch.core.provider.manage.DefaultTableManageProvider;
|
||||
|
||||
public class TdengineTableManageProvider extends DefaultTableManageProvider {
|
||||
|
||||
public TdengineTableManageProvider(ProductFactoryProvider factoryProvider) {
|
||||
super(factoryProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void truncateTableData(String schemaName, String tableName) {
|
||||
String sql = String.format("DELETE FROM %s.%s ",
|
||||
schemaName, tableName);
|
||||
this.executeSql(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropTable(String schemaName, String tableName) {
|
||||
String sql = String.format("DROP TABLE %s.%s ",
|
||||
schemaName, tableName);
|
||||
this.executeSql(sql);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
// Copyright tang. All rights reserved.
|
||||
// https://gitee.com/inrgihc/dbswitch
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
//
|
||||
// Author: Li ZeMin (2413957313@qq.com)
|
||||
// Date : 2024/12/16
|
||||
// Location: nanjing , china
|
||||
/////////////////////////////////////////////////////////////
|
||||
package org.dromara.dbswitch.product.tdengine;
|
||||
|
||||
import org.dromara.dbswitch.core.provider.ProductFactoryProvider;
|
||||
import org.dromara.dbswitch.core.provider.sync.AutoCastTableDataSynchronizeProvider;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
|
||||
public class TdengineTableSynchronizer extends AutoCastTableDataSynchronizeProvider {
|
||||
|
||||
public TdengineTableSynchronizer(ProductFactoryProvider factoryProvider) {
|
||||
super(factoryProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TransactionDefinition getDefaultTransactionDefinition() {
|
||||
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
|
||||
return definition;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1 @@
|
||||
org.dromara.dbswitch.product.tdengine.TdengineFactoryProvider
|
@@ -123,6 +123,11 @@
|
||||
<artifactId>dbswitch-product-oceanbase</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara.dbswitch</groupId>
|
||||
<artifactId>dbswitch-product-tdengine</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -35,6 +35,7 @@
|
||||
<module>dbswitch-product-greenplum</module>
|
||||
<module>dbswitch-product-doris</module>
|
||||
<module>dbswitch-product-oceanbase</module>
|
||||
<module>dbswitch-product-tdengine</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
BIN
drivers/tdengine/tdengine-3.0.0/taos-jdbcdriver-3.0.0.jar
Normal file
BIN
drivers/tdengine/tdengine-3.0.0/taos-jdbcdriver-3.0.0.jar
Normal file
Binary file not shown.
Reference in New Issue
Block a user