同步时执行附加SQL

This commit is contained in:
inrgihc
2023-12-30 20:44:54 +08:00
parent d06a97307a
commit 3f1cd0622c
64 changed files with 589 additions and 184 deletions

View File

@@ -2,7 +2,7 @@
set -e
DBSWITCH_VERSION=1.9.2
DBSWITCH_VERSION=1.9.3
BUILD_DOCKER_DIR="$( cd "$( dirname "$0" )" && pwd )"
PROJECT_ROOT_DIR=$( dirname "$BUILD_DOCKER_DIR")
DOCKER_DBSWITCH_DIR=$BUILD_DOCKER_DIR/dbswitch

View File

@@ -18,7 +18,7 @@ services:
start_period: 30s
dbswitch:
container_name: dbswitch_webui
image: inrgihc/dbswitch:1.9.2
image: inrgihc/dbswitch:1.9.3
environment:
MYSQLDB_HOST: dbswitch_mysqldb
MYSQLDB_PORT: 3306

View File

@@ -192,10 +192,10 @@
</span>
<el-tooltip placement="top">
<div slot="content">
<p>目标端建表并同步数据首次在目标的自动建表(存在重命表时会删除重建)然后执行数据同步(支持有主键表的变化量同步)操作</p>
<p>目标端只创建物理表: 只在目标端自动建表存在重名表时会删除后重建</p>
<p>目标端只同步表里数据如果只同步数据内容则需要目标端需要存在符合映射规则的物理表在执行任务前手动建好该选项通<br />
常适用于两端表结构相同(目标端字段包含源端所有的字段且字段数据类型相似)的数据同步场景</p>
<p>目标端建表并同步数据首次在目标的自动建表(存在重命表时会删除重建)并执行数据加载同步操作再次执行时会根据是否有主键进行变化量同步</p>
<p>目标端只创建物理表: 每次执行时只在目标端自动建表存在重名表时会删除后重建</p>
<p>目标端只同步表里数据每次执行时目标端需要存在符合映射规则的物理表最迟需要在执行任务前已经存在目标表该选项通<br />
常适用于两端表结构一致(目标端字段包含源端所有的字段且字段数据类型一致)的数据同步场景</p>
</div>
<i class="el-icon-question"></i>
</el-tooltip>
@@ -227,29 +227,6 @@
:value=false></el-option>
</el-select>
</el-form-item>
<el-form-item label="数据批次大小"
label-width="240px"
:required=true
v-if=" createform.autoSyncMode!==1 "
prop="batchSize"
style="width:65%">
<el-tooltip placement="top">
<div slot="content">
数据同步时单个批次处理的行记录总数该值越到越占用内存空间建议小字段表设置为10000或20000大字段表设置为1000
</div>
<i class="el-icon-question"></i>
</el-tooltip>
<el-select v-model="createform.batchSize">
<el-option label=1000
:value=1000></el-option>
<el-option label=5000
:value=5000></el-option>
<el-option label=10000
:value=10000></el-option>
<el-option label=20000
:value=20000></el-option>
</el-select>
</el-form-item>
<el-form-item label="表名大小写转换"
label-width="240px"
:required=true
@@ -292,6 +269,90 @@
value='LOWER'></el-option>
</el-select>
</el-form-item>
<el-form-item label="数据批次大小"
label-width="240px"
:required=true
v-if=" createform.autoSyncMode!==1 "
prop="batchSize"
style="width:65%">
<el-tooltip placement="top">
<div slot="content">
数据同步时单个批次处理的行记录总数该值越到越占用内存空间建议小字段表设置为10000或20000大字段表设置为1000
</div>
<i class="el-icon-question"></i>
</el-tooltip>
<el-select v-model="createform.batchSize">
<el-option label=1000
:value=1000></el-option>
<el-option label=5000
:value=5000></el-option>
<el-option label=10000
:value=10000></el-option>
<el-option label=20000
:value=20000></el-option>
</el-select>
</el-form-item>
<el-form-item label="同步操作方法"
label-width="240px"
:required=true
v-if=" createform.autoSyncMode!==1 "
prop="targetSyncOption"
style="width:65%">
<el-tooltip placement="top">
<div slot="content">
数据同步时包括增删改操作这里选择配置执行INSERTUPDATEDELETE操作类型的方法对首次数据加载无效只对数据同步有效
</div>
<i class="el-icon-question"></i>
</el-tooltip>
<el-select v-model="createform.targetSyncOption">
<el-option label='只同步INSERT操作'
value='ONLY_INSERT'></el-option>
<el-option label='只同步UPDATE操作'
value='ONLY_UPDATE'></el-option>
<el-option label='只同步INSERT和UPDATE'
value='INSERT_UPDATE'></el-option>
<el-option label='只同步DELETE操作'
value='INSERT_DELETE'></el-option>
<el-option label='只同步INSERT和DELETE'
value='UPDATE_DELETE'></el-option>
<el-option label='只同步UPDATE和DELETE'
value='ONLY_DELETE'></el-option>
<el-option label='执行所有的同步操作'
value='INSERT_UPDATE_DELETE'></el-option>
</el-select>
</el-form-item>
<el-form-item label="同步前置执行SQL脚本"
label-width="240px"
v-if=" createform.autoSyncMode!==1 "
prop="beforeSqlScripts"
style="width:65%">
<el-tooltip placement="top">
<div slot="content">
数据同步写入目标断数据库前执行的SQL多个SQL间以英文逗号分隔使用场景如MySQL数据库关闭外键约束 SET FOREIGN_KEY_CHECKS = 0
</div>
<i class="el-icon-question"></i>
</el-tooltip>
<el-input v-model="createform.beforeSqlScripts"
type="textarea"
:rows="3"
auto-complete="off"></el-input>
</el-form-item>
<el-form-item label="同步后置执行SQL脚本"
label-width="240px"
v-if=" createform.autoSyncMode!==1 "
prop="afterSqlScripts"
style="width:65%">
<el-tooltip placement="top">
<div slot="content">
数据同步写入目标断数据库后执行的SQL多个SQL间以英文逗号分隔使用场景如MySQL数据库恢复外键约束 SET FOREIGN_KEY_CHECKS = 1
</div>
<i class="el-icon-question"></i>
</el-tooltip>
<el-input v-model="createform.afterSqlScripts"
type="textarea"
:rows="3"
auto-complete="off"></el-input>
</el-form-item>
</div>
<div v-show="active == 4">
<el-alert title="说明信息"
@@ -423,8 +484,6 @@
</el-descriptions-item>
<el-descriptions-item label="建表字段自增"
v-if=" createform.autoSyncMode!==0 ">{{createform.targetAutoIncrement}}</el-descriptions-item>
<el-descriptions-item label="数据批次大小"
v-if=" createform.autoSyncMode!==1 ">{{createform.batchSize}}</el-descriptions-item>
<el-descriptions-item label="表名大小写转换"
v-if=" createform.autoSyncMode!==0 ">
<span v-if="createform.tableNameCase == 'NONE'">
@@ -449,6 +508,20 @@
转小写
</span>
</el-descriptions-item>
<el-descriptions-item label="数据批次大小"
v-if=" createform.autoSyncMode!==1 ">{{createform.batchSize}}</el-descriptions-item>
<el-descriptions-item label="同步操作方法"
v-if=" createform.autoSyncMode!==1 ">{{createform.targetSyncOption}}</el-descriptions-item>
<el-descriptions-item label="同步前置执行SQL脚本"
v-if=" createform.autoSyncMode!==1 ">
<span v-show="!createform.beforeSqlScripts || createform.beforeSqlScripts.length==0">[SQL脚本内容为空]</span>
<span v-show="createform.beforeSqlScripts.length>0">{{createform.beforeSqlScripts}}</span>
</el-descriptions-item>
<el-descriptions-item label="同步后置执行SQL脚本"
v-if=" createform.autoSyncMode!==1 ">
<span v-show="!createform.afterSqlScripts || createform.afterSqlScripts.length==0">[SQL脚本内容为空]</span>
<span v-show="createform.afterSqlScripts.length>0">{{createform.afterSqlScripts}}</span>
</el-descriptions-item>
<el-descriptions-item label="表名映射规则">
<span v-show="createform.tableNameMapper.length==0">[映射关系为空]</span>
<table v-if="createform.tableNameMapper.length>0"
@@ -582,7 +655,10 @@ export default {
targetAutoIncrement: false,
autoSyncMode: 2,
targetSchema: "",
batchSize: 5000
batchSize: 5000,
targetSyncOption: 'INSERT_UPDATE_DELETE',
beforeSqlScripts: '',
afterSqlScripts: '',
},
rules: {
name: [
@@ -663,6 +739,14 @@ export default {
message: "必选选择一个批大小",
trigger: "change"
}
],
targetSyncOption: [
{
required: true,
type: 'string',
message: "必选选择一个同步方法来 ",
trigger: "change"
}
]
},
active: 1,
@@ -963,7 +1047,10 @@ export default {
targetDropTable: this.createform.targetDropTable,
targetOnlyCreate: this.createform.targetOnlyCreate,
targetAutoIncrement: this.createform.targetAutoIncrement,
batchSize: this.createform.batchSize
batchSize: this.createform.batchSize,
targetSyncOption: this.createform.targetSyncOption,
beforeSqlScripts: this.createform.beforeSqlScripts,
afterSqlScripts: this.createform.afterSqlScripts,
}
})
}).then(res => {

View File

@@ -50,8 +50,6 @@
</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!==1 ">{{updateform.batchSize}}</el-descriptions-item>
<el-descriptions-item label="表名大小写转换"
v-if=" updateform.autoSyncMode!==0 ">
<span v-if="updateform.tableNameCase == 'NONE'">
@@ -76,6 +74,20 @@
转小写
</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.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"
@@ -143,7 +155,10 @@ export default {
targetOnlyCreate: false,
autoSyncMode: 2,
targetSchema: "",
batchSize: 5000
batchSize: 5000,
targetSyncOption: 'INSERT_UPDATE_DELETE',
beforeSqlScripts: '',
afterSqlScripts: '',
},
sourceConnection: {},
targetConnection: {},
@@ -190,7 +205,10 @@ export default {
targetAutoIncrement: detail.configuration.targetAutoIncrement,
autoSyncMode: varAutoSyncMode,
targetSchema: detail.configuration.targetSchema,
batchSize: detail.configuration.batchSize
batchSize: detail.configuration.batchSize,
targetSyncOption: detail.configuration.targetSyncOption,
beforeSqlScripts: detail.configuration.beforeSqlScripts,
afterSqlScripts: detail.configuration.afterSqlScripts,
}
this.selectChangedSourceConnection(this.updateform.sourceConnectionId)
this.selectUpdateChangedSourceSchema(this.updateform.sourceSchema)

View File

@@ -191,10 +191,10 @@
</span>
<el-tooltip placement="top">
<div slot="content">
<p>目标端建表并同步数据首次在目标的自动建表(存在重命表时会删除重建)然后执行数据同步(支持有主键表的变化量同步)操作</p>
<p>目标端只创建物理表: 只在目标端自动建表存在重名表时会删除后重建</p>
<p>目标端只同步表里数据如果只同步数据内容则需要目标端需要存在符合映射规则的物理表在执行任务前手动建好该选项通<br />
常适用于两端表结构相同(目标端字段包含源端所有的字段且字段数据类型相似)的数据同步场景</p>
<p>目标端建表并同步数据首次在目标的自动建表(存在重命表时会删除重建)并执行数据加载同步操作再次执行时会根据是否有主键进行变化量同步</p>
<p>目标端只创建物理表: 每次执行时只在目标端自动建表存在重名表时会删除后重建</p>
<p>目标端只同步表里数据每次执行时目标端需要存在符合映射规则的物理表最迟需要在执行任务前已经存在目标表该选项通<br />
常适用于两端表结构一致(目标端字段包含源端所有的字段且字段数据类型一致)的数据同步场景</p>
</div>
<i class="el-icon-question"></i>
</el-tooltip>
@@ -226,29 +226,6 @@
:value=false></el-option>
</el-select>
</el-form-item>
<el-form-item label="数据批次大小"
label-width="240px"
:required=true
v-if=" updateform.autoSyncMode!==1 "
prop="batchSize"
style="width:65%">
<el-tooltip placement="top">
<div slot="content">
数据同步时单个批次处理的行记录总数该值越到越占用内存空间建议小字段表设置为10000或20000大字段表设置为1000
</div>
<i class="el-icon-question"></i>
</el-tooltip>
<el-select v-model="updateform.batchSize">
<el-option label=1000
:value=1000></el-option>
<el-option label=5000
:value=5000></el-option>
<el-option label=10000
:value=10000></el-option>
<el-option label=20000
:value=20000></el-option>
</el-select>
</el-form-item>
<el-form-item label="表名大小写转换"
label-width="240px"
:required=true
@@ -291,6 +268,90 @@
value='LOWER'></el-option>
</el-select>
</el-form-item>
<el-form-item label="数据批次大小"
label-width="240px"
:required=true
v-if=" updateform.autoSyncMode!==1 "
prop="batchSize"
style="width:65%">
<el-tooltip placement="top">
<div slot="content">
数据同步时单个批次处理的行记录总数该值越到越占用内存空间建议小字段表设置为10000或20000大字段表设置为1000
</div>
<i class="el-icon-question"></i>
</el-tooltip>
<el-select v-model="updateform.batchSize">
<el-option label=1000
:value=1000></el-option>
<el-option label=5000
:value=5000></el-option>
<el-option label=10000
:value=10000></el-option>
<el-option label=20000
:value=20000></el-option>
</el-select>
</el-form-item>
<el-form-item label="同步操作方法"
label-width="240px"
:required=true
v-if=" updateform.autoSyncMode!==1 "
prop="targetSyncOption"
style="width:65%">
<el-tooltip placement="top">
<div slot="content">
数据同步时包括增删改操作这里选择配置执行INSERTUPDATEDELETE操作类型的方法对首次数据加载无效只对数据同步有效
</div>
<i class="el-icon-question"></i>
</el-tooltip>
<el-select v-model="updateform.targetSyncOption">
<el-option label='只同步INSERT操作'
value='ONLY_INSERT'></el-option>
<el-option label='只同步UPDATE操作'
value='ONLY_UPDATE'></el-option>
<el-option label='只同步INSERT和UPDATE'
value='INSERT_UPDATE'></el-option>
<el-option label='只同步DELETE操作'
value='INSERT_DELETE'></el-option>
<el-option label='只同步INSERT和DELETE'
value='UPDATE_DELETE'></el-option>
<el-option label='只同步UPDATE和DELETE'
value='ONLY_DELETE'></el-option>
<el-option label='执行所有的同步操作'
value='INSERT_UPDATE_DELETE'></el-option>
</el-select>
</el-form-item>
<el-form-item label="同步前置执行SQL脚本"
label-width="240px"
v-if=" updateform.autoSyncMode!==1 "
prop="beforeSqlScripts"
style="width:65%">
<el-tooltip placement="top">
<div slot="content">
数据同步写入目标断数据库前执行的SQL多个SQL间以英文逗号分隔使用场景如MySQL数据库关闭外键约束 SET FOREIGN_KEY_CHECKS = 0
</div>
<i class="el-icon-question"></i>
</el-tooltip>
<el-input v-model="updateform.beforeSqlScripts"
type="textarea"
:rows="3"
auto-complete="off"></el-input>
</el-form-item>
<el-form-item label="同步后置执行SQL脚本"
label-width="240px"
v-if=" updateform.autoSyncMode!==1 "
prop="afterSqlScripts"
style="width:65%">
<el-tooltip placement="top">
<div slot="content">
数据同步写入目标断数据库后执行的SQL多个SQL间以英文逗号分隔使用场景如MySQL数据库恢复外键约束 SET FOREIGN_KEY_CHECKS = 1
</div>
<i class="el-icon-question"></i>
</el-tooltip>
<el-input v-model="updateform.afterSqlScripts"
type="textarea"
:rows="3"
auto-complete="off"></el-input>
</el-form-item>
</div>
<div v-show="active == 4">
<el-alert title="说明信息"
@@ -422,8 +483,6 @@
</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!==1 ">{{updateform.batchSize}}</el-descriptions-item>
<el-descriptions-item label="表名大小写转换"
v-if=" updateform.autoSyncMode!==0 ">
<span v-if="updateform.tableNameCase == 'NONE'">
@@ -448,6 +507,20 @@
转小写
</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.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"
@@ -587,7 +660,10 @@ export default {
targetAutoIncrement: false,
autoSyncMode: 2,
targetSchema: "",
batchSize: 5000
batchSize: 5000,
targetSyncOption: 'INSERT_UPDATE_DELETE',
beforeSqlScripts: '',
afterSqlScripts: '',
},
rules: {
name: [
@@ -668,6 +744,14 @@ export default {
message: "必选选择一个批大小",
trigger: "change"
}
],
targetSyncOption: [
{
required: true,
type: 'string',
message: "必选选择一个同步方法来 ",
trigger: "change"
}
]
},
can_go_back: true,
@@ -759,7 +843,10 @@ export default {
targetAutoIncrement: detail.configuration.targetAutoIncrement,
autoSyncMode: varAutoSyncMode,
targetSchema: detail.configuration.targetSchema,
batchSize: detail.configuration.batchSize
batchSize: detail.configuration.batchSize,
targetSyncOption: detail.configuration.targetSyncOption,
beforeSqlScripts: detail.configuration.beforeSqlScripts,
afterSqlScripts: detail.configuration.afterSqlScripts,
}
this.selectChangedSourceConnection(this.updateform.sourceConnectionId)
this.selectUpdateChangedSourceSchema(this.updateform.sourceSchema)
@@ -1034,7 +1121,11 @@ export default {
columnNameCase: this.updateform.columnNameCase,
targetDropTable: this.updateform.targetDropTable,
targetOnlyCreate: this.updateform.targetOnlyCreate,
batchSize: this.updateform.batchSize
targetAutoIncrement: this.updateform.targetAutoIncrement,
batchSize: this.updateform.batchSize,
targetSyncOption: this.updateform.targetSyncOption,
beforeSqlScripts: this.updateform.beforeSqlScripts,
afterSqlScripts: this.updateform.afterSqlScripts,
}
})
}).then(res => {

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.gitee.dbswitch</groupId>
<artifactId>dbswitch-parent</artifactId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<artifactId>dbswitch-admin</artifactId>

View File

@@ -53,6 +53,9 @@ public class AssignmentDetailConverter extends
config.setTableNameMapper(taskConfig.getTableNameMap());
config.setColumnNameMapper(taskConfig.getColumnNameMap());
config.setBatchSize(taskConfig.getBatchSize());
config.setTargetSyncOption(taskConfig.getTargetSyncOption());
config.setBeforeSqlScripts(taskConfig.getBeforeSqlScripts());
config.setAfterSqlScripts(taskConfig.getAfterSqlScripts());
AssignmentDetailResponse detailResponse = new AssignmentDetailResponse();
detailResponse.setId(assignmentTaskEntity.getId());

View File

@@ -19,6 +19,7 @@ import com.gitee.dbswitch.admin.handler.ListTypeHandler;
import com.gitee.dbswitch.common.entity.PatternMapper;
import com.gitee.dbswitch.common.type.CaseConvertEnum;
import com.gitee.dbswitch.common.type.ProductTableEnum;
import com.gitee.dbswitch.common.type.SyncOptionEnum;
import java.sql.Timestamp;
import java.util.List;
import lombok.AllArgsConstructor;
@@ -82,6 +83,15 @@ public class AssignmentConfigEntity {
@TableField("target_auto_increment")
private Boolean targetAutoIncrement;
@TableField(value = "target_sync_option", typeHandler = EnumTypeHandler.class)
private SyncOptionEnum targetSyncOption;
@TableField("before_sql_scripts")
private String beforeSqlScripts;
@TableField("after_sql_scripts")
private String afterSqlScripts;
@TableField("batch_size")
private Integer batchSize;

View File

@@ -19,6 +19,7 @@ import com.gitee.dbswitch.admin.util.CronExprUtils;
import com.gitee.dbswitch.common.entity.PatternMapper;
import com.gitee.dbswitch.common.type.CaseConvertEnum;
import com.gitee.dbswitch.common.type.ProductTableEnum;
import com.gitee.dbswitch.common.type.SyncOptionEnum;
import com.gitee.dbswitch.common.util.PatterNameUtils;
import java.util.List;
import java.util.Objects;
@@ -55,6 +56,9 @@ public class AssigmentCreateRequest {
private Boolean targetDropTable;
private Boolean targetOnlyCreate;
private Boolean targetAutoIncrement;
private SyncOptionEnum targetSyncOption;
private String beforeSqlScripts;
private String afterSqlScripts;
private Integer batchSize;
}
@@ -79,26 +83,31 @@ public class AssigmentCreateRequest {
AssignmentConfigEntity assignmentConfigEntity = new AssignmentConfigEntity();
assignmentConfigEntity.setAssignmentId(assignmentId);
assignmentConfigEntity.setSourceConnectionId(this.getConfig().getSourceConnectionId());
assignmentConfigEntity.setSourceSchema(this.getConfig().getSourceSchema());
assignmentConfigEntity.setTableType(this.getConfig().getTableType());
assignmentConfigEntity.setSourceTables(this.getConfig().getSourceTables());
assignmentConfigEntity.setSourceConnectionId(config.getSourceConnectionId());
assignmentConfigEntity.setSourceSchema(config.getSourceSchema());
assignmentConfigEntity.setTableType(config.getTableType());
assignmentConfigEntity.setSourceTables(config.getSourceTables());
assignmentConfigEntity.setExcluded(
this.getConfig().getIncludeOrExclude() == IncludeExcludeEnum.EXCLUDE
config.getIncludeOrExclude() == IncludeExcludeEnum.EXCLUDE
);
assignmentConfigEntity.setTargetConnectionId(this.getConfig().getTargetConnectionId());
assignmentConfigEntity.setTargetSchema(this.getConfig().getTargetSchema());
assignmentConfigEntity.setTableNameCase(this.getConfig().getTableNameCase());
assignmentConfigEntity.setColumnNameCase(this.getConfig().getColumnNameCase());
assignmentConfigEntity.setTableNameMap(this.getConfig().getTableNameMapper());
assignmentConfigEntity.setColumnNameMap(this.getConfig().getColumnNameMapper());
assignmentConfigEntity.setTargetDropTable(this.getConfig().getTargetDropTable());
assignmentConfigEntity.setTargetOnlyCreate(this.getConfig().getTargetOnlyCreate());
assignmentConfigEntity.setTargetAutoIncrement(this.getConfig().getTargetAutoIncrement());
assignmentConfigEntity.setTargetConnectionId(config.getTargetConnectionId());
assignmentConfigEntity.setTargetSchema(config.getTargetSchema());
assignmentConfigEntity.setTableNameCase(config.getTableNameCase());
assignmentConfigEntity.setColumnNameCase(config.getColumnNameCase());
assignmentConfigEntity.setTableNameMap(config.getTableNameMapper());
assignmentConfigEntity.setColumnNameMap(config.getColumnNameMapper());
assignmentConfigEntity.setTargetDropTable(config.getTargetDropTable());
assignmentConfigEntity.setTargetOnlyCreate(config.getTargetOnlyCreate());
assignmentConfigEntity.setTargetAutoIncrement(config.getTargetAutoIncrement());
assignmentConfigEntity.setBeforeSqlScripts(
Objects.nonNull(config.getBeforeSqlScripts()) ? config.getBeforeSqlScripts().trim() : null);
assignmentConfigEntity.setAfterSqlScripts(
Objects.nonNull(config.getAfterSqlScripts()) ? config.getAfterSqlScripts().trim() : null);
assignmentConfigEntity.setTargetSyncOption(config.getTargetSyncOption());
assignmentConfigEntity.setBatchSize(
Objects.isNull(this.config.getBatchSize())
Objects.isNull(config.getBatchSize())
? 10000
: this.config.getBatchSize()
: config.getBatchSize()
);
assignmentConfigEntity.setFirstFlag(Boolean.TRUE);

View File

@@ -19,6 +19,7 @@ import com.gitee.dbswitch.admin.util.CronExprUtils;
import com.gitee.dbswitch.common.entity.PatternMapper;
import com.gitee.dbswitch.common.type.CaseConvertEnum;
import com.gitee.dbswitch.common.type.ProductTableEnum;
import com.gitee.dbswitch.common.type.SyncOptionEnum;
import java.util.List;
import java.util.Objects;
import lombok.Data;
@@ -52,6 +53,10 @@ public class AssigmentUpdateRequest {
private List<PatternMapper> columnNameMapper;
private Boolean targetDropTable;
private Boolean targetOnlyCreate;
private Boolean targetAutoIncrement;
private SyncOptionEnum targetSyncOption;
private String beforeSqlScripts;
private String afterSqlScripts;
private Integer batchSize;
}
@@ -76,25 +81,31 @@ public class AssigmentUpdateRequest {
AssignmentConfigEntity assignmentConfigEntity = new AssignmentConfigEntity();
assignmentConfigEntity.setAssignmentId(assignmentId);
assignmentConfigEntity.setSourceConnectionId(this.getConfig().getSourceConnectionId());
assignmentConfigEntity.setSourceSchema(this.getConfig().getSourceSchema());
assignmentConfigEntity.setTableType(this.getConfig().getTableType());
assignmentConfigEntity.setSourceTables(this.getConfig().getSourceTables());
assignmentConfigEntity.setSourceConnectionId(config.getSourceConnectionId());
assignmentConfigEntity.setSourceSchema(config.getSourceSchema());
assignmentConfigEntity.setTableType(config.getTableType());
assignmentConfigEntity.setSourceTables(config.getSourceTables());
assignmentConfigEntity.setExcluded(
this.getConfig().getIncludeOrExclude() == IncludeExcludeEnum.EXCLUDE
config.getIncludeOrExclude() == IncludeExcludeEnum.EXCLUDE
);
assignmentConfigEntity.setTargetConnectionId(this.getConfig().getTargetConnectionId());
assignmentConfigEntity.setTargetSchema(this.getConfig().getTargetSchema());
assignmentConfigEntity.setTableNameCase(this.getConfig().getTableNameCase());
assignmentConfigEntity.setColumnNameCase(this.getConfig().getColumnNameCase());
assignmentConfigEntity.setTableNameMap(this.getConfig().getTableNameMapper());
assignmentConfigEntity.setColumnNameMap(this.getConfig().getColumnNameMapper());
assignmentConfigEntity.setTargetDropTable(this.getConfig().getTargetDropTable());
assignmentConfigEntity.setTargetOnlyCreate(this.getConfig().getTargetOnlyCreate());
assignmentConfigEntity.setTargetConnectionId(config.getTargetConnectionId());
assignmentConfigEntity.setTargetSchema(config.getTargetSchema());
assignmentConfigEntity.setTableNameCase(config.getTableNameCase());
assignmentConfigEntity.setColumnNameCase(config.getColumnNameCase());
assignmentConfigEntity.setTableNameMap(config.getTableNameMapper());
assignmentConfigEntity.setColumnNameMap(config.getColumnNameMapper());
assignmentConfigEntity.setTargetDropTable(config.getTargetDropTable());
assignmentConfigEntity.setTargetOnlyCreate(config.getTargetOnlyCreate());
assignmentConfigEntity.setTargetAutoIncrement(config.getTargetAutoIncrement());
assignmentConfigEntity.setBeforeSqlScripts(
Objects.nonNull(config.getBeforeSqlScripts()) ? config.getBeforeSqlScripts().trim() : null);
assignmentConfigEntity.setAfterSqlScripts(
Objects.nonNull(config.getAfterSqlScripts()) ? config.getAfterSqlScripts().trim() : null);
assignmentConfigEntity.setTargetSyncOption(config.getTargetSyncOption());
assignmentConfigEntity.setBatchSize(
Objects.isNull(this.config.getBatchSize())
Objects.isNull(config.getBatchSize())
? 10000
: this.config.getBatchSize()
: config.getBatchSize()
);
assignmentConfigEntity.setFirstFlag(Boolean.TRUE);

View File

@@ -15,6 +15,7 @@ import com.gitee.dbswitch.admin.type.ScheduleModeEnum;
import com.gitee.dbswitch.common.entity.PatternMapper;
import com.gitee.dbswitch.common.type.CaseConvertEnum;
import com.gitee.dbswitch.common.type.ProductTableEnum;
import com.gitee.dbswitch.common.type.SyncOptionEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.sql.Timestamp;
@@ -111,5 +112,14 @@ public class AssignmentDetailResponse {
@ApiModelProperty("数据批次大小")
private Integer batchSize;
@ApiModelProperty("同步操作方法")
private SyncOptionEnum targetSyncOption;
@ApiModelProperty("同步前置执行SQL脚本")
private String beforeSqlScripts;
@ApiModelProperty("同步后置执行SQL脚本")
private String afterSqlScripts;
}
}

View File

@@ -0,0 +1,4 @@
ALTER TABLE `DBSWITCH_ASSIGNMENT_CONFIG`
ADD COLUMN `target_sync_option` varchar(32) NOT NULL DEFAULT 'INSERT_UPDATE_DELETE' COMMENT '同步增删改选项' AFTER `target_auto_increment`,
ADD COLUMN `before_sql_scripts` varchar(4096) DEFAULT NULL COMMENT '目标端写入的前置执行SQL脚本' AFTER `target_sync_option`,
ADD COLUMN `after_sql_scripts` varchar(4096) DEFAULT NULL COMMENT '目标端写入的后置执行SQL脚本' AFTER `before_sql_scripts`;

View File

@@ -87,7 +87,7 @@ CREATE TABLE IF NOT EXISTS DBSWITCH_SIMPROP_TRIGGERS
REFERENCES DBSWITCH_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP)
);
CREATE IF NOT EXISTS DBSWITCH_BLOB_TRIGGERS
CREATE TABLE IF NOT EXISTS DBSWITCH_BLOB_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,

View File

@@ -123,6 +123,9 @@ CREATE TABLE IF NOT EXISTS DBSWITCH_ASSIGNMENT_CONFIG (
"target_drop_table" boolean not null default false,
"target_only_create" boolean not null default false,
"target_auto_increment" boolean not null default false,
"target_sync_option" varchar(32) not null default 'INSERT_UPDATE_DELETE',
"before_sql_scripts" text ,
"after_sql_scripts" text ,
"batch_size" int8 not null default 10000,
"first_flag" boolean not null default false,
"create_time" timestamp(6) not null default (CURRENT_TIMESTAMP(0))::timestamp(0) without time zone,
@@ -148,6 +151,10 @@ COMMENT ON COLUMN DBSWITCH_ASSIGNMENT_CONFIG."table_name_map" IS '表名映射
COMMENT ON COLUMN DBSWITCH_ASSIGNMENT_CONFIG."column_name_map" IS '字段名映射关系';
COMMENT ON COLUMN DBSWITCH_ASSIGNMENT_CONFIG."target_drop_table" IS '同步前是否先删除目的表(0:否 1:是)';
COMMENT ON COLUMN DBSWITCH_ASSIGNMENT_CONFIG."target_only_create" IS '是否只建表';
COMMENT ON COLUMN DBSWITCH_ASSIGNMENT_CONFIG."target_auto_increment" IS '是否支持自增';
COMMENT ON COLUMN DBSWITCH_ASSIGNMENT_CONFIG."target_sync_option" IS '同步增删改选项';
COMMENT ON COLUMN DBSWITCH_ASSIGNMENT_CONFIG."before_sql_scripts" IS '目标端写入的前置执行SQL脚本';
COMMENT ON COLUMN DBSWITCH_ASSIGNMENT_CONFIG."after_sql_scripts" IS '目标端写入的后置执行SQL脚本';
COMMENT ON COLUMN DBSWITCH_ASSIGNMENT_CONFIG."batch_size" IS '处理批次大小';
COMMENT ON COLUMN DBSWITCH_ASSIGNMENT_CONFIG."first_flag" IS '首次加载数据';
COMMENT ON COLUMN DBSWITCH_ASSIGNMENT_CONFIG."create_time" IS '创建时间';

View File

@@ -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.20d6eafe6a62211e9c1f22fad71a9db0.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.5d37b4a8aa14c9a3bf1f.js></script><script type=text/javascript src=/static/js/vendor.12f5219d5efab3af9f2f.js></script><script type=text/javascript src=/static/js/app.e8e5e92b2ee7f15cd565.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.f984bdd031eda968c431b973a793e2a1.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.e844cdeced676e179c0a.js></script><script type=text/javascript src=/static/js/vendor.12f5219d5efab3af9f2f.js></script><script type=text/javascript src=/static/js/app.176e0d7828db574e0d50.js></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,2 @@
webpackJsonp([11],{"0eSS":function(e,t,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var l={data:function(){return{loading:!0,lists:[],currentPage:1,pageSize:10,totalCount:0}},methods:{loadData:function(){var e=this;this.$http.get("/dbswitch/admin/api/v1/syslog/list/2/"+this.currentPage+"/"+this.pageSize).then(function(t){e.loading=!1,0===t.data.code?(e.currentPage=t.data.pagination.page,e.pageSize=t.data.pagination.size,e.totalCount=t.data.pagination.total,e.lists=t.data.data):alert("加载数据失败:"+t.data.message)},function(t){e.$message({showClose:!0,message:"数据加载错误",type:"error"})})},boolFormat:function(e,t){return!0===e.failed?"是":"否"},handleSizeChange:function(e){this.loading=!0,this.pageSize=e,this.loadData()},handleCurrentChange:function(e){this.loading=!0,this.currentPage=e,this.loadData()},handleDetail:function(e,t){this.$message({showClose:!0,message:"查看日志详情"+e+" "+t,type:"info"})}},created:function(){this.loadData()}},o={render:function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticStyle:{"margin-top":"15px"}},[a("el-table",{directives:[{name:"loading",rawName:"v-loading",value:e.loading,expression:"loading"}],staticStyle:{width:"100%"},attrs:{"header-cell-style":{background:"#eef1f6",color:"#606266"},"element-loading-text":"拼命加载中","element-loading-spinner":"el-icon-loading","element-loading-background":"rgba(0, 0, 0, 0.8)",data:e.lists,stripe:"",size:"small",border:""}},[a("el-table-column",{attrs:{type:"expand"},scopedSlots:e._u([{key:"default",fn:function(t){return[a("el-form",{staticClass:"demo-table-expand",attrs:{"label-position":"left",inline:""}},[a("el-form-item",{attrs:{label:"日志编号:"}},[a("span",[e._v(e._s(t.row.id))])]),e._v(" "),a("el-form-item",{attrs:{label:"日志时间:"}},[a("span",[e._v(e._s(t.row.createTime))])]),e._v(" "),a("el-form-item",{attrs:{label:"操作用户:"}},[a("span",[e._v(e._s(t.row.username))])]),e._v(" "),a("el-form-item",{attrs:{label:"请求IP地址:"}},[a("span",[e._v(e._s(t.row.ipAddress))])]),e._v(" "),a("el-form-item",{attrs:{label:"操作模块:"}},[a("span",[e._v(e._s(t.row.moduleName))])]),e._v(" "),a("el-form-item",{attrs:{label:"操作描述:"}},[a("span",[e._v(e._s(t.row.content))])]),e._v(" "),a("el-form-item",{attrs:{label:"处理耗时(ms):"}},[a("span",[e._v(e._s(t.row.elapseSeconds))])]),e._v(" "),a("el-form-item",{attrs:{label:"请求路径:"}},[a("span",[e._v(e._s(t.row.urlPath))])]),e._v(" "),a("el-form-item",{attrs:{label:"异常状态:"}},[a("span",[e._v(e._s(t.row.failed))])]),e._v(" "),a("el-form-item",{attrs:{label:""}},[a("span")]),e._v(" "),a("el-form-item",{attrs:{label:"异常日志:"}},[a("el-input",{staticStyle:{"font-size":"12px",width:"700px"},attrs:{type:"textarea",autosize:{minRows:2,maxRows:5}},model:{value:t.row.exception,callback:function(a){e.$set(t.row,"exception",a)},expression:"props.row.exception"}})],1)],1)]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"createTime",label:"日志时间","min-width":"15%","show-overflow-tooltip":!0}}),e._v(" "),a("el-table-column",{attrs:{prop:"username",label:"操作用户","min-width":"10%","show-overflow-tooltip":!0}}),e._v(" "),a("el-table-column",{attrs:{prop:"ipAddress",label:"请求IP","min-width":"10%","show-overflow-tooltip":!0}}),e._v(" "),a("el-table-column",{attrs:{prop:"moduleName",label:"操作类型","min-width":"10%","show-overflow-tooltip":!0}}),e._v(" "),a("el-table-column",{attrs:{prop:"elapseSeconds",label:"耗时(ms)","min-width":"10%","show-overflow-tooltip":!0}}),e._v(" "),a("el-table-column",{attrs:{prop:"urlPath",label:"请求路径","min-width":"20%","show-overflow-tooltip":!0}}),e._v(" "),a("el-table-column",{attrs:{prop:"failed",label:"异常",formatter:e.boolFormat,"min-width":"10%","show-overflow-tooltip":!0}})],1),e._v(" "),a("div",{staticClass:"page",attrs:{align:"right"}},[a("el-pagination",{attrs:{"current-page":e.currentPage,"page-sizes":[5,10,20,40],"page-size":e.pageSize,layout:"total, sizes, prev, pager, next, jumper",total:e.totalCount},on:{"size-change":e.handleSizeChange,"current-change":e.handleCurrentChange}})],1)],1)},staticRenderFns:[]};var n=a("VU/8")(l,o,!1,function(e){a("3GnV")},"data-v-aee4e92e",null);t.default=n.exports},"3GnV":function(e,t){}});
//# sourceMappingURL=11.c61c0ebee350b7e0cba3.js.map
webpackJsonp([13],{"0eSS":function(e,t,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var l={data:function(){return{loading:!0,lists:[],currentPage:1,pageSize:10,totalCount:0}},methods:{loadData:function(){var e=this;this.$http.get("/dbswitch/admin/api/v1/syslog/list/2/"+this.currentPage+"/"+this.pageSize).then(function(t){e.loading=!1,0===t.data.code?(e.currentPage=t.data.pagination.page,e.pageSize=t.data.pagination.size,e.totalCount=t.data.pagination.total,e.lists=t.data.data):alert("加载数据失败:"+t.data.message)},function(t){e.$message({showClose:!0,message:"数据加载错误",type:"error"})})},boolFormat:function(e,t){return!0===e.failed?"是":"否"},handleSizeChange:function(e){this.loading=!0,this.pageSize=e,this.loadData()},handleCurrentChange:function(e){this.loading=!0,this.currentPage=e,this.loadData()},handleDetail:function(e,t){this.$message({showClose:!0,message:"查看日志详情"+e+" "+t,type:"info"})}},created:function(){this.loadData()}},o={render:function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticStyle:{"margin-top":"15px"}},[a("el-table",{directives:[{name:"loading",rawName:"v-loading",value:e.loading,expression:"loading"}],staticStyle:{width:"100%"},attrs:{"header-cell-style":{background:"#eef1f6",color:"#606266"},"element-loading-text":"拼命加载中","element-loading-spinner":"el-icon-loading","element-loading-background":"rgba(0, 0, 0, 0.8)",data:e.lists,stripe:"",size:"small",border:""}},[a("el-table-column",{attrs:{type:"expand"},scopedSlots:e._u([{key:"default",fn:function(t){return[a("el-form",{staticClass:"demo-table-expand",attrs:{"label-position":"left",inline:""}},[a("el-form-item",{attrs:{label:"日志编号:"}},[a("span",[e._v(e._s(t.row.id))])]),e._v(" "),a("el-form-item",{attrs:{label:"日志时间:"}},[a("span",[e._v(e._s(t.row.createTime))])]),e._v(" "),a("el-form-item",{attrs:{label:"操作用户:"}},[a("span",[e._v(e._s(t.row.username))])]),e._v(" "),a("el-form-item",{attrs:{label:"请求IP地址:"}},[a("span",[e._v(e._s(t.row.ipAddress))])]),e._v(" "),a("el-form-item",{attrs:{label:"操作模块:"}},[a("span",[e._v(e._s(t.row.moduleName))])]),e._v(" "),a("el-form-item",{attrs:{label:"操作描述:"}},[a("span",[e._v(e._s(t.row.content))])]),e._v(" "),a("el-form-item",{attrs:{label:"处理耗时(ms):"}},[a("span",[e._v(e._s(t.row.elapseSeconds))])]),e._v(" "),a("el-form-item",{attrs:{label:"请求路径:"}},[a("span",[e._v(e._s(t.row.urlPath))])]),e._v(" "),a("el-form-item",{attrs:{label:"异常状态:"}},[a("span",[e._v(e._s(t.row.failed))])]),e._v(" "),a("el-form-item",{attrs:{label:""}},[a("span")]),e._v(" "),a("el-form-item",{attrs:{label:"异常日志:"}},[a("el-input",{staticStyle:{"font-size":"12px",width:"700px"},attrs:{type:"textarea",autosize:{minRows:2,maxRows:5}},model:{value:t.row.exception,callback:function(a){e.$set(t.row,"exception",a)},expression:"props.row.exception"}})],1)],1)]}}])}),e._v(" "),a("el-table-column",{attrs:{prop:"createTime",label:"日志时间","min-width":"15%","show-overflow-tooltip":!0}}),e._v(" "),a("el-table-column",{attrs:{prop:"username",label:"操作用户","min-width":"10%","show-overflow-tooltip":!0}}),e._v(" "),a("el-table-column",{attrs:{prop:"ipAddress",label:"请求IP","min-width":"10%","show-overflow-tooltip":!0}}),e._v(" "),a("el-table-column",{attrs:{prop:"moduleName",label:"操作类型","min-width":"10%","show-overflow-tooltip":!0}}),e._v(" "),a("el-table-column",{attrs:{prop:"elapseSeconds",label:"耗时(ms)","min-width":"10%","show-overflow-tooltip":!0}}),e._v(" "),a("el-table-column",{attrs:{prop:"urlPath",label:"请求路径","min-width":"20%","show-overflow-tooltip":!0}}),e._v(" "),a("el-table-column",{attrs:{prop:"failed",label:"异常",formatter:e.boolFormat,"min-width":"10%","show-overflow-tooltip":!0}})],1),e._v(" "),a("div",{staticClass:"page",attrs:{align:"right"}},[a("el-pagination",{attrs:{"current-page":e.currentPage,"page-sizes":[5,10,20,40],"page-size":e.pageSize,layout:"total, sizes, prev, pager, next, jumper",total:e.totalCount},on:{"size-change":e.handleSizeChange,"current-change":e.handleCurrentChange}})],1)],1)},staticRenderFns:[]};var n=a("VU/8")(l,o,!1,function(e){a("3GnV")},"data-v-aee4e92e",null);t.default=n.exports},"3GnV":function(e,t){}});
//# sourceMappingURL=13.e54b813cfde8ca750bcd.js.map

