mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-10 11:07:06 +00:00
[improvement][headless]Expression replacement logic supports more complex sql.
This commit is contained in:
@@ -627,7 +627,8 @@ public class SqlReplaceHelper {
|
||||
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);
|
||||
List<PlainSelect> plainSelectList = new ArrayList<>();
|
||||
if (selectStatement instanceof PlainSelect) {
|
||||
@@ -636,9 +637,8 @@ public class SqlReplaceHelper {
|
||||
selectStatement.getWithItemsList().forEach(withItem -> {
|
||||
plainSelectList.add(withItem.getSelect().getPlainSelect());
|
||||
});
|
||||
} else {
|
||||
plainSelectList.add((PlainSelect) selectStatement);
|
||||
}
|
||||
plainSelectList.add((PlainSelect) selectStatement);
|
||||
} else if (selectStatement instanceof SetOperationList) {
|
||||
SetOperationList setOperationList = (SetOperationList) selectStatement;
|
||||
if (!CollectionUtils.isEmpty(setOperationList.getSelects())) {
|
||||
@@ -672,9 +672,12 @@ public class SqlReplaceHelper {
|
||||
|
||||
List<PlainSelect> plainSelects = SqlSelectHelper.getPlainSelects(plainSelectList);
|
||||
for (PlainSelect plainSelect : plainSelects) {
|
||||
replacePlainSelectByExpr(plainSelect, replace);
|
||||
if (SqlSelectHelper.hasAggregateFunction(plainSelect)) {
|
||||
SqlSelectHelper.addMissingGroupby(plainSelect);
|
||||
Table table = (Table) plainSelect.getFromItem();
|
||||
if (table.getName().equals(tableName)) {
|
||||
replacePlainSelectByExpr(plainSelect, replace);
|
||||
if (SqlSelectHelper.hasAggregateFunction(plainSelect)) {
|
||||
SqlSelectHelper.addMissingGroupby(plainSelect);
|
||||
}
|
||||
}
|
||||
}
|
||||
return selectStatement.toString();
|
||||
|
||||
@@ -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.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.SemanticSchemaResp;
|
||||
import com.tencent.supersonic.headless.core.pojo.OntologyQuery;
|
||||
@@ -40,7 +41,9 @@ public class DimExpressionParser implements QueryParser {
|
||||
|
||||
Map<String, String> bizName2Expr = getDimensionExpressions(semanticSchema, ontologyQuery);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.SqlSelectHelper;
|
||||
import com.tencent.supersonic.common.pojo.Constants;
|
||||
import com.tencent.supersonic.headless.api.pojo.Measure;
|
||||
import com.tencent.supersonic.headless.api.pojo.enums.MetricDefineType;
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,6 +347,7 @@ public class SchemaServiceImpl implements SchemaService {
|
||||
DataSetSchemaResp dataSetSchemaResp =
|
||||
fetchDataSetSchema(schemaFilterReq.getDataSetId());
|
||||
BeanUtils.copyProperties(dataSetSchemaResp, semanticSchemaResp);
|
||||
semanticSchemaResp.setDataSetResp(dataSetSchemaResp);
|
||||
List<Long> modelIds = dataSetSchemaResp.getAllModels();
|
||||
MetaFilter metaFilter = new MetaFilter();
|
||||
metaFilter.setIds(modelIds);
|
||||
|
||||
@@ -111,4 +111,18 @@ public class TranslatorTest extends BaseTest {
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
27
launchers/standalone/src/test/resources/sql/testSubquery.sql
Normal file
27
launchers/standalone/src/test/resources/sql/testSubquery.sql
Normal 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_
|
||||
)
|
||||
Reference in New Issue
Block a user