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

com.hazelcast.org.apache.calcite.sql.validate.AliasNamespace 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.validate;

import com.hazelcast.org.apache.calcite.rel.type.RelDataType;
import com.hazelcast.org.apache.calcite.rel.type.RelDataTypeFactoryImpl;
import com.hazelcast.org.apache.calcite.rel.type.RelDataTypeField;
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.fun.SqlStdOperatorTable;
import com.hazelcast.org.apache.calcite.sql.parser.SqlParserPos;
import com.hazelcast.org.apache.calcite.util.Pair;
import com.hazelcast.org.apache.calcite.util.Util;

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

import java.util.List;

import static com.hazelcast.org.apache.calcite.util.Static.RESOURCE;

/**
 * Namespace for an AS t(c1, c2, ...) clause.
 *
 * 

A namespace is necessary only if there is a column list, in order to * re-map column names; a relation AS t clause just uses the same * namespace as relation. */ public class AliasNamespace extends AbstractNamespace { //~ Instance fields -------------------------------------------------------- protected final SqlCall call; //~ Constructors ----------------------------------------------------------- /** * Creates an AliasNamespace. * * @param validator Validator * @param call Call to AS operator * @param enclosingNode Enclosing node */ protected AliasNamespace( SqlValidatorImpl validator, SqlCall call, SqlNode enclosingNode) { super(validator, enclosingNode); this.call = call; assert call.getOperator() == SqlStdOperatorTable.AS; assert call.operandCount() >= 2; } //~ Methods ---------------------------------------------------------------- @Override public boolean supportsModality(SqlModality modality) { final List operands = call.getOperandList(); final SqlValidatorNamespace childNs = validator.getNamespaceOrThrow(operands.get(0)); return childNs.supportsModality(modality); } @Override protected RelDataType validateImpl(RelDataType targetRowType) { final List operands = call.getOperandList(); final SqlValidatorNamespace childNs = validator.getNamespaceOrThrow(operands.get(0)); final RelDataType rowType = childNs.getRowTypeSansSystemColumns(); final RelDataType aliasedType; if (operands.size() == 2) { // Alias is 'AS t' (no column list). // If the sub-query is UNNEST or VALUES, // and the sub-query has one column, // then the namespace's sole column is named after the alias. if (rowType.getFieldCount() == 1) { aliasedType = validator.getTypeFactory().builder() .kind(rowType.getStructKind()) .add(((SqlIdentifier) operands.get(1)).getSimple(), rowType.getFieldList().get(0).getType()) .build(); } else { aliasedType = rowType; } } else { // Alias is 'AS t (c0, ..., cN)' final List columnNames = Util.skip(operands, 2); final List nameList = SqlIdentifier.simpleNames(columnNames); final int i = Util.firstDuplicate(nameList); if (i >= 0) { final SqlIdentifier id = (SqlIdentifier) columnNames.get(i); throw validator.newValidationError(id, RESOURCE.aliasListDuplicate(id.getSimple())); } if (columnNames.size() != rowType.getFieldCount()) { // Position error over all column names final SqlNode node = operands.size() == 3 ? operands.get(2) : new SqlNodeList(columnNames, SqlParserPos.sum(columnNames)); throw validator.newValidationError(node, RESOURCE.aliasListDegree(rowType.getFieldCount(), getString(rowType), columnNames.size())); } aliasedType = validator.getTypeFactory().builder() .addAll( Util.transform(rowType.getFieldList(), f -> Pair.of(nameList.get(f.getIndex()), f.getType()))) .kind(rowType.getStructKind()) .build(); } // As per suggestion in CALCITE-4085, JavaType has its special nullability handling. if (rowType instanceof RelDataTypeFactoryImpl.JavaType) { return aliasedType; } else { return validator.getTypeFactory() .createTypeWithNullability(aliasedType, rowType.isNullable()); } } private static String getString(RelDataType rowType) { StringBuilder buf = new StringBuilder(); buf.append("("); for (RelDataTypeField field : rowType.getFieldList()) { if (field.getIndex() > 0) { buf.append(", "); } buf.append("'"); buf.append(field.getName()); buf.append("'"); } buf.append(")"); return buf.toString(); } @Override public @Nullable SqlNode getNode() { return call; } @Override public String translate(String name) { final RelDataType underlyingRowType = validator.getValidatedNodeType(call.operand(0)); int i = 0; for (RelDataTypeField field : getRowType().getFieldList()) { if (field.getName().equals(name)) { return underlyingRowType.getFieldList().get(i).getName(); } ++i; } throw new AssertionError("unknown field '" + name + "' in rowtype " + underlyingRowType); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy