diff --git a/assets/scripts/dec.js b/assets/scripts/dec.js index 8757f3e..f33b0d6 100644 --- a/assets/scripts/dec.js +++ b/assets/scripts/dec.js @@ -6,6 +6,7 @@ window.DecCst = { LOGIN_INFO_NOT_AVAILABLE: '21300014', LOGIN_INFO_ERROR: '21300018', TIMEOUT: '21300001', + LACK_DRIVER: '22400037' }, Connect: { ConnectionType: { @@ -18,7 +19,9 @@ window.DecCst = { } }, Hyperlink: { - Database: {}, + Database: { + ODPS: "odps" + }, DECISION_HYPERLINK_CONFIG: "hyperlink", WEBSOCKET_CONNECT: "websocket" } @@ -35,6 +38,7 @@ window.Dec = { system: { hyperlink: { websocket: "http://help.finebi.com/doc-view-183.html", + odps: "http://help.finebi.com/doc-view-183.html", }, } } \ No newline at end of file diff --git a/src/modules/__test__/app.test.ts b/src/modules/__test__/app.test.ts index d1a205f..e9711dc 100644 --- a/src/modules/__test__/app.test.ts +++ b/src/modules/__test__/app.test.ts @@ -1,4 +1,6 @@ import { connectionCanEdit, resolveUrlInfo, splitUrl, getJdbcDatabaseType } from '../app.service'; +import '../app.provider'; + const connection = { connectionId: '', connectionType: '', @@ -17,6 +19,7 @@ test('DEC-11030 拼接url', () => { */ test('BI-56355 如果数据库类型和驱动都为空,则为其他jdbc', () => { expect(getJdbcDatabaseType('', '').databaseType).toEqual('otherJDBC'); + expect(getJdbcDatabaseType('otherJDBC', 'org.h2.Driver').databaseType).toEqual('otherJDBC'); expect(getJdbcDatabaseType('mysql', '').databaseType).toEqual('mysql'); expect(getJdbcDatabaseType('', 'com.mysql.jdbc.Driver').databaseType).toEqual('mysql'); }); diff --git a/src/modules/app.provider.ts b/src/modules/app.provider.ts index af4542a..97f6753 100644 --- a/src/modules/app.provider.ts +++ b/src/modules/app.provider.ts @@ -1,9 +1,73 @@ import { CONSTANT_PLUGIN_TYPES } from './app.constant'; 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) => { 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, { + getJdbcResolveByType: (type: string) => this.resolves[type] || jdbcResolve, }); }); diff --git a/src/modules/app.service.ts b/src/modules/app.service.ts index 50728d6..d8a0a2c 100644 --- a/src/modules/app.service.ts +++ b/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 { DatabaseType } from './app.typings'; import { Connection } from './crud/crud.typings'; @@ -31,14 +31,17 @@ export function getJdbcDatabaseType(database: string, driver: string): DatabaseT return DATA_BASE_TYPES_OTHER; } let databaseType = null; - // KERNEL-1655 兼容旧版 由于旧版设计器创建的数据连接database都为other,所以要根据driber来判断数据类型 - if (database && database !== 'other' && DATA_BASE_TYPES.some(item => item.databaseType === database)) { - databaseType = DATA_BASE_TYPES.find(item => item.databaseType === database); + // 从全部数据库类型中获取jdbc类型的 + // 兼容之前的逻辑,otherJdbc要单独处理一下 + 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 { 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'); - databaseType = DATA_BASE_TYPES.find(item => item.databaseType === type); + databaseType = jdbcDatabases.find(item => item.databaseType === type); } if (!databaseType) { return DATA_BASE_TYPES_OTHER; @@ -47,52 +50,10 @@ export function getJdbcDatabaseType(database: string, driver: string): DatabaseT return databaseType; } -export function resolveUrlInfo (url: string) { +export function resolveUrlInfo (url: string, database?: 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 { + return BI.Providers.getProvider('dec.connection.provider.datebase').getJdbcResolveByType(database)(url) || { host: '', port: '', databaseName: '', diff --git a/src/modules/constants/constant.ts b/src/modules/constants/constant.ts index c900d05..0c7549f 100644 --- a/src/modules/constants/constant.ts +++ b/src/modules/constants/constant.ts @@ -9,6 +9,8 @@ export const PAGE_INDEX = { 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_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', link: DecCst.Hyperlink.Database.DERBY, }, + { + databaseType: 'clickhouse', + link: DecCst.Hyperlink.Database.CLICKHOUSE, + }, { databaseType: 'gbase-8a', link: DecCst.Hyperlink.Database.GBASE8A, @@ -123,6 +129,10 @@ export const DATA_BASE_DRIVER_LINK = DecCst && DecCst.Hyperlink ? [ databaseType: 'mysql', link: DecCst.Hyperlink.Database.MYSQL, }, + { + databaseType: 'odps', + link: DecCst.Hyperlink.Database.ODPS, + }, { databaseType: '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', }, }, + { + text: 'ODPS', + databaseType: 'odps', + driver: 'com.aliyun.odps.jdbc.OdpsDriver', + url: 'jdbc:odps:?project=', + commonly: false, + internal: true, + type: 'jdbc', + hasSchema: true, + kerberos: false, + }, { text: 'Oracle', databaseType: 'oracle', diff --git a/src/modules/pages/connection/connection_jdbc/connection_jdbc.ts b/src/modules/pages/connection/connection_jdbc/connection_jdbc.ts index 627438d..9d5aa8c 100644 --- a/src/modules/pages/connection/connection_jdbc/connection_jdbc.ts +++ b/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 { driver, database, user, originalCharsetName, schema, connectionPoolAttr, authType, principal, url } = connectionData; const databaseType = getJdbcDatabaseType(database, driver); - const { host, port, databaseName } = resolveUrlInfo(url); + const { host, port, databaseName } = resolveUrlInfo(url, database); const { hgap, vgap } = CONNECTION_LAYOUT; return { diff --git a/src/modules/pages/maintain/forms/components/form.jdbc.ts b/src/modules/pages/maintain/forms/components/form.jdbc.ts index a52a625..f3f8043 100644 --- a/src/modules/pages/maintain/forms/components/form.jdbc.ts +++ b/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 databaseType = getJdbcDatabaseType(database, driver); this.oldPassword = password; - const { host, port, databaseName } = resolveUrlInfo(url); + const { host, port, databaseName } = resolveUrlInfo(url, database); const { hgap, vgap } = CONNECTION_LAYOUT; const valueRangeConfig = { @@ -112,7 +112,7 @@ export class FormJdbc extends BI.Widget { const connectionType = getJdbcDatabaseType(connectionData.database, connectionData.driver); const url = connectionType.urls ? connectionType.urls[value] : connectionType.url; this.form.url.setValue(url); - const urlInfo = resolveUrlInfo(url); + const urlInfo = resolveUrlInfo(url, connectionData.database); this.form.host.setValue(urlInfo.host); this.form.database.setValue(urlInfo.databaseName); this.form.port.setValue(urlInfo.port); @@ -387,7 +387,7 @@ export class FormJdbc extends BI.Widget { listeners: [{ eventName: 'EVENT_CHANGE', action: () => { - const urlInfo = resolveUrlInfo(this.form.url.getValue()); + const urlInfo = resolveUrlInfo(this.form.url.getValue(), database); this.form.host.setValue(urlInfo.host); this.form.database.setValue(urlInfo.databaseName); this.form.port.setValue(urlInfo.port); diff --git a/src/modules/pages/maintain/forms/form.server.ts b/src/modules/pages/maintain/forms/form.server.ts index e144378..a862e1f 100644 --- a/src/modules/pages/maintain/forms/form.server.ts +++ b/src/modules/pages/maintain/forms/form.server.ts @@ -1,7 +1,8 @@ import { Connection, ConnectionJDBC } from '../../../crud/crud.typings'; 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 { getJdbcDatabaseType } from '../../../app.service'; import { ApiFactory } from '../../../crud/apiFactory'; const api = new ApiFactory().create(); export function testConnection(value: Connection): Promise { @@ -30,8 +31,9 @@ export function testConnection(value: Connection): Promise { return; } const databaseType = (formValue.connectionData as ConnectionJDBC).database; - const databaseLink = BI.get(DATA_BASE_DRIVER_LINK.find(item => item.databaseType === databaseType), 'link'); - testStatus.setFail(re.errorMsg, driver, Dec.system[DecCst.Hyperlink.DECISION_HYPERLINK_CONFIG][databaseLink]); + const databaseLink = BI.get(DATA_BASE_DRIVER_LINK.find(item => item.databaseType === databaseType), 'link', DEFAULT_HELP_LINK); + const link = BI.get(getJdbcDatabaseType(databaseType, driver), 'link') || Dec.system[DecCst.Hyperlink.DECISION_HYPERLINK_CONFIG][databaseLink]; + testStatus.setFail(re.errorMsg, driver, link); } else { testStatus.setFail(re.errorMsg); }