Browse Source

Merge pull request #967 in DEC/decision-webui-dcm from final/10.0 to persist/10.0

* commit '2d6959b8fb36a4432533426a4098b6c5229d0e1d':
  DEC-15854 fix: 【数据连接】新建其他JDBC类型数据连接,默认驱动只有一个
  DEC-15759 fix: 【mysql8隔离插件】帮助文档链接跳转
  DEC-15759 & DEC-15764 帮助文档链接
  DEC-15747 feat: 【BI】ODPS数据库支持适配
  DEC-15719 feat: 数据连接直接支持jdbc插件
persist/10.0 10.0.11.2020.11.25
superman 4 years ago
parent
commit
35037cf9af
  1. 6
      assets/scripts/dec.js
  2. 3
      src/modules/__test__/app.test.ts
  3. 64
      src/modules/app.provider.ts
  4. 61
      src/modules/app.service.ts
  5. 21
      src/modules/constants/constant.ts
  6. 2
      src/modules/pages/connection/connection_jdbc/connection_jdbc.ts
  7. 6
      src/modules/pages/maintain/forms/components/form.jdbc.ts
  8. 8
      src/modules/pages/maintain/forms/form.server.ts

6
assets/scripts/dec.js

@ -6,6 +6,7 @@ window.DecCst = {
LOGIN_INFO_NOT_AVAILABLE: '21300014', LOGIN_INFO_NOT_AVAILABLE: '21300014',
LOGIN_INFO_ERROR: '21300018', LOGIN_INFO_ERROR: '21300018',
TIMEOUT: '21300001', TIMEOUT: '21300001',
LACK_DRIVER: '22400037'
}, },
Connect: { Connect: {
ConnectionType: { ConnectionType: {
@ -18,7 +19,9 @@ window.DecCst = {
} }
}, },
Hyperlink: { Hyperlink: {
Database: {}, Database: {
ODPS: "odps"
},
DECISION_HYPERLINK_CONFIG: "hyperlink", DECISION_HYPERLINK_CONFIG: "hyperlink",
WEBSOCKET_CONNECT: "websocket" WEBSOCKET_CONNECT: "websocket"
} }
@ -35,6 +38,7 @@ window.Dec = {
system: { system: {
hyperlink: { hyperlink: {
websocket: "http://help.finebi.com/doc-view-183.html", websocket: "http://help.finebi.com/doc-view-183.html",
odps: "http://help.finebi.com/doc-view-183.html",
}, },
} }
} }

3
src/modules/__test__/app.test.ts

