blob: bf0bb224859a250467d6739f9e8c3531af4b4289 [file] [log] [blame]
/*
* 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.drill.exec.resolver;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.drill.common.types.TypeProtos.MinorType;
public class ResolverTypePrecedence {
public static final Map<MinorType, Integer> precedenceMap;
public static final Map<MinorType, Set<MinorType>> secondaryImplicitCastRules;
public static int MAX_IMPLICIT_CAST_COST;
static {
/* The precedenceMap is used to decide whether it's allowed to implicitly "promote"
* one type to another type.
*
* The order that each type is inserted into HASHMAP decides its precedence.
* First in ==> lowest precedence.
* A type of lower precedence can be implicitly "promoted" to type of higher precedence.
* For instance, NULL could be promoted to any other type;
* tinyint could be promoted into int; but int could NOT be promoted into tinyint (due to possible precision loss).
*/
int i = 0;
precedenceMap = new HashMap<>();
precedenceMap.put(MinorType.NULL, i += 2); // NULL is legal to implicitly be promoted to any other type
precedenceMap.put(MinorType.FIXEDBINARY, i += 2); // Fixed-length is promoted to var length
precedenceMap.put(MinorType.VARBINARY, i += 2);
precedenceMap.put(MinorType.FIXEDCHAR, i += 2);
precedenceMap.put(MinorType.VARCHAR, i += 2);
precedenceMap.put(MinorType.FIXED16CHAR, i += 2);
precedenceMap.put(MinorType.VAR16CHAR, i += 2);
precedenceMap.put(MinorType.BIT, i += 2);
precedenceMap.put(MinorType.TINYINT, i += 2); //type with few bytes is promoted to type with more bytes ==> no data loss.
precedenceMap.put(MinorType.UINT1, i += 2); //signed is legal to implicitly be promoted to unsigned.
precedenceMap.put(MinorType.SMALLINT, i += 2);
precedenceMap.put(MinorType.UINT2, i += 2);
precedenceMap.put(MinorType.INT, i += 2);
precedenceMap.put(MinorType.UINT4, i += 2);
precedenceMap.put(MinorType.BIGINT, i += 2);
precedenceMap.put(MinorType.UINT8, i += 2);
precedenceMap.put(MinorType.MONEY, i += 2);
precedenceMap.put(MinorType.FLOAT4, i += 2);
precedenceMap.put(MinorType.DECIMAL9, i += 2);
precedenceMap.put(MinorType.DECIMAL18, i += 2);
precedenceMap.put(MinorType.DECIMAL28DENSE, i += 2);
precedenceMap.put(MinorType.DECIMAL28SPARSE, i += 2);
precedenceMap.put(MinorType.DECIMAL38DENSE, i += 2);
precedenceMap.put(MinorType.DECIMAL38SPARSE, i += 2);
precedenceMap.put(MinorType.VARDECIMAL, i += 2);
precedenceMap.put(MinorType.FLOAT8, i += 2);
precedenceMap.put(MinorType.DATE, i += 2);
precedenceMap.put(MinorType.TIMESTAMP, i += 2);
precedenceMap.put(MinorType.TIMETZ, i += 2);
precedenceMap.put(MinorType.TIMESTAMPTZ, i += 2);
precedenceMap.put(MinorType.TIME, i += 2);
precedenceMap.put(MinorType.INTERVALDAY, i+= 2);
precedenceMap.put(MinorType.INTERVALYEAR, i+= 2);
precedenceMap.put(MinorType.INTERVAL, i+= 2);
precedenceMap.put(MinorType.MAP, i += 2);
precedenceMap.put(MinorType.DICT, i += 2);
precedenceMap.put(MinorType.LIST, i += 2);
precedenceMap.put(MinorType.UNION, i += 2);
MAX_IMPLICIT_CAST_COST = i;
/* Currently implicit cast follows the precedence rules.
* It may be useful to perform an implicit cast in
* the opposite direction as specified by the precedence rules.
*
* For example: As per the precedence rules we can implicitly cast
* from VARCHAR ---> BIGINT , but based upon some functions (eg: substr, concat)
* it may be useful to implicitly cast from BIGINT ---> VARCHAR.
*
* To allow for such cases we have a secondary set of rules which will allow the reverse
* implicit casts. Currently we only allow the reverse implicit cast to VARCHAR so we don't
* need any cost associated with it, if we add more of these that may collide we can add costs.
*/
secondaryImplicitCastRules = new HashMap<>();
HashSet<MinorType> rule = new HashSet<>();
// Following cast functions should exist
rule.add(MinorType.TINYINT);
rule.add(MinorType.SMALLINT);
rule.add(MinorType.INT);
rule.add(MinorType.BIGINT);
rule.add(MinorType.UINT1);
rule.add(MinorType.UINT2);
rule.add(MinorType.UINT4);
rule.add(MinorType.UINT8);
rule.add(MinorType.VARDECIMAL);
rule.add(MinorType.MONEY);
rule.add(MinorType.FLOAT4);
rule.add(MinorType.FLOAT8);
rule.add(MinorType.BIT);
rule.add(MinorType.FIXEDCHAR);
rule.add(MinorType.FIXED16CHAR);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.DATE);
rule.add(MinorType.TIME);
rule.add(MinorType.TIMESTAMP);
rule.add(MinorType.TIMESTAMPTZ);
rule.add(MinorType.INTERVAL);
rule.add(MinorType.INTERVALYEAR);
rule.add(MinorType.INTERVALDAY);
secondaryImplicitCastRules.put(MinorType.VARCHAR, rule);
rule = new HashSet<>();
// Be able to implicitly cast to VARBINARY
rule.add(MinorType.INT);
rule.add(MinorType.BIGINT);
rule.add(MinorType.FLOAT4);
rule.add(MinorType.FLOAT8);
rule.add(MinorType.VARCHAR);
secondaryImplicitCastRules.put(MinorType.VARBINARY, rule);
rule = new HashSet<>();
// Be able to implicitly cast to VARDECIMAL
rule.add(MinorType.FLOAT8);
secondaryImplicitCastRules.put(MinorType.VARDECIMAL, rule);
rule = new HashSet<>();
// Be able to implicitly cast to DECIMAL9
rule.add(MinorType.VARDECIMAL);
secondaryImplicitCastRules.put(MinorType.DECIMAL9, rule);
rule = new HashSet<>();
// Be able to implicitly cast to DECIMAL18
rule.add(MinorType.VARDECIMAL);
secondaryImplicitCastRules.put(MinorType.DECIMAL18, rule);
rule = new HashSet<>();
// Be able to implicitly cast to DECIMAL28SPARSE
rule.add(MinorType.VARDECIMAL);
secondaryImplicitCastRules.put(MinorType.DECIMAL28SPARSE, rule);
rule = new HashSet<>();
// Be able to implicitly cast to DECIMAL38SPARSE
rule.add(MinorType.VARDECIMAL);
secondaryImplicitCastRules.put(MinorType.DECIMAL38SPARSE, rule);
}
}