View File

@@ -1,2 +1,2 @@
webpackJsonp([12],{oQRv:function(t,e,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n={data:function(){return{loading:!0,lists:[],currentPage:1,pageSize:10,totalCount:0}},methods:{loadData:function(){var t=this;this.$http.get("/dbswitch/admin/api/v1/syslog/list/1/"+this.currentPage+"/"+this.pageSize).then(function(e){t.loading=!1,0===e.data.code?(t.currentPage=e.data.pagination.page,t.pageSize=e.data.pagination.size,t.totalCount=e.data.pagination.total,t.lists=e.data.data):alert("加载数据失败:"+e.data.message)},function(e){t.$message({showClose:!0,message:"数据加载错误",type:"error"})})},handleSizeChange:function(t){this.loading=!0,this.pageSize=t,this.loadData()},handleCurrentChange:function(t){this.loading=!0,this.currentPage=t,this.loadData()}},created:function(){this.loadData()}},i={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticStyle:{"margin-top":"15px"}},[a("el-table",{directives:[{name:"loading",rawName:"v-loading",value:t.loading,expression:"loading"}],staticStyle:{width:"100%"},attrs:{"header-cell-style":{background:"#eef1f6",color:"#606266"},"element-loading-text":"拼命加载中","element-loading-spinner":"el-icon-loading","element-loading-background":"rgba(0, 0, 0, 0.8)",data:t.lists,stripe:"",size:"small",border:""}},[a("el-table-column",{attrs:{prop:"createTime",label:"日志时间","min-width":"15%","show-overflow-tooltip":!0}}),t._v(" "),a("el-table-column",{attrs:{prop:"ipAddress",label:"请求IP","min-width":"10%","show-overflow-tooltip":!0}}),t._v(" "),a("el-table-column",{attrs:{prop:"content",label:"操作内容","min-width":"20%","show-overflow-tooltip":!0}}),t._v(" "),a("el-table-column",{attrs:{prop:"userAgent",label:"请求代理","min-width":"50%","show-overflow-tooltip":!0}})],1),t._v(" "),a("div",{staticClass:"page",attrs:{align:"right"}},[a("el-pagination",{attrs:{"current-page":t.currentPage,"page-sizes":[5,10,20,40],"page-size":t.pageSize,layout:"total, sizes, prev, pager, next, jumper",total:t.totalCount},on:{"size-change":t.handleSizeChange,"current-change":t.handleCurrentChange}})],1)],1)},staticRenderFns:[]};var o=a("VU/8")(n,i,!1,function(t){a("rPsM")},"data-v-86686ab2",null);e.default=o.exports},rPsM:function(t,e){}});
//# sourceMappingURL=12.e59d78e330bd5e2703c1.js.map
webpackJsonp([14],{oQRv:function(t,e,a){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n={data:function(){return{loading:!0,lists:[],currentPage:1,pageSize:10,totalCount:0}},methods:{loadData:function(){var t=this;this.$http.get("/dbswitch/admin/api/v1/syslog/list/1/"+this.currentPage+"/"+this.pageSize).then(function(e){t.loading=!1,0===e.data.code?(t.currentPage=e.data.pagination.page,t.pageSize=e.data.pagination.size,t.totalCount=e.data.pagination.total,t.lists=e.data.data):alert("加载数据失败:"+e.data.message)},function(e){t.$message({showClose:!0,message:"数据加载错误",type:"error"})})},handleSizeChange:function(t){this.loading=!0,this.pageSize=t,this.loadData()},handleCurrentChange:function(t){this.loading=!0,this.currentPage=t,this.loadData()}},created:function(){this.loadData()}},i={render:function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticStyle:{"margin-top":"15px"}},[a("el-table",{directives:[{name:"loading",rawName:"v-loading",value:t.loading,expression:"loading"}],staticStyle:{width:"100%"},attrs:{"header-cell-style":{background:"#eef1f6",color:"#606266"},"element-loading-text":"拼命加载中","element-loading-spinner":"el-icon-loading","element-loading-background":"rgba(0, 0, 0, 0.8)",data:t.lists,stripe:"",size:"small",border:""}},[a("el-table-column",{attrs:{prop:"createTime",label:"日志时间","min-width":"15%","show-overflow-tooltip":!0}}),t._v(" "),a("el-table-column",{attrs:{prop:"ipAddress",label:"请求IP","min-width":"10%","show-overflow-tooltip":!0}}),t._v(" "),a("el-table-column",{attrs:{prop:"content",label:"操作内容","min-width":"20%","show-overflow-tooltip":!0}}),t._v(" "),a("el-table-column",{attrs:{prop:"userAgent",label:"请求代理","min-width":"50%","show-overflow-tooltip":!0}})],1),t._v(" "),a("div",{staticClass:"page",attrs:{align:"right"}},[a("el-pagination",{attrs:{"current-page":t.currentPage,"page-sizes":[5,10,20,40],"page-size":t.pageSize,layout:"total, sizes, prev, pager, next, jumper",total:t.totalCount},on:{"size-change":t.handleSizeChange,"current-change":t.handleCurrentChange}})],1)],1)},staticRenderFns:[]};var o=a("VU/8")(n,i,!1,function(t){a("rPsM")},"data-v-86686ab2",null);e.default=o.exports},rPsM:function(t,e){}});
//# sourceMappingURL=14.ebafac48d154df9f8737.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,2 @@
webpackJsonp([18],{Modp:function(t,e){},WfA7:function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a={data:function(){return{dialogVisible:!1,loading:!0,connectionTypes:[],versionDrivers:[],isActive:-1}},methods:{loadConnectionTypes:function(){var t=this;this.$http({method:"GET",url:"/dbswitch/admin/api/v1/connection/types"}).then(function(e){0===e.data.code?(t.connectionTypes=e.data.data,t.handleChooseClick("MYSQL",0)):e.data.message&&alert("初始化数据库类型信息失败:"+e.data.message)})},handleChooseClick:function(t,e){var i=this;this.isActive=e,this.$http.get("/dbswitch/admin/api/v1/connection/"+t+"/drivers").then(function(t){0===t.data.code?i.versionDrivers=t.data.data:t.data.message&&alert("查询驱动版本信息失败,"+t.data.message)})},handleClose:function(t){this.$confirm("确认关闭?").then(function(e){t()}).catch(function(t){})},formatJarFileList:function(t,e){return t[e.property].join(";\n")}},created:function(){this.loadConnectionTypes()},beforeDestroy:function(){}},n={render:function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",[i("el-card",[i("div",{staticClass:"container"},[i("el-card",{staticClass:"box-card"},[i("div",{staticClass:"clearfix",attrs:{slot:"header",align:"center"},slot:"header"},[i("span",[i("b",[t._v("数据库产品类型列表")])])]),t._v(" "),i("div",{staticClass:"navsBox"},[i("ul",t._l(t.connectionTypes,function(e,a){return i("li",{key:a,class:{active:a==t.isActive},on:{click:function(i){return t.handleChooseClick(e.type,a)}}},[t._v("["+t._s(e.id)+"]"+t._s(e.type))])}),0)])]),t._v(" "),i("div",{staticClass:"contentBox"},[i("div",{staticStyle:{margin:"10px 5px"},attrs:{align:"right",width:"95%"}},[i("el-button",{attrs:{type:"primary",size:"mini",icon:"el-icon-document-add"},on:{click:function(e){t.dialogVisible=!0}}},[t._v("添加")])],1),t._v(" "),i("el-table",{attrs:{"header-cell-style":{background:"#eef1f6",color:"#606266"},data:t.versionDrivers,size:"small",stripe:"",border:""}},[i("template",{slot:"empty"},[i("span",[t._v("单击左侧数据库类型来查看对应的驱动版本信息")])]),t._v(" "),i("el-table-column",{attrs:{property:"driverVersion",label:"驱动版本号","min-width":"15%"}}),t._v(" "),i("el-table-column",{attrs:{property:"driverClass",label:"驱动类名","min-width":"20%"}}),t._v(" "),i("el-table-column",{attrs:{property:"jarFiles",formatter:t.formatJarFileList,label:"驱动JAR名称","min-width":"30%"}}),t._v(" "),i("el-table-column",{attrs:{property:"driverPath",label:"驱动版本路径","min-width":"50%"}})],2)],1)],1)]),t._v(" "),i("el-dialog",{attrs:{title:"添加数据库驱动JAR说明",visible:t.dialogVisible,width:"40%","before-close":t.handleClose},on:{"update:visible":function(e){t.dialogVisible=e}}},[i("span",[t._v("请按照驱动路径所在的目录${DBSWITCH_HOME}/drivers下在数据库类型为名称的目录下以驱动版本号为名称创建目录并放置对应的驱动jar文件然后重启即可生效。具体可参考https://gitee.com/inrgihc/dbswitch/tree/master/drivers下的目录结构。")]),t._v(" "),i("span"),t._v(" "),i("span",[t._v("特殊说明驱动版本目录下的所有JAR必须无任何外部依赖否则也需将其依赖JAR一起放置到对应的目录下。")]),t._v(" "),i("span",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[i("el-button",{on:{click:function(e){t.dialogVisible=!1}}},[t._v("取 消")]),t._v(" "),i("el-button",{attrs:{type:"primary"},on:{click:function(e){t.dialogVisible=!1}}},[t._v("确 定")])],1)])],1)},staticRenderFns:[]};var s=i("VU/8")(a,n,!1,function(t){i("Modp")},"data-v-25cae184",null);e.default=s.exports}});
//# sourceMappingURL=18.7ac38643e0f275e0bc96.js.map
webpackJsonp([17],{Modp:function(t,e){},WfA7:function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var a={data:function(){return{dialogVisible:!1,loading:!0,connectionTypes:[],versionDrivers:[],isActive:-1}},methods:{loadConnectionTypes:function(){var t=this;this.$http({method:"GET",url:"/dbswitch/admin/api/v1/connection/types"}).then(function(e){0===e.data.code?(t.connectionTypes=e.data.data,t.handleChooseClick("MYSQL",0)):e.data.message&&alert("初始化数据库类型信息失败:"+e.data.message)})},handleChooseClick:function(t,e){var i=this;this.isActive=e,this.$http.get("/dbswitch/admin/api/v1/connection/"+t+"/drivers").then(function(t){0===t.data.code?i.versionDrivers=t.data.data:t.data.message&&alert("查询驱动版本信息失败,"+t.data.message)})},handleClose:function(t){this.$confirm("确认关闭?").then(function(e){t()}).catch(function(t){})},formatJarFileList:function(t,e){return t[e.property].join(";\n")}},created:function(){this.loadConnectionTypes()},beforeDestroy:function(){}},n={render:function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",[i("el-card",[i("div",{staticClass:"container"},[i("el-card",{staticClass:"box-card"},[i("div",{staticClass:"clearfix",attrs:{slot:"header",align:"center"},slot:"header"},[i("span",[i("b",[t._v("数据库产品类型列表")])])]),t._v(" "),i("div",{staticClass:"navsBox"},[i("ul",t._l(t.connectionTypes,function(e,a){return i("li",{key:a,class:{active:a==t.isActive},on:{click:function(i){return t.handleChooseClick(e.type,a)}}},[t._v("["+t._s(e.id)+"]"+t._s(e.type))])}),0)])]),t._v(" "),i("div",{staticClass:"contentBox"},[i("div",{staticStyle:{margin:"10px 5px"},attrs:{align:"right",width:"95%"}},[i("el-button",{attrs:{type:"primary",size:"mini",icon:"el-icon-document-add"},on:{click:function(e){t.dialogVisible=!0}}},[t._v("添加")])],1),t._v(" "),i("el-table",{attrs:{"header-cell-style":{background:"#eef1f6",color:"#606266"},data:t.versionDrivers,size:"small",stripe:"",border:""}},[i("template",{slot:"empty"},[i("span",[t._v("单击左侧数据库类型来查看对应的驱动版本信息")])]),t._v(" "),i("el-table-column",{attrs:{property:"driverVersion",label:"驱动版本号","min-width":"15%"}}),t._v(" "),i("el-table-column",{attrs:{property:"driverClass",label:"驱动类名","min-width":"20%"}}),t._v(" "),i("el-table-column",{attrs:{property:"jarFiles",formatter:t.formatJarFileList,label:"驱动JAR名称","min-width":"30%"}}),t._v(" "),i("el-table-column",{attrs:{property:"driverPath",label:"驱动版本路径","min-width":"50%"}})],2)],1)],1)]),t._v(" "),i("el-dialog",{attrs:{title:"添加数据库驱动JAR说明",visible:t.dialogVisible,width:"40%","before-close":t.handleClose},on:{"update:visible":function(e){t.dialogVisible=e}}},[i("span",[t._v("请按照驱动路径所在的目录${DBSWITCH_HOME}/drivers下在数据库类型为名称的目录下以驱动版本号为名称创建目录并放置对应的驱动jar文件然后重启即可生效。具体可参考https://gitee.com/inrgihc/dbswitch/tree/master/drivers下的目录结构。")]),t._v(" "),i("span"),t._v(" "),i("span",[t._v("特殊说明驱动版本目录下的所有JAR必须无任何外部依赖否则也需将其依赖JAR一起放置到对应的目录下。")]),t._v(" "),i("span",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[i("el-button",{on:{click:function(e){t.dialogVisible=!1}}},[t._v("取 消")]),t._v(" "),i("el-button",{attrs:{type:"primary"},on:{click:function(e){t.dialogVisible=!1}}},[t._v("确 定")])],1)])],1)},staticRenderFns:[]};var s=i("VU/8")(a,n,!1,function(t){i("Modp")},"data-v-25cae184",null);e.default=s.exports}});
//# sourceMappingURL=17.17565790c33e3537001f.js.map

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,2 @@
webpackJsonp([20],{NHnr:function(n,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=t("//Fk"),r=t.n(o),a=t("7+uW"),c={render:function(){var n=this.$createElement,e=this._self._c||n;return e("div",{staticClass:"body-wrapper"},[e("router-view")],1)},staticRenderFns:[]};var i=t("VU/8")({name:"App"},c,!1,function(n){t("Pibb")},"data-v-a97617c2",null).exports,u=t("/ocq");a.default.use(u.a);var l=new u.a({routes:[{path:"/",name:"首页",component:function(){return t.e(4).then(t.bind(null,"4er+"))},redirect:"/dashboard",children:[{path:"/dashboard",name:"概览",icon:"el-icon-menu",component:function(){return Promise.all([t.e(0),t.e(9)]).then(t.bind(null,"ARoL"))}},{path:"/connection",name:"连接配置",icon:"el-icon-s-order",component:function(){return t.e(8).then(t.bind(null,"Hoc+"))},children:[{path:"/connection/driver",name:"驱动配置",icon:"el-icon-help",component:function(){return t.e(18).then(t.bind(null,"WfA7"))}},{path:"/connection/list",name:"连接管理",icon:"el-icon-bank-card",component:function(){return Promise.all([t.e(0),t.e(14)]).then(t.bind(null,"qdtB"))}}]},{path:"/metadata",name:"数据目录",icon:"el-icon-coin",component:function(){return t.e(1).then(t.bind(null,"PJ2q"))}},{path:"/task",name:"任务管理",icon:"el-icon-s-tools",component:function(){return t.e(6).then(t.bind(null,"4KEO"))},children:[{path:"/task/assignment",name:"任务安排",icon:"el-icon-eleme",component:function(){return Promise.all([t.e(0),t.e(17)]).then(t.bind(null,"D0I9"))}},{path:"/task/schedule",name:"调度记录",icon:"el-icon-pie-chart",component:function(){return Promise.all([t.e(0),t.e(10)]).then(t.bind(null,"mKp/"))}}]},{path:"/log",name:"审计日志",icon:"el-icon-platform-eleme",component:function(){return t.e(7).then(t.bind(null,"QWih"))},children:[{path:"/log/access",name:"登录日志",icon:"el-icon-place",component:function(){return t.e(12).then(t.bind(null,"oQRv"))}},{path:"/log/action",name:"操作日志",icon:"el-icon-s-check",component:function(){return t.e(11).then(t.bind(null,"0eSS"))}}]},{path:"/about",name:"关于系统",icon:"el-icon-s-custom",component:function(){return t.e(2).then(t.bind(null,"m25N"))}},{path:"/user/personal",name:"个人中心",hidden:!0,component:function(){return t.e(3).then(t.bind(null,"uTKz"))}},{path:"/task/create",name:"创建任务",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(13)]).then(t.bind(null,"/rCC"))}},{path:"/task/update",name:"修改任务",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(16)]).then(t.bind(null,"txod"))}},{path:"/task/detail",name:"查看任务",hidden:!0,component:function(){return t.e(15).then(t.bind(null,"nrt7"))}}]},{path:"/login",name:"登录",component:function(){return t.e(5).then(t.bind(null,"T+/8"))}}]}),p=t("mtWM"),d=t.n(p).a.create();d.interceptors.request.use(function(n){return n.url=""+n.url,n});var s=d,h=t("zL8q"),m=t.n(h),f=(t("muQq"),t("tvR6"),t("7Vno")),b=t.n(f),v=t("XLwt"),k=t.n(v);a.default.use(s),a.default.use(m.a),a.default.use(b.a),a.default.prototype.$http=s,a.default.config.productionTip=!1,a.default.prototype.$echarts=k.a,s.interceptors.request.use(function(n){var e=sessionStorage.getItem("token");return e&&(n.headers.Authorization="Bearer "+e),n},function(n){return r.a.reject(n)}),s.interceptors.response.use(function(n){return!n.data||401!==n.data.code&&403!==n.data.code&&404!==n.data.code||l.push({path:"/login"}),n},function(n){return console.log(n),r.a.reject(n.response)}),new a.default({el:"#app",router:l,components:{App:i},template:"<App/>"})},Pibb:function(n,e){},muQq:function(n,e){},tvR6:function(n,e){}},["NHnr"]);
//# sourceMappingURL=app.e8e5e92b2ee7f15cd565.js.map
webpackJsonp([20],{NHnr:function(n,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=t("//Fk"),r=t.n(o),a=t("7+uW"),c={render:function(){var n=this.$createElement,e=this._self._c||n;return e("div",{staticClass:"body-wrapper"},[e("router-view")],1)},staticRenderFns:[]};var i=t("VU/8")({name:"App"},c,!1,function(n){t("Pibb")},"data-v-a97617c2",null).exports,u=t("/ocq");a.default.use(u.a);var l=new u.a({routes:[{path:"/",name:"首页",component:function(){return t.e(4).then(t.bind(null,"4er+"))},redirect:"/dashboard",children:[{path:"/dashboard",name:"概览",icon:"el-icon-menu",component:function(){return Promise.all([t.e(0),t.e(9)]).then(t.bind(null,"ARoL"))}},{path:"/connection",name:"连接配置",icon:"el-icon-s-order",component:function(){return t.e(8).then(t.bind(null,"Hoc+"))},children:[{path:"/connection/driver",name:"驱动配置",icon:"el-icon-help",component:function(){return t.e(17).then(t.bind(null,"WfA7"))}},{path:"/connection/list",name:"连接管理",icon:"el-icon-bank-card",component:function(){return Promise.all([t.e(0),t.e(15)]).then(t.bind(null,"qdtB"))}}]},{path:"/metadata",name:"数据目录",icon:"el-icon-coin",component:function(){return t.e(1).then(t.bind(null,"PJ2q"))}},{path:"/task",name:"任务管理",icon:"el-icon-s-tools",component:function(){return t.e(6).then(t.bind(null,"4KEO"))},children:[{path:"/task/assignment",name:"任务安排",icon:"el-icon-eleme",component:function(){return Promise.all([t.e(0),t.e(16)]).then(t.bind(null,"D0I9"))}},{path:"/task/schedule",name:"调度记录",icon:"el-icon-pie-chart",component:function(){return Promise.all([t.e(0),t.e(11)]).then(t.bind(null,"mKp/"))}}]},{path:"/log",name:"审计日志",icon:"el-icon-platform-eleme",component:function(){return t.e(7).then(t.bind(null,"QWih"))},children:[{path:"/log/access",name:"登录日志",icon:"el-icon-place",component:function(){return t.e(14).then(t.bind(null,"oQRv"))}},{path:"/log/action",name:"操作日志",icon:"el-icon-s-check",component:function(){return t.e(13).then(t.bind(null,"0eSS"))}}]},{path:"/about",name:"关于系统",icon:"el-icon-s-custom",component:function(){return t.e(2).then(t.bind(null,"m25N"))}},{path:"/user/personal",name:"个人中心",hidden:!0,component:function(){return t.e(3).then(t.bind(null,"uTKz"))}},{path:"/task/create",name:"创建任务",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(12)]).then(t.bind(null,"/rCC"))}},{path:"/task/update",name:"修改任务",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(10)]).then(t.bind(null,"txod"))}},{path:"/task/detail",name:"查看任务",hidden:!0,component:function(){return t.e(18).then(t.bind(null,"nrt7"))}}]},{path:"/login",name:"登录",component:function(){return t.e(5).then(t.bind(null,"T+/8"))}}]}),p=t("mtWM"),d=t.n(p).a.create();d.interceptors.request.use(function(n){return n.url=""+n.url,n});var s=d,h=t("zL8q"),m=t.n(h),f=(t("muQq"),t("tvR6"),t("7Vno")),b=t.n(f),v=t("XLwt"),k=t.n(v);a.default.use(s),a.default.use(m.a),a.default.use(b.a),a.default.prototype.$http=s,a.default.config.productionTip=!1,a.default.prototype.$echarts=k.a,s.interceptors.request.use(function(n){var e=sessionStorage.getItem("token");return e&&(n.headers.Authorization="Bearer "+e),n},function(n){return r.a.reject(n)}),s.interceptors.response.use(function(n){return!n.data||401!==n.data.code&&403!==n.data.code&&404!==n.data.code||l.push({path:"/login"}),n},function(n){return console.log(n),r.a.reject(n.response)}),new a.default({el:"#app",router:l,components:{App:i},template:"<App/>"})},Pibb:function(n,e){},muQq:function(n,e){},tvR6:function(n,e){}},["NHnr"]);
//# sourceMappingURL=app.176e0d7828db574e0d50.js.map

