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

com.hazelcast.org.apache.calcite.sql.validate.SqlValidatorScope Maven / Gradle / Ivy

There is a newer version: 5.4.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.validate;

import com.hazelcast.org.apache.calcite.rel.type.RelDataType;
import com.hazelcast.org.apache.calcite.rel.type.StructKind;
import com.hazelcast.org.apache.calcite.sql.SqlCall;
import com.hazelcast.org.apache.calcite.sql.SqlIdentifier;
import com.hazelcast.org.apache.calcite.sql.SqlNode;
import com.hazelcast.org.apache.calcite.sql.SqlNodeList;
import com.hazelcast.org.apache.calcite.sql.SqlSelect;
import com.hazelcast.org.apache.calcite.sql.SqlWindow;
import com.hazelcast.org.apache.calcite.util.Pair;
import com.hazelcast.org.apache.calcite.util.Util;

import com.hazelcast.com.google.common.collect.ImmutableList;
import com.hazelcast.com.google.common.collect.Iterables;

import com.hazelcast.org.checkerframework.checker.nullness.qual.Nullable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Name-resolution scope. Represents any position in a parse tree than an
 * expression can be, or anything in the parse tree which has columns.
 *
 * 

When validating an expression, say "foo"."bar", you first use the * {@link #resolve} method of the scope where the expression is defined to * locate "foo". If successful, this returns a * {@link SqlValidatorNamespace namespace} describing the type of the resulting * object. */ public interface SqlValidatorScope { //~ Methods ---------------------------------------------------------------- /** * Returns the validator which created this scope. */ SqlValidator getValidator(); /** * Returns the root node of this scope. Never null. */ SqlNode getNode(); /** * Looks up a node with a given name. Returns null if none is found. * * @param names Name of node to find, maybe partially or fully qualified * @param nameMatcher Name matcher * @param deep Whether to look more than one level deep * @param resolved Callback wherein to write the match(es) we find */ void resolve(List names, SqlNameMatcher nameMatcher, boolean deep, Resolved resolved); // CHECKSTYLE: IGNORE 1 /** @deprecated Use * {@link #findQualifyingTableNames(String, SqlNode, SqlNameMatcher)} */ @Deprecated // to be removed before 2.0 Pair findQualifyingTableName(String columnName, SqlNode ctx); /** * Finds all table aliases which are implicitly qualifying an unqualified * column name. * *

This method is only implemented in scopes (such as * {@link com.hazelcast.org.apache.calcite.sql.validate.SelectScope}) which can be the * context for name-resolution. In scopes such as * {@link com.hazelcast.org.apache.calcite.sql.validate.IdentifierNamespace}, it throws * {@link UnsupportedOperationException}. * * @param columnName Column name * @param ctx Validation context, to appear in any error thrown * @param nameMatcher Name matcher * * @return Map of applicable table alias and namespaces, never null, empty * if no aliases found */ Map findQualifyingTableNames(String columnName, SqlNode ctx, SqlNameMatcher nameMatcher); /** * Collects the {@link SqlMoniker}s of all possible columns in this scope. * * @param result an array list of strings to add the result to */ void findAllColumnNames(List result); /** * Collects the {@link SqlMoniker}s of all table aliases (uses of tables in * query FROM clauses) available in this scope. * * @param result a list of monikers to add the result to */ void findAliases(Collection result); /** * Converts an identifier into a fully-qualified identifier. For example, * the "empno" in "select empno from emp natural join dept" becomes * "emp.empno". * * @return A qualified identifier, never null */ SqlQualified fullyQualify(SqlIdentifier identifier); /** * Registers a relation in this scope. * * @param ns Namespace representing the result-columns of the relation * @param alias Alias with which to reference the relation, must not be null * @param nullable Whether this is a null-generating side of a join */ void addChild(SqlValidatorNamespace ns, String alias, boolean nullable); /** * Finds a window with a given name. Returns null if not found. */ @Nullable SqlWindow lookupWindow(String name); /** * Returns whether an expression is monotonic in this scope. For example, if * the scope has previously been sorted by columns X, Y, then X is monotonic * in this scope, but Y is not. */ SqlMonotonicity getMonotonicity(SqlNode expr); /** * Returns the expressions by which the rows in this scope are sorted. If * the rows are unsorted, returns null. */ @Nullable SqlNodeList getOrderList(); /** * Resolves a single identifier to a column, and returns the datatype of * that column. * *

If it cannot find the column, returns null. If the column is * ambiguous, throws an error with context ctx. * * @param name Name of column * @param ctx Context for exception * @return Type of column, if found and unambiguous; null if not found */ @Nullable RelDataType resolveColumn(String name, SqlNode ctx); /** * Returns the scope within which operands to a call are to be validated. * Usually it is this scope, but when the call is to an aggregate function * and this is an aggregating scope, it will be a a different scope. * * @param call Call * @return Scope within which to validate arguments to call. */ SqlValidatorScope getOperandScope(SqlCall call); /** * Performs any scope-specific validation of an expression. For example, an * aggregating scope requires that expressions are valid aggregations. The * expression has already been validated. */ void validateExpr(SqlNode expr); // CHECKSTYLE: IGNORE 1 /** @deprecated Use * {@link #resolveTable(List, SqlNameMatcher, Path, Resolved)}. */ @Deprecated // to be removed before 2.0 @Nullable SqlValidatorNamespace getTableNamespace(List names); /** * Looks up a table in this scope from its name. If found, calls * {@link Resolved#resolve(List, SqlNameMatcher, boolean, Resolved)}. * {@link TableNamespace} that wraps it. If the "table" is defined in a * {@code WITH} clause it may be a query, not a table after all. * *

The name matcher is not null, and one typically uses * {@link SqlValidatorCatalogReader#nameMatcher()}. * * @param names Name of table, may be qualified or fully-qualified * @param nameMatcher Name matcher * @param path List of names that we have traversed through so far */ void resolveTable(List names, SqlNameMatcher nameMatcher, Path path, Resolved resolved); /** Converts the type of an expression to nullable, if the context * warrants it. */ RelDataType nullifyType(SqlNode node, RelDataType type); /** Returns whether this scope is enclosed within {@code scope2} in such * a way that it can see the contents of {@code scope2}. */ default boolean isWithin(@Nullable SqlValidatorScope scope2) { return this == scope2; } /** Callback from {@link SqlValidatorScope#resolve}. */ interface Resolved { void found(SqlValidatorNamespace namespace, boolean nullable, @Nullable SqlValidatorScope scope, Path path, @Nullable List remainingNames); int count(); } /** A sequence of steps by which an identifier was resolved. Immutable. */ abstract class Path { /** The empty path. */ @SuppressWarnings("StaticInitializerReferencesSubClass") public static final EmptyPath EMPTY = new EmptyPath(); /** Creates a path that consists of this path plus one additional step. */ public Step plus(@Nullable RelDataType rowType, int i, String name, StructKind kind) { return new Step(this, rowType, i, name, kind); } /** Number of steps in this path. */ public int stepCount() { return 0; } /** Returns the steps in this path. */ public List steps() { ImmutableList.Builder paths = new ImmutableList.Builder<>(); build(paths); return paths.build(); } /** Returns a list ["step1", "step2"]. */ List stepNames() { return Util.transform(steps(), input -> input.name); } protected void build(ImmutableList.Builder paths) { } @Override public String toString() { return stepNames().toString(); } } /** A path that has no steps. */ class EmptyPath extends Path { } /** A step in resolving an identifier. */ class Step extends Path { final Path parent; final @Nullable RelDataType rowType; public final int i; public final String name; final StructKind kind; Step(Path parent, @Nullable RelDataType rowType, int i, String name, StructKind kind) { this.parent = Objects.requireNonNull(parent, "parent"); this.rowType = rowType; // may be null this.i = i; this.name = name; this.kind = Objects.requireNonNull(kind, "kind"); } @Override public int stepCount() { return 1 + parent.stepCount(); } @Override protected void build(ImmutableList.Builder paths) { parent.build(paths); paths.add(this); } } /** Default implementation of * {@link com.hazelcast.org.apache.calcite.sql.validate.SqlValidatorScope.Resolved}. */ class ResolvedImpl implements Resolved { final List resolves = new ArrayList<>(); @Override public void found(SqlValidatorNamespace namespace, boolean nullable, @Nullable SqlValidatorScope scope, Path path, @Nullable List remainingNames) { if (scope instanceof TableScope) { scope = scope.getValidator().getSelectScope((SqlSelect) scope.getNode()); } if (scope instanceof AggregatingSelectScope) { scope = ((AggregatingSelectScope) scope).parent; assert scope instanceof SelectScope; } resolves.add( new Resolve(namespace, nullable, scope, path, remainingNames)); } @Override public int count() { return resolves.size(); } public Resolve only() { return Iterables.getOnlyElement(resolves); } /** Resets all state. */ public void clear() { resolves.clear(); } } /** A match found when looking up a name. */ class Resolve { public final SqlValidatorNamespace namespace; private final boolean nullable; public final @Nullable SqlValidatorScope scope; // may be null public final Path path; /** Names not matched; empty if it was a full match. */ final List remainingNames; Resolve(SqlValidatorNamespace namespace, boolean nullable, @Nullable SqlValidatorScope scope, Path path, @Nullable List remainingNames) { this.namespace = Objects.requireNonNull(namespace, "namespace"); this.nullable = nullable; this.scope = scope; assert !(scope instanceof TableScope); this.path = Objects.requireNonNull(path, "path"); this.remainingNames = remainingNames == null ? ImmutableList.of() : ImmutableList.copyOf(remainingNames); } /** The row type of the found namespace, nullable if the lookup has * looked into outer joins. */ public RelDataType rowType() { return namespace.getValidator().getTypeFactory() .createTypeWithNullability(namespace.getRowType(), nullable); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy