001/* 002 * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.mybatisflex.core.dialect; 017 018 019import com.mybatisflex.core.exception.FlexExceptions; 020import com.mybatisflex.core.exception.locale.LocalizedFormats; 021import com.mybatisflex.core.util.StringUtil; 022import org.apache.ibatis.datasource.unpooled.UnpooledDataSource; 023 024import javax.sql.DataSource; 025import java.lang.reflect.Method; 026import java.sql.Connection; 027import java.sql.SQLException; 028import java.util.regex.Pattern; 029 030/** 031 * DbType 解析 工具类 032 */ 033public class DbTypeUtil { 034 035 private DbTypeUtil() { 036 } 037 038 /** 039 * 获取当前配置的 DbType 040 */ 041 public static DbType getDbType(DataSource dataSource) { 042 String jdbcUrl = getJdbcUrl(dataSource); 043 044 if (StringUtil.isNotBlank(jdbcUrl)) { 045 return parseDbType(jdbcUrl); 046 } 047 048 throw new IllegalStateException("Can not get dataSource jdbcUrl: " + dataSource.getClass().getName()); 049 } 050 051 /** 052 * 通过数据源中获取 jdbc 的 url 配置 053 * 符合 HikariCP, druid, c3p0, DBCP, beecp 数据源框架 以及 MyBatis UnpooledDataSource 的获取规则 054 * UnpooledDataSource 参考 @{@link UnpooledDataSource#getUrl()} 055 * 056 * @return jdbc url 配置 057 */ 058 public static String getJdbcUrl(DataSource dataSource) { 059 String[] methodNames = new String[]{"getUrl", "getJdbcUrl"}; 060 for (String methodName : methodNames) { 061 try { 062 Method method = dataSource.getClass().getMethod(methodName); 063 return (String) method.invoke(dataSource); 064 } catch (Exception e) { 065 //ignore 066 } 067 } 068 069 Connection connection = null; 070 try { 071 connection = dataSource.getConnection(); 072 return connection.getMetaData().getURL(); 073 } catch (Exception e) { 074 throw FlexExceptions.wrap(e, LocalizedFormats.DATASOURCE_JDBC_URL); 075 } finally { 076 if (connection != null) { 077 try { 078 connection.close(); 079 } catch (SQLException e) { //ignore 080 } 081 } 082 } 083 } 084 085 086 /** 087 * 参考 druid 和 MyBatis-plus 的 JdbcUtils 088 * {@link com.alibaba.druid.util.JdbcUtils#getDbType(String, String)} 089 * {@link com.baomidou.mybatisplus.extension.toolkit.JdbcUtils#getDbType(String)} 090 * 091 * @param jdbcUrl jdbcURL 092 * @return 返回数据库类型 093 */ 094 public static DbType parseDbType(String jdbcUrl) { 095 jdbcUrl = jdbcUrl.toLowerCase(); 096 if (jdbcUrl.contains(":mysql:") || jdbcUrl.contains(":cobar:")) { 097 return DbType.MYSQL; 098 } else if (jdbcUrl.contains(":mariadb:")) { 099 return DbType.MARIADB; 100 } else if (jdbcUrl.contains(":oracle:")) { 101 return DbType.ORACLE; 102 } else if (jdbcUrl.contains(":sqlserver2012:")) { 103 return DbType.SQLSERVER; 104 } else if (jdbcUrl.contains(":sqlserver:") || jdbcUrl.contains(":microsoft:")) { 105 return DbType.SQLSERVER_2005; 106 } else if (jdbcUrl.contains(":postgresql:")) { 107 return DbType.POSTGRE_SQL; 108 } else if (jdbcUrl.contains(":hsqldb:")) { 109 return DbType.HSQL; 110 } else if (jdbcUrl.contains(":db2:")) { 111 return DbType.DB2; 112 } else if (jdbcUrl.contains(":sqlite:")) { 113 return DbType.SQLITE; 114 } else if (jdbcUrl.contains(":h2:")) { 115 return DbType.H2; 116 } else if (isMatchedRegex(":dm\\d*:", jdbcUrl)) { 117 return DbType.DM; 118 } else if (jdbcUrl.contains(":xugu:")) { 119 return DbType.XUGU; 120 } else if (isMatchedRegex(":kingbase\\d*:", jdbcUrl)) { 121 return DbType.KINGBASE_ES; 122 } else if (jdbcUrl.contains(":phoenix:")) { 123 return DbType.PHOENIX; 124 } else if (jdbcUrl.contains(":zenith:")) { 125 return DbType.GAUSS; 126 } else if (jdbcUrl.contains(":gbase:")) { 127 return DbType.GBASE; 128 } else if (jdbcUrl.contains(":gbasedbt-sqli:") || jdbcUrl.contains(":informix-sqli:")) { 129 return DbType.GBASE_8S; 130 } else if (jdbcUrl.contains(":ch:") || jdbcUrl.contains(":clickhouse:")) { 131 return DbType.CLICK_HOUSE; 132 } else if (jdbcUrl.contains(":oscar:")) { 133 return DbType.OSCAR; 134 } else if (jdbcUrl.contains(":sybase:")) { 135 return DbType.SYBASE; 136 } else if (jdbcUrl.contains(":oceanbase:")) { 137 return DbType.OCEAN_BASE; 138 } else if (jdbcUrl.contains(":highgo:")) { 139 return DbType.HIGH_GO; 140 } else if (jdbcUrl.contains(":cubrid:")) { 141 return DbType.CUBRID; 142 } else if (jdbcUrl.contains(":goldilocks:")) { 143 return DbType.GOLDILOCKS; 144 } else if (jdbcUrl.contains(":csiidb:")) { 145 return DbType.CSIIDB; 146 } else if (jdbcUrl.contains(":sap:")) { 147 return DbType.SAP_HANA; 148 } else if (jdbcUrl.contains(":impala:")) { 149 return DbType.IMPALA; 150 } else if (jdbcUrl.contains(":vertica:")) { 151 return DbType.VERTICA; 152 } else if (jdbcUrl.contains(":xcloud:")) { 153 return DbType.XCloud; 154 } else if (jdbcUrl.contains(":firebirdsql:")) { 155 return DbType.FIREBIRD; 156 } else if (jdbcUrl.contains(":redshift:")) { 157 return DbType.REDSHIFT; 158 } else if (jdbcUrl.contains(":opengauss:")) { 159 return DbType.OPENGAUSS; 160 } else if (jdbcUrl.contains(":taos:") || jdbcUrl.contains(":taos-rs:")) { 161 return DbType.TDENGINE; 162 } else if (jdbcUrl.contains(":informix")) { 163 return DbType.INFORMIX; 164 } else if (jdbcUrl.contains(":sinodb")) { 165 return DbType.SINODB; 166 } else if (jdbcUrl.contains(":uxdb:")) { 167 return DbType.UXDB; 168 } else if (jdbcUrl.contains(":greenplum:")) { 169 return DbType.GREENPLUM; 170 } else if (jdbcUrl.contains(":lealone:")) { 171 return DbType.LEALONE; 172 } else if (jdbcUrl.contains(":hive2:")) { 173 return DbType.HIVE; 174 } else { 175 return DbType.OTHER; 176 } 177 } 178 179 /** 180 * 正则匹配,验证成功返回 true,验证失败返回 false 181 */ 182 public static boolean isMatchedRegex(String regex, String jdbcUrl) { 183 if (null == jdbcUrl) { 184 return false; 185 } 186 return Pattern.compile(regex).matcher(jdbcUrl).find(); 187 } 188 189}