diff --git a/kernel-d-db/db-api/src/main/java/cn/stylefeng/roses/kernel/db/api/util/DatabaseUtil.java b/kernel-d-db/db-api/src/main/java/cn/stylefeng/roses/kernel/db/api/util/DatabaseUtil.java index 4d9323c61..a827c16a6 100644 --- a/kernel-d-db/db-api/src/main/java/cn/stylefeng/roses/kernel/db/api/util/DatabaseUtil.java +++ b/kernel-d-db/db-api/src/main/java/cn/stylefeng/roses/kernel/db/api/util/DatabaseUtil.java @@ -11,6 +11,7 @@ import cn.stylefeng.roses.kernel.db.api.sqladapter.database.CreateDatabaseSql; import cn.stylefeng.roses.kernel.db.api.sqladapter.database.GetDatabasesSql; import cn.stylefeng.roses.kernel.db.api.sqladapter.table.TableFieldListSql; import cn.stylefeng.roses.kernel.db.api.sqladapter.table.TableListSql; +import cn.stylefeng.roses.kernel.rule.enums.DbTypeEnum; import lombok.extern.slf4j.Slf4j; import java.sql.Connection; @@ -19,6 +20,8 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * 数据库操作工具类,可用来获取一些元数据 @@ -182,33 +185,118 @@ public class DatabaseUtil { } /** - * 获取数据库名称 + * 根据数据库配置,获取数据库名称 *
* oracle的数据库会直接返回username作为数据库名称,这里需要注意一下,如果用户名不是数据库名则返回不准确 * * @author fengshuonan - * @since 2021/5/19 10:39 + * @since 2025/5/7 21:45 */ - private static String getDbName(DruidProperties druidProperties) { + public static String getDbName(DruidProperties druidProperties) { + String url = druidProperties.getUrl().toLowerCase(); + return getDbName(url); + } - if (druidProperties.getUrl().contains("oracle")) { - // 如果是oracle,直接返回username - return druidProperties.getUsername(); - } else if (druidProperties.getUrl().contains("postgresql")) { - // postgresql,直接返回最后一个/后边的字符 - int first = druidProperties.getUrl().lastIndexOf("/") + 1; - return druidProperties.getUrl().substring(first); - } else if (druidProperties.getUrl().contains("sqlserver")) { - // sqlserver,直接返回最后一个=后边的字符 - int first = druidProperties.getUrl().lastIndexOf("=") + 1; - return druidProperties.getUrl().substring(first); - } else { - // mysql,返回/和?之间的字符 - String jdbcUrl = druidProperties.getUrl(); - int first = jdbcUrl.lastIndexOf("/") + 1; - int last = jdbcUrl.indexOf("?"); - return jdbcUrl.substring(first, last); + /** + * 根据数据库URL获取数据库配置 + * + * @author fengshuonan + * @since 2025/5/7 21:45 + */ + public static String getDbName(String url) { + try { + // 如果是oracle + if (url.contains(DbTypeEnum.ORACLE.getUrlWords())) { + Pattern pattern = Pattern.compile(":(thin|oci|kprb):@(//)?[^:/]+(:\\d+)?[:/]([^?]+)"); + Matcher matcher = pattern.matcher(url); + return matcher.find() ? matcher.group(4) : parseAfterLastSlash(url); + } + + // 如果是PostgreSQL + else if (url.contains(DbTypeEnum.PG_SQL.getUrlWords())) { + return parseAfterLastSlash(url); + } + + // 如果是sql server + else if (url.contains(DbTypeEnum.MS_SQL.getUrlWords())) { + // SQL Server: databaseName= 或 Initial Catalog= + return parseParameter(url, "databasename=", "initial catalog="); + } + + // 如果是Mysql + else if (url.contains(DbTypeEnum.MYSQL.getUrlWords())) { + int first = url.lastIndexOf("/") + 1; + int last = url.indexOf("?"); + return url.substring(first, last == -1 ? url.length() : last); + } + + // 如果是达梦数据库 + else if (url.contains(DbTypeEnum.DM.getUrlWords())) { + return parseParameter(url, "dbname=", "database="); + } + + // 人大金仓、openGauss、瀚高数据库 + else if (url.contains(DbTypeEnum.KING_BASE.getUrlWords()) || url.contains(DbTypeEnum.OPEN_GAUSS.getUrlWords()) || url.contains(DbTypeEnum.HIGH_GO.getUrlWords())) { + return parseAfterLastSlash(url); + } + } catch (Exception e) { + throw new IllegalArgumentException("Failed to parse database name from URL: " + url, e); + } + + // 尝试通用解析作为最后手段 + try { + return parseAfterLastSlash(url); + } catch (Exception e) { + throw new IllegalArgumentException("Unsupported or malformed database URL: " + url); } } + /** + * 解析URL中最后一个/之后的部分 + * + * @author fengshuonan + * @since 2025/5/7 22:04 + */ + private static String parseAfterLastSlash(String url) { + int lastSlashIndex = url.lastIndexOf('/'); + if (lastSlashIndex == -1) { + return url; // 如果没有 /,返回整个 URL(或抛异常) + } + int paramStart = url.indexOf('?', lastSlashIndex); + if (paramStart == -1) { + return url.substring(lastSlashIndex + 1); + } + return url.substring(lastSlashIndex + 1, paramStart); + } + + /** + * 解析URL参数 + * + * @author fengshuonan + * @since 2025/5/7 22:04 + */ + private static String parseParameter(String url, String... paramNames) { + for (String param : paramNames) { + // 匹配 databaseName=xxx 或 ;databaseName=xxx 或 &databaseName=xxx + Pattern pattern = Pattern.compile("(?:[;&?]|^)" + param + "([^;&?]+)"); + Matcher matcher = pattern.matcher(url.toLowerCase()); + if (matcher.find()) { + return matcher.group(1); + } + } + return parseAfterLastSlash(url); + } + + public static void main(String[] args) { + System.out.println(getDbName("jdbc:oracle:thin:@//127.0.0.1:1521/right_oracle")); + System.out.println(getDbName("jdbc:postgresql://192.168.1.1:5432/right_pg")); + System.out.println(getDbName("jdbc:jtds:sqlserver://172.1.1.1:1433;DatabaseName=rightsqlserver")); + System.out.println(getDbName("jdbc:mysql://localhost:3306/right_mysql?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true")); + System.out.println(getDbName("jdbc:dm://172.1.1.1:5236?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=UTF-8")); + System.out.println(getDbName("jdbc:kingbase8://192.168.1.1:5432/right_king")); + System.out.println(getDbName("jdbc:opengauss://192.168.1.1:5432/right_open_gauss")); + System.out.println(getDbName("jdbc:highgo://localhost:5866/right_highgo")); + System.out.println(getDbName("jdbc:postgresql://172.1.1.1:5432/right_hailiang")); + } + }