content: /*
   * 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.calcite.sql;
  
  import com.google.common.collect.Sets;
  
  import org.apiguardian.api.API;
  
  import java.util.Collection;
  import java.util.EnumSet;
  import java.util.Locale;
  import java.util.Set;
  
  /**
   * Enumerates the possible types of {@link SqlNode}.
   *
   * <p>The values are immutable, canonical constants, so you can use Kinds to
   * find particular types of expressions quickly. To identify a call to a common
   * operator such as '=', use {@link org.apache.calcite.sql.SqlNode#isA}:
   *
   * <blockquote>
   * exp.{@link org.apache.calcite.sql.SqlNode#isA isA}({@link #EQUALS})
   * </blockquote>
   *
   * <p>Only commonly-used nodes have their own type; other nodes are of type
   * {@link #OTHER}. Some of the values, such as {@link #SET_QUERY}, represent
   * aggregates.
   *
   * <p>To quickly choose between a number of options, use a switch statement:
   *
   * <blockquote>
   * <pre>switch (exp.getKind()) {
   * case {@link #EQUALS}:
   *     ...;
   * case {@link #NOT_EQUALS}:
   *     ...;
   * default:
   *     throw new AssertionError("unexpected");
   * }</pre>
   * </blockquote>
   *
   * <p>Note that we do not even have to check that a {@code SqlNode} is a
   * {@link SqlCall}.
   *
   * <p>To identify a category of expressions, use {@code SqlNode.isA} with
   * an aggregate SqlKind. The following expression will return <code>true</code>
   * for calls to '=' and '&gt;=', but <code>false</code> for the constant '5', or
   * a call to '+':
   *
   * <blockquote>
   * <pre>exp.isA({@link #COMPARISON SqlKind.COMPARISON})</pre>
   * </blockquote>
   *
   * <p>RexNode also has a {@code getKind} method; {@code SqlKind} values are
   * preserved during translation from {@code SqlNode} to {@code RexNode}, where
   * applicable.
   *
   * <p>There is no water-tight definition of "common", but that's OK. There will
   * always be operators that don't have their own kind, and for these we use the
   * {@code SqlOperator}. But for really the common ones, e.g. the many places
   * where we are looking for {@code AND}, {@code OR} and {@code EQUALS}, the enum
   * helps.
   *
   * <p>(If we were using Scala, {@link SqlOperator} would be a case
   * class, and we wouldn't need {@code SqlKind}. But we're not.)
   */
  public enum SqlKind {
    //~ Static fields/initializers ---------------------------------------------
  
    // the basics
  
    /**
     * Expression not covered by any other {@link SqlKind} value.
     *
     * @see #OTHER_FUNCTION
     */
    OTHER,
  
    /**
     * SELECT statement or sub-query.
     */
    SELECT,
  
    /**
     * Sql Hint statement.
     */
    HINT,
  
    /**
     * Table reference.
     */
    TABLE_REF,
  
    /**
     * JOIN operator or compound FROM clause.
     *
     * <p>A FROM clause with more than one table is represented as if it were a
     * join. For example, "FROM x, y, z" is represented as
     * "JOIN(x, JOIN(x, y))".
     */
    JOIN,
  
    /** An identifier. */
    IDENTIFIER,
  
    /** A literal. */
    LITERAL,
  
    /** Interval qualifier. */
    INTERVAL_QUALIFIER,
  
    /**
     * Function that is not a special function.
     *
     * @see #FUNCTION
     */
    OTHER_FUNCTION,
  
    /**
     * Input tables have either row semantics or set semantics.
     * <ul>
     * <li>Row semantics means that the result of the table function is
     * decided on a row-by-row basis.
     * <li>Set semantics means that the outcome of the function depends on how
     * the data is partitioned.
     * When the table function is called from a query, the table parameter can
     * optionally be extended with either a PARTITION BY clause or
     * an ORDER BY clause or both.
     * </ul>
     */
    SET_SEMANTICS_TABLE,
  
    /** {@code CONVERT} function. */
    CONVERT,
  
    /** Oracle's {@code CONVERT} function. */
    CONVERT_ORACLE,
  
    /** {@code TRANSLATE} function. */
    TRANSLATE,
  
    /** POSITION function. */
    POSITION,
  
    /** EXPLAIN statement. */
    EXPLAIN,
  
    /** DESCRIBE SCHEMA statement. */
    DESCRIBE_SCHEMA,
  
    /** DESCRIBE TABLE statement. */
    DESCRIBE_TABLE,
  
    /** INSERT statement. */
    INSERT,
  
    /** DELETE statement. */
    DELETE,
  
    /** UPDATE statement. */
    UPDATE,
  
    /** "{@code ALTER scope SET option = value}" statement. */
    SET_OPTION,
  
    /** A dynamic parameter. */
    DYNAMIC_PARAM,
  
    /** The DISTINCT keyword of the GROUP BY clause. */
    GROUP_BY_DISTINCT,
  
    /**
     * ORDER BY clause.
     *
     * @see #DESCENDING
     * @see #NULLS_FIRST
     * @see #NULLS_LAST
     */
    ORDER_BY,
  
    /** WITH clause. */
    WITH,
  
    /** Item in WITH clause. */
    WITH_ITEM,
  
    /** Represents a recursive CTE as a table ref. */
    WITH_ITEM_TABLE_REF,
  
    /** Item expression. */
    ITEM,
  
    /** {@code UNION} relational operator. */
    UNION,
  
    /** {@code EXCEPT} relational operator (known as {@code MINUS} in some SQL
     * dialects). */
    EXCEPT,
  
    /** {@code INTERSECT} relational operator. */
    INTERSECT,
  
    /** {@code AS} operator. */
    AS,
  
    /** {@code MEASURE} operator. */
    MEASURE,
  
    /** {@code V2M} (value-to-measure) internal operator. */
    V2M,
  
    /** {@code M2V} (measure-to-value) internal operator. */
    M2V,
  
    /** {@code M2X} (evaluate measure in context) internal operator. */
    M2X,
  
    /** {@code AGG_M2M} (aggregate measure to measure) internal aggregate
     * function. */
    AGG_M2M,
  
    /** {@code AGG_M2V} (aggregate measure to value) internal aggregate
     * function. */
    AGG_M2V,
  
    /** {@code SAME_PARTITION} pseudo-function. */
    SAME_PARTITION,
  
    /** Argument assignment operator, {@code =>}. */
    ARGUMENT_ASSIGNMENT,
  
    /** {@code DEFAULT} operator. */
    DEFAULT,
  
    /** {@code OVER} operator. */
    OVER,
  
    /** {@code RESPECT NULLS} operator. */
    RESPECT_NULLS("RESPECT NULLS"),
  
    /** {@code IGNORE NULLS} operator. */
    IGNORE_NULLS("IGNORE NULLS"),
  
    /** {@code FILTER} operator. */
    FILTER,
  
    /** {@code WITHIN GROUP} operator. */
    WITHIN_GROUP,
  
    /** {@code WITHIN DISTINCT} operator. */
    WITHIN_DISTINCT,
  
    /** Window specification. */
    WINDOW,
  
    /** MERGE statement. */
    MERGE,
  
    /** TABLESAMPLE relational operator. */
    TABLESAMPLE,
  
    /** PIVOT clause. */
    PIVOT,
  
    /** UNPIVOT clause. */
    UNPIVOT,
  
    /** MATCH_RECOGNIZE clause. */
    MATCH_RECOGNIZE,
  
    /** SNAPSHOT operator. */
    SNAPSHOT,
  
    // binary operators
  
    /** Arithmetic multiplication operator, "*". */
    TIMES,
  
    /** Arithmetic division operator, "/". */
    DIVIDE,
  
    /** Arithmetic remainder operator, "MOD" (and "%" in some dialects). */
    MOD,
  
    /**
     * Arithmetic plus operator, "+".
     *
     * @see #PLUS_PREFIX
     */
    PLUS,
  
    /**
     * Arithmetic minus operator, "-".
     *
     * @see #MINUS_PREFIX
     */
    MINUS,
  
    /**
     * Checked version of PLUS, which produces a runtime error on overflow.
     * Not used for date/time arithmetic.
     */
    CHECKED_PLUS,
  
    /**
     * Checked version of MINUS, which produces a runtime error on overflow.
     * Not used for date/time arithmetic.
     */
    CHECKED_MINUS,
  
    /**
     * Checked version of TIMES, which produces a runtime error on overflow.
     * Not used for date/time arithmetic.
     */
    CHECKED_TIMES,
  
    /**
     * Checked version of DIVIDE, which produces a runtime error on overflow.
     * For example, INT_MIN / -1.
     * Not used for date/time arithmetic.
     */
    CHECKED_DIVIDE,
  
    /**
     * Alternation operator in a pattern expression within a
     * {@code MATCH_RECOGNIZE} clause.
     */
    PATTERN_ALTER,
  
    /**
     * Concatenation operator in a pattern expression within a
     * {@code MATCH_RECOGNIZE} clause.
     */
    PATTERN_CONCAT,
  
    // comparison operators
  
    /** {@code IN} operator. */
    IN,
  
    /**
     * {@code NOT IN} operator.
     *
     * <p>Only occurs in SqlNode trees. Is expanded to NOT(IN ...) before
     * entering RelNode land.
     */
    NOT_IN("NOT IN"),
  
    /** Variant of {@code IN} for the Druid adapter. */
    DRUID_IN,
  
    /** Variant of {@code NOT_IN} for the Druid adapter. */
    DRUID_NOT_IN,
  
    /** Less-than operator, "&lt;". */
    LESS_THAN("<"),
  
    /** Greater-than operator, "&gt;". */
    GREATER_THAN(">"),
  
    /** Less-than-or-equal operator, "&lt;=". */
    LESS_THAN_OR_EQUAL("<="),
  
    /** Greater-than-or-equal operator, "&gt;=". */
    GREATER_THAN_OR_EQUAL(">="),
  
    /** Equals operator, "=". */
    EQUALS("="),
  
    /**
     * Not-equals operator, "&#33;=" or "&lt;&gt;".
     * The latter is standard, and preferred.
     */
    NOT_EQUALS("<>"),
  
    /** {@code IS DISTINCT FROM} operator. */
    IS_DISTINCT_FROM,
  
    /** {@code IS NOT DISTINCT FROM} operator. */
    IS_NOT_DISTINCT_FROM,
  
    /** {@code SEARCH} operator. (Analogous to scalar {@code IN}, used only in
     * RexNode, not SqlNode.) */
    SEARCH,
  
    /** Logical "OR" operator. */
    OR,
  
    /** Logical "AND" operator. */
    AND,
  
    // other infix
  
    /** Dot. */
    DOT,
  
    /** {@code OVERLAPS} operator for periods. */
    OVERLAPS,
  
    /** {@code CONTAINS} operator for periods. */
    CONTAINS,
  
    /** {@code PRECEDES} operator for periods. */
    PRECEDES,
  
    /** {@code IMMEDIATELY PRECEDES} operator for periods. */
    IMMEDIATELY_PRECEDES("IMMEDIATELY PRECEDES"),
  
    /** {@code SUCCEEDS} operator for periods. */
    SUCCEEDS,
  
    /** {@code IMMEDIATELY SUCCEEDS} operator for periods. */
    IMMEDIATELY_SUCCEEDS("IMMEDIATELY SUCCEEDS"),
  
    /** {@code EQUALS} operator for periods. */
    PERIOD_EQUALS("EQUALS"),
  
    /** {@code LIKE} operator. */
    LIKE,
  
    /** {@code RLIKE} operator. */
    RLIKE,
  
    /** {@code SIMILAR} operator. */
    SIMILAR,
  
    /** {@code ~} operator (for POSIX-style regular expressions). */
    POSIX_REGEX_CASE_SENSITIVE,
  
    /** {@code ~*} operator (for case-insensitive POSIX-style regular
     * expressions). */
    POSIX_REGEX_CASE_INSENSITIVE,
  
    /** {@code BETWEEN} operator. */
    BETWEEN,
  
    /** Variant of {@code BETWEEN} for the Druid adapter. */
    DRUID_BETWEEN,
  
    /** {@code CASE} expression. */
    CASE,
  
    /** {@code LAMBDA} expression. */
    LAMBDA,
  
    /** {@code INTERVAL} expression. */
    INTERVAL,
  
    /** {@code SEPARATOR} expression. */
    SEPARATOR,
  
    /** {@code NULLIF} operator. */
    NULLIF,
  
    /** {@code COALESCE} operator. */
    COALESCE,
  
    /** {@code DECODE} function (Oracle). */
    DECODE,
  
    /** {@code NVL} function (Oracle, Spark). */
    NVL,
  
    /** {@code NVL2} function (Oracle, Spark). */
    NVL2,
  
    /** {@code GREATEST} function (Oracle). */
    GREATEST,
  
    /** {@code GREATEST} function (PostgreSQL, Spark). */
    GREATEST_PG,
  
    /** The two-argument {@code CONCAT} function (Oracle). */
    CONCAT2,
  
    /** The {@code CONCAT} function (Postgresql and MSSQL) that ignores NULL. */
    CONCAT_WITH_NULL,
  
    /** The {@code CONCAT_WS} function (MSSQL). */
    CONCAT_WS_MSSQL,
  
    /** The {@code CONCAT_WS} function (Postgresql). */
    CONCAT_WS_POSTGRESQL,
  
  
    /** The {@code CONCAT_WS} function (Spark). */
    CONCAT_WS_SPARK,
  
    /** The "IF" function (BigQuery, Hive, Spark). */
    IF,
  
    /** {@code LEAST} function (Oracle). */
    LEAST,
  
    /** {@code LEAST} function (PostgreSQL, Spark). */
    LEAST_PG,
  
    /** {@code LOG} function. (Mysql, Spark). */
    LOG,
  
    /** {@code DATE_ADD} function (BigQuery Semantics). */
    DATE_ADD,
  
    /** {@code ADD_MONTHS} function (Oracle, Spark). */
    ADD_MONTHS,
  
    /** {@code DATE_TRUNC} function (BigQuery). */
    DATE_TRUNC,
  
    /** {@code DATE_SUB} function (BigQuery). */
    DATE_SUB,
  
    /** {@code TIME_ADD} function (BigQuery). */
    TIME_ADD,
  
    /** {@code TIME_SUB} function (BigQuery). */
    TIME_SUB,
  
    /** {@code TIMESTAMP_ADD} function (ODBC, SQL Server, MySQL). */
    TIMESTAMP_ADD,
  
    /** {@code TIMESTAMP_DIFF} function (ODBC, SQL Server, MySQL). */
    TIMESTAMP_DIFF,
  
    /** {@code TIMESTAMP_SUB} function (BigQuery). */
    TIMESTAMP_SUB,
  
    // prefix operators
  
    /** Logical {@code NOT} operator. */
    NOT,
  
    /**
     * Unary plus operator, as in "+1".
     *
     * @see #PLUS
     */
    PLUS_PREFIX,
  
    /**
     * Unary minus operator, as in "-1".
     *
     * @see #MINUS
     */
    MINUS_PREFIX,
  
    /**
     * Checked version of unary minus operator.
     */
    CHECKED_MINUS_PREFIX,
  
    /** {@code EXISTS} operator. */
    EXISTS,
  
    /** {@code SOME} quantification operator (also called {@code ANY}). */
    SOME,
  
    /** {@code ALL} quantification operator. */
    ALL,
  
    /** {@code VALUES} relational operator. */
    VALUES,
  
    /**
     * Explicit table, e.g. <code>select * from (TABLE t)</code> or <code>TABLE
     * t</code>. See also {@link #COLLECTION_TABLE}.
     */
    EXPLICIT_TABLE,
  
    /**
     * Scalar query; that is, a sub-query used in an expression context, and
     * returning one row and one column.
     */
    SCALAR_QUERY,
  
    /** Procedure call. */
    PROCEDURE_CALL,
  
    /** New specification. */
    NEW_SPECIFICATION,
  
    // special functions in MATCH_RECOGNIZE
  
    /** {@code FINAL} operator in {@code MATCH_RECOGNIZE}. */
    FINAL,
  
    /** {@code FINAL} operator in {@code MATCH_RECOGNIZE}. */
    RUNNING,
  
    /** {@code PREV} operator in {@code MATCH_RECOGNIZE}. */
    PREV,
  
    /** {@code NEXT} operator in {@code MATCH_RECOGNIZE}. */
    NEXT,
  
    /** {@code FIRST} operator in {@code MATCH_RECOGNIZE}. */
    FIRST,
  
    /** {@code LAST} operator in {@code MATCH_RECOGNIZE}. */
    LAST,
  
    /** {@code CLASSIFIER} operator in {@code MATCH_RECOGNIZE}. */
    CLASSIFIER,
  
    /** {@code MATCH_NUMBER} operator in {@code MATCH_RECOGNIZE}. */
    MATCH_NUMBER,
  
    /** {@code SKIP TO FIRST} qualifier of restarting point in a
     * {@code MATCH_RECOGNIZE} clause. */
    SKIP_TO_FIRST,
  
    /** {@code SKIP TO LAST} qualifier of restarting point in a
     * {@code MATCH_RECOGNIZE} clause. */
    SKIP_TO_LAST,
  
    // postfix operators
  
    /** {@code DESC} operator in {@code ORDER BY}. A parse tree, not a true
     * expression. */
    DESCENDING,
  
    /** {@code NULLS FIRST} clause in {@code ORDER BY}. A parse tree, not a true
     * expression. */
    NULLS_FIRST,
  
    /** {@code NULLS LAST} clause in {@code ORDER BY}. A parse tree, not a true
     * expression. */
    NULLS_LAST,
  
    /** {@code IS TRUE} operator. */
    IS_TRUE,
  
    /** {@code IS FALSE} operator. */
    IS_FALSE,
  
    /** {@code IS NOT TRUE} operator. */
    IS_NOT_TRUE,
  
    /** {@code IS NOT FALSE} operator. */
    IS_NOT_FALSE,
  
    /** {@code IS UNKNOWN} operator. */
    IS_UNKNOWN,
  
    /** {@code IS NULL} operator. */
    IS_NULL,
  
    /** {@code IS NOT NULL} operator. */
    IS_NOT_NULL,
  
    /** {@code CAST NOT NULL} operator. */
    CAST_NOT_NULL,
  
    /** {@code PRECEDING} qualifier of an interval end-point in a window
     * specification. */
    PRECEDING,
  
    /** {@code FOLLOWING} qualifier of an interval end-point in a window
     * specification. */
    FOLLOWING,
  
    /**
     * The field access operator, ".".
     *
     * <p>(Only used at the RexNode level; at
     * SqlNode level, a field-access is part of an identifier.)
     */
    FIELD_ACCESS,
  
    /**
     * Reference to an input field.
     *
     * <p>(Only used at the RexNode level.)
     */
    INPUT_REF,
  
    /**
     * Reference to an input field, with a qualified name and an identifier.
     *
     * <p>(Only used at the RexNode level.)
     */
    TABLE_INPUT_REF,
  
    /**
     * Reference to an input field, with pattern var as modifier.
     *
     * <p>(Only used at the RexNode level.)
     */
    PATTERN_INPUT_REF,
    /**
     * Reference to a sub-expression computed within the current relational
     * operator.
     *
     * <p>(Only used at the RexNode level.)
     */
    LOCAL_REF,
  
    /** Reference to lambda expression parameter.
     *
     * <p>(Only used at the RexNode level.)
     */
    LAMBDA_REF,
  
    /**
     * Reference to correlation variable.
     *
     * <p>(Only used at the RexNode level.)
     */
    CORREL_VARIABLE,
  
    /**
     * the repetition quantifier of a pattern factor in a match_recognize clause.
     */
    PATTERN_QUANTIFIER,
  
    // functions
  
    /**
     * The row-constructor function. May be explicit or implicit:
     * {@code VALUES 1, ROW (2)}.
     */
    ROW,
  
    /**
     * The non-standard constructor used to pass a
     * COLUMN_LIST parameter to a user-defined transform.
     */
    COLUMN_LIST,
  
    /**
     * The "CAST" operator, and also the PostgreSQL-style infix cast operator
     * "::".
     */
    CAST,
  
    /** The {@code SAFE_CAST} function, which is similar to {@link #CAST} but
     * returns NULL rather than throwing an error if the conversion fails. */
    SAFE_CAST,
  
    /**
     * The "NEXT VALUE OF sequence" operator.
     */
    NEXT_VALUE,
  
    /**
     * The "CURRENT VALUE OF sequence" operator.
     */
    CURRENT_VALUE,
  
    /** {@code FLOOR} function. */
    FLOOR,
  
    /** {@code CEIL} function. */
    CEIL,
  
    /** {@code TRIM} function. */
    TRIM,
  
    /** {@code LTRIM} function (Oracle). */
    LTRIM,
  
    /** {@code RTRIM} function (Oracle). */
    RTRIM,
  
    /** {@code EXTRACT} function. */
    EXTRACT,
  
    /** {@code ARRAY_APPEND} function (Spark semantics). */
    ARRAY_APPEND,
  
    /** {@code ARRAY_COMPACT} function (Spark semantics). */
    ARRAY_COMPACT,
  
    /** {@code ARRAY_CONCAT} function (BigQuery semantics). */
    ARRAY_CONCAT,
  
    /** {@code ARRAY_CONTAINS} function (Spark semantics). */
    ARRAY_CONTAINS,
  
    /** {@code ARRAY_DISTINCT} function (Spark semantics). */
    ARRAY_DISTINCT,
  
    /** {@code ARRAY_EXCEPT} function (Spark semantics). */
    ARRAY_EXCEPT,
  
    /** {@code ARRAY_INSERT} function (Spark semantics). */
    ARRAY_INSERT,
  
    /** {@code ARRAY_INTERSECT} function (Spark semantics). */
    ARRAY_INTERSECT,
  
    /** {@code ARRAY_JOIN} function (Spark semantics). */
    ARRAY_JOIN,
  
    /** {@code ARRAY_LENGTH} function (Spark semantics). */
    ARRAY_LENGTH,
  
    /** {@code ARRAY_MAX} function (Spark semantics). */
    ARRAY_MAX,
  
    /** {@code ARRAY_MIN} function (Spark semantics). */
    ARRAY_MIN,
  
    /** {@code ARRAY_POSITION} function (Spark semantics). */
    ARRAY_POSITION,
  
    /** {@code ARRAY_PREPEND} function (Spark semantics). */
    ARRAY_PREPEND,
  
    /** {@code ARRAY_REMOVE} function (Spark semantics). */
    ARRAY_REMOVE,
  
    /** {@code ARRAY_REPEAT} function (Spark semantics). */
    ARRAY_REPEAT,
  
    /** {@code ARRAY_REVERSE} function (BigQuery semantics). */
    ARRAY_REVERSE,
  
    /** {@code ARRAY_SIZE} function (Spark semantics). */
    ARRAY_SIZE,
  
    /** {@code ARRAY_SLICE} function (Hive semantics). */
    ARRAY_SLICE,
  
    /** {@code ARRAY_TO_STRING} function (BigQuery semantics). */
    ARRAY_TO_STRING,
  
    /** {@code ARRAY_UNION} function (Spark semantics). */
    ARRAY_UNION,
  
    /** {@code ARRAYS_OVERLAP} function (Spark semantics). */
    ARRAYS_OVERLAP,
  
    /** {@code ARRAYS_ZIP} function (Spark semantics). */
    ARRAYS_ZIP,
  
    /** {@code SORT_ARRAY} function (Spark semantics). */
    SORT_ARRAY,
  
    /** {@code MAP_CONCAT} function (Spark semantics). */
    MAP_CONCAT,
  
    /** {@code MAP_ENTRIES} function (Spark semantics). */
    MAP_ENTRIES,
  
    /** {@code MAP_KEYS} function (Spark semantics). */
    MAP_KEYS,
  
    /** {@code MAP_VALUES} function (Spark semantics). */
    MAP_VALUES,
  
    /** {@code MAP_CONTAINS_KEY} function (Spark semantics). */
    MAP_CONTAINS_KEY,
  
    /** {@code MAP_FROM_ARRAYS} function (Spark semantics). */
    MAP_FROM_ARRAYS,
  
    /** {@code MAP_FROM_ENTRIES} function (Spark semantics). */
    MAP_FROM_ENTRIES,
  
    /** {@code STR_TO_MAP} function (Spark semantics). */
    STR_TO_MAP,
  
    /** {@code SUBSTRING_INDEX} function (Spark semantics). */
    SUBSTRING_INDEX,
  
    /** {@code REVERSE} function (SQL Server, MySQL). */
    REVERSE,
  
    /** {@code REVERSE} function (Spark semantics). */
    REVERSE_SPARK,
  
    /** {@code SOUNDEX} function (Spark semantics). */
    SOUNDEX_SPARK,
  
    /** {@code SUBSTR} function (BigQuery semantics). */
    SUBSTR_BIG_QUERY,
  
    /** {@code SUBSTR} function (MySQL semantics). */
    SUBSTR_MYSQL,
  
    /** {@code SUBSTR} function (Oracle semantics). */
    SUBSTR_ORACLE,
  
    /** {@code SUBSTR} function (PostgreSQL semantics). */
    SUBSTR_POSTGRESQL,
  
    /** {@code CHAR_LENGTH} function. */
    CHAR_LENGTH,
  
    /** {@code ENDS_WITH} function. */
    ENDS_WITH,
  
    /** {@code STARTS_WITH} function. */
    STARTS_WITH,
  
    /** {@code STRING_TO_ARRAY} function (PostgreSQL semantics). */
    STRING_TO_ARRAY,
  
    /** Call to a function using JDBC function syntax. */
    JDBC_FN,
  
    /** {@code MULTISET} value constructor. */
    MULTISET_VALUE_CONSTRUCTOR,
  
    /** {@code MULTISET} query constructor. */
    MULTISET_QUERY_CONSTRUCTOR,
  
    /** {@code JSON} value expression. */
    JSON_VALUE_EXPRESSION,
  
    /** {@code JSON_ARRAYAGG} aggregate function. */
    JSON_ARRAYAGG,
  
    /** {@code JSON_OBJECTAGG} aggregate function. */
    JSON_OBJECTAGG,
  
    /** {@code JSON} type function. */
    JSON_TYPE,
  
    /** {@code UNNEST} operator. */
    UNNEST,
  
    /**
     * The "LATERAL" qualifier to relations in the FROM clause.
     */
    LATERAL,
  
    /**
     * Table operator which converts user-defined transform into a relation, for
     * example, <code>select * from TABLE(udx(x, y, z))</code>. See also the
     * {@link #EXPLICIT_TABLE} prefix operator.
     */
    COLLECTION_TABLE,
  
    /**
     * Array Value Constructor, e.g. {@code Array[1, 2, 3]}.
     */
    ARRAY_VALUE_CONSTRUCTOR,
  
    /**
     * Array Query Constructor, e.g. {@code Array(select deptno from dept)}.
     */
    ARRAY_QUERY_CONSTRUCTOR,
  
    /** MAP value constructor, e.g. {@code MAP ['washington', 1, 'obama', 44]}. */
    MAP_VALUE_CONSTRUCTOR,
  
    /** MAP query constructor,
     * e.g. {@code MAP (SELECT empno, deptno FROM emp)}. */
    MAP_QUERY_CONSTRUCTOR,
  
    /** {@code CURSOR} constructor, for example, <code>SELECT * FROM
     * TABLE(udx(CURSOR(SELECT ...), x, y, z))</code>. */
    CURSOR,
  
    /** {@code CONTAINS_SUBSTR} function (BigQuery semantics). */
    CONTAINS_SUBSTR,
  
    // internal operators (evaluated in validator) 200-299
  
    /** The {@code LITERAL_AGG} aggregate function that always returns the same
     * literal (even if the group is empty).
     *
     * <p>Useful during optimization because it allows you to, say, generate a
     * non-null value (to detect outer joins) in an Aggregate without an extra
     * Project. */
    LITERAL_AGG,
  
    /**
     * Literal chain operator (for composite string literals).
     * An internal operator that does not appear in SQL syntax.
     */
    LITERAL_CHAIN,
  
    /**
     * Escape operator (always part of LIKE or SIMILAR TO expression).
     * An internal operator that does not appear in SQL syntax.
     */
    ESCAPE,
  
    /**
     * The internal REINTERPRET operator (meaning a reinterpret cast).
     * An internal operator that does not appear in SQL syntax.
     */
    REINTERPRET,
  
    /** The internal {@code EXTEND} operator that qualifies a table name in the
     * {@code FROM} clause. */
    EXTEND,
  
    /** The internal {@code CUBE} operator that occurs within a {@code GROUP BY}
     * clause. */
    CUBE,
  
    /** The internal {@code ROLLUP} operator that occurs within a {@code GROUP BY}
     * clause. */
    ROLLUP,
  
    /** The internal {@code GROUPING SETS} operator that occurs within a
     * {@code GROUP BY} clause. */
    GROUPING_SETS,
  
    /** The {@code GROUPING(e, ...)} function. */
    GROUPING,
  
    // CHECKSTYLE: IGNORE 1
    /** @deprecated Use {@link #GROUPING}. */
    @Deprecated // to be removed before 2.0
    GROUPING_ID,
  
    /** The {@code GROUP_ID()} function. */
    GROUP_ID,
  
    /** The internal "permute" function in a MATCH_RECOGNIZE clause. */
    PATTERN_PERMUTE,
  
    /** The special patterns to exclude enclosing pattern from output in a
     * MATCH_RECOGNIZE clause. */
    PATTERN_EXCLUDED,
  
    // Aggregate functions
  
    /** The {@code COUNT} aggregate function. */
    COUNT,
  
    /** The {@code SUM} aggregate function. */
    SUM,
  
    /** The {@code SUM0} aggregate function. */
    SUM0,
  
    /** The {@code MIN} aggregate function. */
    MIN,
  
    /** The {@code MAX} aggregate function. */
    MAX,
  
    /** The {@code LEAD} aggregate function. */
    LEAD,
  
    /** The {@code LAG} aggregate function. */
    LAG,
  
    /** The {@code FIRST_VALUE} aggregate function. */
    FIRST_VALUE,
  
    /** The {@code LAST_VALUE} aggregate function. */
    LAST_VALUE,
  
    /** The {@code ANY_VALUE} aggregate function. */
    ANY_VALUE,
  
    /** The {@code COVAR_POP} aggregate function. */
    COVAR_POP,
  
    /** The {@code COVAR_SAMP} aggregate function. */
    COVAR_SAMP,
  
    /** The {@code REGR_COUNT} aggregate function. */
    REGR_COUNT,
  
    /** The {@code REGR_SXX} aggregate function. */
    REGR_SXX,
  
    /** The {@code REGR_SYY} aggregate function. */
    REGR_SYY,
  
    /** The {@code AVG} aggregate function. */
    AVG,
  
    /** The {@code STDDEV_POP} aggregate function. */
    STDDEV_POP,
  
    /** The {@code STDDEV_SAMP} aggregate function. */
    STDDEV_SAMP,
  
    /** The {@code VAR_POP} aggregate function. */
    VAR_POP,
  
    /** The {@code VAR_SAMP} aggregate function. */
    VAR_SAMP,
  
    /** The {@code NTILE} aggregate function. */
    NTILE,
  
    /** The {@code NTH_VALUE} aggregate function. */
    NTH_VALUE,
  
    /** The {@code LISTAGG} aggregate function. */
    LISTAGG,
  
    /** The {@code STRING_AGG} aggregate function. */
    STRING_AGG,
  
    /** The {@code COUNTIF} aggregate function. */
    COUNTIF,
  
    /** The {@code ARRAY_AGG} aggregate function. */
    ARRAY_AGG,
  
    /** The {@code ARRAY_CONCAT_AGG} aggregate function. */
    ARRAY_CONCAT_AGG,
  
    /** The {@code GROUP_CONCAT} aggregate function. */
    GROUP_CONCAT,
  
    /** The {@code COLLECT} aggregate function. */
    COLLECT,
  
    /** The {@code MODE} aggregate function. */
    MODE,
  
    /** The {@code ARG_MAX} aggregate function. */
    ARG_MAX,
  
    /** The {@code ARG_MIN} aggregate function. */
    ARG_MIN,
  
    /** The {@code PERCENTILE_CONT} aggregate function. */
    PERCENTILE_CONT,
  
    /** The {@code PERCENTILE_DISC} aggregate function. */
    PERCENTILE_DISC,
  
    /** The {@code FUSION} aggregate function. */
    FUSION,
  
    /** The {@code INTERSECTION} aggregate function. */
    INTERSECTION,
  
    /** The {@code SINGLE_VALUE} aggregate function. */
    SINGLE_VALUE,
  
    /** The {@code AGGREGATE} aggregate function. */
    AGGREGATE_FN,
  
    /** The {@code BITAND} scalar function. */
    BITAND,
  
    /** The {@code BITOR} scalar function. */
    BITOR,
  
    /** The {@code BITXOR} scalar function. */
    BITXOR,
  
    /** The {@code BITNOT} scalar function. */
    BITNOT,
  
    /** The {@code BIT_AND} aggregate function. */
    BIT_AND,
  
    /** The {@code BIT_OR} aggregate function. */
    BIT_OR,
  
    /** The {@code BIT_XOR} aggregate function. */
    BIT_XOR,
  
    /** The {@code ROW_NUMBER} window function. */
    ROW_NUMBER,
  
    /** The {@code RANK} window function. */
    RANK,
  
    /** The {@code PERCENT_RANK} window function. */
    PERCENT_RANK,
  
    /** The {@code DENSE_RANK} window function. */
    DENSE_RANK,
  
    /** The {@code ROW_NUMBER} window function. */
    CUME_DIST,
  
    /** The {@code DESCRIPTOR(column_name, ...)}. */
    DESCRIPTOR,
  
    /** The {@code TUMBLE} group function. */
    TUMBLE,
  
    // Group functions
    /** The {@code TUMBLE_START} auxiliary function of
     * the {@link #TUMBLE} group function. */
    // TODO: deprecate TUMBLE_START.
    TUMBLE_START,
  
    /** The {@code TUMBLE_END} auxiliary function of
     * the {@link #TUMBLE} group function. */
    // TODO: deprecate TUMBLE_END.
    TUMBLE_END,
  
    /** The {@code HOP} group function. */
    HOP,
  
    /** The {@code HOP_START} auxiliary function of
     * the {@link #HOP} group function. */
    HOP_START,
  
    /** The {@code HOP_END} auxiliary function of
     * the {@link #HOP} group function. */
    HOP_END,
  
    /** The {@code SESSION} group function. */
    SESSION,
  
    /** The {@code SESSION_START} auxiliary function of
     * the {@link #SESSION} group function. */
    SESSION_START,
  
    /** The {@code SESSION_END} auxiliary function of
     * the {@link #SESSION} group function. */
    SESSION_END,
  
    /** Column declaration. */
    COLUMN_DECL,
  
    /** Attribute definition. */
    ATTRIBUTE_DEF,
  
    /** {@code CHECK} constraint. */
    CHECK,
  
    /** {@code UNIQUE} constraint. */
    UNIQUE,
  
    /** {@code PRIMARY KEY} constraint. */
    PRIMARY_KEY,
  
    /** {@code FOREIGN KEY} constraint. */
    FOREIGN_KEY,
  
    // Spatial functions. They are registered as "user-defined functions" but it
    // is convenient to have a "kind" so that we can quickly match them in planner
    // rules.
  
    /** The {@code ST_DWithin} geo-spatial function. */
    ST_DWITHIN,
  
    /** The {@code ST_Point} function. */
    ST_POINT,
  
    /** The {@code ST_Point} function that makes a 3D point. */
    ST_POINT3,
  
    /** The {@code ST_MakeLine} function that makes a line. */
    ST_MAKE_LINE,
  
    /** The {@code ST_Contains} function that tests whether one geometry contains
     * another. */
    ST_CONTAINS,
  
    /** The {@code Hilbert} function that converts (x, y) to a position on a
     * Hilbert space-filling curve. */
    HILBERT,
  
    // DDL and session control statements follow. The list is not exhaustive: feel
    // free to add more.
  
    /** {@code COMMIT} session control statement. */
    COMMIT,
  
    /** {@code ROLLBACK} session control statement. */
    ROLLBACK,
  
    /** {@code ALTER SESSION} DDL statement. */
    ALTER_SESSION,
  
    /** {@code CREATE SCHEMA} DDL statement. */
    CREATE_SCHEMA,
  
    /** {@code CREATE FOREIGN SCHEMA} DDL statement. */
    CREATE_FOREIGN_SCHEMA,
  
    /** {@code DROP SCHEMA} DDL statement. */
    DROP_SCHEMA,
  
    /** {@code CREATE TABLE} DDL statement. */
    CREATE_TABLE,
  
    /** {@code CREATE TABLE LIKE} DDL statement. */
    CREATE_TABLE_LIKE,
  
    /** {@code ALTER TABLE} DDL statement. */
    ALTER_TABLE,
  
    /** {@code DROP TABLE} DDL statement. */
    DROP_TABLE,
  
    /** {@code TRUNCATE TABLE} DDL statement. */
    TRUNCATE_TABLE,
  
    /** {@code CREATE VIEW} DDL statement. */
    CREATE_VIEW,
  
    /** {@code ALTER VIEW} DDL statement. */
    ALTER_VIEW,
  
    /** {@code DROP VIEW} DDL statement. */
    DROP_VIEW,
  
    /** {@code CREATE MATERIALIZED VIEW} DDL statement. */
    CREATE_MATERIALIZED_VIEW,
  
    /** {@code ALTER MATERIALIZED VIEW} DDL statement. */
    ALTER_MATERIALIZED_VIEW,
  
    /** {@code DROP MATERIALIZED VIEW} DDL statement. */
    DROP_MATERIALIZED_VIEW,
  
    /** {@code CREATE SEQUENCE} DDL statement. */
    CREATE_SEQUENCE,
  
    /** {@code ALTER SEQUENCE} DDL statement. */
    ALTER_SEQUENCE,
  
    /** {@code DROP SEQUENCE} DDL statement. */
    DROP_SEQUENCE,
  
    /** {@code CREATE INDEX} DDL statement. */
    CREATE_INDEX,
  
    /** {@code ALTER INDEX} DDL statement. */
    ALTER_INDEX,
  
    /** {@code DROP INDEX} DDL statement. */
    DROP_INDEX,
  
    /** {@code CREATE TYPE} DDL statement. */
    CREATE_TYPE,
  
    /** {@code DROP TYPE} DDL statement. */
    DROP_TYPE,
  
    /** {@code CREATE FUNCTION} DDL statement. */
    CREATE_FUNCTION,
  
    /** {@code DROP FUNCTION} DDL statement. */
    DROP_FUNCTION,
  
    /** DDL statement not handled above.
     *
     * <p><b>Note to other projects</b>: If you are extending Calcite's SQL parser
     * and have your own object types you no doubt want to define CREATE and DROP
     * commands for them. Use OTHER_DDL in the short term, but we are happy to add
     * new enum values for your object types. Just ask!
     */
    OTHER_DDL;
  
    //~ Static fields/initializers ---------------------------------------------
  
    // Most of the static fields are categories, aggregating several kinds into
    // a set.
  
    /**
     * Category consisting of set-query node types.
     *
     * <p>Consists of:
     * {@link #EXCEPT},
     * {@link #INTERSECT},
     * {@link #UNION}.
     */
    public static final EnumSet<SqlKind> SET_QUERY =
        EnumSet.of(UNION, INTERSECT, EXCEPT);
  
    /**
     * Category consisting of all built-in aggregate functions.
     */
    public static final EnumSet<SqlKind> AGGREGATE =
        EnumSet.of(COUNT, SUM, SUM0, MIN, MAX, LEAD, LAG, FIRST_VALUE,
            LAST_VALUE, COVAR_POP, COVAR_SAMP, REGR_COUNT, REGR_SXX, REGR_SYY,
            AVG, STDDEV_POP, STDDEV_SAMP, VAR_POP, VAR_SAMP, NTILE, COLLECT,
            MODE, FUSION, SINGLE_VALUE, ROW_NUMBER, RANK, PERCENT_RANK, DENSE_RANK,
            CUME_DIST, JSON_ARRAYAGG, JSON_OBJECTAGG, BIT_AND, BIT_OR, BIT_XOR,
            LISTAGG, STRING_AGG, ARRAY_AGG, ARRAY_CONCAT_AGG, GROUP_CONCAT, COUNTIF,
            PERCENTILE_CONT, PERCENTILE_DISC,
            INTERSECTION, ANY_VALUE);
  
    /**
     * Category consisting of all DML operators.
     *
     * <p>Consists of:
     * {@link #INSERT},
     * {@link #UPDATE},
     * {@link #DELETE},
     * {@link #MERGE},
     * {@link #PROCEDURE_CALL}.
     *
     * <p>NOTE jvs 1-June-2006: For now we treat procedure calls as DML;
     * this makes it easy for JDBC clients to call execute or
     * executeUpdate and not have to process dummy cursor results.  If
     * in the future we support procedures which return results sets,
     * we'll need to refine this.
     */
    public static final EnumSet<SqlKind> DML =
        EnumSet.of(INSERT, DELETE, UPDATE, MERGE, PROCEDURE_CALL);
  
    /**
     * Category consisting of all DDL operators.
     */
    public static final EnumSet<SqlKind> DDL =
        EnumSet.of(COMMIT, ROLLBACK, ALTER_SESSION,
            CREATE_SCHEMA, CREATE_FOREIGN_SCHEMA, DROP_SCHEMA,
            CREATE_TABLE, CREATE_TABLE_LIKE,
            ALTER_TABLE, DROP_TABLE, TRUNCATE_TABLE,
            CREATE_FUNCTION, DROP_FUNCTION,
            CREATE_VIEW, ALTER_VIEW, DROP_VIEW,
            CREATE_MATERIALIZED_VIEW, ALTER_MATERIALIZED_VIEW,
            DROP_MATERIALIZED_VIEW,
            CREATE_SEQUENCE, ALTER_SEQUENCE, DROP_SEQUENCE,
            CREATE_INDEX, ALTER_INDEX, DROP_INDEX,
            CREATE_TYPE, DROP_TYPE,
            SET_OPTION, OTHER_DDL);
  
    /**
     * Category consisting of query node types.
     *
     * <p>Consists of:
     * {@link #SELECT},
     * {@link #EXCEPT},
     * {@link #INTERSECT},
     * {@link #UNION},
     * {@link #VALUES},
     * {@link #ORDER_BY},
     * {@link #EXPLICIT_TABLE}.
     */
    public static final EnumSet<SqlKind> QUERY =
        EnumSet.of(SELECT, UNION, INTERSECT, EXCEPT, VALUES, WITH, ORDER_BY,
            EXPLICIT_TABLE);
  
    /**
     * Category consisting of all expression operators.
     *
     * <p>A node is an expression if it is NOT one of the following:
     * {@link #AS},
     * {@link #ARGUMENT_ASSIGNMENT},
     * {@link #DEFAULT},
     * {@link #DESCENDING},
     * {@link #SELECT},
     * {@link #JOIN},
     * {@link #OTHER_FUNCTION},
     * {@link #CAST},
     * {@link #CONVERT},
     * {@link #TRIM},
     * {@link #LITERAL_CHAIN},
     * {@link #JDBC_FN},
     * {@link #PRECEDING},
     * {@link #FOLLOWING},
     * {@link #ORDER_BY},
     * {@link #COLLECTION_TABLE},
     * {@link #TABLESAMPLE},
     * {@link #UNNEST}
     * or an aggregate function, DML or DDL.
     */
    public static final Set<SqlKind> EXPRESSION =
        EnumSet.complementOf(
            concat(
                EnumSet.of(AS, ARGUMENT_ASSIGNMENT, CONVERT, CONVERT_ORACLE, TRANSLATE,
                    DEFAULT, RUNNING, FINAL, LAST, FIRST, PREV, NEXT,
                    FILTER, WITHIN_GROUP, IGNORE_NULLS, RESPECT_NULLS, SEPARATOR,
                    DESCENDING, CUBE, ROLLUP, GROUPING_SETS, EXTEND, LATERAL,
                    SELECT, JOIN, OTHER_FUNCTION, POSITION, CAST, TRIM, FLOOR, CEIL,
                    DATE_ADD, DATE_SUB, TIME_ADD, TIME_SUB,
                    TIMESTAMP_ADD, TIMESTAMP_DIFF, TIMESTAMP_SUB,
                    EXTRACT, INTERVAL,
                    LITERAL_CHAIN, JDBC_FN, PRECEDING, FOLLOWING, ORDER_BY,
                    NULLS_FIRST, NULLS_LAST, COLLECTION_TABLE, TABLESAMPLE,
                    VALUES, WITH, WITH_ITEM, ITEM, SKIP_TO_FIRST, SKIP_TO_LAST,
                    JSON_VALUE_EXPRESSION, UNNEST),
                SET_QUERY, AGGREGATE, DML, DDL));
  
    /**
     * Category of all SQL statement types.
     *
     * <p>Consists of all types in {@link #QUERY}, {@link #DML} and {@link #DDL}.
     */
    public static final EnumSet<SqlKind> TOP_LEVEL = concat(QUERY, DML, DDL);
  
    /**
     * Category consisting of regular and special functions.
     *
     * <p>Consists of regular functions {@link #OTHER_FUNCTION} and special
     * functions {@link #ROW}, {@link #TRIM}, {@link #CAST}, {@link #REVERSE},
     * {@link #JDBC_FN}.
     */
    public static final Set<SqlKind> FUNCTION =
        EnumSet.of(OTHER_FUNCTION, ROW, TRIM, LTRIM, RTRIM, CAST, REVERSE,
            JDBC_FN, POSITION, CONVERT);
  
    /**
     * Category of SqlAvgAggFunction.
     *
     * <p>Consists of {@link #AVG}, {@link #STDDEV_POP}, {@link #STDDEV_SAMP},
     * {@link #VAR_POP}, {@link #VAR_SAMP}.
     */
    public static final Set<SqlKind> AVG_AGG_FUNCTIONS =
        EnumSet.of(AVG, STDDEV_POP, STDDEV_SAMP, VAR_POP, VAR_SAMP);
  
    /**
     * Category of SqlCovarAggFunction.
     *
     * <p>Consists of {@link #COVAR_POP}, {@link #COVAR_SAMP}, {@link #REGR_SXX},
     * {@link #REGR_SYY}.
     */
    public static final Set<SqlKind> COVAR_AVG_AGG_FUNCTIONS =
        EnumSet.of(COVAR_POP, COVAR_SAMP, REGR_COUNT, REGR_SXX, REGR_SYY);
  
    /**
     * Category of comparison operators.
     *
     * <p>Consists of:
     * {@link #IN},
     * {@link #NOT_IN},
     * {@link #EQUALS},
     * {@link #NOT_EQUALS},
     * {@link #LESS_THAN},
     * {@link #GREATER_THAN},
     * {@link #LESS_THAN_OR_EQUAL},
     * {@link #GREATER_THAN_OR_EQUAL}.
     */
    public static final Set<SqlKind> COMPARISON =
        EnumSet.of(
            IN, NOT_IN, EQUALS, NOT_EQUALS,
            LESS_THAN, GREATER_THAN,
            GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL);
  
    /**
     * Comparison operators that order values.
     *
     * <p>Consists of:
     * {@link #LESS_THAN},
     * {@link #GREATER_THAN},
     * {@link #LESS_THAN_OR_EQUAL},
     * {@link #GREATER_THAN_OR_EQUAL}.
     */
    public static final Set<SqlKind> ORDER_COMPARISON =
        EnumSet.of(
            LESS_THAN, GREATER_THAN,
            GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL);
  
    /**
     * Category of binary arithmetic.
     *
     * <p>Consists of:
     * {@link #PLUS}
     * {@link #MINUS}
     * {@link #TIMES}
     * {@link #DIVIDE}
     * {@link #MOD}
     * and the corresponding checked arithmetic operations.
     */
    public static final Set<SqlKind> BINARY_ARITHMETIC =
        EnumSet.of(PLUS, MINUS, TIMES, DIVIDE, MOD,
            CHECKED_PLUS, CHECKED_MINUS, CHECKED_TIMES, CHECKED_DIVIDE);
  
    public static final Set<SqlKind> CHECKED_ARITHMETIC =
        EnumSet.of(CHECKED_PLUS, CHECKED_MINUS, CHECKED_TIMES, CHECKED_DIVIDE, CHECKED_MINUS_PREFIX);
  
  
    /**
     * Category of binary equality.
     *
     * <p>Consists of:
     * {@link #EQUALS}
     * {@link #NOT_EQUALS}
     */
    public static final Set<SqlKind> BINARY_EQUALITY =
        EnumSet.of(EQUALS, NOT_EQUALS);
  
    /**
     * Category of binary comparison.
     *
     * <p>Consists of:
     * {@link #EQUALS}
     * {@link #NOT_EQUALS}
     * {@link #GREATER_THAN}
     * {@link #GREATER_THAN_OR_EQUAL}
     * {@link #LESS_THAN}
     * {@link #LESS_THAN_OR_EQUAL}
     * {@link #IS_DISTINCT_FROM}
     * {@link #IS_NOT_DISTINCT_FROM}
     */
    public static final Set<SqlKind> BINARY_COMPARISON =
        EnumSet.of(
            EQUALS, NOT_EQUALS,
            GREATER_THAN, GREATER_THAN_OR_EQUAL,
            LESS_THAN, LESS_THAN_OR_EQUAL,
            IS_DISTINCT_FROM, IS_NOT_DISTINCT_FROM);
  
    /**
     * Category of operators that do not depend on the argument order.
     *
     * <p>For instance: {@link #AND}, {@link #OR}, {@link #EQUALS},
     * {@link #LEAST}.
     *
     * <p>Note: {@link #PLUS} does depend on the argument oder if argument types
     * are different.
     */
    @API(since = "1.22", status = API.Status.EXPERIMENTAL)
    public static final Set<SqlKind> SYMMETRICAL =
        EnumSet.of(AND, OR, EQUALS, NOT_EQUALS,
            IS_DISTINCT_FROM, IS_NOT_DISTINCT_FROM,
            GREATEST, LEAST);
  
    /**
     * Category of operators that do not depend on the argument order if argument
     * types are equal.
     *
     * <p>For instance: {@link #PLUS}, {@link #TIMES}.
     */
    @API(since = "1.22", status = API.Status.EXPERIMENTAL)
    public static final Set<SqlKind> SYMMETRICAL_SAME_ARG_TYPE =
        EnumSet.of(PLUS, TIMES, CHECKED_PLUS, CHECKED_TIMES);
  
    /**
     * Simple binary operators are those operators which expects operands from the same Domain.
     *
     * <p>Example: simple comparisons ({@code =}, {@code <}).
     *
     * <p>Note: it does not contain {@code IN} because that is defined on D x D^n.
     */
    @API(since = "1.24", status = API.Status.EXPERIMENTAL)
    public static final Set<SqlKind> SIMPLE_BINARY_OPS;
  
    static {
      EnumSet<SqlKind> kinds = EnumSet.copyOf(SqlKind.BINARY_ARITHMETIC);
      kinds.remove(SqlKind.MOD);
      kinds.addAll(SqlKind.BINARY_COMPARISON);
      SIMPLE_BINARY_OPS = Sets.immutableEnumSet(kinds);
    }
  
    /** Lower-case name. */
    public final String lowerName = name().toLowerCase(Locale.ROOT);
    public final String sql;
  
    SqlKind() {
      sql = name();
    }
  
    SqlKind(String sql) {
      this.sql = sql;
    }
  
    /** Returns the kind that corresponds to this operator but in the opposite
     * direction. Or returns this, if this kind is not reversible.
     *
     * <p>For example, {@code GREATER_THAN.reverse()} returns {@link #LESS_THAN}.
     */
    public SqlKind reverse() {
      switch (this) {
      case GREATER_THAN:
        return LESS_THAN;
      case GREATER_THAN_OR_EQUAL:
        return LESS_THAN_OR_EQUAL;
      case LESS_THAN:
        return GREATER_THAN;
      case LESS_THAN_OR_EQUAL:
        return GREATER_THAN_OR_EQUAL;
      default:
        return this;
      }
    }
  
    /** Returns the kind that you get if you apply NOT to this kind.
     *
     * <p>For example, {@code IS_NOT_NULL.negate()} returns {@link #IS_NULL}.
     *
     * <p>For {@link #IS_TRUE}, {@link #IS_FALSE}, {@link #IS_NOT_TRUE},
     * {@link #IS_NOT_FALSE}, nullable inputs need to be treated carefully.
     *
     * <p>{@code NOT(IS_TRUE(null))} = {@code NOT false} = {@code true},
     * while {@code IS_FALSE(null)} = {@code false},
     * so {@code NOT(IS_TRUE(X))} should be {@code IS_NOT_TRUE(X)}.
     * On the other hand,
     * {@code IS_TRUE(NOT(null))} = {@code IS_TRUE(null)} = {@code false}.
     *
     * <p>This is why negate() != negateNullSafe() for these operators.
     */
    public SqlKind negate() {
      switch (this) {
      case IS_TRUE:
        return IS_NOT_TRUE;
      case IS_FALSE:
        return IS_NOT_FALSE;
      case IS_NULL:
        return IS_NOT_NULL;
      case IS_NOT_TRUE:
        return IS_TRUE;
      case IS_NOT_FALSE:
        return IS_FALSE;
      case IS_NOT_NULL:
        return IS_NULL;
      case IS_DISTINCT_FROM:
        return IS_NOT_DISTINCT_FROM;
      case IS_NOT_DISTINCT_FROM:
        return IS_DISTINCT_FROM;
      default:
        return this;
      }
    }
  
    /** Returns the kind that you get if you negate this kind.
     * To conform to null semantics, null value should not be compared.
     *
     * <p>For {@link #IS_TRUE}, {@link #IS_FALSE}, {@link #IS_NOT_TRUE} and
     * {@link #IS_NOT_FALSE}, nullable inputs need to be treated carefully:
     *
     * <ul>
     * <li>NOT(IS_TRUE(null)) = NOT(false) = true
     * <li>IS_TRUE(NOT(null)) = IS_TRUE(null) = false
     * <li>IS_FALSE(null) = false
     * <li>IS_NOT_TRUE(null) = true
     * </ul>
     */
    public SqlKind negateNullSafe() {
      switch (this) {
      case EQUALS:
        return NOT_EQUALS;
      case NOT_EQUALS:
        return EQUALS;
      case LESS_THAN:
        return GREATER_THAN_OR_EQUAL;
      case GREATER_THAN:
        return LESS_THAN_OR_EQUAL;
      case LESS_THAN_OR_EQUAL:
        return GREATER_THAN;
      case GREATER_THAN_OR_EQUAL:
        return LESS_THAN;
      case IN:
        return NOT_IN;
      case NOT_IN:
        return IN;
      case DRUID_IN:
        return DRUID_NOT_IN;
      case DRUID_NOT_IN:
        return DRUID_IN;
      case IS_TRUE:
        return IS_FALSE;
      case IS_FALSE:
        return IS_TRUE;
      case IS_NOT_TRUE:
        return IS_NOT_FALSE;
      case IS_NOT_FALSE:
        return IS_NOT_TRUE;
       // (NOT x) IS NULL => x IS NULL
       // Similarly (NOT x) IS NOT NULL => x IS NOT NULL
      case IS_NOT_NULL:
      case IS_NULL:
        return this;
      default:
        return this.negate();
      }
    }
  
    /**
     * Returns whether this {@code SqlKind} belongs to a given category.
     *
     * <p>A category is a collection of kinds, not necessarily disjoint. For
     * example, QUERY is { SELECT, UNION, INTERSECT, EXCEPT, VALUES, ORDER_BY,
     * EXPLICIT_TABLE }.
     *
     * @param category Category
     * @return Whether this kind belongs to the given category
     */
    public final boolean belongsTo(Collection<SqlKind> category) {
      return category.contains(this);
    }
  
    /**
     * If this kind represents a non-standard function, return OTHER_FUNCTION, otherwise
     * return this.  Do not add standard functions here.
     */
    public SqlKind getFunctionKind() {
      switch (this) {
      case CONVERT:
      case TRANSLATE:
      case POSITION:
      case DECODE:
      case NVL:
      case NVL2:
      case GREATEST:
      case GREATEST_PG:
      case CONCAT2:
      case CONCAT_WITH_NULL:
      case CONCAT_WS_MSSQL:
      case CONCAT_WS_POSTGRESQL:
      case CONCAT_WS_SPARK:
      case IF:
      case LEAST:
      case LEAST_PG:
      case LOG:
      case DATE_ADD:
      case DATE_TRUNC:
      case DATE_SUB:
      case TIME_ADD:
      case TIME_SUB:
      case TIMESTAMP_ADD:
      case TIMESTAMP_DIFF:
      case TIMESTAMP_SUB:
      case SAFE_CAST:
      case FLOOR:
      case CEIL:
      case TRIM:
      case LTRIM:
      case RTRIM:
      case ARRAY_APPEND:
      case ARRAY_COMPACT:
      case ARRAY_CONCAT:
      case ARRAY_CONTAINS:
      case ARRAY_DISTINCT:
      case ARRAY_EXCEPT:
      case ARRAY_INSERT:
      case ARRAY_INTERSECT:
      case ARRAY_JOIN:
      case ARRAY_LENGTH:
      case ARRAY_MAX:
      case ARRAY_MIN:
      case ARRAY_POSITION:
      case ARRAY_PREPEND:
      case ARRAY_REMOVE:
      case ARRAY_REPEAT:
      case ARRAY_REVERSE:
      case ARRAY_SIZE:
      case ARRAY_SLICE:
      case ARRAY_TO_STRING:
      case ARRAY_UNION:
      case ARRAYS_OVERLAP:
      case ARRAYS_ZIP:
      case SORT_ARRAY:
      case MAP_CONCAT:
      case MAP_ENTRIES:
      case MAP_KEYS:
      case MAP_VALUES:
      case MAP_CONTAINS_KEY:
      case MAP_FROM_ARRAYS:
      case MAP_FROM_ENTRIES:
      case STR_TO_MAP:
      case REVERSE:
      case REVERSE_SPARK:
      case SOUNDEX_SPARK:
      case STRING_TO_ARRAY:
      case SUBSTR_BIG_QUERY:
      case SUBSTR_MYSQL:
      case SUBSTR_ORACLE:
      case SUBSTR_POSTGRESQL:
      case CHAR_LENGTH:
      case ENDS_WITH:
      case STARTS_WITH:
      case JSON_TYPE:
      case CONTAINS_SUBSTR:
      case ST_DWITHIN:
      case ST_POINT:
      case ST_POINT3:
      case ST_MAKE_LINE:
      case ST_CONTAINS:
      case HILBERT:
        return OTHER_FUNCTION;
      default:
        return this;
      }
    }
  
    @SafeVarargs
    private static <E extends Enum<E>> EnumSet<E> concat(EnumSet<E> set0,
        EnumSet<E>... sets) {
      EnumSet<E> set = set0.clone();
      for (EnumSet<E> s : sets) {
        set.addAll(s);
      }
      return set;
    }
  }
  