diff --git a/common/src/main/java/com/tencent/supersonic/common/util/jsqlparser/SqlParserSelectHelper.java b/common/src/main/java/com/tencent/supersonic/common/util/jsqlparser/SqlParserSelectHelper.java index af38bd9b2..4a053fe6f 100644 --- a/common/src/main/java/com/tencent/supersonic/common/util/jsqlparser/SqlParserSelectHelper.java +++ b/common/src/main/java/com/tencent/supersonic/common/util/jsqlparser/SqlParserSelectHelper.java @@ -9,10 +9,12 @@ import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.BinaryExpression; +import net.sf.jsqlparser.expression.CaseExpression; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitorAdapter; import net.sf.jsqlparser.expression.Function; import net.sf.jsqlparser.expression.StringValue; +import net.sf.jsqlparser.expression.WhenClause; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; import net.sf.jsqlparser.expression.operators.conditional.OrExpression; import net.sf.jsqlparser.expression.operators.conditional.XorExpression; @@ -500,6 +502,18 @@ public class SqlParserSelectHelper { getColumnFromExpr(expr, columns); } } + if (expression instanceof CaseExpression) { + CaseExpression expr = (CaseExpression) expression; + if (Objects.nonNull(expr.getWhenClauses())) { + for (WhenClause whenClause : expr.getWhenClauses()) { + getColumnFromExpr(whenClause.getWhenExpression(), columns); + getColumnFromExpr(whenClause.getThenExpression(), columns); + } + } + if (Objects.nonNull(expr.getElseExpression())) { + getColumnFromExpr(expr.getElseExpression(), columns); + } + } if (expression instanceof BinaryExpression) { BinaryExpression expr = (BinaryExpression) expression; getColumnFromExpr(expr.getLeftExpression(), columns); diff --git a/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/s2sql/MetricTypeParams.java b/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/s2sql/MetricTypeParams.java index 3242ff1c6..4197dbd99 100644 --- a/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/s2sql/MetricTypeParams.java +++ b/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/s2sql/MetricTypeParams.java @@ -9,7 +9,7 @@ public class MetricTypeParams { private List measures; private List metrics; private List fields; - + private boolean isFieldMetric = false; private String expr; } diff --git a/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/node/MetricNode.java b/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/node/MetricNode.java index 1bfa2f38d..1b5736634 100644 --- a/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/node/MetricNode.java +++ b/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/node/MetricNode.java @@ -2,8 +2,10 @@ package com.tencent.supersonic.headless.core.parser.calcite.sql.node; import com.tencent.supersonic.headless.core.parser.calcite.s2sql.Metric; +import com.tencent.supersonic.headless.core.parser.calcite.schema.SemanticSchema; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import lombok.Data; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.validate.SqlValidatorScope; @@ -26,4 +28,14 @@ public class MetricNode extends SemanticNode { return buildAs(metric.getName(), sqlNode); } + public static Boolean isMetricField(String name, SemanticSchema schema) { + Optional metric = schema.getMetrics().stream().filter(m -> m.getName().equalsIgnoreCase(name)) + .findFirst(); + return metric.isPresent() && metric.get().getMetricTypeParams().isFieldMetric(); + } + + public static Boolean isMetricField(Metric metric) { + return metric.getMetricTypeParams().isFieldMetric(); + } + } diff --git a/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/render/FilterRender.java b/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/render/FilterRender.java index 653085e03..84672e236 100644 --- a/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/render/FilterRender.java +++ b/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/render/FilterRender.java @@ -11,17 +11,16 @@ import com.tencent.supersonic.headless.core.parser.calcite.sql.TableView; import com.tencent.supersonic.headless.core.parser.calcite.sql.node.FilterNode; import com.tencent.supersonic.headless.core.parser.calcite.sql.node.MetricNode; import com.tencent.supersonic.headless.core.parser.calcite.sql.node.SemanticNode; -import org.apache.calcite.sql.SqlIdentifier; -import org.apache.calcite.sql.SqlNode; -import org.apache.calcite.sql.parser.SqlParserPos; -import org.apache.calcite.sql.validate.SqlValidatorScope; - import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.validate.SqlValidatorScope; /** * process query specified filtering information @@ -30,7 +29,7 @@ public class FilterRender extends Renderer { @Override public void render(MetricQueryReq metricCommand, List dataSources, SqlValidatorScope scope, - SemanticSchema schema, boolean nonAgg) throws Exception { + SemanticSchema schema, boolean nonAgg) throws Exception { TableView tableView = super.tableView; SqlNode filterNode = null; List queryMetrics = new ArrayList<>(metricCommand.getMetrics()); @@ -54,6 +53,10 @@ public class FilterRender extends Renderer { } for (String metric : queryMetrics) { Optional optionalMetric = Renderer.getMetricByName(metric, schema); + if (optionalMetric.isPresent() && MetricNode.isMetricField(optionalMetric.get())) { + // metric from field ignore + continue; + } if (optionalMetric.isPresent()) { tableView.getMeasure().add(MetricNode.build(optionalMetric.get(), scope)); } else { diff --git a/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/render/OutputRender.java b/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/render/OutputRender.java index 860b09e75..08e02b5ed 100644 --- a/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/render/OutputRender.java +++ b/headless/core/src/main/java/com/tencent/supersonic/headless/core/parser/calcite/sql/render/OutputRender.java @@ -1,14 +1,14 @@ package com.tencent.supersonic.headless.core.parser.calcite.sql.render; -import com.tencent.supersonic.headless.api.request.MetricQueryReq; import com.tencent.supersonic.common.pojo.ColumnOrder; +import com.tencent.supersonic.headless.api.request.MetricQueryReq; import com.tencent.supersonic.headless.core.parser.calcite.s2sql.DataSource; import com.tencent.supersonic.headless.core.parser.calcite.schema.SemanticSchema; import com.tencent.supersonic.headless.core.parser.calcite.sql.Renderer; import com.tencent.supersonic.headless.core.parser.calcite.sql.TableView; +import com.tencent.supersonic.headless.core.parser.calcite.sql.node.MetricNode; import com.tencent.supersonic.headless.core.parser.calcite.sql.node.SemanticNode; - import java.util.ArrayList; import java.util.List; import org.apache.calcite.sql.SqlNode; @@ -25,12 +25,16 @@ public class OutputRender extends Renderer { @Override public void render(MetricQueryReq metricCommand, List dataSources, SqlValidatorScope scope, - SemanticSchema schema, boolean nonAgg) throws Exception { + SemanticSchema schema, boolean nonAgg) throws Exception { TableView selectDataSet = super.tableView; for (String dimension : metricCommand.getDimensions()) { selectDataSet.getMeasure().add(SemanticNode.parse(dimension, scope)); } for (String metric : metricCommand.getMetrics()) { + if (MetricNode.isMetricField(metric, schema)) { + // metric from field ignore + continue; + } selectDataSet.getMeasure().add(SemanticNode.parse(metric, scope)); } diff --git a/headless/server/src/main/java/com/tencent/supersonic/headless/server/manager/SemanticSchemaManager.java b/headless/server/src/main/java/com/tencent/supersonic/headless/server/manager/SemanticSchemaManager.java index a7631387c..795ec42f0 100644 --- a/headless/server/src/main/java/com/tencent/supersonic/headless/server/manager/SemanticSchemaManager.java +++ b/headless/server/src/main/java/com/tencent/supersonic/headless/server/manager/SemanticSchemaManager.java @@ -174,16 +174,19 @@ public class SemanticSchemaManager { private static MetricTypeParams getMetricTypeParams(MetricTypeParamsYamlTpl metricTypeParamsYamlTpl) { MetricTypeParams metricTypeParams = new MetricTypeParams(); metricTypeParams.setExpr(metricTypeParamsYamlTpl.getExpr()); + metricTypeParams.setFieldMetric(false); if (!CollectionUtils.isEmpty(metricTypeParamsYamlTpl.getMeasures())) { metricTypeParams.setMeasures(getMeasureParams(metricTypeParamsYamlTpl.getMeasures())); } if (!CollectionUtils.isEmpty(metricTypeParamsYamlTpl.getMetrics())) { metricTypeParams.setMeasures(getMetricParams(metricTypeParamsYamlTpl.getMetrics())); metricTypeParams.setExpr(metricTypeParams.getMeasures().get(0).getExpr()); + metricTypeParams.setFieldMetric(true); } if (!CollectionUtils.isEmpty(metricTypeParamsYamlTpl.getFields())) { metricTypeParams.setMeasures(getFieldParams(metricTypeParamsYamlTpl.getFields())); metricTypeParams.setExpr(metricTypeParams.getMeasures().get(0).getExpr()); + metricTypeParams.setFieldMetric(true); } return metricTypeParams;