From 858feb9c3ca85d01a48eb7035ef0ad4eca4f6e5b Mon Sep 17 00:00:00 2001 From: jipeli <54889677+jipeli@users.noreply.github.com> Date: Wed, 30 Oct 2024 22:13:13 +0800 Subject: [PATCH] (improvement)(Headless) define the measure without agg funciton by the model (#1864) --- .../common/calcite/SqlMergeWithUtils.java | 14 +++++++++++++ .../translator/DefaultSemanticTranslator.java | 20 +++++++++++++------ .../calcite/CalciteQueryParser.java | 3 +++ .../server/utils/QueryReqConverter.java | 5 +++++ 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/com/tencent/supersonic/common/calcite/SqlMergeWithUtils.java b/common/src/main/java/com/tencent/supersonic/common/calcite/SqlMergeWithUtils.java index 79ca83dc0..38f745c21 100644 --- a/common/src/main/java/com/tencent/supersonic/common/calcite/SqlMergeWithUtils.java +++ b/common/src/main/java/com/tencent/supersonic/common/calcite/SqlMergeWithUtils.java @@ -89,4 +89,18 @@ public class SqlMergeWithUtils { SqlPrettyWriter writer = new SqlPrettyWriter(config); return writer.format(resultNode); } + + public static boolean hasWith(EngineType engineType, String sql) throws SqlParseException { + SqlParser.Config parserConfig = Configuration.getParserConfig(engineType); + SqlParser parser = SqlParser.create(sql, parserConfig); + SqlNode sqlNode = parser.parseQuery(); + SqlNode sqlSelect = sqlNode; + if (sqlNode instanceof SqlOrderBy) { + SqlOrderBy sqlOrderBy = (SqlOrderBy) sqlNode; + sqlSelect = sqlOrderBy.query; + } else if (sqlNode instanceof SqlSelect) { + sqlSelect = (SqlSelect) sqlNode; + } + return sqlSelect instanceof SqlWith; + } } diff --git a/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/DefaultSemanticTranslator.java b/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/DefaultSemanticTranslator.java index 465309ba6..0f59f50b7 100644 --- a/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/DefaultSemanticTranslator.java +++ b/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/DefaultSemanticTranslator.java @@ -99,12 +99,20 @@ public class DefaultSemanticTranslator implements SemanticTranslator { if (!tables.isEmpty()) { String sql; if (dataSetQueryParam.isSupportWith()) { - List parentWithNameList = - tables.stream().map(table -> table[0]).collect(Collectors.toList()); - List parentSqlList = - tables.stream().map(table -> table[1]).collect(Collectors.toList()); - sql = SqlMergeWithUtils.mergeWith(engineType, dataSetQueryParam.getSql(), - parentSqlList, parentWithNameList); + if (!SqlMergeWithUtils.hasWith(engineType, dataSetQueryParam.getSql())) { + sql = "with " + + tables.stream() + .map(t -> String.format("%s as (%s)", t[0], t[1])) + .collect(Collectors.joining(",")) + + "\n" + dataSetQueryParam.getSql(); + } else { + List parentWithNameList = tables.stream().map(table -> table[0]) + .collect(Collectors.toList()); + List parentSqlList = tables.stream().map(table -> table[1]) + .collect(Collectors.toList()); + sql = SqlMergeWithUtils.mergeWith(engineType, + dataSetQueryParam.getSql(), parentSqlList, parentWithNameList); + } } else { sql = dataSetQueryParam.getSql(); for (String[] tb : tables) { diff --git a/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/calcite/CalciteQueryParser.java b/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/calcite/CalciteQueryParser.java index 61589d72b..4153f8f2e 100644 --- a/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/calcite/CalciteQueryParser.java +++ b/headless/core/src/main/java/com/tencent/supersonic/headless/core/translator/calcite/CalciteQueryParser.java @@ -69,6 +69,9 @@ public class CalciteQueryParser implements QueryParser { private String getSqlByDataSet(EngineType engineType, String parentSql, String dataSetSql, String parentAlias) throws SqlParseException { + if (!SqlMergeWithUtils.hasWith(engineType, dataSetSql)) { + return String.format("with %s as (%s) %s", parentAlias, parentSql, dataSetSql); + } return SqlMergeWithUtils.mergeWith(engineType, dataSetSql, Collections.singletonList(parentSql), Collections.singletonList(parentAlias)); } diff --git a/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/QueryReqConverter.java b/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/QueryReqConverter.java index f5a65db84..55f3d45fd 100644 --- a/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/QueryReqConverter.java +++ b/headless/server/src/main/java/com/tencent/supersonic/headless/server/utils/QueryReqConverter.java @@ -171,6 +171,11 @@ public class QueryReqConverter { log.debug("getAggOption find null defaultAgg metric set to NATIVE"); return AggOption.OUTER; } + if (!SqlSelectFunctionHelper.hasAggregateFunction(sql) && !SqlSelectHelper.hasGroupBy(sql) + && !SqlSelectHelper.hasWith(sql) && !SqlSelectHelper.hasSubSelect(sql)) { + log.debug("getAggOption simple sql set to NATIVE"); + return AggOption.NATIVE; + } return AggOption.DEFAULT; }