(improvement)(headless) Fix automatically inject dimension default values into SQL (#765)

Co-authored-by: jolunoluo
This commit is contained in:
LXW
2024-02-27 13:07:26 +08:00
committed by GitHub
parent b72e280990
commit 3a38200448
2 changed files with 42 additions and 25 deletions

View File

@@ -1,5 +1,6 @@
package com.tencent.supersonic.headless.api.pojo; package com.tencent.supersonic.headless.api.pojo;
import com.google.common.collect.Lists;
import com.tencent.supersonic.headless.api.pojo.enums.AggOption; import com.tencent.supersonic.headless.api.pojo.enums.AggOption;
import lombok.Data; import lombok.Data;
@@ -9,8 +10,8 @@ import java.util.List;
public class MetricTable { public class MetricTable {
private String alias; private String alias;
private List<String> metrics; private List<String> metrics = Lists.newArrayList();
private List<String> dimensions; private List<String> dimensions = Lists.newArrayList();
private String where; private String where;
private AggOption aggOption = AggOption.DEFAULT; private AggOption aggOption = AggOption.DEFAULT;

View File

@@ -1,16 +1,25 @@
package com.tencent.supersonic.headless.core.parser.converter; package com.tencent.supersonic.headless.core.parser.converter;
import com.tencent.supersonic.common.pojo.Filter; import com.google.common.collect.Lists;
import com.tencent.supersonic.common.pojo.enums.FilterOperatorEnum; import com.tencent.supersonic.common.pojo.enums.TimeDimensionEnum;
import com.tencent.supersonic.headless.api.pojo.QueryParam; import com.tencent.supersonic.common.util.jsqlparser.SqlAddHelper;
import com.tencent.supersonic.common.util.jsqlparser.SqlSelectHelper;
import com.tencent.supersonic.headless.api.pojo.MetricTable;
import com.tencent.supersonic.headless.core.parser.calcite.s2sql.Dimension; import com.tencent.supersonic.headless.core.parser.calcite.s2sql.Dimension;
import com.tencent.supersonic.headless.core.pojo.QueryStatement; import com.tencent.supersonic.headless.core.pojo.QueryStatement;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.schema.Column;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@Slf4j @Slf4j
@Component("DefaultDimValueConverter") @Component("DefaultDimValueConverter")
@@ -18,36 +27,43 @@ public class DefaultDimValueConverter implements HeadlessConverter {
@Override @Override
public boolean accept(QueryStatement queryStatement) { public boolean accept(QueryStatement queryStatement) {
if (Objects.isNull(queryStatement.getQueryParam()) || queryStatement.getIsS2SQL()) { return !Objects.isNull(queryStatement.getViewQueryParam())
return false; && !StringUtils.isBlank(queryStatement.getViewQueryParam().getSql());
}
return true;
} }
@Override @Override
public void convert(QueryStatement queryStatement) { public void convert(QueryStatement queryStatement) {
QueryParam queryParam = queryStatement.getQueryParam();
List<Dimension> dimensions = queryStatement.getSemanticModel().getDimensions().stream() List<Dimension> dimensions = queryStatement.getSemanticModel().getDimensions().stream()
.filter(dimension -> !CollectionUtils.isEmpty(dimension.getDefaultValues())) .filter(dimension -> !CollectionUtils.isEmpty(dimension.getDefaultValues()))
.collect(Collectors.toList()); .collect(Collectors.toList());
if (CollectionUtils.isEmpty(dimensions)) { if (CollectionUtils.isEmpty(dimensions)) {
return; return;
} }
log.info("dimension with default values:{}, queryStruct:{}", dimensions, queryParam); String sql = queryStatement.getViewQueryParam().getSql();
//add dimension default value to filter List<String> whereFields = SqlSelectHelper.getWhereFields(sql)
List<String> dimensionFilterBizName = queryParam.getDimensionFilters().stream() .stream().filter(field -> !TimeDimensionEnum.containsTimeDimension(field))
.map(Filter::getBizName).collect(Collectors.toList()); .collect(Collectors.toList());
if (!CollectionUtils.isEmpty(dimensionFilterBizName)) { if (!CollectionUtils.isEmpty(whereFields)) {
return; return;
} }
for (Dimension dimensionResp : dimensions) { MetricTable metricTable = queryStatement.getViewQueryParam()
Filter filter = new Filter(); .getTables().stream().findFirst().orElse(null);
filter.setBizName(dimensionResp.getBizName()); List<Expression> expressions = Lists.newArrayList();
filter.setValue(dimensionResp.getDefaultValues()); for (Dimension dimension : dimensions) {
filter.setOperator(FilterOperatorEnum.IN); ExpressionList expressionList = new ExpressionList();
filter.setName(dimensionResp.getName()); List<Expression> exprs = new ArrayList<>();
queryParam.getDimensionFilters().add(filter); dimension.getDefaultValues().forEach(value -> exprs.add(new StringValue(value)));
expressionList.setExpressions(exprs);
InExpression inExpression = new InExpression();
inExpression.setLeftExpression(new Column(dimension.getBizName()));
inExpression.setRightItemsList(expressionList);
expressions.add(inExpression);
if (metricTable != null) {
metricTable.getDimensions().add(dimension.getBizName());
} }
} }
sql = SqlAddHelper.addWhere(sql, expressions);
queryStatement.getViewQueryParam().setSql(sql);
}
} }