com.hazelcast.org.apache.calcite.sql.validate.EmptyScope Maven / Gradle / Ivy
/*
* 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.jdbc.CalciteSchema;
import com.hazelcast.org.apache.calcite.plan.RelOptSchema;
import com.hazelcast.org.apache.calcite.prepare.Prepare;
import com.hazelcast.org.apache.calcite.prepare.RelOptTableImpl;
import com.hazelcast.org.apache.calcite.rel.type.RelDataType;
import com.hazelcast.org.apache.calcite.rel.type.StructKind;
import com.hazelcast.org.apache.calcite.schema.Table;
import com.hazelcast.org.apache.calcite.schema.Wrapper;
import com.hazelcast.org.apache.calcite.sql.SqlCall;
import com.hazelcast.org.apache.calcite.sql.SqlDataTypeSpec;
import com.hazelcast.org.apache.calcite.sql.SqlDynamicParam;
import com.hazelcast.org.apache.calcite.sql.SqlIdentifier;
import com.hazelcast.org.apache.calcite.sql.SqlLiteral;
import com.hazelcast.org.apache.calcite.sql.SqlNode;
import com.hazelcast.org.apache.calcite.sql.SqlNodeList;
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.ImmutableMap;
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 static com.hazelcast.org.apache.calcite.util.Static.RESOURCE;
/**
* Deviant implementation of {@link SqlValidatorScope} for the top of the scope
* stack.
*
* It is convenient, because we never need to check whether a scope's parent
* is null. (This scope knows not to ask about its parents, just like Adam.)
*/
class EmptyScope implements SqlValidatorScope {
//~ Instance fields --------------------------------------------------------
protected final SqlValidatorImpl validator;
//~ Constructors -----------------------------------------------------------
EmptyScope(SqlValidatorImpl validator) {
this.validator = validator;
}
//~ Methods ----------------------------------------------------------------
@Override public SqlValidator getValidator() {
return validator;
}
@Override public SqlQualified fullyQualify(SqlIdentifier identifier) {
return SqlQualified.create(this, 1, null, identifier);
}
@Override public SqlNode getNode() {
throw new UnsupportedOperationException();
}
@Override public void resolve(List names, SqlNameMatcher nameMatcher,
boolean deep, Resolved resolved) {
}
@SuppressWarnings("deprecation")
@Override public @Nullable SqlValidatorNamespace getTableNamespace(List names) {
SqlValidatorTable table = validator.catalogReader.getTable(names);
return table != null
? new TableNamespace(validator, table)
: null;
}
@Override public void resolveTable(List names, SqlNameMatcher nameMatcher,
Path path, Resolved resolved) {
final List imperfectResolves = new ArrayList<>();
final List resolves = ((ResolvedImpl) resolved).resolves;
// Look in the default schema, then default catalog, then root schema.
for (List schemaPath : validator.catalogReader.getSchemaPaths()) {
resolve_(validator.catalogReader.getRootSchema(), names, schemaPath,
nameMatcher, path, resolved);
for (Resolve resolve : resolves) {
if (resolve.remainingNames.isEmpty()) {
// There is a full match. Return it as the only match.
((ResolvedImpl) resolved).clear();
resolves.add(resolve);
return;
}
}
imperfectResolves.addAll(resolves);
}
// If there were no matches in the last round, restore those found in
// previous rounds
if (resolves.isEmpty()) {
resolves.addAll(imperfectResolves);
}
}
private void resolve_(final CalciteSchema rootSchema, List names,
List schemaNames, SqlNameMatcher nameMatcher, Path path,
Resolved resolved) {
final List concat = ImmutableList.builder()
.addAll(schemaNames).addAll(names).build();
CalciteSchema schema = rootSchema;
SqlValidatorNamespace namespace = null;
List remainingNames = concat;
for (String schemaName : concat) {
if (schema == rootSchema
&& nameMatcher.matches(schemaName, schema.name)) {
remainingNames = Util.skip(remainingNames);
continue;
}
final CalciteSchema subSchema =
schema.getSubSchema(schemaName, nameMatcher.isCaseSensitive());
if (subSchema != null) {
path = path.plus(null, -1, subSchema.name, StructKind.NONE);
remainingNames = Util.skip(remainingNames);
schema = subSchema;
namespace = new SchemaNamespace(validator,
ImmutableList.copyOf(path.stepNames()));
continue;
}
CalciteSchema.TableEntry entry =
schema.getTable(schemaName, nameMatcher.isCaseSensitive());
if (entry == null) {
entry = schema.getTableBasedOnNullaryFunction(schemaName,
nameMatcher.isCaseSensitive());
}
if (entry != null) {
path = path.plus(null, -1, entry.name, StructKind.NONE);
remainingNames = Util.skip(remainingNames);
final Table table = entry.getTable();
SqlValidatorTable table2 = null;
if (table instanceof Wrapper) {
table2 = ((Wrapper) table).unwrap(Prepare.PreparingTable.class);
}
if (table2 == null) {
final RelOptSchema relOptSchema =
validator.catalogReader.unwrap(RelOptSchema.class);
final RelDataType rowType = table.getRowType(validator.typeFactory);
table2 = RelOptTableImpl.create(relOptSchema, rowType, entry, null);
}
namespace = new TableNamespace(validator, table2);
resolved.found(namespace, false, null, path, remainingNames);
return;
}
// neither sub-schema nor table
if (namespace != null
&& !remainingNames.equals(names)) {
resolved.found(namespace, false, null, path, remainingNames);
}
return;
}
}
@Override public RelDataType nullifyType(SqlNode node, RelDataType type) {
return type;
}
@Override public void findAllColumnNames(List result) {
}
public void findAllTableNames(List result) {
}
@Override public void findAliases(Collection result) {
}
@Override public @Nullable RelDataType resolveColumn(String name, SqlNode ctx) {
return null;
}
@Override public SqlValidatorScope getOperandScope(SqlCall call) {
return this;
}
@Override public void validateExpr(SqlNode expr) {
// valid
}
@SuppressWarnings("deprecation")
@Override public Pair findQualifyingTableName(
String columnName, SqlNode ctx) {
throw validator.newValidationError(ctx,
RESOURCE.columnNotFound(columnName));
}
@Override public Map findQualifyingTableNames(String columnName,
SqlNode ctx, SqlNameMatcher nameMatcher) {
return ImmutableMap.of();
}
@Override public void addChild(SqlValidatorNamespace ns, String alias,
boolean nullable) {
// cannot add to the empty scope
throw new UnsupportedOperationException();
}
@Override public @Nullable SqlWindow lookupWindow(String name) {
// No windows defined in this scope.
return null;
}
@Override public SqlMonotonicity getMonotonicity(SqlNode expr) {
return
((expr instanceof SqlLiteral)
|| (expr instanceof SqlDynamicParam)
|| (expr instanceof SqlDataTypeSpec)) ? SqlMonotonicity.CONSTANT
: SqlMonotonicity.NOT_MONOTONIC;
}
@Override public @Nullable SqlNodeList getOrderList() {
// scope is not ordered
return null;
}
}