public void semanticCheck()

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.");
      }
    }
  }