View File

@@ -1,2 +1,2 @@
!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,a,o){for(var f,d,i,u=0,b=[];u<r.length;u++)d=r[u],t[d]&&b.push(t[d][0]),t[d]=0;for(f in a)Object.prototype.hasOwnProperty.call(a,f)&&(e[f]=a[f]);for(n&&n(r,a,o);b.length;)b.shift()();if(o)for(u=0;u<o.length;u++)i=c(c.s=o[u]);return i};var r={},t={21:0};function c(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,c),t.l=!0,t.exports}c.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,c){n=t[e]=[r,c]});n[2]=r;var a=document.getElementsByTagName("head")[0],o=document.createElement("script");o.type="text/javascript",o.charset="utf-8",o.async=!0,o.timeout=12e4,c.nc&&o.setAttribute("nonce",c.nc),o.src=c.p+"static/js/"+e+"."+{0:"ca67e87d8c000a42e592",1:"4917c0d3a0abb78cb20b",2:"39a763d3b4021d291917",3:"3bad9aaf46ce9329fd19",4:"880c74c2473cd4493cad",5:"837a4a67f1fcf6ee6c6a",6:"7f56c2238fb7e4ee2ecd",7:"d5dc80a855f66a3208ff",8:"0b82703c6f3d2dd72354",9:"9b19245845e7fa49300a",10:"3ded61c33158be9eb6b4",11:"c61c0ebee350b7e0cba3",12:"e59d78e330bd5e2703c1",13:"7884eb53460e4e42abf9",14:"ddb30a741298637bb87a",15:"ffe8a9ca84181f830332",16:"eefa40313135866bdcd8",17:"8f9664eb8becc2013aca",18:"7ac38643e0f275e0bc96"}[e]+".js";var f=setTimeout(d,12e4);function d(){o.onerror=o.onload=null,clearTimeout(f);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),t[e]=void 0)}return o.onerror=o.onload=d,a.appendChild(o),r},c.m=e,c.c=r,c.d=function(e,n,r){c.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},c.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return c.d(n,"a",n),n},c.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},c.p="/",c.oe=function(e){throw console.error(e),e}}([]);
//# sourceMappingURL=manifest.5d37b4a8aa14c9a3bf1f.js.map
!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,a,o){for(var f,d,i,u=0,b=[];u<r.length;u++)d=r[u],t[d]&&b.push(t[d][0]),t[d]=0;for(f in a)Object.prototype.hasOwnProperty.call(a,f)&&(e[f]=a[f]);for(n&&n(r,a,o);b.length;)b.shift()();if(o)for(u=0;u<o.length;u++)i=c(c.s=o[u]);return i};var r={},t={21:0};function c(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,c),t.l=!0,t.exports}c.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,c){n=t[e]=[r,c]});n[2]=r;var a=document.getElementsByTagName("head")[0],o=document.createElement("script");o.type="text/javascript",o.charset="utf-8",o.async=!0,o.timeout=12e4,c.nc&&o.setAttribute("nonce",c.nc),o.src=c.p+"static/js/"+e+"."+{0:"ca67e87d8c000a42e592",1:"4917c0d3a0abb78cb20b",2:"39a763d3b4021d291917",3:"3bad9aaf46ce9329fd19",4:"880c74c2473cd4493cad",5:"837a4a67f1fcf6ee6c6a",6:"7f56c2238fb7e4ee2ecd",7:"d5dc80a855f66a3208ff",8:"0b82703c6f3d2dd72354",9:"9b19245845e7fa49300a",10:"1cb7ab08f0d8a65401af",11:"534a23e4700cfe1e4a59",12:"7d79e4642d466e680331",13:"e54b813cfde8ca750bcd",14:"ebafac48d154df9f8737",15:"e3875ce9a863a129e085",16:"c306d3fe5360e077b1b4",17:"17565790c33e3537001f",18:"4db9651b215318fbc4be"}[e]+".js";var f=setTimeout(d,12e4);function d(){o.onerror=o.onload=null,clearTimeout(f);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),t[e]=void 0)}return o.onerror=o.onload=d,a.appendChild(o),r},c.m=e,c.c=r,c.d=function(e,n,r){c.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},c.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return c.d(n,"a",n),n},c.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},c.p="/",c.oe=function(e){throw console.error(e),e}}([]);
//# sourceMappingURL=manifest.e844cdeced676e179c0a.js.map

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.gitee.dbswitch</groupId>
<artifactId>dbswitch-parent</artifactId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<artifactId>dbswitch-common</artifactId>

