From 6ec0fb945ddca78267fbf02a9349f94e88086eb3 Mon Sep 17 00:00:00 2001 From: zhaotao5 Date: Tue, 24 Feb 2026 17:07:39 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DKingbaseES=20MySQL?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=A8=A1=E5=BC=8F=E7=9A=84=E5=A4=9A=E9=A1=B9?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=80=A7=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 标识符引用:双引号改为反引号(KingbaseES MySQL模式不支持双引号) 2. Comment语法:MySQL内联comment改为PostgreSQL标准COMMENT ON语法 3. AlterTable:MysqlAlterTableSqlBuilder改为PostgresqlAlterTableSqlBuilder 4. 元数据解析:information_schema数值字段增加CAST转换,修复ClassCastException --- .../KingbaseMysqlCreateTableSqlBuilder.java | 21 ++++-- .../kingbase/mysql/KingbaseMysqlDialect.java | 6 +- .../mysql/KingbaseMysqlSchemaMetadata.java | 13 ++-- .../KingbaseMysqlTableMetadataParser.java | 73 +++++++++++++++++-- 4 files changed, 88 insertions(+), 25 deletions(-) diff --git a/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlCreateTableSqlBuilder.java b/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlCreateTableSqlBuilder.java index d974b47e..fb6b7da0 100644 --- a/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlCreateTableSqlBuilder.java +++ b/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlCreateTableSqlBuilder.java @@ -12,16 +12,18 @@ import org.hswebframework.ezorm.rdb.operator.builder.fragments.ddl.CreateIndexParameter; import org.hswebframework.ezorm.rdb.operator.builder.fragments.ddl.CreateIndexSqlBuilder; import org.hswebframework.ezorm.rdb.operator.builder.fragments.ddl.CreateTableSqlBuilder; -import org.hswebframework.ezorm.rdb.supports.mysql.MysqlCreateTableSqlBuilder; + +import static org.hswebframework.ezorm.rdb.executor.SqlRequests.of; /** * KingbaseES MySQL 兼容模式的建表 SQL 构建器. *

- * 与 {@link MysqlCreateTableSqlBuilder} 的区别: + * 与 {@link org.hswebframework.ezorm.rdb.supports.mysql.MysqlCreateTableSqlBuilder} 的区别: *

* * @since 4.2 @@ -61,18 +63,21 @@ public SqlRequest build(RDBTableMetadata table) { createTable.addSql("default", ((NativeSql) defaultValue).getSql()); } } - if (column.getComment() != null) { - createTable.addSql(" comment ", - StringUtils.concat("'", column.getComment(), "'")); - } + } + // 使用 PostgreSQL 标准的 COMMENT ON COLUMN 语法(作为单独的批量 SQL) + if (column.getComment() != null) { + sql.addBatch(of(String.format("comment on column %s is '%s'", + column.getFullTableName(), column.getComment()))); } } // KingbaseES 不支持 ENGINE= 和 DEFAULT CHARSET=,直接关闭括号 createTable.addSql(")"); + // 使用 PostgreSQL 标准的 COMMENT ON TABLE 语法 if (table.getComment() != null) { - createTable.addSql("COMMENT=", StringUtils.concat("'", table.getComment(), "'")); + sql.addBatch(of(String.format("comment on table %s is '%s'", + table.getFullName(), table.getComment()))); } sql.setSql(createTable.toRequest().getSql()); diff --git a/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlDialect.java b/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlDialect.java index 21fdf6a3..c2cdfe3e 100644 --- a/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlDialect.java +++ b/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlDialect.java @@ -16,7 +16,7 @@ * 因此: * * * @since 4.2 @@ -66,12 +66,12 @@ public KingbaseMysqlDialect() { @Override public String getQuoteStart() { - return "\""; + return "`"; } @Override public String getQuoteEnd() { - return "\""; + return "`"; } @Override diff --git a/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlSchemaMetadata.java b/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlSchemaMetadata.java index 36f832df..b2d56c61 100644 --- a/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlSchemaMetadata.java +++ b/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlSchemaMetadata.java @@ -4,10 +4,10 @@ import org.hswebframework.ezorm.rdb.metadata.RDBSchemaMetadata; import org.hswebframework.ezorm.rdb.metadata.RDBTableMetadata; import org.hswebframework.ezorm.rdb.operator.CompositeExceptionTranslation; -import org.hswebframework.ezorm.rdb.supports.mysql.MysqlAlterTableSqlBuilder; import org.hswebframework.ezorm.rdb.supports.mysql.MysqlEnumInFragmentBuilder; import org.hswebframework.ezorm.rdb.supports.mysql.MysqlIndexMetadataParser; import org.hswebframework.ezorm.rdb.supports.mysql.MysqlPaginator; +import org.hswebframework.ezorm.rdb.supports.postgres.PostgresqlAlterTableSqlBuilder; import org.hswebframework.ezorm.rdb.supports.postgres.PostgresqlR2DBCExceptionTranslation; import org.hswebframework.ezorm.rdb.utils.FeatureUtils; @@ -16,11 +16,12 @@ *

* KingbaseES 底层使用 PostgreSQL 协议通信,但 SQL 语法兼容 MySQL。因此: *

* * @since 4.2 @@ -30,9 +31,9 @@ public class KingbaseMysqlSchemaMetadata extends RDBSchemaMetadata { public KingbaseMysqlSchemaMetadata(String name) { super(name); - // DDL 构建器 - 去掉 ENGINE=/CHARSET= + // DDL 构建器 - 去掉 ENGINE=/CHARSET=,使用 COMMENT ON 语法 addFeature(new KingbaseMysqlCreateTableSqlBuilder()); - addFeature(new MysqlAlterTableSqlBuilder()); + addFeature(new PostgresqlAlterTableSqlBuilder()); // 分页器 - 复用 MySQL 的 LIMIT ?,? 语法 addFeature(new MysqlPaginator()); diff --git a/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlTableMetadataParser.java b/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlTableMetadataParser.java index 557f8233..f03b3f0c 100644 --- a/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlTableMetadataParser.java +++ b/hsweb-easy-orm-rdb/src/main/java/org/hswebframework/ezorm/rdb/supports/kingbase/mysql/KingbaseMysqlTableMetadataParser.java @@ -1,24 +1,81 @@ package org.hswebframework.ezorm.rdb.supports.kingbase.mysql; import org.hswebframework.ezorm.rdb.metadata.RDBSchemaMetadata; -import org.hswebframework.ezorm.rdb.supports.mysql.MysqlTableMetadataParser; +import org.hswebframework.ezorm.rdb.metadata.RDBTableMetadata; +import org.hswebframework.ezorm.rdb.supports.commons.RDBTableMetadataParser; +import reactor.core.publisher.Flux; + +import java.util.List; /** * KingbaseES MySQL 兼容模式的表元数据解析器. *

- * KingbaseES MySQL 兼容模式的 {@code information_schema.columns} 和 - * {@code information_schema.tables} 与 MySQL 高度兼容, - * 因此直接继承 {@link MysqlTableMetadataParser}。 - *

- * 如果后续发现字段差异(如 {@code column_type} 不存在等), - * 可在此类中覆盖对应的 SQL 方法。 + * 通过 r2dbc-postgresql 驱动查询 information_schema 时, + * {@code character_maximum_length}、{@code numeric_precision}、{@code numeric_scale} + * 等字段的返回类型为 varchar(而非 int),需要在 SQL 中进行显式 CAST 转换, + * 避免 {@code ClassCastException: Cannot cast String to Number}。 * * @since 4.2 */ -public class KingbaseMysqlTableMetadataParser extends MysqlTableMetadataParser { +public class KingbaseMysqlTableMetadataParser extends RDBTableMetadataParser { + + private static final String TABLE_META_SQL = String.join(" ", + "select", + "column_name as `name`,", + "data_type as `data_type`,", + "cast(character_maximum_length as integer) as `data_length`,", + "cast(numeric_precision as integer) as `data_precision`,", + "cast(numeric_scale as integer) as `data_scale`,", + "column_comment as `comment`,", + "table_name as `table_name`,", + "column_type as `column_type`,", + "case when is_nullable='YES' then 0 else 1 end as `not_null`", + "from information_schema.columns where table_schema=#{schema} and table_name like #{table}"); + + private static final String TABLE_COMMENT_SQL = String.join(" ", + "select ", + "table_comment as `comment`", + ",table_name as `table_name`", + "from information_schema.tables where table_schema=#{schema} and table_name like #{table}"); + + private static final String ALL_TABLE_SQL = + "select table_name as `name` from information_schema.`TABLES` where table_schema=#{schema}"; + + private static final String TABLE_EXISTS_SQL = + "select count(1) as `total` from information_schema.`TABLES` where table_schema=#{schema} and table_name=#{table}"; public KingbaseMysqlTableMetadataParser(RDBSchemaMetadata schema) { super(schema); } + @Override + protected String getTableMetaSql(String name) { + return TABLE_META_SQL; + } + + @Override + protected String getTableCommentSql(String name) { + return TABLE_COMMENT_SQL; + } + + @Override + protected String getAllTableSql() { + return ALL_TABLE_SQL; + } + + @Override + public String getTableExistsSql() { + return TABLE_EXISTS_SQL; + } + + @Override + public List parseAll() { + return super.fastParseAll(); + } + + @Override + public Flux parseAllReactive() { + return super.fastParseAllReactive(); + } + }