feat(数据源): 配置数据源支持直接输入jdbcurl字符串,而不是必须输入ip

This commit is contained in:
taojinlong 2024-05-20 16:53:33 +08:00
parent f9441058bd
commit 0fe834ce24
16 changed files with 152 additions and 43 deletions

View File

@ -39,6 +39,8 @@ import java.math.BigDecimal;
import java.net.URL;
import java.sql.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -731,6 +733,7 @@ public class CalciteProvider {
List<String> tableSqls = new ArrayList<>();
DatasourceConfiguration.DatasourceType datasourceType = DatasourceConfiguration.DatasourceType.valueOf(datasourceRequest.getDatasource().getType());
DatasourceConfiguration configuration = null;
String database = "";
switch (datasourceType) {
case mysql:
case mongo:
@ -739,7 +742,16 @@ public class CalciteProvider {
case StarRocks:
case doris:
configuration = JsonUtil.parseObject(datasourceRequest.getDatasource().getConfiguration(), Mysql.class);
tableSqls.add(String.format("SELECT TABLE_NAME,TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '%s' ;", configuration.getDataBase()));
if (configuration.getUrlType().equalsIgnoreCase("")) {
database = configuration.getDataBase();
} else {
Pattern WITH_SQL_FRAGMENT = Pattern.compile("jdbc:mysql://(.*):(\\d+)/(.*)");
Matcher matcher = WITH_SQL_FRAGMENT.matcher(configuration.getJdbcUrl());
matcher.find();
String[] databasePrams = matcher.group(3).split("\\?");
database = databasePrams[0];
}
tableSqls.add(String.format("SELECT TABLE_NAME,TABLE_COMMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '%s' ;", database));
break;
case oracle:
configuration = JsonUtil.parseObject(datasourceRequest.getDatasource().getConfiguration(), Oracle.class);
@ -781,7 +793,17 @@ public class CalciteProvider {
break;
case ck:
configuration = JsonUtil.parseObject(datasourceRequest.getDatasource().getConfiguration(), CK.class);
tableSqls.add("SELECT name FROM system.tables where database='DATABASE';".replace("DATABASE", configuration.getDataBase()));
if (configuration.getUrlType().equalsIgnoreCase("")) {
database = configuration.getDataBase();
} else {
Pattern WITH_SQL_FRAGMENT = Pattern.compile("jdbc:clickhouse://(.*):(\\d+)/(.*)");
Matcher matcher = WITH_SQL_FRAGMENT.matcher(configuration.getJdbcUrl());
matcher.find();
String[] databasePrams = matcher.group(3).split("\\?");
database = databasePrams[0];
}
tableSqls.add("SELECT name FROM system.tables where database='DATABASE';".replace("DATABASE", database));
break;
default:
tableSqls.add("show tables");

View File

@ -12,6 +12,9 @@ public class CK extends DatasourceConfiguration {
private String extraParams = "";
public String getJdbc() {
if(StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")){
return getJdbcUrl();
}
if(StringUtils.isEmpty(extraParams.trim())){
return "jdbc:clickhouse://HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getHost().trim())

View File

@ -12,6 +12,9 @@ public class Db2 extends DatasourceConfiguration {
private String extraParams = "";
public String getJdbc() {
if(StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")){
return getJdbcUrl();
}
if(StringUtils.isEmpty(extraParams.trim())){
if (StringUtils.isEmpty(getSchema())) {
return "jdbc:db2://HOSTNAME:PORT/DATABASE"

View File

@ -17,6 +17,9 @@ public class Impala extends DatasourceConfiguration {
private List<String> showTableSqls = Arrays.asList("show tables");
public String getJdbc() {
if(StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")){
return getJdbcUrl();
}
if(StringUtils.isEmpty(extraParams.trim())){
return "jdbc:impala://HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getHost().trim())

View File

@ -17,6 +17,9 @@ public class Mongo extends DatasourceConfiguration {
private List<String> showTableSqls = Arrays.asList("show tables");
public String getJdbc() {
if(StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")){
return getJdbcUrl();
}
if (StringUtils.isEmpty(extraParams.trim())) {
return "jdbc:mysql://HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getHost().trim())

View File

@ -19,6 +19,9 @@ public class Mysql extends DatasourceConfiguration {
private List<String> showTableSqls = Arrays.asList("show tables");
public String getJdbc() {
if(StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")){
return getJdbcUrl();
}
if (StringUtils.isEmpty(extraParams.trim())) {
return "jdbc:mysql://HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getHost().trim())

View File

@ -12,6 +12,9 @@ public class Oracle extends DatasourceConfiguration {
private String extraParams = "";
public String getJdbc() {
if(StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")){
return getJdbcUrl();
}
if (StringUtils.isNotEmpty(getConnectionType()) && getConnectionType().equalsIgnoreCase("serviceName")) {
return "jdbc:oracle:thin:@HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getHost().trim())

View File

@ -12,6 +12,9 @@ public class Pg extends DatasourceConfiguration {
private String extraParams = "";
public String getJdbc() {
if(StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")){
return getJdbcUrl();
}
if(StringUtils.isEmpty(extraParams.trim())){
if (StringUtils.isEmpty(getSchema())) {
return "jdbc:postgresql://HOSTNAME:PORT/DATABASE"

View File

@ -12,6 +12,9 @@ public class Redshift extends DatasourceConfiguration {
private String extraParams = "";
public String getJdbc() {
if(StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")){
return getJdbcUrl();
}
return "jdbc:redshift://HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getHost().trim())
.replace("PORT", getPort().toString().trim())

View File

@ -17,6 +17,9 @@ public class Sqlserver extends DatasourceConfiguration {
private List<String> showTableSqls = Arrays.asList("show tables");
public String getJdbc() {
if(StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")){
return getJdbcUrl();
}
if (StringUtils.isEmpty(extraParams.trim())) {
return "jdbc:sqlserver://HOSTNAME:PORT;DatabaseName=DATABASE"
.replace("HOSTNAME", getHost().trim())

View File

@ -284,6 +284,7 @@ export default {
datasource_url: '地址',
please_input_datasource_url: '请输入 Elasticsearch 地址: http://es_host:es_port',
please_input_data_base: '请输入数据库名称',
please_input_jdbc_url: '请输入JDBC 连接',
please_select_oracle_type: '选择连接类型',
please_input_user_name: '请输入用户名',
please_input_password: '请输入密码',

View File

@ -5,7 +5,7 @@ import type { FormInstance, FormRules } from 'element-plus-secondary'
import EmptyBackground from '@/components/empty-background/src/EmptyBackground.vue'
import { cloneDeep } from 'lodash-es'
import ApiHttpRequestDraw from './ApiHttpRequestDraw.vue'
import { Configuration, ApiConfiguration, SyncSetting } from './index.vue'
import type { Configuration, ApiConfiguration, SyncSetting } from './option'
import { Icon } from '@/components/icon-custom'
import { getSchema } from '@/api/datasource'
import { Base64 } from 'js-base64'
@ -102,6 +102,8 @@ const initForm = type => {
if (type !== 'API') {
form.value.configuration = {
dataBase: '',
jdbcUrl: '',
urlType: 'hostName',
extraParams: '',
username: '',
password: '',
@ -153,6 +155,13 @@ const authMethodList = [
]
const setRules = () => {
const configRules = {
'configuration.jdbcUrl': [
{
required: true,
message: t('datasource.please_input_jdbc_url'),
trigger: 'blur'
}
],
'configuration.dataBase': [
{
required: true,
@ -602,14 +611,41 @@ defineExpose({
</template>
</template>
<template v-if="notapiexcelconfig">
<el-form-item :label="t('datasource.host')" prop="configuration.host">
<el-form-item label="连接方式" prop="type">
<el-radio-group v-model="form.configuration.urlType">
<el-radio label="hostName">主机名</el-radio>
<el-radio label="jdbcUrl">JDBC 连接</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label="JDBC连接字符串"
prop="configuration.jdbcUrl"
v-if="form.configuration.urlType === 'jdbcUrl'"
>
<el-input
v-model="form.configuration.jdbcUrl"
placeholder="JDBC连接字符串"
autocomplete="off"
/>
</el-form-item>
<el-form-item
:label="t('datasource.host')"
prop="configuration.host"
v-if="form.configuration.urlType !== 'jdbcUrl'"
>
<el-input
v-model="form.configuration.host"
:placeholder="t('datasource._ip_address')"
autocomplete="off"
/>
</el-form-item>
<el-form-item :label="t('datasource.port')" prop="configuration.port">
<el-form-item
:label="t('datasource.port')"
prop="configuration.port"
v-if="form.configuration.urlType !== 'jdbcUrl'"
>
<el-input-number
v-model="form.configuration.port"
autocomplete="off"
@ -621,13 +657,49 @@ defineExpose({
type="number"
/>
</el-form-item>
<el-form-item :label="t('datasource.data_base')" prop="configuration.dataBase">
<el-form-item
:label="t('datasource.data_base')"
prop="configuration.dataBase"
v-if="form.configuration.urlType !== 'jdbcUrl'"
>
<el-input
v-model="form.configuration.dataBase"
:placeholder="t('datasource.please_input_data_base')"
autocomplete="off"
/>
</el-form-item>
<el-form-item
v-if="['oracle', 'sqlServer', 'pg', 'redshift', 'db2'].includes(form.type)"
class="schema-label"
:prop="showSchema ? '' : 'configuration.schema'"
>
<template v-slot:label>
<span class="name">{{ t('datasource.schema') }}<i class="required" /></span>
<el-button text size="small" @click="getDsSchema()">
<template #icon>
<Icon name="icon_add_outlined"></Icon>
</template>
{{ t('datasource.get_schema') }}
</el-button>
</template>
<el-select
v-model="form.configuration.schema"
filterable
:placeholder="t('common.please_select')"
class="de-select"
@change="validatorSchema"
@blur="validatorSchema"
>
<el-option v-for="item in schemas" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<el-form-item :label="t('datasource.extra_params')">
<el-input
:placeholder="t('common.inputText') + t('datasource.extra_params')"
v-model="form.configuration.extraParams"
autocomplete="off"
/>
</el-form-item>
<el-form-item
:label="t('datasource.auth_method')"
prop="configuration.authMethod"
@ -687,13 +759,6 @@ defineExpose({
v-model="form.configuration.password"
/>
</el-form-item>
<el-form-item :label="t('datasource.extra_params')">
<el-input
:placeholder="t('common.inputText') + t('datasource.extra_params')"
v-model="form.configuration.extraParams"
autocomplete="off"
/>
</el-form-item>
<el-form-item
v-if="form.type == 'oracle'"
:label="t('datasource.connection_mode')"
@ -706,31 +771,6 @@ defineExpose({
{{ t('datasource.oracle_service_name') }}
</el-radio>
</el-form-item>
<el-form-item
v-if="['oracle', 'sqlServer', 'pg', 'redshift', 'db2'].includes(form.type)"
class="schema-label"
:prop="showSchema ? '' : 'configuration.schema'"
>
<template v-slot:label>
<span class="name">{{ t('datasource.schema') }}<i class="required" /></span>
<el-button text size="small" @click="getDsSchema()">
<template #icon>
<Icon name="icon_add_outlined"></Icon>
</template>
{{ t('datasource.get_schema') }}
</el-button>
</template>
<el-select
v-model="form.configuration.schema"
filterable
:placeholder="t('common.please_select')"
class="de-select"
@change="validatorSchema"
@blur="validatorSchema"
>
<el-option v-for="item in schemas" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<span
v-if="!['es', 'api'].includes(form.type)"
class="de-expand"

View File

@ -465,6 +465,9 @@ const init = (nodeInfo: Form | Param, id?: string, res?: object) => {
Object.assign(form2, cloneDeep(nodeInfo))
} else {
Object.assign(form, cloneDeep(nodeInfo))
if (form.hasOwnProperty('configuration') && form.configuration.urlType == undefined) {
form.configuration.urlType = 'hostName'
}
}
pid.value = nodeInfo.pid || '0'
} else {

View File

@ -122,6 +122,8 @@ export const nameMap = {
export interface Configuration {
dataBase: string
jdbcUrl: string
urlType: string
connectionType: string
schema: string
extraParams: string

View File

@ -1122,14 +1122,14 @@ const getMenuList = (val: boolean) => {
</el-col>
</el-row>
<template v-if="!['Excel', 'API'].includes(nodeInfo.type)">
<el-row :gutter="24">
<el-row :gutter="24" v-show="nodeInfo.configuration.urlType === 'hostName'">
<el-col :span="12">
<BaseInfoItem :label="t('datasource.host')">{{
nodeInfo.configuration.host
}}</BaseInfoItem>
</el-col>
</el-row>
<el-row :gutter="24">
<el-row :gutter="24" v-show="nodeInfo.configuration.urlType === 'hostName'">
<el-col :span="12">
<BaseInfoItem :label="t('datasource.port')">{{
nodeInfo.configuration.port
@ -1141,7 +1141,7 @@ const getMenuList = (val: boolean) => {
}}</BaseInfoItem>
</el-col>
</el-row>
<el-row :gutter="24">
<el-row :gutter="24" v-show="nodeInfo.configuration.urlType === 'hostName'">
<el-col :span="12">
<BaseInfoItem :label="t('datasource.user_name')">{{
nodeInfo.configuration.username
@ -1153,6 +1153,20 @@ const getMenuList = (val: boolean) => {
}}</BaseInfoItem>
</el-col>
</el-row>
<el-row :gutter="24" v-show="nodeInfo.configuration.urlType !== 'hostName'">
<el-col :span="12">
<BaseInfoItem :label="t('datasource.jdbcUrl')">{{
nodeInfo.configuration.jdbcUrl
}}</BaseInfoItem>
</el-col>
</el-row>
<el-row :gutter="24" v-show="nodeInfo.configuration.urlType !== 'hostName'">
<el-col :span="12">
<BaseInfoItem :label="t('datasource.user_name')">{{
nodeInfo.configuration.username
}}</BaseInfoItem>
</el-col>
</el-row>
<span
v-if="!['es', 'api'].includes(nodeInfo.type.toLowerCase())"
class="de-expand"

View File

@ -2,8 +2,6 @@ package io.dataease.api.ds.vo;
import lombok.Data;
import java.util.List;
@Data
public class Configuration {
private String type;
@ -17,6 +15,8 @@ public class Configuration {
private String aliasSuffix = "";
private String jdbc;
private String host;
private String jdbcUrl;
private String urlType;
private Integer port;
private String username;
private String password;