| /* |
| * 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.type; |
| |
| import org.apache.calcite.rel.type.RelDataType; |
| import org.apache.calcite.rel.type.RelDataTypePrecedenceList; |
| import org.apache.calcite.util.Glossary; |
| import org.apache.calcite.util.ImmutableNullableList; |
| import org.apache.calcite.util.Util; |
| |
| import com.google.common.collect.ImmutableMap; |
| |
| import org.checkerframework.checker.nullness.qual.Nullable; |
| |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * SqlTypeExplicitPrecedenceList implements the |
| * {@link RelDataTypePrecedenceList} interface via an explicit list of |
| * {@link SqlTypeName} entries. |
| */ |
| public class SqlTypeExplicitPrecedenceList |
| implements RelDataTypePrecedenceList { |
| //~ Static fields/initializers --------------------------------------------- |
| |
| private static final List<SqlTypeName> NUMERIC_TYPES = |
| ImmutableNullableList.of( |
| SqlTypeName.TINYINT, |
| SqlTypeName.SMALLINT, |
| SqlTypeName.INTEGER, |
| SqlTypeName.BIGINT, |
| SqlTypeName.DECIMAL, |
| SqlTypeName.REAL, |
| SqlTypeName.FLOAT, |
| SqlTypeName.DOUBLE); |
| |
| /** |
| * Map from SqlTypeName to corresponding precedence list. |
| * |
| * @see Glossary#SQL2003 SQL:2003 Part 2 Section 9.5 |
| */ |
| private static final Map<SqlTypeName, SqlTypeExplicitPrecedenceList> |
| TYPE_NAME_TO_PRECEDENCE_LIST = |
| ImmutableMap.<SqlTypeName, SqlTypeExplicitPrecedenceList>builder() |
| .put(SqlTypeName.BOOLEAN, list(SqlTypeName.BOOLEAN)) |
| .put(SqlTypeName.TINYINT, numeric(SqlTypeName.TINYINT)) |
| .put(SqlTypeName.SMALLINT, numeric(SqlTypeName.SMALLINT)) |
| .put(SqlTypeName.INTEGER, numeric(SqlTypeName.INTEGER)) |
| .put(SqlTypeName.BIGINT, numeric(SqlTypeName.BIGINT)) |
| .put(SqlTypeName.DECIMAL, numeric(SqlTypeName.DECIMAL)) |
| .put(SqlTypeName.REAL, numeric(SqlTypeName.REAL)) |
| .put( |
| SqlTypeName.FLOAT, list( |
| SqlTypeName.FLOAT, SqlTypeName.REAL, |
| SqlTypeName.DOUBLE, SqlTypeName.DECIMAL)) |
| .put( |
| SqlTypeName.DOUBLE, list( |
| SqlTypeName.FLOAT, SqlTypeName.REAL, |
| SqlTypeName.DOUBLE, SqlTypeName.DECIMAL)) |
| .put(SqlTypeName.CHAR, list(SqlTypeName.CHAR, SqlTypeName.VARCHAR)) |
| .put(SqlTypeName.VARCHAR, list(SqlTypeName.VARCHAR)) |
| .put(SqlTypeName.BINARY, |
| list(SqlTypeName.BINARY, SqlTypeName.VARBINARY)) |
| .put(SqlTypeName.VARBINARY, list(SqlTypeName.VARBINARY)) |
| .put(SqlTypeName.DATE, list(SqlTypeName.DATE)) |
| .put(SqlTypeName.TIME, list(SqlTypeName.TIME)) |
| .put(SqlTypeName.TIMESTAMP, |
| list(SqlTypeName.TIMESTAMP, SqlTypeName.DATE, SqlTypeName.TIME)) |
| .put(SqlTypeName.INTERVAL_YEAR, |
| list(SqlTypeName.YEAR_INTERVAL_TYPES)) |
| .put(SqlTypeName.INTERVAL_YEAR_MONTH, |
| list(SqlTypeName.YEAR_INTERVAL_TYPES)) |
| .put(SqlTypeName.INTERVAL_MONTH, |
| list(SqlTypeName.YEAR_INTERVAL_TYPES)) |
| .put(SqlTypeName.INTERVAL_DAY, |
| list(SqlTypeName.DAY_INTERVAL_TYPES)) |
| .put(SqlTypeName.INTERVAL_DAY_HOUR, |
| list(SqlTypeName.DAY_INTERVAL_TYPES)) |
| .put(SqlTypeName.INTERVAL_DAY_MINUTE, |
| list(SqlTypeName.DAY_INTERVAL_TYPES)) |
| .put(SqlTypeName.INTERVAL_DAY_SECOND, |
| list(SqlTypeName.DAY_INTERVAL_TYPES)) |
| .put(SqlTypeName.INTERVAL_HOUR, |
| list(SqlTypeName.DAY_INTERVAL_TYPES)) |
| .put(SqlTypeName.INTERVAL_HOUR_MINUTE, |
| list(SqlTypeName.DAY_INTERVAL_TYPES)) |
| .put(SqlTypeName.INTERVAL_HOUR_SECOND, |
| list(SqlTypeName.DAY_INTERVAL_TYPES)) |
| .put(SqlTypeName.INTERVAL_MINUTE, |
| list(SqlTypeName.DAY_INTERVAL_TYPES)) |
| .put(SqlTypeName.INTERVAL_MINUTE_SECOND, |
| list(SqlTypeName.DAY_INTERVAL_TYPES)) |
| .put(SqlTypeName.INTERVAL_SECOND, |
| list(SqlTypeName.DAY_INTERVAL_TYPES)) |
| .build(); |
| |
| //~ Instance fields -------------------------------------------------------- |
| |
| private final List<SqlTypeName> typeNames; |
| |
| //~ Constructors ----------------------------------------------------------- |
| |
| public SqlTypeExplicitPrecedenceList(Iterable<SqlTypeName> typeNames) { |
| this.typeNames = ImmutableNullableList.copyOf(typeNames); |
| } |
| |
| //~ Methods ---------------------------------------------------------------- |
| |
| private static SqlTypeExplicitPrecedenceList list(SqlTypeName... typeNames) { |
| return list(Arrays.asList(typeNames)); |
| } |
| |
| private static SqlTypeExplicitPrecedenceList list(Iterable<SqlTypeName> typeNames) { |
| return new SqlTypeExplicitPrecedenceList(typeNames); |
| } |
| |
| private static SqlTypeExplicitPrecedenceList numeric(SqlTypeName typeName) { |
| int i = getListPosition(typeName, NUMERIC_TYPES); |
| return new SqlTypeExplicitPrecedenceList( |
| Util.skip(NUMERIC_TYPES, i)); |
| } |
| |
| // implement RelDataTypePrecedenceList |
| @Override public boolean containsType(RelDataType type) { |
| SqlTypeName typeName = type.getSqlTypeName(); |
| return typeName != null && typeNames.contains(typeName); |
| } |
| |
| // implement RelDataTypePrecedenceList |
| @Override public int compareTypePrecedence(RelDataType type1, RelDataType type2) { |
| assert containsType(type1) : type1; |
| assert containsType(type2) : type2; |
| |
| int p1 = |
| getListPosition( |
| type1.getSqlTypeName(), |
| typeNames); |
| int p2 = |
| getListPosition( |
| type2.getSqlTypeName(), |
| typeNames); |
| return p2 - p1; |
| } |
| |
| private static int getListPosition(SqlTypeName type, List<SqlTypeName> list) { |
| int i = list.indexOf(type); |
| assert i != -1; |
| return i; |
| } |
| |
| static @Nullable RelDataTypePrecedenceList getListForType(RelDataType type) { |
| SqlTypeName typeName = type.getSqlTypeName(); |
| if (typeName == null) { |
| return null; |
| } |
| return TYPE_NAME_TO_PRECEDENCE_LIST.get(typeName); |
| } |
| } |