View File

@@ -0,0 +1,26 @@
// Copyright tang. All rights reserved.
// https://gitee.com/inrgihc/dbswitch
//
// Use of this source code is governed by a BSD-style license
//
// Author: tang (inrgihc@126.com)
// Date : 2020/1/2
// Location: beijing , china
/////////////////////////////////////////////////////////////
package com.gitee.dbswitch.common.entity;
import java.util.Objects;
import java.util.function.Function;
@FunctionalInterface
public interface ThreeArgsFunction<U, V, W, R> {
R apply(U var1, V var2, W var3);
default <T> ThreeArgsFunction<U, V, W, T> andThen(Function<? super R, ? extends T> after) {
Objects.requireNonNull(after);
return (u, v, w) -> {
return after.apply(this.apply(u, v, w));
};
}
}

View File

@@ -0,0 +1,57 @@
// Copyright tang. All rights reserved.
// https://gitee.com/inrgihc/dbswitch
//
// Use of this source code is governed by a BSD-style license
//
// Author: tang (inrgihc@126.com)
// Date : 2020/1/2
// Location: beijing , china
/////////////////////////////////////////////////////////////
package com.gitee.dbswitch.common.type;
/**
* 同步操作类型的枚举类
*
* @author tang
*/
public enum SyncOptionEnum {
ONLY_INSERT(1),
ONLY_UPDATE(2),
INSERT_UPDATE(3),
ONLY_DELETE(4),
INSERT_DELETE(5),
UPDATE_DELETE(6),
INSERT_UPDATE_DELETE(7),
;
private static int MASK_INSERT = 1;
private static int MASK_UPDATE = 2;
private static int MASK_DELETE = 4;
private int flag;
SyncOptionEnum(int flat) {
this.flag = flat;
}
public boolean callInsert() {
return (flag & MASK_INSERT) != 0;
}
public boolean callUpdate() {
return (flag & MASK_UPDATE) != 0;
}
public boolean callDelete() {
return (flag & MASK_DELETE) != 0;
}
public static void main(String[] args) {
for (SyncOptionEnum optionEnum : values()) {
System.out.println(optionEnum.name() + ":"
+ String.format("insert(%s),update(%s),delete(%s)",
optionEnum.callInsert(), optionEnum.callUpdate(), optionEnum.callDelete()));
}
}
}

