shardingSphere5.1.1 适配人大金仓
1. 官网适配数据库说明
图例可见,官网不支持人大金仓国产数据库,若要使用shardingSphere需要修改源码
2. 需要修改的类
2.1 KingBase8DatabaseType.java
package org.apache.shardingsphere.infra.database.type.dialect;
import org.apache.shardingsphere.infra.database.metadata.dialect.KingBase8DataSourceMetaData;
import org.apache.shardingsphere.infra.database.type.BranchDatabaseType;
import org.apache.shardingsphere.infra.database.type.DatabaseType;
import org.apache.shardingsphere.infra.database.type.DatabaseTypeRegistry;
import org.apache.shardingsphere.sql.parser.sql.common.constant.QuoteCharacter;
import java.sql.Connection;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
/**
* Database type of KingBase.
*/
public final class KingBase8DatabaseType implements BranchDatabaseType {
@Override
public String getName() {
return "kingbase8";
}
@Override
public QuoteCharacter getQuoteCharacter() {
return QuoteCharacter.QUOTE;
}
@Override
public Collection<String> getJdbcUrlPrefixes() {
return Collections.singleton(String.format("jdbc:%s:", getName().toLowerCase()));
}
@Override
public KingBase8DataSourceMetaData getDataSourceMetaData(final String url, final String username) {
return new KingBase8DataSourceMetaData(url);
}
@Override
public Optional<String> getDataSourceClassName() {
return Optional.empty();
}
@Override
public Map<String, Collection<String>> getSystemDatabaseSchemaMap() {
return Collections.emptyMap();
}
@Override
public Collection<String> getSystemSchemas() {
return Collections.emptyList();
}
@Override
public String getSchema(final Connection connection) {
return "public";
}
@Override
public DatabaseType getTrunkDatabaseType() {
return DatabaseTypeRegistry.getActualDatabaseType("MySQL");
}
}
2.2 在META-INFO/services配置文件文件中添加配置,加载文件
2.3 KingBase8DataSourceMetaData.java
package org.apache.shardingsphere.infra.database.metadata.dialect;
import lombok.Getter;
import org.apache.shardingsphere.infra.database.metadata.DataSourceMetaData;
import org.apache.shardingsphere.infra.database.metadata.url.JdbcUrl;
import org.apache.shardingsphere.infra.database.metadata.url.StandardJdbcUrlParser;
import java.util.Properties;
/**
* Data source meta data for KingBase.
*/
@Getter
public class KingBase8DataSourceMetaData implements DataSourceMetaData {
private static final int DEFAULT_PORT = 54321;
private final String hostname;
private final int port;
private final String catalog;
private final String schema;
private final Properties queryProperties;
private final Properties defaultQueryProperties = new Properties();
public KingBase8DataSourceMetaData(final String url) {
JdbcUrl jdbcUrl = new StandardJdbcUrlParser().parse(url);
hostname = jdbcUrl.getHostname();
port = -1 == jdbcUrl.getPort() ? DEFAULT_PORT : jdbcUrl.getPort();
catalog = jdbcUrl.getDatabase();
schema = "public";
queryProperties = jdbcUrl.getQueryProperties();
}
@Override
public Properties getDefaultQueryProperties() {
return new Properties();
}
private void buildDefaultQueryProperties() {
defaultQueryProperties.setProperty("useServerPrepStmts", Boolean.TRUE.toString());
defaultQueryProperties.setProperty("cachePrepStmts", Boolean.TRUE.toString());
defaultQueryProperties.setProperty("prepStmtCacheSize", "200000");
defaultQueryProperties.setProperty("prepStmtCacheSqlLimit", "2048");
defaultQueryProperties.setProperty("useLocalSessionState", Boolean.TRUE.toString());
defaultQueryProperties.setProperty("rewriteBatchedStatements", Boolean.TRUE.toString());
defaultQueryProperties.setProperty("cacheResultSetMetadata", Boolean.FALSE.toString());
defaultQueryProperties.setProperty("cacheServerConfiguration", Boolean.TRUE.toString());
defaultQueryProperties.setProperty("elideSetAutoCommits", Boolean.TRUE.toString());
defaultQueryProperties.setProperty("maintainTimeStats", Boolean.FALSE.toString());
defaultQueryProperties.setProperty("netTimeoutForStreamingResults", "0");
defaultQueryProperties.setProperty("tinyInt1isBit", Boolean.FALSE.toString());
defaultQueryProperties.setProperty("useSSL", Boolean.FALSE.toString());
defaultQueryProperties.setProperty("serverTimezone", "UTC");
defaultQueryProperties.setProperty("zeroDateTimeBehavior", "round");
}
}
2.4 KingBaseOptimizerBuilder.java
package org.apache.shardingsphere.infra.federation.optimizer.context.parser.dialect.impl;
import org.apache.calcite.config.CalciteConnectionProperty;
import org.apache.calcite.config.Lex;
import org.apache.calcite.sql.fun.SqlLibrary;
import org.apache.calcite.sql.validate.SqlConformanceEnum;
import org.apache.shardingsphere.infra.federation.optimizer.context.parser.dialect.OptimizerSQLDialectBuilder;
import java.util.Properties;
/**
* Optimizer properties builder for KingBase.
*/
public class KingBaseOptimizerBuilder implements OptimizerSQLDialectBuilder {
@Override
public Properties build() {
Properties result = new Properties();
result.setProperty(CalciteConnectionProperty.LEX.camelName(), Lex.JAVA.name());
result.setProperty(CalciteConnectionProperty.CONFORMANCE.camelName(), SqlConformanceEnum.BABEL.name());
result.setProperty(CalciteConnectionProperty.FUN.camelName(), SqlLibrary.POSTGRESQL.fun);
return result;
}
@Override
public String getType() {
return "kingbase8";
}
@Override
public boolean isDefault() {
return true;
}
}
2.5 在META-INFO/services配置文件文件中添加配置,加载文件
2.6 修改ShardingSphereResultSet.java中的getIndexFromColumnLabelAndIndexMap()方法
//解决分页count别名找不到问题
private Integer getIndexFromColumnLabelAndIndexMap(final String columnLabel) throws SQLFeatureNotSupportedException {
Integer columnIndex;
if("count".equalsIgnoreCase(columnLabel)){
columnIndex = columnLabelAndIndexMap.get("count(0)");
}else{
columnIndex = columnLabelAndIndexMap.get(columnLabel);
}
if (null == columnIndex) {
throw new SQLFeatureNotSupportedException(String.format("can't get index from columnLabel[%s].", columnLabel));
}
return columnIndex;
}
2.7 打包说明
修改完文件之后,执行maven install打到本地仓库,应用服务引用修改过后的jar,就可以正常启动运行了
3. 源码编译问题总结
3.1 Caused by: com.kingbase8.util.KsQLExceptionat :
The _column name config_id was not found in this ResultSet
分析: 这是因为表名字与人大金仓默认表名字重叠,获取列元数据的时候,执行失败
解决方案:
1. 指定获取元数据的数据库模式(比如直接写死public,推荐)
2. 修改表名字
3.2 can’t get index from columnLabel[count]
分析: 分页count别名找不到问题
解决方法:
1. 参考2.6 (推荐)
2. 修改分页插件,重写分页拦截器,指定别名 (不推荐)