mirror of
https://gitee.com/dromara/dbswitch.git
synced 2025-10-15 06:10:23 +00:00
前端在线SQL执行
This commit is contained in:
@@ -54,6 +54,7 @@
|
||||
├── dbswitch-product-clickhouse // -> clickhouse方言实现类
|
||||
├── dbswitch-product-mongodb // -> mongodb方言实现类
|
||||
├── dbswitch-product-elasticsearch // -> elasticsearch方言实现类
|
||||
├── dbswitch-product-starrocks // -> starrocks方言实现类
|
||||
├── dbswitch-data // 工具入口模块,读取配置文件中的参数执行异构迁移同步
|
||||
├── dbswitch-admin // 在以上模块的基础上引入Quartz的调度服务与接口
|
||||
├── dbswitch-admin-ui // 基于Vue2的前段WEB交互页面
|
||||
@@ -364,6 +365,8 @@ jdbc连接地址:jdbc:mongodb://172.17.2.12:27017/admin?authSource=admin&authM
|
||||
jdbc驱动名称:com.gitee.jdbc.mongodb.JdbcDriver
|
||||
```
|
||||
|
||||
> 项目地址:https://gitee.com/inrgihc/jdbc-mongodb-driver
|
||||
|
||||
**ElasticSearch数据库**
|
||||
|
||||
```
|
||||
@@ -371,6 +374,8 @@ jdbc连接地址:jdbc:jest://172.17.2.12:9200?useHttps=false
|
||||
jdbc驱动名称:com.gitee.jdbc.elasticsearch.JdbcDriver
|
||||
```
|
||||
|
||||
> 项目地址:https://gitee.com/inrgihc/jdbc-jest-driver
|
||||
|
||||
#### (2)、启动方法
|
||||
|
||||
- linux系统下:
|
||||
@@ -504,6 +509,8 @@ bin/startup.sh
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
164
dbswitch-admin-ui/package-lock.json
generated
164
dbswitch-admin-ui/package-lock.json
generated
@@ -11,6 +11,7 @@
|
||||
"echarts": "^4.9.0",
|
||||
"element-ui": "^2.15.6",
|
||||
"qs": "^6.11.2",
|
||||
"sql-formatter": "^15.3.1",
|
||||
"urlencode": "^1.1.0",
|
||||
"vue": "^2.5.2",
|
||||
"vue-count-to": "^1.0.13",
|
||||
@@ -3892,6 +3893,11 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/discontinuous-range": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
|
||||
"integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ=="
|
||||
},
|
||||
"node_modules/dns-equal": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/dns-equal/-/dns-equal-1.0.0.tgz",
|
||||
@@ -7140,6 +7146,11 @@
|
||||
"mkdirp": "bin/cmd.js"
|
||||
}
|
||||
},
|
||||
"node_modules/moo": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmmirror.com/moo/-/moo-0.5.2.tgz",
|
||||
"integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q=="
|
||||
},
|
||||
"node_modules/move-concurrently": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||
@@ -7225,6 +7236,28 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/nearley": {
|
||||
"version": "2.20.1",
|
||||
"resolved": "https://registry.npmmirror.com/nearley/-/nearley-2.20.1.tgz",
|
||||
"integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==",
|
||||
"dependencies": {
|
||||
"commander": "^2.19.0",
|
||||
"moo": "^0.5.0",
|
||||
"railroad-diagrams": "^1.0.0",
|
||||
"randexp": "0.4.6"
|
||||
},
|
||||
"bin": {
|
||||
"nearley-railroad": "bin/nearley-railroad.js",
|
||||
"nearley-test": "bin/nearley-test.js",
|
||||
"nearley-unparse": "bin/nearley-unparse.js",
|
||||
"nearleyc": "bin/nearleyc.js"
|
||||
}
|
||||
},
|
||||
"node_modules/nearley/node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz",
|
||||
@@ -10867,6 +10900,23 @@
|
||||
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/railroad-diagrams": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
|
||||
"integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A=="
|
||||
},
|
||||
"node_modules/randexp": {
|
||||
"version": "0.4.6",
|
||||
"resolved": "https://registry.npmmirror.com/randexp/-/randexp-0.4.6.tgz",
|
||||
"integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
|
||||
"dependencies": {
|
||||
"discontinuous-range": "1.0.0",
|
||||
"ret": "~0.1.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz",
|
||||
@@ -11322,7 +11372,6 @@
|
||||
"version": "0.1.15",
|
||||
"resolved": "https://registry.npmmirror.com/ret/-/ret-0.1.15.tgz",
|
||||
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
}
|
||||
@@ -12136,6 +12185,32 @@
|
||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/sql-formatter": {
|
||||
"version": "15.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/sql-formatter/-/sql-formatter-15.3.1.tgz",
|
||||
"integrity": "sha512-L/dqan+Hrt0PpPdCbHcI9bdfOvqaQZR7v5c5SWMJ3bUGQSezK09Mm9q2I3B4iObjaq7FyoldIM+fDSmfzGRXCA==",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1",
|
||||
"get-stdin": "=8.0.0",
|
||||
"nearley": "^2.20.1"
|
||||
},
|
||||
"bin": {
|
||||
"sql-formatter": "bin/sql-formatter-cli.cjs"
|
||||
}
|
||||
},
|
||||
"node_modules/sql-formatter/node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||
},
|
||||
"node_modules/sql-formatter/node_modules/get-stdin": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-8.0.0.tgz",
|
||||
"integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/ssri": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/ssri/-/ssri-5.3.0.tgz",
|
||||
@@ -13301,6 +13376,18 @@
|
||||
"vue": "^2.5.9"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-drag-resize": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmmirror.com/vue-drag-resize/-/vue-drag-resize-1.5.4.tgz",
|
||||
"integrity": "sha512-SR3U7n6TAZEBgP7zw7bR9mjtAlYBjqIoaWTDPz5HXN/nYhOxKSA31aD7p71fmq1jtyt9reAnCx62valNL9ZAcg==",
|
||||
"dependencies": {
|
||||
"vue-drag-resize": "^1.5.0-rc3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-hot-reload-api": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
|
||||
@@ -17978,6 +18065,11 @@
|
||||
"path-type": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"discontinuous-range": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
|
||||
"integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ=="
|
||||
},
|
||||
"dns-equal": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/dns-equal/-/dns-equal-1.0.0.tgz",
|
||||
@@ -20643,6 +20735,11 @@
|
||||
"minimist": "^1.2.6"
|
||||
}
|
||||
},
|
||||
"moo": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmmirror.com/moo/-/moo-0.5.2.tgz",
|
||||
"integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q=="
|
||||
},
|
||||
"move-concurrently": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||
@@ -20716,6 +20813,24 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"nearley": {
|
||||
"version": "2.20.1",
|
||||
"resolved": "https://registry.npmmirror.com/nearley/-/nearley-2.20.1.tgz",
|
||||
"integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==",
|
||||
"requires": {
|
||||
"commander": "^2.19.0",
|
||||
"moo": "^0.5.0",
|
||||
"railroad-diagrams": "^1.0.0",
|
||||
"randexp": "0.4.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz",
|
||||
@@ -23738,6 +23853,20 @@
|
||||
"integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
|
||||
"dev": true
|
||||
},
|
||||
"railroad-diagrams": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
|
||||
"integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A=="
|
||||
},
|
||||
"randexp": {
|
||||
"version": "0.4.6",
|
||||
"resolved": "https://registry.npmmirror.com/randexp/-/randexp-0.4.6.tgz",
|
||||
"integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
|
||||
"requires": {
|
||||
"discontinuous-range": "1.0.0",
|
||||
"ret": "~0.1.10"
|
||||
}
|
||||
},
|
||||
"randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz",
|
||||
@@ -24123,8 +24252,7 @@
|
||||
"ret": {
|
||||
"version": "0.1.15",
|
||||
"resolved": "https://registry.npmmirror.com/ret/-/ret-0.1.15.tgz",
|
||||
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
|
||||
},
|
||||
"rgb-regex": {
|
||||
"version": "1.0.1",
|
||||
@@ -24818,6 +24946,28 @@
|
||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
|
||||
"dev": true
|
||||
},
|
||||
"sql-formatter": {
|
||||
"version": "15.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/sql-formatter/-/sql-formatter-15.3.1.tgz",
|
||||
"integrity": "sha512-L/dqan+Hrt0PpPdCbHcI9bdfOvqaQZR7v5c5SWMJ3bUGQSezK09Mm9q2I3B4iObjaq7FyoldIM+fDSmfzGRXCA==",
|
||||
"requires": {
|
||||
"argparse": "^2.0.1",
|
||||
"get-stdin": "=8.0.0",
|
||||
"nearley": "^2.20.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||
},
|
||||
"get-stdin": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/get-stdin/-/get-stdin-8.0.0.tgz",
|
||||
"integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ssri": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/ssri/-/ssri-5.3.0.tgz",
|
||||
@@ -25787,6 +25937,14 @@
|
||||
"vue": "^2.5.9"
|
||||
}
|
||||
},
|
||||
"vue-drag-resize": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmmirror.com/vue-drag-resize/-/vue-drag-resize-1.5.4.tgz",
|
||||
"integrity": "sha512-SR3U7n6TAZEBgP7zw7bR9mjtAlYBjqIoaWTDPz5HXN/nYhOxKSA31aD7p71fmq1jtyt9reAnCx62valNL9ZAcg==",
|
||||
"requires": {
|
||||
"vue-drag-resize": "^1.5.0-rc3"
|
||||
}
|
||||
},
|
||||
"vue-hot-reload-api": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmmirror.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
|
||||
|
@@ -14,6 +14,7 @@
|
||||
"echarts": "^4.9.0",
|
||||
"element-ui": "^2.15.6",
|
||||
"qs": "^6.11.2",
|
||||
"sql-formatter": "^15.3.1",
|
||||
"urlencode": "^1.1.0",
|
||||
"vue": "^2.5.2",
|
||||
"vue-count-to": "^1.0.13",
|
||||
|
@@ -121,14 +121,14 @@ const constantRouter = new Router({
|
||||
},
|
||||
{
|
||||
path: '/connection/list/addDataSource1',
|
||||
name: '接入数据源',
|
||||
name: '数据源创建步骤1',
|
||||
icon: "el-icon-menu",
|
||||
hidden: true,
|
||||
component: () => import('@/views/connection/addDataSource1.vue')
|
||||
},
|
||||
{
|
||||
path: '/connection/list/addDataSource2',
|
||||
name: '接入数据源',
|
||||
name: '数据源创建步骤2',
|
||||
icon: "el-icon-menu",
|
||||
hidden: true,
|
||||
component: () => import('@/views/connection/addDataSource2.vue')
|
||||
|
@@ -144,7 +144,7 @@
|
||||
<el-row style="text-align: center">
|
||||
<el-button type="success"
|
||||
class="startTest"
|
||||
@click="startTest">开始检测</el-button>
|
||||
@click="startTest">测试</el-button>
|
||||
<el-button type="primary"
|
||||
class="createDataSource"
|
||||
@click="createDataSource">创建</el-button>
|
||||
|
@@ -53,7 +53,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-dialog title="添加数据库驱动JAR说明"
|
||||
<el-dialog title="添加说明"
|
||||
:visible.sync="dialogVisible"
|
||||
width="40%"
|
||||
:before-close="handleClose">
|
||||
|
@@ -41,7 +41,7 @@
|
||||
</el-form-item>
|
||||
<el-form-item :required=true
|
||||
label="数据库类型">
|
||||
<label>{{ this.selectedDataSource.name }}</label>
|
||||
<label>{{ this.updateform.type }}</label>
|
||||
</el-form-item>
|
||||
<el-form-item prop="version"
|
||||
label="驱动版本">
|
||||
@@ -144,7 +144,7 @@
|
||||
<el-row style="text-align: center">
|
||||
<el-button type="success"
|
||||
class="startTest"
|
||||
@click="startTest">开始检测</el-button>
|
||||
@click="startTest">测试</el-button>
|
||||
<el-button type="primary"
|
||||
class="createDataSource"
|
||||
@click="updateDataSource">修改</el-button>
|
||||
|
@@ -1,38 +1,46 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-card>
|
||||
<div class="flex-between">
|
||||
<div class="tree-container">
|
||||
<el-select placeholder="请选择数据源"
|
||||
v-model="dataSourceId"
|
||||
@change="loadTreeData">
|
||||
<el-option v-for="(item,index) in connectionList"
|
||||
:key="index"
|
||||
:label="`[${item.id}]${item.name}`"
|
||||
:value="item.id"></el-option>
|
||||
</el-select>
|
||||
<el-scrollbar style="height: 800px;">
|
||||
<el-tree ref="metadataTree"
|
||||
empty-text="请选择数据源后查看"
|
||||
:indent=6
|
||||
:data="treeData"
|
||||
:props="props"
|
||||
:load="loadTreeNode"
|
||||
:expand-on-click-node="true"
|
||||
:highlight-current="true"
|
||||
:render-content="renderContent"
|
||||
@node-click="handleNodeClick"
|
||||
lazy>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<el-tabs v-model="tabActiveTabName"
|
||||
type="border-card">
|
||||
<el-tab-pane label="元数据"
|
||||
name="metadata">
|
||||
<el-tabs v-model="tabActiveTabName"
|
||||
type="border-card">
|
||||
<el-tab-pane label="元数据"
|
||||
name="metadata">
|
||||
<div class="flex-between">
|
||||
<el-aside>
|
||||
<div class="select-datasource-container">
|
||||
<el-select placeholder="请选择数据源"
|
||||
v-model="dataSourceId"
|
||||
@change="loadTreeData">
|
||||
<el-option v-for="(item,index) in connectionList"
|
||||
:key="index"
|
||||
:label="`[${item.id}]${item.name}`"
|
||||
:value="item.id"></el-option>
|
||||
</el-select>
|
||||
<el-button type="primary"
|
||||
size="mini"
|
||||
:disabled="metadataLoading"
|
||||
icon="el-icon-refresh"
|
||||
@click="loadTreeData">刷新</el-button>
|
||||
</div>
|
||||
<el-scrollbar style="height: 800px;">
|
||||
<el-tree ref="metadataTree"
|
||||
empty-text="请选择数据源后查看"
|
||||
:indent=6
|
||||
:data="treeData"
|
||||
:props="props"
|
||||
:load="loadTreeNode"
|
||||
:expand-on-click-node="true"
|
||||
:highlight-current="true"
|
||||
:render-content="renderContent"
|
||||
@node-click="handleNodeClick"
|
||||
lazy>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
</el-aside>
|
||||
<el-main class="metadata-container">
|
||||
当前表:<el-tag size="medium">{{currentNode.schemaName}} / {{currentNode.tableName}}</el-tag>
|
||||
<el-tabs v-model="metadataActiveTabName">
|
||||
<el-tabs v-model="metadataActiveTabName"
|
||||
type="border-card">
|
||||
<el-tab-pane label="基本信息"
|
||||
name="first">
|
||||
<el-descriptions size="small"
|
||||
@@ -64,7 +72,7 @@
|
||||
border
|
||||
style="width: 100%">
|
||||
<template slot="empty">
|
||||
<span>单击左侧展开"数据源导航树"来查看表的元数据记录</span>
|
||||
<span>单击点击左侧节点查看对应表的字段信息</span>
|
||||
</template>
|
||||
<el-table-column prop="fieldName"
|
||||
min-width="20%"
|
||||
@@ -73,11 +81,11 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="typeName"
|
||||
min-width="20%"
|
||||
label="类型">
|
||||
label="数据类型">
|
||||
</el-table-column>
|
||||
<el-table-column prop="fieldType"
|
||||
min-width="7%"
|
||||
label="枚举值">
|
||||
label="类型枚举">
|
||||
</el-table-column>
|
||||
<el-table-column prop="displaySize"
|
||||
min-width="7%"
|
||||
@@ -118,7 +126,7 @@
|
||||
border
|
||||
style="width: 100%">
|
||||
<template slot="empty">
|
||||
<span>单击左侧展开"数据源导航树"来查看表的元数据记录</span>
|
||||
<span>单击点击左侧节点查看对应表的索引信息</span>
|
||||
</template>
|
||||
<el-table-column prop="indexType"
|
||||
min-width="20%"
|
||||
@@ -143,7 +151,7 @@
|
||||
:data="sampleData.rows"
|
||||
border>
|
||||
<template slot="empty">
|
||||
<span>单击左侧展开"数据源导航树"来查看表的数据记录</span>
|
||||
<span>单击点击左侧节点查看对应表的取样数据</span>
|
||||
</template>
|
||||
<el-table-column v-for="(item,index) in sampleData.columns"
|
||||
:prop="item"
|
||||
@@ -154,14 +162,111 @@
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-tab-pane>
|
||||
<!-- <el-tab-pane label="SQL在线"
|
||||
name="sqlQuery">
|
||||
<multi-sql-editor ref="sqlEditors"></multi-sql-editor>
|
||||
</el-tab-pane> -->
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</el-main>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="SQL在线"
|
||||
name="sqlQuery">
|
||||
<el-row :gutter=12
|
||||
class="padding-row-stype">
|
||||
<el-col :span="6">
|
||||
<div class="sqlonline-select-suffix">
|
||||
<span class="text-label">数据源:</span>
|
||||
<el-select size="small"
|
||||
placeholder="请选择数据源"
|
||||
v-model="sqlDataSourceId">
|
||||
<el-option v-for="(item,index) in connectionList"
|
||||
:key="index"
|
||||
:label="`[${item.id}]${item.name}`"
|
||||
:value="item.id"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="sqlonline-select-suffix">
|
||||
<span class="text-label">最大记录数:</span>
|
||||
<el-select size="small"
|
||||
placeholder="选择结果集MaxRow"
|
||||
v-model="rsMaxRowCount">
|
||||
<el-option v-for="(item,index) in maxRowCountList"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item.id"></el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="sqlonline-select-suffix">
|
||||
<span class="text-label">编辑器高度:</span>
|
||||
<el-input-number v-model="editorHeightNum"
|
||||
size="small"
|
||||
:step="10"
|
||||
step-strictly></el-input-number>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<div class="tool">
|
||||
<div class="item-button"
|
||||
@click="runAll"><i class="el-icon-video-play"></i><span>执行</span></div>
|
||||
<div class="item-button"
|
||||
@click="runSelected"><i class="el-icon-caret-right"></i><span>选中执行</span></div>
|
||||
<div class="item-button"
|
||||
@click="formatSql"><i class="el-icon-postcard"></i><span>格式化</span></div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row class="padding-row-stype">
|
||||
</el-row>
|
||||
<el-row class="padding-row-stype">
|
||||
<div v-loading="sqlResultLoading"
|
||||
:style="'height: ' + editorHeightNum + 'px'">
|
||||
<ace ref="sqlEditor"
|
||||
@init="initEditor"
|
||||
lang="sql"
|
||||
width="100%"
|
||||
height="100%"
|
||||
theme="monokai"
|
||||
:options="sqlEditorOption">
|
||||
</ace>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-row class="padding-row-stype">
|
||||
<el-tabs v-model="activeResultTab"
|
||||
tab-position="top"
|
||||
type="border-card">
|
||||
<el-tab-pane label="信息"
|
||||
name="0">
|
||||
<div v-for="(one,idx) in sqlExecuteResult.summaries"
|
||||
:key="idx">
|
||||
[SQL]: {{one.sql}}<br />{{one.summary}}<br /><br />
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane v-for="(one,idx) in sqlExecuteResult.results"
|
||||
:key="(idx+1)"
|
||||
:label="'结果'+(idx+1)"
|
||||
:name="''+(idx+1)">
|
||||
<el-table :header-cell-style="{background:'#eef1f6',color:'#606266','font-size': '12px'}"
|
||||
style="width: 100%; max-height: 400px; overflow: auto;"
|
||||
height="400px"
|
||||
:data="one.rows"
|
||||
border>
|
||||
<template slot="empty">
|
||||
<span>SQL结果为空</span>
|
||||
</template>
|
||||
<el-table-column v-for="(item,index) in one.columns"
|
||||
:prop="item.columnName"
|
||||
:key="index"
|
||||
show-overflow-tooltip>
|
||||
<template slot="header">
|
||||
{{item.columnName}}<br />({{item.columnType}})
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
@@ -169,14 +274,15 @@
|
||||
<script>
|
||||
import urlencode from "urlencode";
|
||||
import ace from 'vue2-ace-editor'
|
||||
const sqlformatter = require("sql-formatter");
|
||||
|
||||
// 参考文章:https://blog.csdn.net/m0_50255772/article/details/109484828
|
||||
export default {
|
||||
components: {
|
||||
ace
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
metadataLoading: false,
|
||||
props: {
|
||||
label: 'label',
|
||||
children: 'children',
|
||||
@@ -210,7 +316,34 @@ export default {
|
||||
columns: []
|
||||
},
|
||||
count: 1,
|
||||
sampleData: []
|
||||
sampleData: [],
|
||||
sqlDataSourceId: null,
|
||||
sqlEditorOption: {
|
||||
enableBasicAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: true,
|
||||
showPrintMargin: false,
|
||||
showLineNumbers: true,
|
||||
tabSize: 6,
|
||||
fontSize: 18,
|
||||
},
|
||||
rsMaxRowCount: 200,
|
||||
maxRowCountList: [
|
||||
{ id: 100, name: '100条' },
|
||||
{ id: 200, name: '200条' },
|
||||
{ id: 500, name: '500条' },
|
||||
{ id: 1000, name: '1000条' },
|
||||
{ id: 2000, name: '2000条' },
|
||||
{ id: 5000, name: '5000条' },
|
||||
{ id: 10000, name: '10000条' },
|
||||
],
|
||||
editorHeightNum: 200,
|
||||
sqlResultLoading: false,
|
||||
sqlExecuteResult: {
|
||||
summaries: [],
|
||||
results: [],
|
||||
},
|
||||
activeResultTab: "0",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -248,12 +381,14 @@ export default {
|
||||
loadTreeData: function () {
|
||||
if (this.dataSourceId && this.dataSourceId > 0) {
|
||||
this.treeData = []
|
||||
this.metadataLoading = true;
|
||||
setTimeout(() => {
|
||||
this.$http({
|
||||
method: "GET",
|
||||
url: "/dbswitch/admin/api/v1/connection/schemas/get/" + this.dataSourceId
|
||||
}).then(
|
||||
res => {
|
||||
this.metadataLoading = false;
|
||||
if (0 === res.data.code) {
|
||||
for (let element of res.data.data) {
|
||||
let obj = new Object();
|
||||
@@ -304,11 +439,13 @@ export default {
|
||||
},
|
||||
loadTablesList: function (resolve, dataSourceId, schema, type) {
|
||||
var tableType = 'VIEW' === type ? 'views' : 'tables'
|
||||
this.metadataLoading = true;
|
||||
this.$http({
|
||||
method: "GET",
|
||||
url: "/dbswitch/admin/api/v1/connection/" + tableType + "/get/" + dataSourceId + "?schema=" + urlencode(schema)
|
||||
}).then(
|
||||
res => {
|
||||
this.metadataLoading = false;
|
||||
if (0 === res.data.code) {
|
||||
let tableList = []
|
||||
for (let element of res.data.data) {
|
||||
@@ -400,6 +537,7 @@ export default {
|
||||
if (!data.hasChild && datasourceId && schema && table) {
|
||||
this.tabActiveTabName = 'metadata';
|
||||
this.metadataActiveTabName = 'first';
|
||||
this.clearDataSet();
|
||||
this.getTableMeta(datasourceId, schema, table);
|
||||
this.getTableData(datasourceId, schema, table);
|
||||
}
|
||||
@@ -415,8 +553,8 @@ export default {
|
||||
createSql: "",
|
||||
primaryKeys: [],
|
||||
columns: []
|
||||
},
|
||||
this.sampleData = []
|
||||
};
|
||||
this.sampleData = []
|
||||
},
|
||||
getTableMeta (id, schema, table) {
|
||||
this.$http({
|
||||
@@ -431,7 +569,6 @@ export default {
|
||||
this.currentNode.schemaName = schema;
|
||||
} else {
|
||||
this.$alert("加载失败,原因:" + res.data.message, '数据加载失败');
|
||||
this.clearDataSet();
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -447,7 +584,6 @@ export default {
|
||||
//console.log(this.sampleData)
|
||||
} else {
|
||||
this.$alert("加载失败,原因:" + res.data.message, '数据加载失败');
|
||||
this.clearDataSet();
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -477,6 +613,78 @@ export default {
|
||||
}
|
||||
);
|
||||
},
|
||||
formatSql: function () {
|
||||
if (this.sqlResultLoading === true) {
|
||||
return
|
||||
}
|
||||
let editor = this.$refs.sqlEditor.editor;
|
||||
let sqlcontent = editor.getSelectedText();
|
||||
if (sqlcontent && sqlcontent.length > 0) {
|
||||
let formatSql = sqlformatter.format(sqlcontent)
|
||||
editor.session.replace(editor.getSelectionRange(), formatSql);
|
||||
} else {
|
||||
sqlcontent = editor.getValue();
|
||||
if (!sqlcontent || sqlcontent.length === 0) {
|
||||
alert("SQL文本内容为空");
|
||||
return
|
||||
}
|
||||
editor.setValue(sqlformatter.format(editor.getValue()));
|
||||
}
|
||||
},
|
||||
runAll: function () {
|
||||
let editor = this.$refs.sqlEditor.editor;
|
||||
let sqlcontent = editor.getValue();
|
||||
if (!sqlcontent || 0 === sqlcontent.length) {
|
||||
alert("SQL文本内容为空");
|
||||
return
|
||||
}
|
||||
this.executeSqlScript(sqlcontent)
|
||||
},
|
||||
runSelected: function () {
|
||||
let editor = this.$refs.sqlEditor.editor;
|
||||
let sqlcontent = editor.getSelectedText();
|
||||
if (!sqlcontent || 0 === sqlcontent.length) {
|
||||
alert("请首先选择SQL文本内容");
|
||||
return
|
||||
}
|
||||
this.executeSqlScript(sqlcontent)
|
||||
},
|
||||
executeSqlScript: function (sqlScript) {
|
||||
if (this.sqlResultLoading === true) {
|
||||
alert("已有一个查询正在进行中");
|
||||
return
|
||||
}
|
||||
if (!this.sqlDataSourceId || this.dataSourceId < 0) {
|
||||
alert("请首先选择一个数据源来");
|
||||
return
|
||||
}
|
||||
this.sqlResultLoading = true;
|
||||
this.sqlExecuteResult = {
|
||||
summaries: [],
|
||||
results: [],
|
||||
};
|
||||
this.$http({
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
url: "/dbswitch/admin/api/v1/metadata/data/sql/" + this.sqlDataSourceId,
|
||||
data: JSON.stringify({
|
||||
script: sqlScript,
|
||||
page: 1,
|
||||
size: this.rsMaxRowCount
|
||||
})
|
||||
}).then(res => {
|
||||
this.sqlResultLoading = false;
|
||||
if (0 === res.data.code) {
|
||||
this.sqlExecuteResult = res.data.data;
|
||||
this.activeResultTab = "0";
|
||||
} else {
|
||||
alert("SQL执行报错:" + res.data.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
},
|
||||
created () {
|
||||
this.loadConnections();
|
||||
@@ -521,8 +729,12 @@ export default {
|
||||
.tree-container .tree {
|
||||
overflow: auto;
|
||||
}
|
||||
.metadata-container {
|
||||
padding: 4px;
|
||||
}
|
||||
.table-container {
|
||||
width: 100%;
|
||||
border: darkblue;
|
||||
}
|
||||
.table-container-data-table {
|
||||
height: 90%;
|
||||
@@ -551,4 +763,35 @@ el-tabs--border-card > .el-tabs__header .el-tabs__item {
|
||||
background-color: #0065d5;
|
||||
color: #ffffff;
|
||||
}
|
||||
.sqlonline-select-suffix {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center; /* 垂直居中 */
|
||||
}
|
||||
.text-label {
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.select-datasource-container {
|
||||
display: flex;
|
||||
}
|
||||
.tool {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.tool .item-button {
|
||||
display: inline-block;
|
||||
font-size: 20px;
|
||||
color: #009966;
|
||||
margin: 0 20px 0 0;
|
||||
line-height: 26px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.tool .item-button span {
|
||||
color: #000;
|
||||
font-size: 16px;
|
||||
}
|
||||
.padding-row-stype {
|
||||
padding: 5px;
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,121 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="tool">
|
||||
<div class="item-button"><i class="iconfont icon-play"></i><span>执行</span></div>
|
||||
<div class="item-button"><i class="iconfont icon-play"></i><span>执行选中</span></div>
|
||||
<div class="item-button"><i class="iconfont icon-play"></i><span>格式化</span></div>
|
||||
</div>
|
||||
<ace ref="editor"
|
||||
:value="content"
|
||||
@init="initEditor"
|
||||
:lang="lang"
|
||||
:height="height === 0 ? '100%' : height"
|
||||
:theme="theme"
|
||||
:options="options"
|
||||
width="100%"
|
||||
v-bind="config">
|
||||
</ace>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ace from 'vue2-ace-editor'
|
||||
|
||||
export default {
|
||||
name: "multiSqlEditer",
|
||||
components: {
|
||||
ace
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
props: {
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 300
|
||||
},
|
||||
readOnly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
theme: {
|
||||
type: String,
|
||||
default: 'monokai'
|
||||
},
|
||||
lang: {
|
||||
type: String,
|
||||
default: 'sql'
|
||||
},
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
font_size: 16,
|
||||
sql_atom: true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
options () {
|
||||
if (this.readOnly) {
|
||||
return {
|
||||
enableBasicAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: this.config.sql_atom,
|
||||
showPrintMargin: false,
|
||||
fontSize: this.config.font_size,
|
||||
readOnly: true
|
||||
}
|
||||
}
|
||||
return {
|
||||
enableBasicAutocompletion: true,
|
||||
enableSnippets: true,
|
||||
enableLiveAutocompletion: this.config.sql_atom,
|
||||
showPrintMargin: false,
|
||||
fontSize: this.config.font_size
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initEditor (editor) {
|
||||
require('brace/ext/language_tools')
|
||||
// 设置语言
|
||||
require('brace/mode/sql')
|
||||
require('brace/snippets/sql')
|
||||
// 设置主题 按需加载
|
||||
require('brace/theme/monokai')
|
||||
require('brace/theme/chrome')
|
||||
require('brace/theme/crimson_editor')
|
||||
// 监听值的变化
|
||||
editor.getSession().on('change', val => {
|
||||
this.$emit('change', editor.getValue())
|
||||
})
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
created () {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tool .item-button {
|
||||
display: inline-block;
|
||||
font-size: 20px;
|
||||
color: #009966;
|
||||
margin: 0 20px 0 0;
|
||||
line-height: 26px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.tool .item-button span {
|
||||
color: #000;
|
||||
font-size: 16px;
|
||||
}
|
||||
</style>
|
@@ -17,6 +17,7 @@ import com.gitee.dbswitch.admin.util.ExecuteSqlUtils;
|
||||
import com.gitee.dbswitch.admin.util.ExecuteSqlUtils.ScriptExecuteResult;
|
||||
import com.gitee.dbswitch.admin.util.PageUtils;
|
||||
import com.gitee.dbswitch.common.entity.CloseableDataSource;
|
||||
import com.gitee.dbswitch.common.type.ProductTypeEnum;
|
||||
import com.gitee.dbswitch.schema.SchemaTableData;
|
||||
import com.gitee.dbswitch.schema.SchemaTableMeta;
|
||||
import com.gitee.dbswitch.schema.TableDescription;
|
||||
@@ -132,6 +133,11 @@ public class MetaDataService {
|
||||
}
|
||||
|
||||
public Result<OnlineSqlDataResponse> sqlData(Long id, OnlineSqlDataRequest request) {
|
||||
DatabaseConnectionEntity databaseConn = connectionService.getDatabaseConnectionById(id);
|
||||
ProductTypeEnum productType = databaseConn.getType();
|
||||
if (!productType.isUseSql()) {
|
||||
throw new RuntimeException("不支持的SQL操作数据库类型:" + productType.name());
|
||||
}
|
||||
List<String> statements = new ArrayList<>();
|
||||
ScriptUtils.splitSqlScript(
|
||||
null,
|
||||
@@ -143,7 +149,7 @@ public class MetaDataService {
|
||||
statements);
|
||||
Integer page = Optional.ofNullable(request.getPage()).orElse(1);
|
||||
Integer size = Optional.ofNullable(request.getSize()).orElse(100);
|
||||
try (CloseableDataSource dataSource = connectionService.getDataSource(id)) {
|
||||
try (CloseableDataSource dataSource = connectionService.getDataSource(databaseConn)) {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
List<SqlInput> summaries = new ArrayList<>(statements.size());
|
||||
List<SqlResult> results = new ArrayList<>(statements.size());
|
||||
@@ -151,28 +157,25 @@ public class MetaDataService {
|
||||
try {
|
||||
ScriptExecuteResult result = ExecuteSqlUtils.execute(connection, sql, page, size);
|
||||
summaries.add(SqlInput.builder().sql(sql).summary(result.getResultSummary()).build());
|
||||
results.add(
|
||||
SqlResult.builder()
|
||||
.columns(result.getResultHeader().stream()
|
||||
.map(one ->
|
||||
ColumnItem.builder()
|
||||
.columnName(specialReplace(one.getKey()))
|
||||
.columnType(one.getValue())
|
||||
.build()
|
||||
).collect(Collectors.toList()))
|
||||
.rows(result.getResultData())
|
||||
.build());
|
||||
if (CollectionUtils.isNotEmpty(result.getResultHeader())) {
|
||||
results.add(
|
||||
SqlResult.builder()
|
||||
.columns(result.getResultHeader().stream()
|
||||
.map(one ->
|
||||
ColumnItem.builder()
|
||||
.columnName(specialReplace(one.getKey()))
|
||||
.columnType(one.getValue())
|
||||
.build()
|
||||
).collect(Collectors.toList()))
|
||||
.rows(convertRows(result.getResultData()))
|
||||
.build());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
summaries.add(
|
||||
SqlInput.builder()
|
||||
.sql(sql)
|
||||
.summary(e.getMessage())
|
||||
.build());
|
||||
results.add(
|
||||
SqlResult.builder()
|
||||
.columns(Collections.emptyList())
|
||||
.rows(Collections.emptyList())
|
||||
.build());
|
||||
}
|
||||
}
|
||||
return Result.success(
|
||||
@@ -210,6 +213,22 @@ public class MetaDataService {
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> convertRows(List<Map<String, Object>> rows) {
|
||||
if (null == rows || rows.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<Map<String, Object>> result = new ArrayList<>(rows.size());
|
||||
for (Map<String, Object> row : rows) {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> entry : row.entrySet()) {
|
||||
Object v = entry.getValue();
|
||||
map.put(entry.getKey(), Objects.nonNull(v) ? v.toString() : null);
|
||||
}
|
||||
result.add(map);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String toStr(Boolean value) {
|
||||
if (null == value) {
|
||||
return "未知";
|
||||
|
@@ -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.01a417d6ceadacbc5f419b7ca49a3b8e.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.bf67a9f5837c2101612d.js></script><script type=text/javascript src=/static/js/vendor.804b029d66a1d9f36ac1.js></script><script type=text/javascript src=/static/js/app.510de779934f2bc79267.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.e8f93316f0672fafa7fc92fac082f131.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.a75c86cba0d382d89449.js></script><script type=text/javascript src=/static/js/vendor.8200341f98478c8f7552.js></script><script type=text/javascript src=/static/js/app.6479f74f2c348b271749.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
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
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
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
@@ -1,2 +1,2 @@
|
||||
webpackJsonp([12],{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("ru48")},"data-v-8a3240f4",null);e.default=s.exports},ru48:function(t,e){}});
|
||||
//# sourceMappingURL=12.9f1bc065d4fb5d823725.js.map
|
||||
webpackJsonp([12],{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:"添加说明",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("bCkE")},"data-v-acee6216",null);e.default=s.exports},bCkE:function(t,e){}});
|
||||
//# sourceMappingURL=12.9511a964c93be4d9ab2c.js.map
|
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
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
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
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
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
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
@@ -1,2 +0,0 @@
|
||||
webpackJsonp([24],{NHnr:function(n,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=t("//Fk"),i=t.n(o),c=t("7+uW"),a={render:function(){var n=this.$createElement,e=this._self._c||n;return e("div",{staticClass:"body-wrapper"},[e("router-view")],1)},staticRenderFns:[]};var r=t("VU/8")({name:"App"},a,!1,function(n){t("O8ez")},"data-v-a97617c2",null).exports,u=t("/ocq");c.default.use(u.a);var l=new u.a({routes:[{path:"/",name:"首页",component:function(){return t.e(5).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/list",name:"数据源",icon:"el-icon-bank-card",component:function(){return Promise.all([t.e(0),t.e(16)]).then(t.bind(null,"qdtB"))}},{path:"/connection/driver",name:"驱动配置",icon:"el-icon-help",component:function(){return t.e(12).then(t.bind(null,"WfA7"))}}]},{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(21)]).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(13).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(4).then(t.bind(null,"m25N"))}},{path:"/user/personal",name:"个人中心",hidden:!0,component:function(){return t.e(2).then(t.bind(null,"uTKz"))}},{path:"/task/create",name:"创建任务",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(14)]).then(t.bind(null,"/rCC"))}},{path:"/task/update",name:"修改任务",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(15)]).then(t.bind(null,"txod"))}},{path:"/task/detail",name:"查看任务",hidden:!0,component:function(){return t.e(19).then(t.bind(null,"nrt7"))}},{path:"/connection/list/addDataSource1",name:"接入数据源",icon:"el-icon-menu",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(22)]).then(t.bind(null,"Vr+S"))}},{path:"/connection/list/addDataSource2",name:"接入数据源",icon:"el-icon-menu",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(20)]).then(t.bind(null,"7aEP"))}},{path:"/connection/list/dataSourceInfo",name:"数据源详情",icon:"el-icon-menu",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(17)]).then(t.bind(null,"+HtE"))}},{path:"/connection/list/updateDataSource",name:"编辑数据源",icon:"el-icon-menu",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(18)]).then(t.bind(null,"QTjM"))}}]},{path:"/login",name:"登录",component:function(){return t.e(3).then(t.bind(null,"T+/8"))}}]}),d=t("mtWM"),p=t.n(d).a.create();p.interceptors.request.use(function(n){return n.url=""+n.url,n});var m=p,s=t("zL8q"),h=t.n(s),f=(t("muQq"),t("tvR6"),t("7Vno")),b=t.n(f),v=t("XLwt"),P=t.n(v);c.default.use(m),c.default.use(h.a),c.default.use(b.a),c.default.prototype.$http=m,c.default.config.productionTip=!1,c.default.prototype.$echarts=P.a,m.interceptors.request.use(function(n){var e=sessionStorage.getItem("token");return e&&(n.headers.Authorization="Bearer "+e),n},function(n){return i.a.reject(n)}),m.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),i.a.reject(n.response)}),new c.default({el:"#app",router:l,components:{App:r},template:"<App/>"})},O8ez:function(n,e){},muQq:function(n,e){},tvR6:function(n,e){}},["NHnr"]);
|
||||
//# sourceMappingURL=app.510de779934f2bc79267.js.map
|
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
webpackJsonp([24],{NHnr:function(n,e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=t("//Fk"),i=t.n(o),c=t("7+uW"),a={render:function(){var n=this.$createElement,e=this._self._c||n;return e("div",{staticClass:"body-wrapper"},[e("router-view")],1)},staticRenderFns:[]};var r=t("VU/8")({name:"App"},a,!1,function(n){t("O8ez")},"data-v-a97617c2",null).exports,u=t("/ocq");c.default.use(u.a);var l=new u.a({routes:[{path:"/",name:"首页",component:function(){return t.e(5).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/list",name:"数据源",icon:"el-icon-bank-card",component:function(){return Promise.all([t.e(0),t.e(17)]).then(t.bind(null,"qdtB"))}},{path:"/connection/driver",name:"驱动配置",icon:"el-icon-help",component:function(){return t.e(12).then(t.bind(null,"WfA7"))}}]},{path:"/metadata",name:"数据导航",icon:"el-icon-coin",component:function(){return Promise.all([t.e(0),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(21)]).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(13).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(4).then(t.bind(null,"m25N"))}},{path:"/user/personal",name:"个人中心",hidden:!0,component:function(){return t.e(2).then(t.bind(null,"uTKz"))}},{path:"/task/create",name:"创建任务",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(15)]).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(20).then(t.bind(null,"nrt7"))}},{path:"/connection/list/addDataSource1",name:"数据源创建步骤1",icon:"el-icon-menu",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(22)]).then(t.bind(null,"Vr+S"))}},{path:"/connection/list/addDataSource2",name:"数据源创建步骤2",icon:"el-icon-menu",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(19)]).then(t.bind(null,"7aEP"))}},{path:"/connection/list/dataSourceInfo",name:"数据源详情",icon:"el-icon-menu",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(18)]).then(t.bind(null,"+HtE"))}},{path:"/connection/list/updateDataSource",name:"编辑数据源",icon:"el-icon-menu",hidden:!0,component:function(){return Promise.all([t.e(0),t.e(14)]).then(t.bind(null,"QTjM"))}}]},{path:"/login",name:"登录",component:function(){return t.e(3).then(t.bind(null,"T+/8"))}}]}),d=t("mtWM"),p=t.n(d).a.create();p.interceptors.request.use(function(n){return n.url=""+n.url,n});var m=p,s=t("zL8q"),h=t.n(s),f=(t("muQq"),t("tvR6"),t("7Vno")),b=t.n(f),v=t("XLwt"),P=t.n(v);c.default.use(m),c.default.use(h.a),c.default.use(b.a),c.default.prototype.$http=m,c.default.config.productionTip=!1,c.default.prototype.$echarts=P.a,m.interceptors.request.use(function(n){var e=sessionStorage.getItem("token");return e&&(n.headers.Authorization="Bearer "+e),n},function(n){return i.a.reject(n)}),m.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),i.a.reject(n.response)}),new c.default({el:"#app",router:l,components:{App:r},template:"<App/>"})},O8ez:function(n,e){},muQq:function(n,e){},tvR6:function(n,e){}},["NHnr"]);
|
||||
//# sourceMappingURL=app.6479f74f2c348b271749.js.map
|
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
|
||||
!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,c,f){for(var o,d,b,i=0,u=[];i<r.length;i++)d=r[i],t[d]&&u.push(t[d][0]),t[d]=0;for(o in c)Object.prototype.hasOwnProperty.call(c,o)&&(e[o]=c[o]);for(n&&n(r,c,f);u.length;)u.shift()();if(f)for(i=0;i<f.length;i++)b=a(a.s=f[i]);return b};var r={},t={25:0};function a(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,a),t.l=!0,t.exports}a.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,a){n=t[e]=[r,a]});n[2]=r;var c=document.getElementsByTagName("head")[0],f=document.createElement("script");f.type="text/javascript",f.charset="utf-8",f.async=!0,f.timeout=12e4,a.nc&&f.setAttribute("nonce",a.nc),f.src=a.p+"static/js/"+e+"."+{0:"b25ba583c782da8df088",1:"431ebdfd77ec151f12e7",2:"5d102c48d5747fb106e0",3:"ef5e983cf9ad9dc27899",4:"c08b2c8b16b2d0d50f62",5:"de32c8bd9fcd7cba61b2",6:"d7f3aa182a9403e7c6f6",7:"2c3ef6028bafee6fbaca",8:"535ff4d6dbb1131433ea",9:"4590fe5acd44e077ba19",10:"1d1a99a89d92bca35121",11:"9ea92898e3919b2a671f",12:"9511a964c93be4d9ab2c",13:"522b8e9b509523953170",14:"c04809c50fa291ee4b57",15:"b413da284ca8a4266148",16:"d0a4d814849a4cb8dde5",17:"68d3bb07f9efaf16b653",18:"b6bf70f4f372e952d31f",19:"60fcf0f9bb311b02607d",20:"51523f2d886fb89f48dc",21:"f9fd831656eab671bdc4",22:"b623f8b56b9a9aa1c02b"}[e]+".js";var o=setTimeout(d,12e4);function d(){f.onerror=f.onload=null,clearTimeout(o);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),t[e]=void 0)}return f.onerror=f.onload=d,c.appendChild(f),r},a.m=e,a.c=r,a.d=function(e,n,r){a.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},a.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(n,"a",n),n},a.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},a.p="/",a.oe=function(e){throw console.error(e),e}}([]);
|
||||
//# sourceMappingURL=manifest.a75c86cba0d382d89449.js.map
|
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
||||
!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,a,o){for(var f,d,b,i=0,u=[];i<r.length;i++)d=r[i],t[d]&&u.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);u.length;)u.shift()();if(o)for(i=0;i<o.length;i++)b=c(c.s=o[i]);return b};var r={},t={25: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:"3b7f8081fc55ac124770",1:"4d0d71cf223fb51aef41",2:"5d102c48d5747fb106e0",3:"ef5e983cf9ad9dc27899",4:"c08b2c8b16b2d0d50f62",5:"de32c8bd9fcd7cba61b2",6:"d7f3aa182a9403e7c6f6",7:"2c3ef6028bafee6fbaca",8:"535ff4d6dbb1131433ea",9:"4590fe5acd44e077ba19",10:"1d1a99a89d92bca35121",11:"9ea92898e3919b2a671f",12:"9f1bc065d4fb5d823725",13:"522b8e9b509523953170",14:"738015ac6e8a94eade30",15:"fefb5f8ed908101124ea",16:"4685d9de4b41bb601703",17:"3d6c2ceca6cfacb5839e",18:"50d7d00bb23d9bdc4fce",19:"56c4e47b2b21dcdd31c1",20:"d09d39413af7b0a23b59",21:"f9fd831656eab671bdc4",22:"b623f8b56b9a9aa1c02b"}[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.bf67a9f5837c2101612d.js.map
|
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
@@ -10,6 +10,7 @@
|
||||
package com.gitee.dbswitch.common.type;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -320,6 +321,15 @@ public enum ProductTypeEnum {
|
||||
return this == ELASTICSEARCH;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为支持使用SQL的数据库类型
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean isUseSql() {
|
||||
return this != MONGODB && this != ELASTICSEARCH;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为ClickHouse数据库类型
|
||||
*
|
||||
@@ -369,4 +379,22 @@ public enum ProductTypeEnum {
|
||||
return url.startsWith(prefix1);
|
||||
}
|
||||
|
||||
public static ProductTypeEnum getProductType(String url) {
|
||||
return getProductType(url, null);
|
||||
}
|
||||
|
||||
public static ProductTypeEnum getProductType(String url, Set<ProductTypeEnum> excludes) {
|
||||
if (null != url) {
|
||||
for (ProductTypeEnum productType : ProductTypeEnum.values()) {
|
||||
if (null != excludes && excludes.contains(productType)) {
|
||||
continue;
|
||||
}
|
||||
if (url.startsWith(productType.getUrlPrefix())) {
|
||||
return productType;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -10,12 +10,15 @@
|
||||
package com.gitee.dbswitch.common.util;
|
||||
|
||||
import com.gitee.dbswitch.common.type.ProductTypeEnum;
|
||||
import com.google.common.collect.Sets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.sql.DataSource;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -70,10 +73,10 @@ public final class DatabaseAwareUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据库的产品名
|
||||
* 获取数据库的产品枚举
|
||||
*
|
||||
* @param dataSource 数据源
|
||||
* @return 数据库产品名称字符串
|
||||
* @return 数据库产品枚举
|
||||
*/
|
||||
public static ProductTypeEnum getProductTypeByDataSource(DataSource dataSource) {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
@@ -83,35 +86,27 @@ public final class DatabaseAwareUtils {
|
||||
ProductTypeEnum productType = driverNameMap.get(driverName);
|
||||
if (productType == ProductTypeEnum.POSTGRESQL) {
|
||||
String url = connection.getMetaData().getURL();
|
||||
if (null != url && url.contains("jdbc:opengauss:")) {
|
||||
return ProductTypeEnum.OPENGAUSS;
|
||||
Set<ProductTypeEnum> excludes = Sets.immutableEnumSet(ProductTypeEnum.POSTGRESQL);
|
||||
ProductTypeEnum pgLikeType = ProductTypeEnum.getProductType(url, excludes);
|
||||
if (null != pgLikeType) {
|
||||
return pgLikeType;
|
||||
}
|
||||
if (null != url && url.contains("jdbc:highgo:")) {
|
||||
return ProductTypeEnum.HIGHGO;
|
||||
} else if (productType == ProductTypeEnum.MYSQL) {
|
||||
if (isStarRocks(connection)) {
|
||||
return ProductTypeEnum.STARROCKS;
|
||||
}
|
||||
}
|
||||
return productType;
|
||||
}
|
||||
boolean haveStarRocks = false;
|
||||
try {
|
||||
// 此查询语句是Starrocks查询be节点是否存活,可以用来判断是否是Starrocks数据源
|
||||
haveStarRocks = connection.createStatement().execute("show backends");
|
||||
} catch (Exception sqlException) {
|
||||
log.info("Failed to execute sql :show backends, so guesses it is mysql datasource!");
|
||||
}
|
||||
if (haveStarRocks) {
|
||||
return ProductTypeEnum.STARROCKS;
|
||||
}
|
||||
|
||||
ProductTypeEnum type = productNameMap.get(productName);
|
||||
if (null != type) {
|
||||
return type;
|
||||
}
|
||||
String url = connection.getMetaData().getURL();
|
||||
if (null != url && url.contains("mongodb://")) {
|
||||
return ProductTypeEnum.MONGODB;
|
||||
}
|
||||
if (null != url && url.contains("jest://")) {
|
||||
return ProductTypeEnum.ELASTICSEARCH;
|
||||
type = ProductTypeEnum.getProductType(url);
|
||||
if (null != type) {
|
||||
return type;
|
||||
}
|
||||
throw new IllegalStateException("Unable to detect database type from data source instance");
|
||||
} catch (SQLException se) {
|
||||
@@ -119,6 +114,19 @@ public final class DatabaseAwareUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isStarRocks(Connection connection) {
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
// 此查询语句是Starrocks查询be节点是否存活,可以用来判断是否是Starrocks数据源
|
||||
String sql = "SHOW BACKENDS";
|
||||
return statement.execute(sql);
|
||||
} catch (Exception sqlException) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Failed to execute sql :show backends, and guesses it is mysql datasource!");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查MySQL数据库表的存储引擎是否为Innodb
|
||||
*
|
||||
|
@@ -53,7 +53,8 @@ public final class ObjectCastUtils {
|
||||
}
|
||||
} else if (in instanceof java.sql.Clob) {
|
||||
try {
|
||||
return Byte.parseByte(clob2Str((java.sql.Clob) in));
|
||||
String v = clob2Str((java.sql.Clob) in);
|
||||
return null == v ? null : Byte.parseByte(v);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new RuntimeException(
|
||||
String.format("无法将java.sql.Clob类型转换为java.lang.Byte类型:%s", e.getMessage()));
|
||||
@@ -126,8 +127,10 @@ public final class ObjectCastUtils {
|
||||
}
|
||||
} else if (in instanceof java.sql.Clob) {
|
||||
try {
|
||||
String s = clob2Str((java.sql.Clob) in).trim();
|
||||
if (s.equalsIgnoreCase("true")) {
|
||||
String s = clob2Str((java.sql.Clob) in);
|
||||
if (null == s) {
|
||||
return null;
|
||||
} else if (s.equalsIgnoreCase("true")) {
|
||||
return Short.valueOf((short) 1);
|
||||
} else if (s.equalsIgnoreCase("false")) {
|
||||
return Short.valueOf((short) 0);
|
||||
@@ -181,8 +184,10 @@ public final class ObjectCastUtils {
|
||||
}
|
||||
} else if (in instanceof java.sql.Clob) {
|
||||
try {
|
||||
String s = clob2Str((java.sql.Clob) in).trim();
|
||||
if (s.equalsIgnoreCase("true")) {
|
||||
String s = clob2Str((java.sql.Clob) in);
|
||||
if (null == s) {
|
||||
return null;
|
||||
} else if (s.equalsIgnoreCase("true")) {
|
||||
return Integer.valueOf(1);
|
||||
} else if (s.equalsIgnoreCase("false")) {
|
||||
return Integer.valueOf(0);
|
||||
@@ -236,8 +241,10 @@ public final class ObjectCastUtils {
|
||||
}
|
||||
} else if (in instanceof java.sql.Clob) {
|
||||
try {
|
||||
String s = clob2Str((java.sql.Clob) in).trim();
|
||||
if (s.equalsIgnoreCase("true")) {
|
||||
String s = clob2Str((java.sql.Clob) in);
|
||||
if (null == s) {
|
||||
return null;
|
||||
} else if (s.equalsIgnoreCase("true")) {
|
||||
return Long.valueOf(1);
|
||||
} else if (s.equalsIgnoreCase("false")) {
|
||||
return Long.valueOf(0);
|
||||
@@ -289,8 +296,10 @@ public final class ObjectCastUtils {
|
||||
}
|
||||
} else if (in instanceof java.sql.Clob) {
|
||||
try {
|
||||
String s = clob2Str((java.sql.Clob) in).trim();
|
||||
if (s.equalsIgnoreCase("true")) {
|
||||
String s = clob2Str((java.sql.Clob) in);
|
||||
if (null == s) {
|
||||
return null;
|
||||
} else if (s.equalsIgnoreCase("true")) {
|
||||
return Integer.valueOf(1);
|
||||
} else if (s.equalsIgnoreCase("false")) {
|
||||
return Integer.valueOf(0);
|
||||
@@ -342,8 +351,10 @@ public final class ObjectCastUtils {
|
||||
}
|
||||
} else if (in instanceof java.sql.Clob) {
|
||||
try {
|
||||
String s = clob2Str((java.sql.Clob) in).trim();
|
||||
if (s.equalsIgnoreCase("true")) {
|
||||
String s = clob2Str((java.sql.Clob) in);
|
||||
if (null == s) {
|
||||
return null;
|
||||
} else if (s.equalsIgnoreCase("true")) {
|
||||
return Float.valueOf(1);
|
||||
} else if (s.equalsIgnoreCase("false")) {
|
||||
return Float.valueOf(0);
|
||||
@@ -395,8 +406,10 @@ public final class ObjectCastUtils {
|
||||
}
|
||||
} else if (in instanceof java.sql.Clob) {
|
||||
try {
|
||||
String s = clob2Str((java.sql.Clob) in).trim();
|
||||
if (s.equalsIgnoreCase("true")) {
|
||||
String s = clob2Str((java.sql.Clob) in);
|
||||
if (null == s) {
|
||||
return null;
|
||||
} else if (s.equalsIgnoreCase("true")) {
|
||||
return Double.valueOf(1);
|
||||
} else if (s.equalsIgnoreCase("false")) {
|
||||
return Double.valueOf(0);
|
||||
@@ -423,7 +436,8 @@ public final class ObjectCastUtils {
|
||||
public static LocalDate castToLocalDate(final Object in) {
|
||||
if (in instanceof java.sql.Time) {
|
||||
java.sql.Time date = (java.sql.Time) in;
|
||||
LocalDate localDate = Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault())
|
||||
LocalDate localDate = Instant.ofEpochMilli(date.getTime())
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDate();
|
||||
return localDate;
|
||||
} else if (in instanceof java.sql.Timestamp) {
|
||||
@@ -432,12 +446,14 @@ public final class ObjectCastUtils {
|
||||
return localDateTime.toLocalDate();
|
||||
} else if (in instanceof java.util.Date) {
|
||||
java.util.Date date = (java.util.Date) in;
|
||||
LocalDate localDate = Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault())
|
||||
LocalDate localDate = Instant.ofEpochMilli(date.getTime())
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDate();
|
||||
return localDate;
|
||||
} else if (in instanceof java.util.Calendar) {
|
||||
java.sql.Date date = new java.sql.Date(((java.util.Calendar) in).getTime().getTime());
|
||||
LocalDate localDate = Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault())
|
||||
LocalDate localDate = Instant.ofEpochMilli(date.getTime())
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDate();
|
||||
return localDate;
|
||||
} else if (in instanceof LocalDate) {
|
||||
@@ -471,23 +487,29 @@ public final class ObjectCastUtils {
|
||||
}
|
||||
} else if (in instanceof String || in instanceof Character) {
|
||||
try {
|
||||
java.sql.Time date = java.sql.Time.valueOf(in.toString());
|
||||
LocalDate localDate = Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault())
|
||||
java.sql.Date date = java.sql.Date.valueOf(in.toString());
|
||||
LocalDate localDate = Instant.ofEpochMilli(date.getTime())
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDate();
|
||||
return localDate;
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException(
|
||||
String.format("无法将java.lang.String类型转换为java.sql.Time类型:%s", e.getMessage()));
|
||||
String.format("无法将java.lang.String类型转换为java.time.LocalDate类型:%s", e.getMessage()));
|
||||
}
|
||||
} else if (in instanceof java.sql.Clob) {
|
||||
try {
|
||||
java.sql.Time date = java.sql.Time.valueOf(clob2Str((java.sql.Clob) in));
|
||||
LocalDate localDate = Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault())
|
||||
String v = clob2Str((java.sql.Clob) in);
|
||||
if (null == v) {
|
||||
return null;
|
||||
}
|
||||
java.sql.Date date = java.sql.Date.valueOf(v);
|
||||
LocalDate localDate = Instant.ofEpochMilli(date.getTime())
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDate();
|
||||
return localDate;
|
||||
} catch (NumberFormatException e) {
|
||||
throw new RuntimeException(
|
||||
String.format("无法将java.sql.Clob类型转换为java.sql.Time类型:%s", e.getMessage()));
|
||||
String.format("无法将java.sql.Clob类型转换为java.time.LocalDate类型:%s", e.getMessage()));
|
||||
}
|
||||
} else if (in instanceof Number) {
|
||||
java.sql.Timestamp t = new java.sql.Timestamp(((Number) in).longValue());
|
||||
@@ -562,7 +584,11 @@ public final class ObjectCastUtils {
|
||||
}
|
||||
} else if (in instanceof java.sql.Clob) {
|
||||
try {
|
||||
java.sql.Time date = java.sql.Time.valueOf(clob2Str((java.sql.Clob) in));
|
||||
String v = clob2Str((java.sql.Clob) in);
|
||||
if (null == v) {
|
||||
return null;
|
||||
}
|
||||
java.sql.Time date = java.sql.Time.valueOf(v);
|
||||
return LocalTime.ofSecondOfDay(date.getTime());
|
||||
} catch (NumberFormatException e) {
|
||||
throw new RuntimeException(
|
||||
@@ -655,7 +681,11 @@ public final class ObjectCastUtils {
|
||||
}
|
||||
} else if (in instanceof java.sql.Clob) {
|
||||
try {
|
||||
java.sql.Timestamp t = java.sql.Timestamp.valueOf(clob2Str((java.sql.Clob) in));
|
||||
String v = clob2Str((java.sql.Clob) in);
|
||||
if (null == v) {
|
||||
return null;
|
||||
}
|
||||
java.sql.Timestamp t = java.sql.Timestamp.valueOf(v);
|
||||
LocalDateTime localDateTime = LocalDateTime
|
||||
.ofInstant(t.toInstant(), ZoneId.systemDefault());
|
||||
return localDateTime;
|
||||
@@ -742,7 +772,11 @@ public final class ObjectCastUtils {
|
||||
}
|
||||
} else if (in instanceof java.sql.Clob) {
|
||||
try {
|
||||
java.sql.Timestamp t = java.sql.Timestamp.valueOf(clob2Str((java.sql.Clob) in));
|
||||
String v = clob2Str((java.sql.Clob) in);
|
||||
if (null == v) {
|
||||
return null;
|
||||
}
|
||||
java.sql.Timestamp t = java.sql.Timestamp.valueOf(v);
|
||||
LocalDateTime localDateTime = LocalDateTime
|
||||
.ofInstant(t.toInstant(), ZoneId.systemDefault());
|
||||
return Timestamp.valueOf(localDateTime);
|
||||
@@ -779,7 +813,8 @@ public final class ObjectCastUtils {
|
||||
}
|
||||
} else if (in instanceof java.sql.Clob) {
|
||||
try {
|
||||
return Boolean.parseBoolean(clob2Str((java.sql.Clob) in));
|
||||
String v = clob2Str((java.sql.Clob) in);
|
||||
return null == v ? null : Boolean.parseBoolean(v);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new RuntimeException(
|
||||
String.format("无法将java.sql.Clob类型转换为java.lang.Boolean类型:%s", e.getMessage()));
|
||||
@@ -913,7 +948,7 @@ public final class ObjectCastUtils {
|
||||
return new String((byte[]) in);
|
||||
} else if (in instanceof Map) {
|
||||
return JSONUtil.toJsonStr(in);
|
||||
} else if(in instanceof Collection){
|
||||
} else if (in instanceof Collection) {
|
||||
return JSONUtil.toJsonStr(in);
|
||||
}
|
||||
|
||||
|
@@ -11,7 +11,6 @@ package com.gitee.dbswitch.product.sr;
|
||||
|
||||
import com.gitee.dbswitch.common.consts.Constants;
|
||||
import com.gitee.dbswitch.common.type.ProductTypeEnum;
|
||||
import com.gitee.dbswitch.common.util.DDLFormatterUtils;
|
||||
import com.gitee.dbswitch.provider.ProductFactoryProvider;
|
||||
import com.gitee.dbswitch.provider.meta.AbstractMetadataProvider;
|
||||
import com.gitee.dbswitch.schema.ColumnDescription;
|
||||
@@ -31,6 +30,11 @@ import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/**
|
||||
* https://docs.starrocks.io/zh/docs/3.1/quick_start/Create_table/
|
||||
* <p>
|
||||
* https://docs.starrocks.io/zh/docs/3.1/quick_start/deploy_with_docker/
|
||||
*/
|
||||
@Slf4j
|
||||
public class StarrocksMetadataQueryProvider extends AbstractMetadataProvider {
|
||||
|
||||
@@ -130,7 +134,6 @@ public class StarrocksMetadataQueryProvider extends AbstractMetadataProvider {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<ColumnDescription> queryTableColumnMeta(Connection connection, String schemaName,
|
||||
String tableName) {
|
||||
@@ -159,7 +162,6 @@ public class StarrocksMetadataQueryProvider extends AbstractMetadataProvider {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<String> queryTablePrimaryKeys(Connection connection, String schemaName, String tableName) {
|
||||
List<String> ret = new ArrayList<>();
|
||||
@@ -311,7 +313,7 @@ public class StarrocksMetadataQueryProvider extends AbstractMetadataProvider {
|
||||
if (length == 1) {
|
||||
retval += "CHAR(1)";
|
||||
} else if (length < 256) {
|
||||
retval += "VARCHAR(" + length*2 + ")";
|
||||
retval += "VARCHAR(" + length * 2 + ")";
|
||||
} else if (null != pks && !pks.isEmpty() && pks.contains(fieldname)) {
|
||||
/*
|
||||
* MySQL5.6中varchar字段为主键时最大长度为254,例如如下的建表语句在MySQL5.7下能通过,但在MySQL5.6下无法通过:
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 126 KiB |
BIN
images/admin_04_01.png
Normal file
BIN
images/admin_04_01.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 67 KiB |
Reference in New Issue
Block a user