Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 构建器.
* <p>
* 与 {@link MysqlCreateTableSqlBuilder} 的区别:
* 与 {@link org.hswebframework.ezorm.rdb.supports.mysql.MysqlCreateTableSqlBuilder} 的区别:
* <ul>
* <li>去掉了 {@code ENGINE=InnoDB DEFAULT CHARSET=utf8mb4} 等 MySQL 特有子句</li>
* <li>comment 使用 PostgreSQL 标准的 {@code COMMENT ON COLUMN/TABLE} 语法,
* 而非 MySQL 的内联 {@code comment 'xxx'}</li>
* <li>保留了 {@code auto_increment}(KingbaseES MySQL 兼容版支持)</li>
* <li>保留了 {@code comment} 语法</li>
* </ul>
*
* @since 4.2
Expand Down Expand Up @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* 因此:
* <ul>
* <li>数据类型映射:复用 MySQL 的类型映射</li>
* <li>标识符引用:使用双引号(PostgreSQL 风格),因为驱动层是 r2dbc-postgresql</li>
* <li>标识符引用:使用反引号(MySQL 风格),KingbaseES MySQL 兼容模式不支持双引号</li>
* </ul>
*
* @since 4.2
Expand Down Expand Up @@ -66,12 +66,12 @@ public KingbaseMysqlDialect() {

@Override
public String getQuoteStart() {
return "\"";
return "`";
}

@Override
public String getQuoteEnd() {
return "\"";
return "`";
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -16,11 +16,12 @@
* <p>
* KingbaseES 底层使用 PostgreSQL 协议通信,但 SQL 语法兼容 MySQL。因此:
* <ul>
* <li>DDL 构建器:使用 KingbaseES 适配版(去掉 ENGINE=/CHARSET=)</li>
* <li>DDL 构建器:使用 KingbaseES 适配版(去掉 ENGINE=/CHARSET=,COMMENT ON 语法)</li>
* <li>ALTER TABLE:使用 PostgreSQL 风格(避免 MySQL 内联 comment 不兼容问题)</li>
* <li>分页器:复用 MySQL 的 LIMIT ?,? 语法</li>
* <li>元数据解析器:复用 MySQL information_schema 查询</li>
* <li>元数据解析器:基于 MySQL information_schema 查询,增加 CAST 转换</li>
* <li>异常翻译:使用 <b>PostgreSQL</b> 异常翻译(因为驱动层是 r2dbc-postgresql)</li>
* <li>方言:使用 {@link KingbaseMysqlDialect}(MySQL 类型映射 + 双引号引用)</li>
* <li>方言:使用 {@link KingbaseMysqlDialect}(MySQL 类型映射 + 反引号引用)</li>
* </ul>
*
* @since 4.2
Expand All @@ -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());
Expand Down
Original file line number Diff line number Diff line change
@@ -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 兼容模式的表元数据解析器.
* <p>
* KingbaseES MySQL 兼容模式的 {@code information_schema.columns} 和
* {@code information_schema.tables} 与 MySQL 高度兼容,
* 因此直接继承 {@link MysqlTableMetadataParser}。
* <p>
* 如果后续发现字段差异(如 {@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<RDBTableMetadata> parseAll() {
return super.fastParseAll();
}

@Override
public Flux<RDBTableMetadata> parseAllReactive() {
return super.fastParseAllReactive();
}

}
Loading