@ -1,4 +1,6 @@
import { connectionCanEdit, resolveUrlInfo, splitUrl, getJdbcDatabaseType } from '../app.service'; import { connectionCanEdit, resolveUrlInfo, splitUrl, getJdbcDatabaseType } from '../app.service';
import '../app.provider';
const connection = { const connection = {
connectionId: '', connectionId: '',
connectionType: '', connectionType: '',
@ -17,6 +19,7 @@ test('DEC-11030 拼接url', () => {
*/ */
test('BI-56355 如果数据库类型和驱动都为空,则为其他jdbc', () => { test('BI-56355 如果数据库类型和驱动都为空,则为其他jdbc', () => {
expect(getJdbcDatabaseType('', '').databaseType).toEqual('otherJDBC'); expect(getJdbcDatabaseType('', '').databaseType).toEqual('otherJDBC');
expect(getJdbcDatabaseType('otherJDBC', 'org.h2.Driver').databaseType).toEqual('otherJDBC');
expect(getJdbcDatabaseType('mysql', '').databaseType).toEqual('mysql'); expect(getJdbcDatabaseType('mysql', '').databaseType).toEqual('mysql');
expect(getJdbcDatabaseType('', 'com.mysql.jdbc.Driver').databaseType).toEqual('mysql'); expect(getJdbcDatabaseType('', 'com.mysql.jdbc.Driver').databaseType).toEqual('mysql');
}); });

64
src/modules/app.provider.ts

@ -1,9 +1,73 @@
import { CONSTANT_PLUGIN_TYPES } from './app.constant'; import { CONSTANT_PLUGIN_TYPES } from './app.constant';
BI.provider('dec.connection.provider.datebase', function() { BI.provider('dec.connection.provider.datebase', function() {
this.resolves = {};
// 原service中resolveUrlInfo方法
function jdbcResolve (url: string) {
if (BI.isNull(url)) return {};
const oracleUlr = url.match(/^jdbc:(oracle):(thin:([0-9a-zA-Z/]*)?@|thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(:|\/)([^]+)(.*)/i);
if (oracleUlr) {
return {
host: oracleUlr[5],
port: oracleUlr[7] === 'port' ? '' : oracleUlr[7],
databaseName: oracleUlr[9],
urlInfo: oracleUlr[10],
};
}
const greenplumUrl = url.match(/^jdbc:(pivotal:greenplum):(thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(\/|;)([^]+)(.*)/i);
if (greenplumUrl) {
return {
host: greenplumUrl[4],
port: greenplumUrl[6] === 'port' ? '' : greenplumUrl[6],
databaseName: greenplumUrl[8],
urlInfo: greenplumUrl[9],
};
}
const result = url.match(/^jdbc:(mysql|sqlserver|db2|impala|kylin|phoenix|derby|gbase|gbasedbt-sqli|informix-sqli|h2|postgresql|hive2|vertica|kingbase|presto|redshift|postgresql|clickhouse):(thin:([0-9a-zA-Z/]*)?@|thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(\/|;DatabaseName=)?([^]+)?(.*)/i);
if (result) {
return {
host: result[5],
port: result[7] === 'port' ? '' : result[7],
databaseName: result[9] || '',
urlInfo: result[10],
};
}
// 处理oracle的RAC方式
if (/^jdbc:oracle:thin:([0-9a-zA-Z/]*)?@\(DESCRIPTION/i.test(url)) {
const host = url.match(/\(HOST\s*=\s*([0-9a-zA-Z_\\.-]+)\)/i);
const port = url.match(/\(PORT\s*=\s*([0-9]+)\)/i);
const databaseName = url.match(/\(SERVICE_NAME\s*=\s*([\s0-9a-zA-Z_\\.]+)\)/i);
return {
host: host ? host[1] : '',
port: port && port[1] !== 'port' ? port[1] : '',
databaseName: databaseName ? databaseName[1] : '',
urlInfo: '',
};
}
return {
host: '',
port: '',
databaseName: '',
urlInfo: '',
};
}
this.registerDatabaseType = (config: any) => { this.registerDatabaseType = (config: any) => {
BI.config(CONSTANT_PLUGIN_TYPES, connections => BI.concat(connections, config)); BI.config(CONSTANT_PLUGIN_TYPES, connections => BI.concat(connections, config));
}; };
this.registerJdbcDatabase = (config: any, resolve?: Function) => {
BI.config(CONSTANT_PLUGIN_TYPES, connections => BI.concat(connections, { ...config, type: 'jdbc' }));
BI.isFunction(resolve) && (this.resolves[config.databaseType] = resolve);
};
this.$get = () => BI.inherit(BI.OB, { this.$get = () => BI.inherit(BI.OB, {
getJdbcResolveByType: (type: string) => this.resolves[type] || jdbcResolve,
}); });
}); });

61
src/modules/app.service.ts

@ -1,4 +1,4 @@
import { DATA_BASE_TYPES, DATA_BASE_TYPES_OTHER, DESIGN_DRIVER_TYPE } from '@constants/constant'; import { DATA_BASE_TYPES, DATA_BASE_TYPES_OTHER, DESIGN_DRIVER_TYPE, OTHER_JDBC } from '@constants/constant';
import { CONSTANT_PLUGIN_TYPES } from './app.constant'; import { CONSTANT_PLUGIN_TYPES } from './app.constant';
import { DatabaseType } from './app.typings'; import { DatabaseType } from './app.typings';
import { Connection } from './crud/crud.typings'; import { Connection } from './crud/crud.typings';
@ -31,14 +31,17 @@ export function getJdbcDatabaseType(database: string, driver: string): DatabaseT
return DATA_BASE_TYPES_OTHER; return DATA_BASE_TYPES_OTHER;
} }
let databaseType = null; let databaseType = null;
// KERNEL-1655 兼容旧版 由于旧版设计器创建的数据连接database都为other,所以要根据driber来判断数据类型 // 从全部数据库类型中获取jdbc类型的
if (database && database !== 'other' && DATA_BASE_TYPES.some(item => item.databaseType === database)) { // 兼容之前的逻辑,otherJdbc要单独处理一下
databaseType = DATA_BASE_TYPES.find(item => item.databaseType === database); const jdbcDatabases = getAllDatabaseTypes().filter(v => v.type === 'jdbc' || v.type === OTHER_JDBC);
// KERNEL-1655 兼容旧版 由于旧版设计器创建的数据连接database都为other,所以要根据driver来判断数据类型
if (database && database !== 'other' && jdbcDatabases.some(item => item.databaseType === database)) {
databaseType = jdbcDatabases.find(item => item.databaseType === database);
} else { } else {
const designDatabase = DESIGN_DRIVER_TYPE.find(item => item.driver === driver); const designDatabase = DESIGN_DRIVER_TYPE.find(item => item.driver === driver);
const decisionDatabase = DATA_BASE_TYPES.find(item => item.driver === driver); const decisionDatabase = jdbcDatabases.find(item => item.driver === driver);
const type = designDatabase ? BI.get(designDatabase, 'type') : BI.get(decisionDatabase, 'databaseType'); const type = designDatabase ? BI.get(designDatabase, 'type') : BI.get(decisionDatabase, 'databaseType');
databaseType = DATA_BASE_TYPES.find(item => item.databaseType === type); databaseType = jdbcDatabases.find(item => item.databaseType === type);
} }
if (!databaseType) { if (!databaseType) {
return DATA_BASE_TYPES_OTHER; return DATA_BASE_TYPES_OTHER;
@ -47,52 +50,10 @@ export function getJdbcDatabaseType(database: string, driver: string): DatabaseT
return databaseType; return databaseType;
} }
export function resolveUrlInfo (url: string) { export function resolveUrlInfo (url: string, database?: string) {
if (BI.isNull(url)) return {}; if (BI.isNull(url)) return {};
const oracleUlr = url.match(/^jdbc:(oracle):(thin:([0-9a-zA-Z/]*)?@|thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(:|\/)([^]+)(.*)/i);
if (oracleUlr) {
return {
host: oracleUlr[5],
port: oracleUlr[7] === 'port' ? '' : oracleUlr[7],
databaseName: oracleUlr[9],
urlInfo: oracleUlr[10],
};
}
const greenplumUrl = url.match(/^jdbc:(pivotal:greenplum):(thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(\/|;)([^]+)(.*)/i); return BI.Providers.getProvider('dec.connection.provider.datebase').getJdbcResolveByType(database)(url) || {
if (greenplumUrl) {
return {
host: greenplumUrl[4],
port: greenplumUrl[6] === 'port' ? '' : greenplumUrl[6],
databaseName: greenplumUrl[8],
urlInfo: greenplumUrl[9],
};
}
const result = url.match(/^jdbc:(mysql|sqlserver|db2|impala|kylin|phoenix|derby|gbase|gbasedbt-sqli|informix-sqli|h2|postgresql|hive2|vertica|kingbase|presto|redshift|postgresql|clickhouse):(thin:([0-9a-zA-Z/]*)?@|thin:([0-9a-zA-Z/]*)?@\/\/|\/\/|)([0-9a-zA-Z_\\.-]+)(:([0-9|port]+))?(\/|;DatabaseName=)?([^]+)?(.*)/i);
if (result) {
return {
host: result[5],
port: result[7] === 'port' ? '' : result[7],
databaseName: result[9] || '',
urlInfo: result[10],
};
}
// 处理oracle的RAC方式
if (/^jdbc:oracle:thin:([0-9a-zA-Z/]*)?@\(DESCRIPTION/i.test(url)) {
const host = url.match(/\(HOST\s*=\s*([0-9a-zA-Z_\\.-]+)\)/i);
const port = url.match(/\(PORT\s*=\s*([0-9]+)\)/i);
const databaseName = url.match(/\(SERVICE_NAME\s*=\s*([\s0-9a-zA-Z_\\.]+)\)/i);
return {
host: host ? host[1] : '',
port: port && port[1] !== 'port' ? port[1] : '',
databaseName: databaseName ? databaseName[1] : '',
urlInfo: '',
};
}
return {
host: '', host: '',
port: '', port: '',
databaseName: '', databaseName: '',

21
src/modules/constants/constant.ts

@ -9,6 +9,8 @@ export const PAGE_INDEX = {
export const OTHER_JDBC = 'otherJDBC'; export const OTHER_JDBC = 'otherJDBC';
export const DEFAULT_HELP_LINK = 'databaseHelpLink';
export const JDBC_ODBC_DRIVER = 'sun.jdbc.odbc.JdbcOdbcDriver'; export const JDBC_ODBC_DRIVER = 'sun.jdbc.odbc.JdbcOdbcDriver';
export const JDBC_ODBC_DRIVER_HELP_LINK = DecCst && DecCst.Hyperlink ? DecCst.Hyperlink.Database.OTHER_ODBC : ''; export const JDBC_ODBC_DRIVER_HELP_LINK = DecCst && DecCst.Hyperlink ? DecCst.Hyperlink.Database.OTHER_ODBC : '';
@ -55,6 +57,10 @@ export const DATA_BASE_DRIVER_LINK = DecCst && DecCst.Hyperlink ? [
databaseType: 'derby', databaseType: 'derby',
link: DecCst.Hyperlink.Database.DERBY, link: DecCst.Hyperlink.Database.DERBY,
}, },
{
databaseType: 'clickhouse',
link: DecCst.Hyperlink.Database.CLICKHOUSE,
},
{ {
databaseType: 'gbase-8a', databaseType: 'gbase-8a',
link: DecCst.Hyperlink.Database.GBASE8A, link: DecCst.Hyperlink.Database.GBASE8A,
@ -123,6 +129,10 @@ export const DATA_BASE_DRIVER_LINK = DecCst && DecCst.Hyperlink ? [
databaseType: 'mysql', databaseType: 'mysql',
link: DecCst.Hyperlink.Database.MYSQL, link: DecCst.Hyperlink.Database.MYSQL,
}, },
{
databaseType: 'odps',
link: DecCst.Hyperlink.Database.ODPS,
},
{ {
databaseType: 'oracle', databaseType: 'oracle',
link: DecCst.Hyperlink.Database.ORACLE, link: DecCst.Hyperlink.Database.ORACLE,
@ -464,6 +474,17 @@ export const DATA_BASE_TYPES = [
'org.gjt.mm.mysql.Driver': 'jdbc:mysql://hostname:port/database', 'org.gjt.mm.mysql.Driver': 'jdbc:mysql://hostname:port/database',
}, },
}, },
{
text: 'ODPS',
databaseType: 'odps',
driver: 'com.aliyun.odps.jdbc.OdpsDriver',
url: 'jdbc:odps:<maxcompute_endpoint>?project=<maxcompute_project_name>',
commonly: false,
internal: true,
type: 'jdbc',
hasSchema: true,
kerberos: false,
},
{ {
text: 'Oracle', text: 'Oracle',
databaseType: 'oracle', databaseType: 'oracle',

2
src/modules/pages/connection/connection_jdbc/connection_jdbc.ts

@ -19,7 +19,7 @@ export class ConnectionJdbc extends BI.Widget {
const connectionData = this.model.connectionSelectedOne.connectionData as ConnectionJDBC; const connectionData = this.model.connectionSelectedOne.connectionData as ConnectionJDBC;
const { driver, database, user, originalCharsetName, schema, connectionPoolAttr, authType, principal, url } = connectionData; const { driver, database, user, originalCharsetName, schema, connectionPoolAttr, authType, principal, url } = connectionData;
const databaseType = getJdbcDatabaseType(database, driver); const databaseType = getJdbcDatabaseType(database, driver);
const { host, port, databaseName } = resolveUrlInfo(url); const { host, port, databaseName } = resolveUrlInfo(url, database);
const { hgap, vgap } = CONNECTION_LAYOUT; const { hgap, vgap } = CONNECTION_LAYOUT;
return { return {

6
src/modules/pages/maintain/forms/components/form.jdbc.ts

@ -62,7 +62,7 @@ export class FormJdbc extends BI.Widget {
const { initialSize, maxActive, maxIdle, maxWait, validationQuery, testOnBorrow, testOnReturn, testWhileIdle, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minIdle, minEvictableIdleTimeMillis } = connectionPoolAttr as ConnectionPoolJDBC; const { initialSize, maxActive, maxIdle, maxWait, validationQuery, testOnBorrow, testOnReturn, testWhileIdle, timeBetweenEvictionRunsMillis, numTestsPerEvictionRun, minIdle, minEvictableIdleTimeMillis } = connectionPoolAttr as ConnectionPoolJDBC;
const databaseType = getJdbcDatabaseType(database, driver); const databaseType = getJdbcDatabaseType(database, driver);
this.oldPassword = password; this.oldPassword = password;
const { host, port, databaseName } = resolveUrlInfo(url); const { host, port, databaseName } = resolveUrlInfo(url, database);
const { hgap, vgap } = CONNECTION_LAYOUT; const { hgap, vgap } = CONNECTION_LAYOUT;
const valueRangeConfig = { const valueRangeConfig = {
@ -112,7 +112,7 @@ export class FormJdbc extends BI.Widget {
const connectionType = getJdbcDatabaseType(connectionData.database, connectionData.driver); const connectionType = getJdbcDatabaseType(connectionData.database, connectionData.driver);
const url = connectionType.urls ? connectionType.urls[value] : connectionType.url; const url = connectionType.urls ? connectionType.urls[value] : connectionType.url;
this.form.url.setValue(url); this.form.url.setValue(url);
const urlInfo = resolveUrlInfo(url); const urlInfo = resolveUrlInfo(url, connectionData.database);
this.form.host.setValue(urlInfo.host); this.form.host.setValue(urlInfo.host);
this.form.database.setValue(urlInfo.databaseName); this.form.database.setValue(urlInfo.databaseName);
this.form.port.setValue(urlInfo.port); this.form.port.setValue(urlInfo.port);
@ -387,7 +387,7 @@ export class FormJdbc extends BI.Widget {
listeners: [{ listeners: [{
eventName: 'EVENT_CHANGE', eventName: 'EVENT_CHANGE',
action: () => { action: () => {
const urlInfo = resolveUrlInfo(this.form.url.getValue()); const urlInfo = resolveUrlInfo(this.form.url.getValue(), database);
this.form.host.setValue(urlInfo.host); this.form.host.setValue(urlInfo.host);
this.form.database.setValue(urlInfo.databaseName); this.form.database.setValue(urlInfo.databaseName);
this.form.port.setValue(urlInfo.port); this.form.port.setValue(urlInfo.port);

8
src/modules/pages/maintain/forms/form.server.ts

@ -1,7 +1,8 @@
import { Connection, ConnectionJDBC } from '../../../crud/crud.typings'; import { Connection, ConnectionJDBC } from '../../../crud/crud.typings';
import { connectionType, errorCode } from '@constants/env'; import { connectionType, errorCode } from '@constants/env';
import { DATA_BASE_DRIVER_LINK, JDBC_ODBC_DRIVER, JDBC_ODBC_DRIVER_HELP_LINK } from '@constants/constant'; import { DATA_BASE_DRIVER_LINK, JDBC_ODBC_DRIVER, JDBC_ODBC_DRIVER_HELP_LINK, DEFAULT_HELP_LINK } from '@constants/constant';
import { TestStatusXtype, EVENT_RELOAD, EVENT_CLOSE } from '../../../components/test_status/test_status'; import { TestStatusXtype, EVENT_RELOAD, EVENT_CLOSE } from '../../../components/test_status/test_status';
import { getJdbcDatabaseType } from '../../../app.service';
import { ApiFactory } from '../../../crud/apiFactory'; import { ApiFactory } from '../../../crud/apiFactory';
const api = new ApiFactory().create(); const api = new ApiFactory().create();
export function testConnection(value: Connection): Promise<string[]> { export function testConnection(value: Connection): Promise<string[]> {
@ -30,8 +31,9 @@ export function testConnection(value: Connection): Promise<string[]> {
return; return;
} }
const databaseType = (formValue.connectionData as ConnectionJDBC).database; const databaseType = (formValue.connectionData as ConnectionJDBC).database;
const databaseLink = BI.get(DATA_BASE_DRIVER_LINK.find(item => item.databaseType === databaseType), 'link'); const databaseLink = BI.get(DATA_BASE_DRIVER_LINK.find(item => item.databaseType === databaseType), 'link', DEFAULT_HELP_LINK);
testStatus.setFail(re.errorMsg, driver, Dec.system[DecCst.Hyperlink.DECISION_HYPERLINK_CONFIG][databaseLink]); const link = BI.get(getJdbcDatabaseType(databaseType, driver), 'link') || Dec.system[DecCst.Hyperlink.DECISION_HYPERLINK_CONFIG][databaseLink];
testStatus.setFail(re.errorMsg, driver, link);
} else { } else {
testStatus.setFail(re.errorMsg); testStatus.setFail(re.errorMsg);
} }

Loading…
Cancel
Save