Skip to content

Commit

Permalink
fix the logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Beyyes committed Oct 28, 2024
1 parent ccc44e2 commit d683dda
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public class IoTDBAlignByDeviceIT {
"insert into root.vehicle.d1(timestamp,s0) values(1,999)",
"insert into root.vehicle.d1(timestamp,s0) values(1000,888)",
"insert into root.other.d1(timestamp,s0) values(2, 3.14)",
"insert into root.other.d2(timestamp,s6) values(6, 6.66)",
};

@BeforeClass
Expand Down Expand Up @@ -1184,4 +1185,48 @@ public void removeDeviceWhereMeasurementWhenNoDeviceSelectTest() {
+ e.getMessage());
}
}

@Test
public void nonExistMeasurementInHavingTest() {
String[] retArray =
new String[] {
"1,root.other.d1,3.14,null,", "5,root.other.d2,null,6.66,",
};

try (Connection connection = EnvFactory.getEnv().getConnection();
Statement statement = connection.createStatement()) {

try (ResultSet resultSet =
statement.executeQuery(
"select last_value(s0),last_value(s6) from root.other.** group by ([1,10),2ms) having last_value(s0) is not null or last_value(s6) is not null align by device")) {
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
List<Integer> actualIndexToExpectedIndexList =
checkHeader(
resultSetMetaData,
"Time,Device,last_value(s0),last_value(s6)",
new int[] {
Types.TIMESTAMP, Types.VARCHAR, Types.FLOAT, Types.DOUBLE,
});

int cnt = 0;
while (resultSet.next()) {
String[] expectedStrings = retArray[cnt].split(",");
StringBuilder expectedBuilder = new StringBuilder();
StringBuilder actualBuilder = new StringBuilder();
for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
actualBuilder.append(resultSet.getString(i)).append(",");
expectedBuilder
.append(expectedStrings[actualIndexToExpectedIndexList.get(i - 1)])
.append(",");
}
Assert.assertEquals(expectedBuilder.toString(), actualBuilder.toString());
cnt++;
}
Assert.assertEquals(retArray.length, cnt);
}
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
import org.apache.iotdb.db.queryengine.plan.expression.leaf.ConstantOperand;
import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimeSeriesOperand;
import org.apache.iotdb.db.queryengine.plan.expression.multi.FunctionExpression;
import org.apache.iotdb.db.queryengine.plan.expression.visitor.ExistUnknownTypeInExpression;
import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner;
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metadata.write.MeasurementGroup;
import org.apache.iotdb.db.queryengine.plan.planner.plan.parameter.DeviceViewIntoPathDescriptor;
Expand Down Expand Up @@ -210,6 +211,7 @@
import static org.apache.iotdb.db.queryengine.plan.analyze.AnalyzeUtils.validateSchema;
import static org.apache.iotdb.db.queryengine.plan.analyze.ExpressionAnalyzer.bindSchemaForExpression;
import static org.apache.iotdb.db.queryengine.plan.analyze.ExpressionAnalyzer.concatDeviceAndBindSchemaForExpression;
import static org.apache.iotdb.db.queryengine.plan.analyze.ExpressionAnalyzer.concatDeviceAndBindSchemaForHaving;
import static org.apache.iotdb.db.queryengine.plan.analyze.ExpressionAnalyzer.getMeasurementExpression;
import static org.apache.iotdb.db.queryengine.plan.analyze.ExpressionAnalyzer.normalizeExpression;
import static org.apache.iotdb.db.queryengine.plan.analyze.ExpressionAnalyzer.searchAggregationExpressions;
Expand Down Expand Up @@ -1074,8 +1076,7 @@ private void analyzeHaving(

for (PartialPath device : deviceSet) {
List<Expression> expressionsInHaving =
concatDeviceAndBindSchemaForExpression(
havingExpression, device, schemaTree, queryContext);
concatDeviceAndBindSchemaForHaving(havingExpression, device, schemaTree, queryContext);

conJunctions.addAll(
expressionsInHaving.stream()
Expand All @@ -1091,6 +1092,10 @@ private void analyzeHaving(
analyzeExpressionType(analysis, aggregationExpression);
analyzeExpressionType(analysis, normalizedAggregationExpression);

if (!new ExistUnknownTypeInExpression().process(aggregationExpression, null).isEmpty()) {
continue;
}

aggregationExpressions.add(aggregationExpression);
normalizedAggregationExpressions.add(normalizedAggregationExpression);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.BindSchemaForExpressionVisitor;
import org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.BindSchemaForPredicateVisitor;
import org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.ConcatDeviceAndBindSchemaForExpressionVisitor;
import org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.ConcatDeviceAndBindSchemaForHavingVisitor;
import org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.ConcatDeviceAndBindSchemaForPredicateVisitor;
import org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.ConcatExpressionWithSuffixPathsVisitor;
import org.apache.iotdb.db.queryengine.plan.statement.component.ResultColumn;
Expand Down Expand Up @@ -490,6 +491,18 @@ public static List<Expression> concatDeviceAndBindSchemaForPredicate(
devicePath, schemaTree, isWhere, queryContext));
}

public static List<Expression> concatDeviceAndBindSchemaForHaving(
final Expression predicate,
final PartialPath devicePath,
final ISchemaTree schemaTree,
final MPPQueryContext queryContext) {
return new ConcatDeviceAndBindSchemaForHavingVisitor()
.process(
predicate,
new ConcatDeviceAndBindSchemaForHavingVisitor.Context(
devicePath, schemaTree, queryContext));
}

/**
* Search for subexpressions that can be queried natively, including all time series.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
import java.util.stream.Collectors;

import static org.apache.iotdb.db.queryengine.plan.expression.ExpressionType.BETWEEN;
import static org.apache.tsfile.enums.TSDataType.UNKNOWN;

/** Responsible for constructing {@link ColumnTransformer} through Expression. */
public class ColumnTransformerVisitor
Expand Down Expand Up @@ -584,7 +585,16 @@ public TSDataType getType(Expression expression) {
if (typeProvider != null) {
return typeProvider.getTreeModelType(expression.getOutputSymbol());
}
return expressionTypes.get(NodeRef.of(expression));
if (expressionTypes.get(NodeRef.of(expression)) != UNKNOWN) {
return expressionTypes.get(NodeRef.of(expression));
} else {
for (Map.Entry<NodeRef<Expression>, TSDataType> entry : expressionTypes.entrySet()) {
if (entry.getKey().getNode().equals(expression) && entry.getValue() != UNKNOWN) {
return entry.getValue();
}
}
return UNKNOWN;
}
}

public TypeProvider getTypeProvider() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.iotdb.db.queryengine.plan.expression.visitor;

import org.apache.iotdb.db.queryengine.plan.expression.Expression;
import org.apache.iotdb.db.queryengine.plan.expression.leaf.LeafOperand;
import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimeSeriesOperand;
import org.apache.iotdb.db.queryengine.plan.expression.multi.FunctionExpression;

import org.apache.tsfile.enums.TSDataType;

import java.util.Collections;
import java.util.List;

public class ExistUnknownTypeInExpression extends CollectVisitor {

@Override
public List<Expression> visitLeafOperand(LeafOperand leafOperand, Void context) {
return Collections.emptyList();
}

@Override
public List<Expression> visitFunctionExpression(
FunctionExpression functionExpression, Void context) {
List<List<Expression>> ret = getResultsFromChild(functionExpression, null);
for (List<Expression> row : ret) {
if (!row.isEmpty()) {
return row;
}
}
return Collections.emptyList();
}

@Override
public List<Expression> visitTimeSeriesOperand(
TimeSeriesOperand timeSeriesOperand, Void context) {
if (timeSeriesOperand.getPath().getSeriesType() == TSDataType.UNKNOWN) {
return Collections.singletonList(timeSeriesOperand);
}

return Collections.emptyList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian;

import org.apache.iotdb.commons.path.MeasurementPath;
import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.db.exception.sql.SemanticException;
import org.apache.iotdb.db.queryengine.plan.analyze.ExpressionUtils;
import org.apache.iotdb.db.queryengine.plan.expression.Expression;
import org.apache.iotdb.db.queryengine.plan.expression.leaf.TimeSeriesOperand;

import org.apache.tsfile.enums.TSDataType;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static org.apache.iotdb.db.queryengine.plan.expression.visitor.cartesian.BindSchemaForExpressionVisitor.transformViewPath;

public class ConcatDeviceAndBindSchemaForHavingVisitor
extends ConcatDeviceAndBindSchemaForExpressionVisitor {
@Override
public List<Expression> visitTimeSeriesOperand(
TimeSeriesOperand timeSeriesOperand, Context context) {
PartialPath measurement = timeSeriesOperand.getPath();
PartialPath concatPath = context.getDevicePath().concatPath(measurement);

List<MeasurementPath> actualPaths =
context.getSchemaTree().searchMeasurementPaths(concatPath).left;
if (actualPaths.isEmpty()) {
return Collections.singletonList(
new TimeSeriesOperand(new MeasurementPath(concatPath, TSDataType.UNKNOWN)));
}

List<MeasurementPath> nonViewActualPaths = new ArrayList<>();
List<MeasurementPath> viewPaths = new ArrayList<>();
for (MeasurementPath measurementPath : actualPaths) {
if (measurementPath.getMeasurementSchema().isLogicalView()) {
viewPaths.add(measurementPath);
} else {
nonViewActualPaths.add(measurementPath);
}
}
List<Expression> reconstructTimeSeriesOperands =
ExpressionUtils.reconstructTimeSeriesOperandsWithMemoryCheck(
timeSeriesOperand, nonViewActualPaths, context.getQueryContext());
// handle logical views
for (MeasurementPath measurementPath : viewPaths) {
Expression replacedExpression = transformViewPath(measurementPath, context.getSchemaTree());
if (!(replacedExpression instanceof TimeSeriesOperand)) {
throw new SemanticException(
"Only writable view timeseries are supported in ALIGN BY DEVICE queries.");
}

replacedExpression.setViewPath(measurementPath);
reconstructTimeSeriesOperands.add(replacedExpression);
}
return reconstructTimeSeriesOperands;
}
}

0 comments on commit d683dda

Please sign in to comment.