All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.org.apache.calcite.sql.SqlNode Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * 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 com.hazelcast.org.apache.calcite.sql;

import com.hazelcast.org.apache.calcite.sql.dialect.AnsiSqlDialect;
import com.hazelcast.org.apache.calcite.sql.parser.SqlParserPos;
import com.hazelcast.org.apache.calcite.sql.pretty.SqlPrettyWriter;
import com.hazelcast.org.apache.calcite.sql.util.SqlString;
import com.hazelcast.org.apache.calcite.sql.util.SqlVisitor;
import com.hazelcast.org.apache.calcite.sql.validate.SqlMoniker;
import com.hazelcast.org.apache.calcite.sql.validate.SqlMonotonicity;
import com.hazelcast.org.apache.calcite.sql.validate.SqlValidator;
import com.hazelcast.org.apache.calcite.sql.validate.SqlValidatorScope;
import com.hazelcast.org.apache.calcite.util.Litmus;
import com.hazelcast.org.apache.calcite.util.Util;

import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.UnaryOperator;
import javax.annotation.Nonnull;

/**
 * A SqlNode is a SQL parse tree.
 *
 * 

It may be an * {@link SqlOperator operator}, {@link SqlLiteral literal}, * {@link SqlIdentifier identifier}, and so forth. */ public abstract class SqlNode implements Cloneable { //~ Static fields/initializers --------------------------------------------- public static final SqlNode[] EMPTY_ARRAY = new SqlNode[0]; //~ Instance fields -------------------------------------------------------- protected final SqlParserPos pos; //~ Constructors ----------------------------------------------------------- /** * Creates a node. * * @param pos Parser position, must not be null. */ SqlNode(SqlParserPos pos) { this.pos = Objects.requireNonNull(pos); } //~ Methods ---------------------------------------------------------------- /** @deprecated Please use {@link #clone(SqlNode)}; this method brings * along too much baggage from early versions of Java */ @Deprecated @SuppressWarnings("MethodDoesntCallSuperMethod") public Object clone() { return clone(getParserPosition()); } /** Creates a copy of a SqlNode. */ public static E clone(E e) { //noinspection unchecked return (E) e.clone(e.pos); } /** * Clones a SqlNode with a different position. */ public abstract SqlNode clone(SqlParserPos pos); /** * Returns the type of node this is, or * {@link com.hazelcast.org.apache.calcite.sql.SqlKind#OTHER} if it's nothing special. * * @return a {@link SqlKind} value, never null * @see #isA */ public @Nonnull SqlKind getKind() { return SqlKind.OTHER; } /** * Returns whether this node is a member of an aggregate category. * *

For example, {@code node.isA(SqlKind.QUERY)} returns {@code true} * if the node is a SELECT, INSERT, UPDATE etc. * *

This method is shorthand: {@code node.isA(category)} is always * equivalent to {@code node.getKind().belongsTo(category)}. * * @param category Category * @return Whether this node belongs to the given category. */ public final boolean isA(Set category) { return getKind().belongsTo(category); } @Deprecated // to be removed before 2.0 public static SqlNode[] cloneArray(SqlNode[] nodes) { SqlNode[] clones = nodes.clone(); for (int i = 0; i < clones.length; i++) { SqlNode node = clones[i]; if (node != null) { clones[i] = SqlNode.clone(node); } } return clones; } public String toString() { return toSqlString(c -> c.withDialect(AnsiSqlDialect.DEFAULT) .withAlwaysUseParentheses(false) .withSelectListItemsOnSeparateLines(false) .withUpdateSetListNewline(false) .withIndentation(0)).getSql(); } /** * Returns the SQL text of the tree of which this SqlNode is * the root. * *

Typical return values are: * *

    *
  • 'It''s a bird!' *
  • NULL *
  • 12.3 *
  • DATE '1969-04-29' *
* * @param transform Transform that sets desired writer configuration */ public SqlString toSqlString(UnaryOperator transform) { final SqlWriterConfig config = transform.apply(SqlPrettyWriter.config()); SqlPrettyWriter writer = new SqlPrettyWriter(config); unparse(writer, 0, 0); return writer.toSqlString(); } /** * Returns the SQL text of the tree of which this SqlNode is * the root. * *

Typical return values are: * *

    *
  • 'It''s a bird!' *
  • NULL *
  • 12.3 *
  • DATE '1969-04-29' *
* * @param dialect Dialect (null for ANSI SQL) * @param forceParens Whether to wrap all expressions in parentheses; * useful for parse test, but false by default */ public SqlString toSqlString(SqlDialect dialect, boolean forceParens) { return toSqlString(c -> c.withDialect(Util.first(dialect, AnsiSqlDialect.DEFAULT)) .withAlwaysUseParentheses(forceParens) .withSelectListItemsOnSeparateLines(false) .withUpdateSetListNewline(false) .withIndentation(0)); } public SqlString toSqlString(SqlDialect dialect) { return toSqlString(dialect, false); } /** * Writes a SQL representation of this node to a writer. * *

The leftPrec and rightPrec parameters give * us enough context to decide whether we need to enclose the expression in * parentheses. For example, we need parentheses around "2 + 3" if preceded * by "5 *". This is because the precedence of the "*" operator is greater * than the precedence of the "+" operator. * *

The algorithm handles left- and right-associative operators by giving * them slightly different left- and right-precedence. * *

If {@link SqlWriter#isAlwaysUseParentheses()} is true, we use * parentheses even when they are not required by the precedence rules. * *

For the details of this algorithm, see {@link SqlCall#unparse}. * * @param writer Target writer * @param leftPrec The precedence of the {@link SqlNode} immediately * preceding this node in a depth-first scan of the parse * tree * @param rightPrec The precedence of the {@link SqlNode} immediately */ public abstract void unparse( SqlWriter writer, int leftPrec, int rightPrec); public SqlParserPos getParserPosition() { return pos; } /** * Validates this node. * *

The typical implementation of this method will make a callback to the * validator appropriate to the node type and context. The validator has * methods such as {@link SqlValidator#validateLiteral} for these purposes. * * @param scope Validator */ public abstract void validate( SqlValidator validator, SqlValidatorScope scope); /** * Lists all the valid alternatives for this node if the parse position of * the node matches that of pos. Only implemented now for SqlCall and * SqlOperator. * * @param validator Validator * @param scope Validation scope * @param pos SqlParserPos indicating the cursor position at which * completion hints are requested for * @param hintList list of valid options */ public void findValidOptions( SqlValidator validator, SqlValidatorScope scope, SqlParserPos pos, Collection hintList) { // no valid options } /** * Validates this node in an expression context. * *

Usually, this method does much the same as {@link #validate}, but a * {@link SqlIdentifier} can occur in expression and non-expression * contexts. */ public void validateExpr( SqlValidator validator, SqlValidatorScope scope) { validate(validator, scope); Util.discard(validator.deriveType(scope, this)); } /** * Accepts a generic visitor. * *

Implementations of this method in subtypes simply call the appropriate * visit method on the * {@link com.hazelcast.org.apache.calcite.sql.util.SqlVisitor visitor object}. * *

The type parameter R must be consistent with the type * parameter of the visitor. */ public abstract R accept(SqlVisitor visitor); /** * Returns whether this node is structurally equivalent to another node. * Some examples: * *

    *
  • 1 + 2 is structurally equivalent to 1 + 2
  • *
  • 1 + 2 + 3 is structurally equivalent to (1 + 2) + 3, but not to 1 + * (2 + 3), because the '+' operator is left-associative
  • *
*/ public abstract boolean equalsDeep(SqlNode node, Litmus litmus); @Deprecated // to be removed before 2.0 public final boolean equalsDeep(SqlNode node, boolean fail) { return equalsDeep(node, fail ? Litmus.THROW : Litmus.IGNORE); } /** * Returns whether two nodes are equal (using * {@link #equalsDeep(SqlNode, Litmus)}) or are both null. * * @param node1 First expression * @param node2 Second expression * @param litmus What to do if an error is detected (expressions are * not equal) */ public static boolean equalDeep( SqlNode node1, SqlNode node2, Litmus litmus) { if (node1 == null) { return node2 == null; } else if (node2 == null) { return false; } else { return node1.equalsDeep(node2, litmus); } } /** * Returns whether expression is always ascending, descending or constant. * This property is useful because it allows to safely aggregate infinite * streams of values. * *

The default implementation returns * {@link SqlMonotonicity#NOT_MONOTONIC}. * * @param scope Scope */ public SqlMonotonicity getMonotonicity(SqlValidatorScope scope) { return SqlMonotonicity.NOT_MONOTONIC; } /** Returns whether two lists of operands are equal. */ public static boolean equalDeep(List operands0, List operands1, Litmus litmus) { if (operands0.size() != operands1.size()) { return litmus.fail(null); } for (int i = 0; i < operands0.size(); i++) { if (!SqlNode.equalDeep(operands0.get(i), operands1.get(i), litmus)) { return litmus.fail(null); } } return litmus.succeed(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy