in iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/QueryStatement.java [611:804]
public void semanticCheck() {
if (hasModelInference) {
if (isAlignByDevice()) {
throw new SemanticException("Model inference does not support align by device now.");
}
if (isSelectInto()) {
throw new SemanticException("Model inference does not support select into now.");
}
}
if (isAggregationQuery()) {
if (groupByComponent != null && isGroupByLevel()) {
throw new SemanticException("GROUP BY CLAUSES doesn't support GROUP BY LEVEL now.");
}
if (isGroupByLevel() && isAlignByDevice()) {
throw new SemanticException("GROUP BY LEVEL does not support align by device now.");
}
if (isGroupByTag() && isAlignByDevice()) {
throw new SemanticException("GROUP BY TAGS does not support align by device now.");
}
Set<String> outputColumn = new HashSet<>();
for (ResultColumn resultColumn : selectComponent.getResultColumns()) {
if (resultColumn.getColumnType() != ResultColumn.ColumnType.AGGREGATION) {
throw new SemanticException(RAW_AGGREGATION_HYBRID_QUERY_ERROR_MSG);
}
String expressionString = resultColumn.getExpression().getExpressionString();
if (expressionString.toLowerCase().contains(COUNT_TIME)) {
checkCountTimeValidationInSelect(
resultColumn.getExpression(), outputColumn, selectComponent.getResultColumns());
}
outputColumn.add(
resultColumn.getAlias() != null ? resultColumn.getAlias() : expressionString);
}
for (Expression expression : getExpressionSortItemList()) {
if (!hasAggregationFunction(expression)) {
throw new SemanticException(RAW_AGGREGATION_HYBRID_QUERY_ERROR_MSG);
}
}
if (isGroupByTag()) {
if (hasHaving()) {
throw new SemanticException("Having clause is not supported yet in GROUP BY TAGS query");
}
for (String s : getGroupByTagComponent().getTagKeys()) {
if (outputColumn.contains(s)) {
throw new SemanticException("Output column is duplicated with the tag key: " + s);
}
}
if (rowLimit > 0 || rowOffset > 0 || seriesLimit > 0 || seriesOffset > 0) {
throw new SemanticException("Limit or slimit are not supported yet in GROUP BY TAGS");
}
for (ResultColumn resultColumn : selectComponent.getResultColumns()) {
Expression expression = resultColumn.getExpression();
if (!(expression instanceof FunctionExpression
&& expression.getExpressions().get(0) instanceof TimeSeriesOperand
&& expression.isAggregationFunctionExpression())) {
throw new SemanticException(
expression + " can't be used in group by tag. It will be supported in the future.");
}
}
}
if (hasGroupByExpression()) {
// Aggregation expression shouldn't exist in group by clause.
List<Expression> aggregationExpression =
ExpressionAnalyzer.searchAggregationExpressions(
groupByComponent.getControlColumnExpression());
if (aggregationExpression != null && !aggregationExpression.isEmpty()) {
throw new SemanticException("Aggregation expression shouldn't exist in group by clause");
}
}
} else {
if (isGroupBy() || isGroupByLevel() || isGroupByTag()) {
throw new SemanticException(
"Common queries and aggregated queries are not allowed to appear at the same time");
}
for (Expression expression : getExpressionSortItemList()) {
if (hasAggregationFunction(expression)) {
throw new SemanticException(RAW_AGGREGATION_HYBRID_QUERY_ERROR_MSG);
}
}
}
if (hasWhere()) {
Expression whereExpression = getWhereCondition().getPredicate();
if (ExpressionAnalyzer.identifyOutputColumnType(whereExpression, true)
== ResultColumn.ColumnType.AGGREGATION) {
throw new SemanticException("aggregate functions are not supported in WHERE clause");
}
}
if (hasHaving()) {
Expression havingExpression = getHavingCondition().getPredicate();
if (ExpressionAnalyzer.identifyOutputColumnType(havingExpression, true)
!= ResultColumn.ColumnType.AGGREGATION) {
throw new SemanticException("Expression of HAVING clause must to be an Aggregation");
}
if (!isAggregationQuery()) {
throw new SemanticException(
"Expression of HAVING clause can not be used in NonAggregationQuery");
}
if (havingExpression.toString().toLowerCase().contains(COUNT_TIME)
&& (!new CountTimeAggregationAmountVisitor().process(havingExpression, null).isEmpty())) {
throw new SemanticException(COUNT_TIME_NOT_SUPPORT_USE_WITH_HAVING);
}
try {
if (isGroupByLevel()) {
// check path in SELECT and HAVING only have one node
for (ResultColumn resultColumn : getSelectComponent().getResultColumns()) {
ExpressionAnalyzer.checkIsAllMeasurement(resultColumn.getExpression());
}
ExpressionAnalyzer.checkIsAllMeasurement(havingExpression);
}
} catch (SemanticException e) {
throw new SemanticException("When Having used with GroupByLevel: " + e.getMessage());
}
}
if (isAlignByDevice()) {
// the paths can only be measurement or one-level wildcard in ALIGN BY DEVICE
try {
for (ResultColumn resultColumn : selectComponent.getResultColumns()) {
ExpressionAnalyzer.checkIsAllMeasurement(resultColumn.getExpression());
}
if (hasGroupByExpression()) {
ExpressionAnalyzer.checkIsAllMeasurement(
getGroupByComponent().getControlColumnExpression());
}
if (hasOrderByExpression()) {
for (Expression expression : getExpressionSortItemList()) {
ExpressionAnalyzer.checkIsAllMeasurement(expression);
}
}
if (getWhereCondition() != null) {
ExpressionAnalyzer.checkIsAllMeasurement(getWhereCondition().getPredicate());
}
if (hasHaving()) {
ExpressionAnalyzer.checkIsAllMeasurement(getHavingCondition().getPredicate());
}
} catch (SemanticException e) {
throw new SemanticException("ALIGN BY DEVICE: " + e.getMessage());
}
if (isOrderByTimeseries()) {
throw new SemanticException("Sorting by timeseries is only supported in last queries.");
}
}
if (isLastQuery()) {
if (isAlignByDevice()) {
throw new SemanticException("Last query doesn't support align by device.");
}
for (ResultColumn resultColumn : selectComponent.getResultColumns()) {
Expression expression = resultColumn.getExpression();
if (!(expression instanceof TimeSeriesOperand)) {
throw new SemanticException("Last queries can only be applied on raw time series.");
}
}
if (isOrderByDevice()) {
throw new SemanticException(
"Sorting by device is only supported in ALIGN BY DEVICE queries.");
}
if (seriesLimit != 0 || seriesOffset != 0) {
throw new SemanticException("SLIMIT and SOFFSET can not be used in LastQuery.");
}
}
if (!isAlignByDevice() && !isLastQuery()) {
if (isOrderByTimeseries()) {
throw new SemanticException("Sorting by timeseries is only supported in last queries.");
}
if (isOrderByDevice()) {
throw new SemanticException(
"Sorting by device is only supported in ALIGN BY DEVICE queries.");
}
}
if (isSelectInto()) {
if (getSeriesLimit() > 0) {
throw new SemanticException("select into: slimit clauses are not supported.");
}
if (getSeriesOffset() > 0) {
throw new SemanticException("select into: soffset clauses are not supported.");
}
if (isLastQuery()) {
throw new SemanticException("select into: last clauses are not supported.");
}
if (isGroupByTag()) {
throw new SemanticException("select into: GROUP BY TAGS clause are not supported.");
}
}
}