View File

@@ -152,4 +152,13 @@ public final class JdbcTypesUtils {
}
}
public static long getRecordSize(Object[] record, int[] jdbcTypes) {
long bytes = 0;
if (record.length == jdbcTypes.length) {
for (int i = 0; i < record.length; ++i) {
bytes += getObjectSize(jdbcTypes[i], record[i]);
}
}
return bytes;
}
}

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.gitee.dbswitch</groupId>
<artifactId>dbswitch-parent</artifactId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<artifactId>dbswitch-core</artifactId>

View File

@@ -9,8 +9,8 @@
/////////////////////////////////////////////////////////////
package com.gitee.dbswitch.core.exchange;
import com.gitee.dbswitch.common.entity.ThreeArgsFunction;
import java.util.List;
import java.util.function.BiFunction;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -33,7 +33,7 @@ public class BatchElement {
/**
* 数据写入回调函数
*/
private BiFunction<List<String>, List<Object[]>, Long> handler;
private ThreeArgsFunction<List<String>, List<Object[]>, org.slf4j.Logger, Long> handler;
/**
* 写入回调函数的第1个参数

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.gitee.dbswitch</groupId>
<artifactId>dbswitch-parent</artifactId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<artifactId>dbswitch-data</artifactId>

View File

@@ -10,6 +10,7 @@
package com.gitee.dbswitch.data.entity;
import com.gitee.dbswitch.common.type.CaseConvertEnum;
import com.gitee.dbswitch.common.type.SyncOptionEnum;
import java.util.concurrent.TimeUnit;
import lombok.Data;
@@ -35,7 +36,11 @@ public class TargetDataSourceProperties {
private CaseConvertEnum columnNameCase = CaseConvertEnum.NONE;
private Boolean targetDrop = Boolean.TRUE;
private Boolean onlyCreate = Boolean.FALSE;
private Boolean changeDataSync = Boolean.FALSE;
private Boolean createTableAutoIncrement = Boolean.FALSE;
private Boolean writerEngineInsert = Boolean.FALSE;
private Boolean changeDataSync = Boolean.FALSE;
private String beforeSqlScripts;
private String afterSqlScripts;
private SyncOptionEnum targetSyncOption = SyncOptionEnum.INSERT_UPDATE_DELETE;
}

View File

@@ -31,6 +31,7 @@ import com.gitee.dbswitch.data.config.DbswichPropertiesConfiguration;
import com.gitee.dbswitch.data.domain.ReaderTaskParam;
import com.gitee.dbswitch.data.domain.ReaderTaskResult;
import com.gitee.dbswitch.data.entity.SourceDataSourceProperties;
import com.gitee.dbswitch.data.entity.TargetDataSourceProperties;
import com.gitee.dbswitch.provider.ProductFactoryProvider;
import com.gitee.dbswitch.provider.ProductProviderFactory;
import com.gitee.dbswitch.provider.manage.TableManageProvider;
@@ -73,6 +74,7 @@ public class ReaderTaskThread extends TaskProcessor<ReaderTaskResult> {
private final DbswichPropertiesConfiguration properties;
private final SourceDataSourceProperties sourceProperties;
private final TargetDataSourceProperties targetProperties;
private int fetchSize = Constants.MINIMUM_FETCH_SIZE;
private TableDescription tableDescription;
private MemChannel memChannel;
@@ -112,6 +114,7 @@ public class ReaderTaskThread extends TaskProcessor<ReaderTaskResult> {
this.memChannel = taskParam.getMemChannel();
this.properties = taskParam.getConfiguration();
this.sourceProperties = this.properties.getSource();
this.targetProperties = this.properties.getTarget();
this.sourceSchemaName = this.sourceProperties.getSourceSchema();
this.sourceTableName = this.tableDescription.getTableName();
this.targetExistTables = taskParam.getTargetExistTables();
@@ -431,9 +434,9 @@ public class ReaderTaskThread extends TaskProcessor<ReaderTaskResult> {
this.memChannel.add(
BatchElement.builder()
.tableNameMapString(tableNameMapString)
.handler((arg1, arg2) -> {
.handler((arg1, arg2, logger) -> {
long ret = tableWriter.write(arg1, arg2);
log.info("[FullCoverSync] handle write table [{}] batch record count: {}, the bytes size: {}",
logger.info("[FullCoverSync] handle write table [{}] batch record count: {}, the bytes size: {}",
tableNameMapString, ret, DataSizeUtil.format(finalCacheBytes));
return ret;
})
@@ -452,9 +455,9 @@ public class ReaderTaskThread extends TaskProcessor<ReaderTaskResult> {
this.memChannel.add(
BatchElement.builder()
.tableNameMapString(tableNameMapString)
.handler((arg1, arg2) -> {
.handler((arg1, arg2, logger) -> {
long ret = tableWriter.write(arg1, arg2);
log.info("[FullCoverSync] handle write table [{}] batch record count: {}, the bytes size: {}",
logger.info("[FullCoverSync] handle write table [{}] batch record count: {}, the bytes size: {}",
tableNameMapString, ret, DataSizeUtil.format(finalCacheBytes));
return ret;
})
@@ -549,22 +552,34 @@ public class ReaderTaskThread extends TaskProcessor<ReaderTaskResult> {
@Override
public void handle(List<String> fields, Object[] record, int[] jdbcTypes, RowChangeTypeEnum flag) {
if (flag == RowChangeTypeEnum.VALUE_INSERT) {
cacheInsert.add(record);
countInsert++;
} else if (flag == RowChangeTypeEnum.VALUE_CHANGED) {
cacheUpdate.add(record);
countUpdate++;
} else {
cacheDelete.add(record);
countDelete++;
switch (flag) {
case VALUE_INSERT:
if (!targetProperties.getTargetSyncOption().callInsert()) {
return;
}
cacheInsert.add(record);
countInsert++;
break;
case VALUE_CHANGED:
if (!targetProperties.getTargetSyncOption().callUpdate()) {
return;
}
cacheUpdate.add(record);
countUpdate++;
break;
case VALUE_DELETED:
if (!targetProperties.getTargetSyncOption().callDelete()) {
return;
} else {
cacheDelete.add(record);
countDelete++;
}
break;
default:
return;
}
long bytes = 0;
for (int i = 0; i < record.length; ++i) {
Object value = record[i];
bytes += JdbcTypesUtils.getObjectSize(jdbcTypes[i], value);
}
long bytes = JdbcTypesUtils.getRecordSize(record, jdbcTypes);
cacheBytes += bytes;
totalBytes.addAndGet(bytes);
totalCount.addAndGet(1);
@@ -619,9 +634,10 @@ public class ReaderTaskThread extends TaskProcessor<ReaderTaskResult> {
ReaderTaskThread.this.memChannel.add(
BatchElement.builder()
.tableNameMapString(tableNameMapString)
.handler((arg1, arg2) -> {
.handler((arg1, arg2, logger) -> {
long ret = synchronizer.executeInsert(arg2);
log.info("[IncreaseSync] Handle write table [{}] record Insert count: {}", tableNameMapString, ret);
logger.info("[IncreaseSync] Handle write table [{}] record Insert count: {}",
tableNameMapString, ret);
return ret;
})
.arg1(fields)
@@ -635,9 +651,10 @@ public class ReaderTaskThread extends TaskProcessor<ReaderTaskResult> {
ReaderTaskThread.this.memChannel.add(
BatchElement.builder()
.tableNameMapString(tableNameMapString)
.handler((arg1, arg2) -> {
.handler((arg1, arg2, logger) -> {
long ret = synchronizer.executeUpdate(arg2);
log.info("[IncreaseSync] Handle write table [{}] record Update count: {}", tableNameMapString, ret);
logger.info("[IncreaseSync] Handle write table [{}] record Update count: {}",
tableNameMapString, ret);
return ret;
})
.arg1(fields)
@@ -651,9 +668,10 @@ public class ReaderTaskThread extends TaskProcessor<ReaderTaskResult> {
ReaderTaskThread.this.memChannel.add(
BatchElement.builder()
.tableNameMapString(tableNameMapString)
.handler((arg1, arg2) -> {
.handler((arg1, arg2, logger) -> {
long ret = synchronizer.executeDelete(arg2);
log.info("[IncreaseSync] Handle write table [{}] record Delete count: {}", tableNameMapString, ret);
logger.info("[IncreaseSync] Handle write table [{}] record Delete count: {}",
tableNameMapString, ret);
return ret;
})
.arg1(fields)

View File

@@ -50,7 +50,7 @@ public class WriterTaskThread extends TaskProcessor<WriterTaskResult> {
if (null != elem) {
try {
Long ret = Long.valueOf(elem.getArg2().size());
elem.getHandler().apply(elem.getArg1(), elem.getArg2());
elem.getHandler().apply(elem.getArg1(), elem.getArg2(), log);
Long count = taskResult.getPerf().get(elem.getTableNameMapString());
Long total = ret + Optional.ofNullable(count).orElse(0L);
taskResult.getPerf().put(elem.getTableNameMapString(), total);

View File

@@ -9,22 +9,26 @@
/////////////////////////////////////////////////////////////
package com.gitee.dbswitch.data.service;
import cn.hutool.system.SystemUtil;
import com.gitee.dbswitch.common.entity.CloseableDataSource;
import com.gitee.dbswitch.common.entity.LoggingRunnable;
import com.gitee.dbswitch.common.entity.MdcKeyValue;
import com.gitee.dbswitch.common.entity.PrintablePerfStat;
import com.gitee.dbswitch.common.util.MachineInfoUtils;
import com.gitee.dbswitch.core.exchange.AbstractBatchExchanger;
import com.gitee.dbswitch.core.robot.RobotReader;
import com.gitee.dbswitch.core.robot.RobotWriter;
import com.gitee.dbswitch.data.config.DbswichPropertiesConfiguration;
import com.gitee.dbswitch.data.entity.GlobalParamConfigProperties;
import com.gitee.dbswitch.data.util.DataSourceUtils;
import java.sql.Connection;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.jdbc.datasource.init.ScriptUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;
@@ -106,7 +110,9 @@ public class MigrationService {
watch.start();
log.info("dbswitch data service is started....");
log.info(MachineInfoUtils.getOSInfo());
log.info(SystemUtil.getOsInfo().toString());
log.info(SystemUtil.getJvmInfo().toString());
log.info(SystemUtil.getRuntimeInfo().toString());
//log.info("input configuration \n{}", JsonUtils.toJsonString(configuration));
GlobalParamConfigProperties globalParam = configuration.getConfig();
@@ -116,7 +122,14 @@ public class MigrationService {
try (CloseableDataSource sourceDataSource = DataSourceUtils.createSourceDataSource(configuration.getSource())) {
robotReader = new DefaultReaderRobot(mdcKeyValue, configuration, sourceDataSource, targetDataSource);
robotWriter = new DefaultWriterRobot(mdcKeyValue, robotReader, globalParam.getWriteThreadNum());
exchanger.exchange(robotReader, robotWriter);
boolean success = executeSqlScripts(targetDataSource, configuration.getTarget().getBeforeSqlScripts());
try {
exchanger.exchange(robotReader, robotWriter);
} finally {
if (success) {
executeSqlScripts(targetDataSource, configuration.getTarget().getAfterSqlScripts());
}
}
}
} catch (Throwable t) {
if (t instanceof RuntimeException) {
@@ -137,4 +150,29 @@ public class MigrationService {
}
}
private boolean executeSqlScripts(CloseableDataSource targetDataSource, String sqlScripts) {
if (StringUtils.isBlank(sqlScripts) || StringUtils.isBlank(sqlScripts.trim())) {
return true;
}
List<String> sqlList = new ArrayList<>();
ScriptUtils.splitSqlScript(null, sqlScripts,
ScriptUtils.DEFAULT_STATEMENT_SEPARATOR, ScriptUtils.DEFAULT_COMMENT_PREFIX,
ScriptUtils.DEFAULT_BLOCK_COMMENT_START_DELIMITER, ScriptUtils.DEFAULT_BLOCK_COMMENT_END_DELIMITER,
sqlList);
if (!sqlList.isEmpty()) {
try {
try (Connection connection = targetDataSource.getConnection();
Statement statement = connection.createStatement()) {
for (String sql : sqlList) {
log.info("Execute sql : {}", sql);
statement.execute(sql);
}
}
return true;
} catch (Throwable t) {
log.error("Failed to execute sql script: {}", t.getMessage(), t);
}
}
return false;
}
}

View File

@@ -47,4 +47,6 @@ dbswitch:
## Only useful for PostgreSQL/Greenplum database
writer-engine-insert: false
## whether use change data synchronize to target database table
change-data-sync: true
change-data-sync: true
## data sync option for increment synchronize, see: com.gitee.dbswitch.common.type.SyncOptionEnum
target-sync-option: INSERT_UPDATE_DELETE

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>com.gitee.dbswitch</groupId>
<artifactId>dbswitch-parent</artifactId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<artifactId>dbswitch-dist</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dbswitch-product-dm</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dbswitch-product-elasticsearch</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dbswitch-product-mongodb</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dbswitch-product-mysql</artifactId>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent>
<artifactId>dbswitch-parent</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.2</version>
<version>1.9.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dbswitch-product</artifactId>

View File

@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.gitee.dbswitch</groupId>
<artifactId>dbswitch-parent</artifactId>
<version>1.9.2</version>
<version>1.9.3</version>
<packaging>pom</packaging>
<name>dbswitch</name>
<description>database switch project</description>

View File

@@ -1,6 +1,6 @@
@echo off
set APP_VERSION=1.9.2
set APP_VERSION=1.9.3
echo "Clean Project ..."
call mvn clean -f pom.xml