Class DruidSqlParserUtils

java.lang.Object
org.apache.druid.sql.calcite.parser.DruidSqlParserUtils

public class DruidSqlParserUtils extends Object
  • Field Details

  • Constructor Details

    • DruidSqlParserUtils

      public DruidSqlParserUtils()
  • Method Details

    • convertSqlNodeToGranularity

      @Nullable public static Granularity convertSqlNodeToGranularity(org.apache.calcite.sql.SqlNode sqlNode)
      This method is used to extract the granularity from a SqlNode which represents the argument to the PARTITIONED BY clause. The node can be any of the following:
      • A literal with a string that matches the SQL keywords from DOCUMENTED_GRANULARITIES
      • A literal string with a period in ISO 8601 format.
      • Function call: FLOOR(__time TO TimeUnit)
      • Function call: TIME_FLOOR(__time, 'PT1H')}

      Validation of the function sqlNode is contingent to following conditions:

      1. sqlNode is an instance of SqlCall
      2. Operator is either one of TIME_FLOOR or FLOOR
      3. Number of operands in the call are 2
      4. First operand is a SimpleIdentifier representing __time
      5. If operator is TIME_FLOOR, the second argument is a literal, and can be converted to the Granularity class
      6. If operator is FLOOR, the second argument is a TimeUnit, and can be mapped using TimeUnits

      This method is called during validation, which will catch any errors. It is then called again during conversion, at which time we assume the node is valid.

      Parameters:
      sqlNode - SqlNode representing a call to a function
      Returns:
      Granularity as intended by the function call
      Throws:
      DruidException - if SqlNode cannot be converted to a granularity
    • validateQueryAndConvertToIntervals

      public static List<String> validateQueryAndConvertToIntervals(org.apache.calcite.sql.SqlNode replaceTimeQuery, Granularity granularity, org.joda.time.DateTimeZone dateTimeZone)
      Validates and converts a SqlNode representing a query into an optimized list of intervals to be used in creating an ingestion spec. If the sqlNode is an SqlLiteral of ALL, returns a singleton list of "ALL". Otherwise, it converts and optimizes the query using MoveTimeFiltersToIntervals into a list of intervals which contain all valid values of time as per the query.

      The following validations are performed 1. Only __time column and timestamp literals are present in the query 2. The interval after optimization is not empty 3. The operands in the expression are supported 4. The intervals after adjusting for timezone are aligned with the granularity parameter

      Parameters:
      replaceTimeQuery - Sql node representing the query
      granularity - granularity of the query for validation
      dateTimeZone - timezone
      Returns:
      List of string representation of intervals
      Throws:
      DruidException - if the SqlNode cannot be converted to a list of intervals
    • convertClusterByToOrderBy

      public static org.apache.calcite.sql.SqlOrderBy convertClusterByToOrderBy(org.apache.calcite.sql.SqlNode query, org.apache.calcite.sql.SqlNodeList clusteredByList)
      Extracts and converts the information in the CLUSTERED BY clause to a new SqlOrderBy node.
      Parameters:
      query - sql query
      clusteredByList - List of clustered by columns
      Returns:
      SqlOrderBy node containing the clusteredByList information
      Throws:
      DruidException - if any of the clustered by columns contain DESCENDING order.
    • resolveClusteredByColumnsToOutputColumns

      @Nullable public static List<String> resolveClusteredByColumnsToOutputColumns(org.apache.calcite.sql.SqlNodeList clusteredByNodes, List<Map.Entry<Integer,String>> sourceFieldMappings)
      Return resolved clustered by column output names. For example, consider the following SQL:
       EXPLAIN PLAN FOR
       INSERT INTO w000
       SELECT
        TIME_PARSE("timestamp") AS __time,
        page AS page_alias,
        FLOOR("cost"),
        country,
        citName
       FROM ...
       PARTITIONED BY DAY
       CLUSTERED BY 1, 2, 3, cityName
       

      The function will return the following clusteredBy columns for the above SQL: ["__time", "page_alias", "FLOOR(\"cost\")", cityName"]. Any ordinal and expression specified in the CLUSTERED BY clause will resolve to the final output column name.

      This function must be called after the query is prepared when all the validations are complete, including validateClusteredByColumns(org.apache.calcite.sql.SqlNodeList), so we can safely access the arguments.

      Parameters:
      clusteredByNodes - List of SqlNodes representing columns to be clustered by.
      sourceFieldMappings - The source field output mappings extracted from the validated root query rel node post prepare phase.
    • validateClusteredByColumns

      public static void validateClusteredByColumns(org.apache.calcite.sql.SqlNodeList clusteredByNodes)
      Validates the clustered by columns to ensure that it does not contain DESCENDING order columns.
      Parameters:
      clusteredByNodes - List of SqlNodes representing columns to be clustered by.
    • parseColumnName

      public static String parseColumnName(org.apache.calcite.sql.SqlNode sqlNode)
      Converts a SqlNode identifier into a string representation
      Parameters:
      sqlNode - the SQL node
      Returns:
      string representing the column name
      Throws:
      DruidException - if the SQL node is not an SqlIdentifier
    • validateSupportedGranularityForPartitionedBy

      public static void validateSupportedGranularityForPartitionedBy(@Nullable org.apache.calcite.sql.SqlNode originalNode, Granularity granularity)
    • problemParsing

      public static DruidException problemParsing(String message)
    • invalidParameterTypeException

      public static DruidException invalidParameterTypeException(String functionName, String parameterName, String expectedType, @Nullable Object actualValue)
      Creates a DruidException for invalid SQL function parameter types.
      Parameters:
      functionName - the SQL function name (e.g., "SPECTATOR_PERCENTILE")
      parameterName - the parameter name
      expectedType - the expected type
      actualValue - the value provided needed to determine type
      Returns:
      DruidException with INVALID_INPUT category and USER persona
    • getNumericLiteral

      public static Number getNumericLiteral(@Nullable Object value, String functionName, String parameterName)
      Validates and returns a numeric value from a RexLiteral, or throws invalidParameterTypeException if invalid.
      Parameters:
      value - the value extracted from RexLiteral.value()
      functionName - the SQL function name
      parameterName - the parameter name
      Returns:
      the value as a Number
      Throws:
      DruidException - if value is not a Number