[improvement][headless]Expression replacement logic supports more complex sql.
Some checks failed
supersonic CentOS CI / build (21) (push) Has been cancelled
supersonic mac CI / build (21) (push) Has been cancelled
supersonic ubuntu CI / build (21) (push) Has been cancelled
supersonic windows CI / build (21) (push) Has been cancelled

This commit is contained in:
jerryjzhang
2025-01-05 16:09:42 +08:00
parent 6fcfdc15e1
commit 4e653c1fb1
6 changed files with 59 additions and 8 deletions

View File

@@ -627,7 +627,8 @@ public class SqlReplaceHelper {
return expr; return expr;
} }
public static String replaceSqlByExpression(String sql, Map<String, String> replace) { public static String replaceSqlByExpression(String tableName, String sql,
Map<String, String> replace) {
Select selectStatement = SqlSelectHelper.getSelect(sql); Select selectStatement = SqlSelectHelper.getSelect(sql);
List<PlainSelect> plainSelectList = new ArrayList<>(); List<PlainSelect> plainSelectList = new ArrayList<>();
if (selectStatement instanceof PlainSelect) { if (selectStatement instanceof PlainSelect) {
@@ -636,9 +637,8 @@ public class SqlReplaceHelper {
selectStatement.getWithItemsList().forEach(withItem -> { selectStatement.getWithItemsList().forEach(withItem -> {
plainSelectList.add(withItem.getSelect().getPlainSelect()); plainSelectList.add(withItem.getSelect().getPlainSelect());
}); });
} else {
plainSelectList.add((PlainSelect) selectStatement);
} }
plainSelectList.add((PlainSelect) selectStatement);
} else if (selectStatement instanceof SetOperationList) { } else if (selectStatement instanceof SetOperationList) {
SetOperationList setOperationList = (SetOperationList) selectStatement; SetOperationList setOperationList = (SetOperationList) selectStatement;
if (!CollectionUtils.isEmpty(setOperationList.getSelects())) { if (!CollectionUtils.isEmpty(setOperationList.getSelects())) {
@@ -672,9 +672,12 @@ public class SqlReplaceHelper {
List<PlainSelect> plainSelects = SqlSelectHelper.getPlainSelects(plainSelectList); List<PlainSelect> plainSelects = SqlSelectHelper.getPlainSelects(plainSelectList);
for (PlainSelect plainSelect : plainSelects) { for (PlainSelect plainSelect : plainSelects) {
replacePlainSelectByExpr(plainSelect, replace); Table table = (Table) plainSelect.getFromItem();
if (SqlSelectHelper.hasAggregateFunction(plainSelect)) { if (table.getName().equals(tableName)) {
SqlSelectHelper.addMissingGroupby(plainSelect); replacePlainSelectByExpr(plainSelect, replace);
if (SqlSelectHelper.hasAggregateFunction(plainSelect)) {
SqlSelectHelper.addMissingGroupby(plainSelect);
}
} }
} }
return selectStatement.toString(); return selectStatement.toString();

View File

@@ -2,6 +2,7 @@ package com.tencent.supersonic.headless.core.translator.parser;
import com.tencent.supersonic.common.jsqlparser.SqlReplaceHelper; import com.tencent.supersonic.common.jsqlparser.SqlReplaceHelper;
import com.tencent.supersonic.common.jsqlparser.SqlSelectHelper; import com.tencent.supersonic.common.jsqlparser.SqlSelectHelper;
import com.tencent.supersonic.common.pojo.Constants;
import com.tencent.supersonic.headless.api.pojo.response.DimSchemaResp; import com.tencent.supersonic.headless.api.pojo.response.DimSchemaResp;
import com.tencent.supersonic.headless.api.pojo.response.SemanticSchemaResp; import com.tencent.supersonic.headless.api.pojo.response.SemanticSchemaResp;
import com.tencent.supersonic.headless.core.pojo.OntologyQuery; import com.tencent.supersonic.headless.core.pojo.OntologyQuery;
@@ -40,7 +41,9 @@ public class DimExpressionParser implements QueryParser {
Map<String, String> bizName2Expr = getDimensionExpressions(semanticSchema, ontologyQuery); Map<String, String> bizName2Expr = getDimensionExpressions(semanticSchema, ontologyQuery);
if (!CollectionUtils.isEmpty(bizName2Expr)) { if (!CollectionUtils.isEmpty(bizName2Expr)) {
String sql = SqlReplaceHelper.replaceSqlByExpression(sqlQuery.getSql(), bizName2Expr); String sql = SqlReplaceHelper.replaceSqlByExpression(
Constants.TABLE_PREFIX + queryStatement.getDataSetId(), sqlQuery.getSql(),
bizName2Expr);
sqlQuery.setSql(sql); sqlQuery.setSql(sql);
} }
} }

View File

@@ -2,6 +2,7 @@ package com.tencent.supersonic.headless.core.translator.parser;
import com.tencent.supersonic.common.jsqlparser.SqlReplaceHelper; import com.tencent.supersonic.common.jsqlparser.SqlReplaceHelper;
import com.tencent.supersonic.common.jsqlparser.SqlSelectHelper; import com.tencent.supersonic.common.jsqlparser.SqlSelectHelper;
import com.tencent.supersonic.common.pojo.Constants;
import com.tencent.supersonic.headless.api.pojo.Measure; import com.tencent.supersonic.headless.api.pojo.Measure;
import com.tencent.supersonic.headless.api.pojo.enums.MetricDefineType; import com.tencent.supersonic.headless.api.pojo.enums.MetricDefineType;
import com.tencent.supersonic.headless.api.pojo.response.MetricSchemaResp; import com.tencent.supersonic.headless.api.pojo.response.MetricSchemaResp;
@@ -39,7 +40,9 @@ public class MetricExpressionParser implements QueryParser {
Map<String, String> bizName2Expr = getMetricExpressions(semanticSchema, ontologyQuery); Map<String, String> bizName2Expr = getMetricExpressions(semanticSchema, ontologyQuery);
if (!CollectionUtils.isEmpty(bizName2Expr)) { if (!CollectionUtils.isEmpty(bizName2Expr)) {
String sql = SqlReplaceHelper.replaceSqlByExpression(sqlQuery.getSql(), bizName2Expr); String sql = SqlReplaceHelper.replaceSqlByExpression(
Constants.TABLE_PREFIX + queryStatement.getDataSetId(), sqlQuery.getSql(),
bizName2Expr);
sqlQuery.setSql(sql); sqlQuery.setSql(sql);
} }
} }

View File

@@ -347,6 +347,7 @@ public class SchemaServiceImpl implements SchemaService {
DataSetSchemaResp dataSetSchemaResp = DataSetSchemaResp dataSetSchemaResp =
fetchDataSetSchema(schemaFilterReq.getDataSetId()); fetchDataSetSchema(schemaFilterReq.getDataSetId());
BeanUtils.copyProperties(dataSetSchemaResp, semanticSchemaResp); BeanUtils.copyProperties(dataSetSchemaResp, semanticSchemaResp);
semanticSchemaResp.setDataSetResp(dataSetSchemaResp);
List<Long> modelIds = dataSetSchemaResp.getAllModels(); List<Long> modelIds = dataSetSchemaResp.getAllModels();
MetaFilter metaFilter = new MetaFilter(); MetaFilter metaFilter = new MetaFilter();
metaFilter.setIds(modelIds); metaFilter.setIds(modelIds);

View File

@@ -111,4 +111,18 @@ public class TranslatorTest extends BaseTest {
executeSql(explain.getQuerySQL()); executeSql(explain.getQuerySQL());
} }
@Test
@SetSystemProperty(key = "s2.test", value = "true")
public void testSql_subquery() throws Exception {
String sql = new String(
Files.readAllBytes(
Paths.get(ClassLoader.getSystemResource("sql/testSubquery.sql").toURI())),
StandardCharsets.UTF_8);
SemanticTranslateResp explain = semanticLayerService
.translate(QueryReqBuilder.buildS2SQLReq(sql, dataSetId), User.getDefaultUser());
assertNotNull(explain);
assertNotNull(explain.getQuerySQL());
executeSql(explain.getQuerySQL());
}
} }

View File

@@ -0,0 +1,27 @@
WITH
_average_stay_duration_ AS (
SELECT
AVG() AS _avg_duration_
FROM
)
SELECT
,
SUM() AS _total_stay_duration_
FROM
GROUP BY
HAVING
SUM() > (
SELECT
_avg_duration_ * 1.5
FROM
_average_stay_duration_
)
OR SUM() < (
SELECT
_avg_duration_ * 0.5
FROM
_average_stay_duration_
)