This is an automated email from the ASF dual-hosted git repository.
hui pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new a751beccc1 [IOTDB-3922] Fix incorrect column name in some scenarios
for GroupByLevel (#6789)
a751beccc1 is described below
commit a751beccc1f889de8a1d6ffd9cc4917455b05160
Author: liuminghui233 <[email protected]>
AuthorDate: Thu Jul 28 09:40:50 2022 +0800
[IOTDB-3922] Fix incorrect column name in some scenarios for GroupByLevel
(#6789)
---
.../org/apache/iotdb/db/it/query/IoTDBAliasIT.java | 27 ++++++
.../iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java | 97 +++++++++++++++-------
.../db/mpp/plan/analyze/ExpressionAnalyzer.java | 8 +-
.../mpp/plan/analyze/GroupByLevelController.java | 16 +++-
.../iotdb/db/qp/utils/GroupByLevelController.java | 35 +++++---
5 files changed, 133 insertions(+), 50 deletions(-)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBAliasIT.java
b/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBAliasIT.java
index 8ef5fc7181..21bc7371bd 100644
---
a/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBAliasIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/db/it/query/IoTDBAliasIT.java
@@ -381,4 +381,31 @@ public class IoTDBAliasIT {
resultSetEqualTest(sqls.get(i), expectHeaders.get(i), retArrays.get(i));
}
}
+
+ // ------------------------------------ Function name
--------------------------------------
+
+ @Test
+ public void aggregationFuncNameTest() {
+ String expectedHeader =
+ "count(root.sg.d1.temperature),count(root.sg.d2.temperature),"
+ + "COUNT(root.sg.d1.s2),COUNT(root.sg.d2.s2),"
+ + "CoUnT(root.sg.d1.temperature),CoUnT(root.sg.d2.temperature),";
+ String[] retArray = new String[] {"4,4,4,4,4,4,"};
+
+ resultSetEqualTest(
+ "select count(temperature),COUNT(s2),CoUnT(temperature) from
root.sg.*",
+ expectedHeader,
+ retArray);
+ }
+
+ @Test
+ public void groupByLevelFuncNameTest() {
+ String expectedHeader =
"count(root.sg.*.s2),COUNT(root.sg.*.temperature),CoUnT(root.sg.*.s2),";
+ String[] retArray = new String[] {"8,8,8,"};
+
+ resultSetEqualTest(
+ "select count(s2),COUNT(temperature),CoUnT(s2) from root.sg.* group by
level = 1",
+ expectedHeader,
+ retArray);
+ }
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
index 69980a72f1..3541df27ef 100644
---
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
+++
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
@@ -424,11 +424,12 @@ public class AnalyzeVisitor extends
StatementVisitor<Analysis, MPPQueryContext>
private List<Pair<Expression, String>> analyzeSelect(
QueryStatement queryStatement, SchemaTree schemaTree) {
List<Pair<Expression, String>> outputExpressions = new ArrayList<>();
+ boolean isGroupByLevel = queryStatement.isGroupByLevel();
ColumnPaginationController paginationController =
new ColumnPaginationController(
queryStatement.getSeriesLimit(),
queryStatement.getSeriesOffset(),
- queryStatement.isLastQuery() || queryStatement.isGroupByLevel());
+ queryStatement.isLastQuery() || isGroupByLevel);
for (ResultColumn resultColumn :
queryStatement.getSelectComponent().getResultColumns()) {
boolean hasAlias = resultColumn.hasAlias();
@@ -445,22 +446,28 @@ public class AnalyzeVisitor extends
StatementVisitor<Analysis, MPPQueryContext>
continue;
}
if (paginationController.hasCurLimit()) {
- Expression expressionWithoutAlias =
- ExpressionAnalyzer.removeAliasFromExpression(expression);
- String alias =
- !Objects.equals(expressionWithoutAlias, expression)
- ? expression.getExpressionString()
- : null;
- alias = hasAlias ? resultColumn.getAlias() : alias;
- outputExpressions.add(new Pair<>(expressionWithoutAlias, alias));
- if (queryStatement.isGroupByLevel()
- && resultColumn.getExpression() instanceof FunctionExpression) {
- queryStatement
- .getGroupByLevelComponent()
- .updateIsCountStar((FunctionExpression)
resultColumn.getExpression());
+ if (isGroupByLevel) {
+ ExpressionAnalyzer.updateTypeProvider(expression, typeProvider);
+ expression.inferTypes(typeProvider);
+ outputExpressions.add(new Pair<>(expression,
resultColumn.getAlias()));
+ if (resultColumn.getExpression() instanceof FunctionExpression) {
+ queryStatement
+ .getGroupByLevelComponent()
+ .updateIsCountStar((FunctionExpression)
resultColumn.getExpression());
+ }
+ } else {
+ Expression expressionWithoutAlias =
+ ExpressionAnalyzer.removeAliasFromExpression(expression);
+ String alias =
+ !Objects.equals(expressionWithoutAlias, expression)
+ ? expression.getExpressionString()
+ : null;
+ alias = hasAlias ? resultColumn.getAlias() : alias;
+
+ ExpressionAnalyzer.updateTypeProvider(expressionWithoutAlias,
typeProvider);
+ expressionWithoutAlias.inferTypes(typeProvider);
+ outputExpressions.add(new Pair<>(expressionWithoutAlias, alias));
}
- ExpressionAnalyzer.updateTypeProvider(expressionWithoutAlias,
typeProvider);
- expressionWithoutAlias.inferTypes(typeProvider);
paginationController.consumeLimit();
} else {
break;
@@ -681,6 +688,7 @@ public class AnalyzeVisitor extends
StatementVisitor<Analysis, MPPQueryContext>
rawPathToGroupedPathMap.putAll(groupByLevelController.getRawPathToGroupedPathMap());
Map<Expression, Set<Expression>> groupByLevelExpressions = new
LinkedHashMap<>();
+ outputExpressions.clear();
ColumnPaginationController paginationController =
new ColumnPaginationController(
queryStatement.getSeriesLimit(), queryStatement.getSeriesOffset(),
false);
@@ -690,34 +698,59 @@ public class AnalyzeVisitor extends
StatementVisitor<Analysis, MPPQueryContext>
continue;
}
if (paginationController.hasCurLimit()) {
- groupByLevelExpressions.put(
- groupedExpression,
rawGroupByLevelExpressions.get(groupedExpression));
+ Pair<Expression, String> outputExpression =
+ removeAliasFromExpression(
+ groupedExpression,
+
groupByLevelController.getAlias(groupedExpression.getExpressionString()));
+ Expression groupedExpressionWithoutAlias = outputExpression.left;
+
+ Set<Expression> rawExpressions =
rawGroupByLevelExpressions.get(groupedExpression);
+ rawExpressions.forEach(
+ expression -> ExpressionAnalyzer.updateTypeProvider(expression,
typeProvider));
+ rawExpressions.forEach(expression ->
expression.inferTypes(typeProvider));
+
+ Set<Expression> rawExpressionsWithoutAlias =
+ rawExpressions.stream()
+ .map(ExpressionAnalyzer::removeAliasFromExpression)
+ .collect(Collectors.toSet());
+ rawExpressionsWithoutAlias.forEach(
+ expression -> ExpressionAnalyzer.updateTypeProvider(expression,
typeProvider));
+ rawExpressionsWithoutAlias.forEach(expression ->
expression.inferTypes(typeProvider));
+
+ groupByLevelExpressions.put(groupedExpressionWithoutAlias,
rawExpressionsWithoutAlias);
+
+ TSDataType dataType =
+ typeProvider.getType(
+ new
ArrayList<>(groupByLevelExpressions.get(groupedExpressionWithoutAlias))
+ .get(0)
+ .getExpressionString());
+ typeProvider.setType(groupedExpression.getExpressionString(),
dataType);
+
typeProvider.setType(groupedExpressionWithoutAlias.getExpressionString(),
dataType);
+ outputExpressions.add(outputExpression);
paginationController.consumeLimit();
} else {
break;
}
}
- // reset outputExpressions & transformExpressions after applying
SLIMIT/SOFFSET
- outputExpressions.clear();
- for (Expression groupedExpression : groupByLevelExpressions.keySet()) {
- TSDataType dataType =
- typeProvider.getType(
- new ArrayList<>(groupByLevelExpressions.get(groupedExpression))
- .get(0)
- .getExpressionString());
- typeProvider.setType(groupedExpression.getExpressionString(), dataType);
- outputExpressions.add(
- new Pair<>(
- groupedExpression,
-
groupByLevelController.getAlias(groupedExpression.getExpressionString())));
- }
+ // reset transformExpressions after applying SLIMIT/SOFFSET
transformExpressions.clear();
transformExpressions.addAll(
groupByLevelExpressions.values().stream().flatMap(Set::stream).collect(Collectors.toSet()));
return groupByLevelExpressions;
}
+ private Pair<Expression, String> removeAliasFromExpression(
+ Expression rawExpression, String rawAlias) {
+ Expression expressionWithoutAlias =
ExpressionAnalyzer.removeAliasFromExpression(rawExpression);
+ String alias =
+ !Objects.equals(expressionWithoutAlias, rawExpression)
+ ? rawExpression.getExpressionString()
+ : null;
+ alias = rawAlias == null ? alias : rawAlias;
+ return new Pair<>(expressionWithoutAlias, alias);
+ }
+
private DatasetHeader analyzeOutput(
QueryStatement queryStatement, List<Pair<Expression, String>>
outputExpressions) {
boolean isIgnoreTimestamp =
diff --git
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/ExpressionAnalyzer.java
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/ExpressionAnalyzer.java
index 584849ab36..b3ddc5d2c2 100644
---
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/ExpressionAnalyzer.java
+++
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/ExpressionAnalyzer.java
@@ -983,10 +983,12 @@ public class ExpressionAnalyzer {
functionExpression.getFunctionAttributes(),
childExpressions);
} else if (expression instanceof TimeSeriesOperand) {
- MeasurementPath rawPath = (MeasurementPath) ((TimeSeriesOperand)
expression).getPath();
+ PartialPath rawPath = ((TimeSeriesOperand) expression).getPath();
if (rawPath.isMeasurementAliasExists()) {
- MeasurementPath newPath = new MeasurementPath(rawPath,
rawPath.getMeasurementSchema());
- newPath.setUnderAlignedEntity(rawPath.isUnderAlignedEntity());
+ MeasurementPath measurementPath = (MeasurementPath) rawPath;
+ MeasurementPath newPath =
+ new MeasurementPath(measurementPath,
measurementPath.getMeasurementSchema());
+ newPath.setUnderAlignedEntity(measurementPath.isUnderAlignedEntity());
return new TimeSeriesOperand(newPath);
}
return expression;
diff --git
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/GroupByLevelController.java
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/GroupByLevelController.java
index a583805e33..4f8da81f15 100644
---
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/GroupByLevelController.java
+++
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/GroupByLevelController.java
@@ -23,6 +23,7 @@ import org.apache.iotdb.commons.conf.IoTDBConstant;
import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.db.exception.sql.SemanticException;
import org.apache.iotdb.db.exception.sql.StatementAnalyzeException;
+import org.apache.iotdb.db.metadata.path.MeasurementPath;
import org.apache.iotdb.db.mpp.plan.expression.Expression;
import org.apache.iotdb.db.mpp.plan.expression.leaf.TimeSeriesOperand;
import org.apache.iotdb.db.mpp.plan.expression.multi.FunctionExpression;
@@ -81,7 +82,7 @@ public class GroupByLevelController {
}
PartialPath rawPath = ((TimeSeriesOperand)
expression.getExpressions().get(0)).getPath();
- PartialPath groupedPath = generatePartialPathByLevel(isCountStar,
rawPath.getNodes(), levels);
+ PartialPath groupedPath = generatePartialPathByLevel(isCountStar, rawPath,
levels);
checkDatatypeConsistency(
groupedPath.getFullPath(), ((FunctionExpression)
expression).getFunctionName(), rawPath);
@@ -179,7 +180,8 @@ public class GroupByLevelController {
* @return result partial path
*/
public PartialPath generatePartialPathByLevel(
- boolean isCountStar, String[] nodes, int[] pathLevels) {
+ boolean isCountStar, PartialPath rawPath, int[] pathLevels) {
+ String[] nodes = rawPath.getNodes();
Set<Integer> levelSet = new HashSet<>();
for (int level : pathLevels) {
levelSet.add(level);
@@ -200,7 +202,15 @@ public class GroupByLevelController {
} else {
transformedNodes.add(nodes[nodes.length - 1]);
}
- return new PartialPath(transformedNodes.toArray(new String[0]));
+
+ MeasurementPath groupedPath =
+ new MeasurementPath(
+ new PartialPath(transformedNodes.toArray(new String[0])),
+ ((MeasurementPath) rawPath).getMeasurementSchema());
+ if (rawPath.isMeasurementAliasExists()) {
+ groupedPath.setMeasurementAlias(rawPath.getMeasurementAlias());
+ }
+ return groupedPath;
}
public Map<Expression, Set<Expression>> getGroupedPathMap() {
diff --git
a/server/src/main/java/org/apache/iotdb/db/qp/utils/GroupByLevelController.java
b/server/src/main/java/org/apache/iotdb/db/qp/utils/GroupByLevelController.java
index 781838c88b..0261b0a3b6 100644
---
a/server/src/main/java/org/apache/iotdb/db/qp/utils/GroupByLevelController.java
+++
b/server/src/main/java/org/apache/iotdb/db/qp/utils/GroupByLevelController.java
@@ -22,14 +22,15 @@ package org.apache.iotdb.db.qp.utils;
import org.apache.iotdb.commons.conf.IoTDBConstant;
import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.db.exception.query.LogicalOptimizeException;
+import org.apache.iotdb.db.metadata.path.MeasurementPath;
import org.apache.iotdb.db.mpp.plan.expression.Expression;
import org.apache.iotdb.db.mpp.plan.expression.ResultColumn;
import org.apache.iotdb.db.mpp.plan.expression.multi.FunctionExpression;
import org.apache.iotdb.db.qp.logical.crud.QueryOperator;
-import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -113,8 +114,7 @@ public class GroupByLevelController {
List<PartialPath> paths = ((FunctionExpression)
expression).getPaths();
String functionName = ((FunctionExpression)
expression).getFunctionName();
boolean isCountStar = countWildcardIterIndices.contains(idx++);
- String groupedPath =
- generatePartialPathByLevel(isCountStar, paths.get(0).getNodes(),
levels);
+ String groupedPath = generatePartialPathByLevel(isCountStar,
paths.get(0), levels);
String rawPath = String.format("%s(%s)", functionName,
paths.get(0).getFullPath());
String pathWithFunction = String.format("%s(%s)", functionName,
groupedPath);
@@ -207,28 +207,39 @@ public class GroupByLevelController {
*
* @return result partial path
*/
- public String generatePartialPathByLevel(boolean isCountStar, String[]
nodes, int[] pathLevels) {
+ public String generatePartialPathByLevel(
+ boolean isCountStar, PartialPath rawPath, int[] pathLevels) {
+ String[] nodes = rawPath.getNodes();
Set<Integer> levelSet = new HashSet<>();
for (int level : pathLevels) {
levelSet.add(level);
}
- StringBuilder transformedPath = new StringBuilder();
- transformedPath.append(nodes[0]).append(TsFileConstant.PATH_SEPARATOR);
+ List<String> transformedNodes = new ArrayList<>(nodes.length);
+
+ transformedNodes.add(nodes[0]);
for (int k = 1; k < nodes.length - 1; k++) {
if (levelSet.contains(k)) {
- transformedPath.append(nodes[k]);
+ transformedNodes.add(nodes[k]);
} else {
- transformedPath.append(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD);
+ transformedNodes.add(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD);
}
- transformedPath.append(TsFileConstant.PATH_SEPARATOR);
}
if (isCountStar) {
- transformedPath.append(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD);
+ transformedNodes.add(IoTDBConstant.ONE_LEVEL_PATH_WILDCARD);
} else {
- transformedPath.append(nodes[nodes.length - 1]);
+ transformedNodes.add(nodes[nodes.length - 1]);
+ }
+
+ MeasurementPath groupedPath =
+ new MeasurementPath(
+ new PartialPath(transformedNodes.toArray(new String[0])),
+ ((MeasurementPath) rawPath).getMeasurementSchema());
+ if (rawPath.isMeasurementAliasExists()) {
+ groupedPath.setMeasurementAlias(rawPath.getMeasurementAlias());
+ return groupedPath.getFullPathWithAlias();
}
- return transformedPath.toString();
+ return groupedPath.getFullPath();
}
public void serialize(ByteBuffer byteBuffer) {