SAP HANA DATABASE Source support improvement[优化SAPhana数据库的支持] (#1959)

* (improvement)(database) update the support for sap hana database source

* (fix)(common) add the default timeout for ZhipuAiEmbeddingModel,avoid the program error
This commit is contained in:
wwsheng009
2024-12-17 21:52:19 +08:00
committed by GitHub
parent 2e28a4c7a5
commit b57eed47e2
7 changed files with 151 additions and 4 deletions

View File

@@ -7,7 +7,7 @@ public class HanadbAdaptor extends DefaultDbAdaptor {
@Override
public String rewriteSql(String sql) {
return sql.replaceAll("`", "\"");
return sql.replaceAll("`(.*?)`", "\"$1\"").replaceAll("\"([A-Z0-9_]+?)\"", "$1");
}
}

View File

@@ -1,5 +1,6 @@
package com.tencent.supersonic.headless.core.translator.converter;
import com.tencent.supersonic.common.jsqlparser.SqlAsHelper;
import com.tencent.supersonic.common.jsqlparser.SqlReplaceHelper;
import com.tencent.supersonic.common.jsqlparser.SqlSelectFunctionHelper;
import com.tencent.supersonic.common.jsqlparser.SqlSelectHelper;
@@ -78,6 +79,9 @@ public class SqlQueryConverter implements QueryConverter {
generateDerivedMetric(sqlGenerateUtils, queryStatement);
queryStatement.setSql(sqlQueryParam.getSql());
// replace sql fields for db, must called after convertNameToBizName
String sqlRewrite = replaceSqlFieldsForHanaDB(queryStatement, sqlQueryParam.getSql());
sqlQueryParam.setSql(sqlRewrite);
log.info("parse sqlQuery [{}] ", sqlQueryParam);
}
@@ -224,6 +228,54 @@ public class SqlQueryConverter implements QueryConverter {
}
/**
* special process for hanaDB,the sap hana DB don't support the chinese name as
* the column name,
* so we need to quote the column name after converting the convertNameToBizName
* called
*
* sap hana DB will auto translate the colume to upper case letter if not
* quoted.
* also we need to quote the field name if it is a lower case letter.
*
* @param queryStatement
* @param sql
* @return
*/
private String replaceSqlFieldsForHanaDB(QueryStatement queryStatement, String sql) {
SemanticSchemaResp semanticSchemaResp = queryStatement.getSemanticSchemaResp();
if (!semanticSchemaResp.getDatabaseResp().getType().equalsIgnoreCase(EngineType.HANADB.getName())) {
return sql;
}
Map<String, String> fieldNameToBizNameMap = getFieldNameToBizNameMap(semanticSchemaResp);
Map<String, String> fieldNameToBizNameMapQuote = new HashMap<>();
fieldNameToBizNameMap.forEach((key, value) -> {
if (!fieldNameToBizNameMapQuote.containsKey(value) && !value.matches("\".*\"")
&& !value.matches("[A-Z0-9_].*?")) {
fieldNameToBizNameMapQuote.put(value, "\"" + value + "\"");
}
});
String sqlNew = sql;
if (fieldNameToBizNameMapQuote.size() > 0) {
sqlNew = SqlReplaceHelper.replaceFields(sql, fieldNameToBizNameMapQuote, true);
}
// replace alias field name
List<String> asFields = SqlAsHelper.getAsFields(sqlNew);
Map<String, String> fieldMapput = new HashMap<>();
for (String asField : asFields) {
String value = asField;
if (!value.matches("\".*?\"") && !value.matches("[A-Z0-9_].*?")) {
value = "\"" + asField + "\"";
fieldMapput.put(asField, value);
}
}
if (fieldMapput.size() > 0) {
sqlNew = SqlReplaceHelper.replaceAliasFieldName(sqlNew, fieldMapput);
}
return sqlNew;
}
private void convertNameToBizName(QueryStatement queryStatement) {
SemanticSchemaResp semanticSchemaResp = queryStatement.getSemanticSchemaResp();
Map<String, String> fieldNameToBizNameMap = getFieldNameToBizNameMap(semanticSchemaResp);

View File

@@ -80,9 +80,13 @@ public abstract class SemanticNode {
scope.getValidator().getCatalogReader().getRootSchema(), engineType);
if (Configuration.getSqlAdvisor(sqlValidatorWithHints, engineType).getReservedAndKeyWords()
.contains(expression.toUpperCase())) {
expression = String.format("`%s`", expression);
if (engineType == EngineType.HANADB) {
expression = String.format("\"%s\"", expression);
} else {
expression = String.format("`%s`", expression);
}
}
SqlParser sqlParser =
SqlParser sqlParser =
SqlParser.create(expression, Configuration.getParserConfig(engineType));
SqlNode sqlNode = sqlParser.parseExpression();
scope.validateExpr(sqlNode);