blob: 8603b208defea42cdbb310f667d2a5a5f199f782 [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.List;
import java.util.Map;
import java.util.Set;
import org.apache.drill.common.expression.LogicalExpression;
import org.apache.drill.common.expression.MajorTypeInLogicalExpression;
import org.apache.drill.common.types.TypeProtos.DataMode;
import org.apache.drill.common.types.TypeProtos.MajorType;
import org.apache.drill.common.types.TypeProtos.MinorType;
import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
import org.apache.drill.exec.expr.fn.DrillFuncHolder;
import org.apache.drill.shaded.guava.com.google.common.collect.Lists;
import org.apache.drill.shaded.guava.com.google.common.collect.Sets;
import static org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM;
public class TypeCastRules {
private static Map<MinorType, Set<MinorType>> rules;
public TypeCastRules() {
}
static {
initTypeRules();
}
private static void initTypeRules() {
rules = new HashMap<>();
Set<MinorType> rule;
/** TINYINT cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
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.FIXEDBINARY);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.TINYINT, rule);
/** SMALLINT cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
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.FIXEDBINARY);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.SMALLINT, rule);
/** INT cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
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.FIXEDBINARY);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.INT, rule);
/** BIGINT cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
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.FIXEDBINARY);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.BIGINT, rule);
/** UINT4 cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
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.FIXEDBINARY);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.UINT4, rule);
/** UINT8 cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
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.FIXEDBINARY);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.UINT8, rule);
/** DECIMAL9 cast able from **/
rule = new HashSet<>();
rule.add(MinorType.DECIMAL9);
rule.add(MinorType.VARDECIMAL);
rules.put(MinorType.DECIMAL9, rule);
/** DECIMAL18 cast able from **/
rule = new HashSet<>();
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.VARDECIMAL);
rules.put(MinorType.DECIMAL18, rule);
/** DECIMAL28Dense cast able from **/
rule = new HashSet<>();
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.VARDECIMAL);
rules.put(MinorType.DECIMAL28DENSE, rule);
/** DECIMAL28Sparse cast able from **/
rule = new HashSet<>();
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.VARDECIMAL);
rules.put(MinorType.DECIMAL28SPARSE, rule);
/* VARDECIMAL cast able from **/
rule = new HashSet<>();
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);
rules.put(MinorType.VARDECIMAL, rule);
/** DECIMAL38Dense cast able from **/
rule = new HashSet<>();
rule.add(MinorType.DECIMAL38DENSE);
rule.add(MinorType.VARDECIMAL);
rules.put(MinorType.DECIMAL38DENSE, rule);
/** DECIMAL38Sparse cast able from **/
rule = new HashSet<>();
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.VARDECIMAL);
rules.put(MinorType.DECIMAL38SPARSE, rule);
/** MONEY cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
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.FIXEDBINARY);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.MONEY, rule);
/** DATE cast able from **/
rule = new HashSet<>();
rule.add(MinorType.DATE);
rule.add(MinorType.TIMESTAMP);
rule.add(MinorType.TIMESTAMPTZ);
rule.add(MinorType.FIXEDCHAR);
rule.add(MinorType.FIXED16CHAR);
rule.add(MinorType.FIXEDBINARY);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.DATE, rule);
/** TIME cast able from **/
rule = new HashSet<>();
rule.add(MinorType.TIME);
rule.add(MinorType.DATE);
rule.add(MinorType.TIMESTAMP);
rule.add(MinorType.TIMESTAMPTZ);
rule.add(MinorType.FIXEDCHAR);
rule.add(MinorType.FIXED16CHAR);
rule.add(MinorType.FIXEDBINARY);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.TIME, rule);
/** TIMESTAMP cast able from **/
rule = new HashSet<>();
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VARBINARY);
rule.add(MinorType.TIMESTAMP);
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.DATE);
rule.add(MinorType.TIMESTAMPTZ);
rules.put(MinorType.TIMESTAMP, rule);
/** TIMESTAMPTZ cast able from **/
rule = new HashSet<>();
rule.add(MinorType.TIMESTAMPTZ);
rule.add(MinorType.DATE);
rule.add(MinorType.TIMESTAMP);
rule.add(MinorType.TIME);
rule.add(MinorType.FIXEDCHAR);
rule.add(MinorType.FIXED16CHAR);
rule.add(MinorType.FIXEDBINARY);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.TIMESTAMPTZ, rule);
/** Interval cast able from **/
rule = new HashSet<>();
rule.add(MinorType.INTERVAL);
rule.add(MinorType.INTERVALDAY);
rule.add(MinorType.INTERVALYEAR);
rule.add(MinorType.DATE);
rule.add(MinorType.TIMESTAMP);
rule.add(MinorType.TIMESTAMPTZ);
rule.add(MinorType.FIXEDCHAR);
rule.add(MinorType.FIXED16CHAR);
rule.add(MinorType.FIXEDBINARY);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.INTERVAL, rule);
/** INTERVAL YEAR cast able from **/
rule = new HashSet<>();
rule.add(MinorType.INTERVALYEAR);
rule.add(MinorType.INTERVAL);
rule.add(MinorType.INTERVALDAY);
rule.add(MinorType.DATE);
rule.add(MinorType.TIMESTAMP);
rule.add(MinorType.TIMESTAMPTZ);
rule.add(MinorType.FIXEDCHAR);
rule.add(MinorType.FIXED16CHAR);
rule.add(MinorType.FIXEDBINARY);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.INTERVALYEAR, rule);
/** INTERVAL DAY cast able from **/
rule = new HashSet<>();
rule.add(MinorType.INTERVALDAY);
rule.add(MinorType.INTERVALYEAR);
rule.add(MinorType.INTERVAL);
rule.add(MinorType.DATE);
rule.add(MinorType.TIMESTAMP);
rule.add(MinorType.TIMESTAMPTZ);
rule.add(MinorType.FIXEDCHAR);
rule.add(MinorType.FIXED16CHAR);
rule.add(MinorType.FIXEDBINARY);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.INTERVALDAY, rule);
/** FLOAT4 cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
rule.add(MinorType.VARDECIMAL);
rule.add(MinorType.MONEY);
rule.add(MinorType.FLOAT4);
rule.add(MinorType.BIT);
rule.add(MinorType.FIXEDCHAR);
rule.add(MinorType.FIXED16CHAR);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rules.put(MinorType.FLOAT4, rule);
/** FLOAT8 cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
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.VAR16CHAR);
rules.put(MinorType.FLOAT8, rule);
/** BIT cast able from **/
rule = new HashSet<>();
rule.add(MinorType.TINYINT);
rule.add(MinorType.BIT);
rule.add(MinorType.FIXEDCHAR);
rule.add(MinorType.FIXED16CHAR);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rules.put(MinorType.BIT, rule);
/** FIXEDCHAR cast able from **/
rule = new HashSet<>();
rule.add(MinorType.TINYINT);
rule.add(MinorType.SMALLINT);
rule.add(MinorType.INT);
rule.add(MinorType.BIGINT);
rule.add(MinorType.MONEY);
rule.add(MinorType.UINT1);
rule.add(MinorType.UINT2);
rule.add(MinorType.UINT4);
rule.add(MinorType.UINT8);
rule.add(MinorType.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
rule.add(MinorType.VARDECIMAL);
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.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rule.add(MinorType.FIXEDBINARY);
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);
rules.put(MinorType.FIXEDCHAR, rule);
/** FIXED16CHAR cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
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.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rule.add(MinorType.FIXEDBINARY);
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);
rules.put(MinorType.FIXED16CHAR, rule);
/** FIXEDBINARY cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
rule.add(MinorType.VARDECIMAL);
rule.add(MinorType.MONEY);
rule.add(MinorType.FLOAT4);
rule.add(MinorType.FLOAT8);
rule.add(MinorType.BIT);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rule.add(MinorType.FIXEDBINARY);
rules.put(MinorType.FIXEDBINARY, rule);
/** VARCHAR cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
rule.add(MinorType.VARDECIMAL);
rule.add(MinorType.MONEY);
rule.add(MinorType.TIMESTAMPTZ);
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.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rule.add(MinorType.FIXEDBINARY);
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);
rules.put(MinorType.VARCHAR, rule);
/** VAR16CHAR cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
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.VAR16CHAR);
rule.add(MinorType.VARBINARY);
rule.add(MinorType.FIXEDBINARY);
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);
rules.put(MinorType.VAR16CHAR, rule);
/** VARBINARY cast able from **/
rule = new HashSet<>();
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.DECIMAL9);
rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
rule.add(MinorType.VARDECIMAL);
rule.add(MinorType.MONEY);
rule.add(MinorType.TIMESTAMP);
rule.add(MinorType.TIMESTAMPTZ);
rule.add(MinorType.FLOAT4);
rule.add(MinorType.FLOAT8);
rule.add(MinorType.BIT);
rule.add(MinorType.VARCHAR);
rule.add(MinorType.VARBINARY);
rule.add(MinorType.FIXEDBINARY);
rules.put(MinorType.VARBINARY, rule);
rules.put(MinorType.MAP, Sets.newHashSet(MinorType.MAP));
rules.put(MinorType.LIST, Sets.newHashSet(MinorType.LIST));
rules.put(MinorType.UNION, Sets.newHashSet(MinorType.UNION));
rules.put(MinorType.DICT, Sets.newHashSet(MinorType.DICT));
}
public static boolean isCastableWithNullHandling(MajorType from, MajorType to, NullHandling nullHandling) {
if ((from.getMode() == DataMode.REPEATED || to.getMode() == DataMode.REPEATED) && from.getMode() != to.getMode()) {
return false;
}
if (nullHandling == NullHandling.INTERNAL && from.getMode() != to.getMode()) {
return false;
}
return isCastable(from.getMinorType(), to.getMinorType());
}
public static boolean isCastable(MinorType from, MinorType to) {
return from.equals(MinorType.NULL) || //null could be casted to any other type.
(rules.get(to) != null && rules.get(to).contains(from));
}
public static DataMode getLeastRestrictiveDataMode(List<DataMode> dataModes) {
boolean hasOptional = false;
for(DataMode dataMode : dataModes) {
switch (dataMode) {
case REPEATED:
return dataMode;
case OPTIONAL:
hasOptional = true;
}
}
if(hasOptional) {
return DataMode.OPTIONAL;
} else {
return DataMode.REQUIRED;
}
}
/*
* Function checks if casting is allowed from the 'from' -> 'to' minor type. If its allowed
* we also check if the precedence map allows such a cast and return true if both cases are satisfied
*/
public static MinorType getLeastRestrictiveType(List<MinorType> types) {
assert types.size() >= 2;
MinorType result = types.get(0);
if (result == MinorType.UNION) {
return result;
}
int resultPrec = ResolverTypePrecedence.precedenceMap.get(result);
for (int i = 1; i < types.size(); i++) {
MinorType next = types.get(i);
if (next == MinorType.UNION) {
return next;
}
if (next == result) {
// both args are of the same type; continue
continue;
}
int nextPrec = ResolverTypePrecedence.precedenceMap.get(next);
if (isCastable(next, result) && resultPrec >= nextPrec) {
// result is the least restrictive between the two args; nothing to do continue
continue;
} else if(isCastable(result, next) && nextPrec >= resultPrec) {
result = next;
resultPrec = nextPrec;
} else {
return null;
}
}
return result;
}
private static final int DATAMODE_CAST_COST = 1;
private static final int VARARG_COST = Integer.MAX_VALUE / 2;
/**
* Decide whether it's legal to do implicit cast. -1 : not allowed for
* implicit cast > 0: cost associated with implicit cast. ==0: params are
* exactly same type of arg. No need of implicit.
*/
public static int getCost(List<MajorType> argumentTypes, DrillFuncHolder holder) {
int cost = 0;
if (argumentTypes.size() != holder.getParamCount() && !holder.isVarArg()) {
return -1;
}
// Indicates whether we used secondary cast rules
boolean secondaryCast = false;
// number of arguments that could implicitly casts using precedence map or
// didn't require casting at all
int nCasts = 0;
/*
* If we are determining function holder for decimal data type, we need to
* make sure the output type of the function can fit the precision that we
* need based on the input types.
*/
if (holder.checkPrecisionRange()) {
List<LogicalExpression> logicalExpressions = Lists.newArrayList();
for(MajorType majorType : argumentTypes) {
logicalExpressions.add(
new MajorTypeInLogicalExpression(majorType));
}
if (DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision() <
holder.getReturnType(logicalExpressions).getPrecision()) {
return -1;
}
}
final int numOfArgs = argumentTypes.size();
for (int i = 0; i < numOfArgs; i++) {
final MajorType argType = argumentTypes.get(i);
final MajorType paramType = holder.getParamMajorType(i);
//@Param FieldReader will match any type
if (holder.isFieldReader(i)) {
// if (Types.isComplex(call.args.get(i).getMajorType()) ||Types.isRepeated(call.args.get(i).getMajorType()) )
// add the max cost when encountered with a field reader considering
// that it is the most expensive factor contributing to the cost.
cost += ResolverTypePrecedence.MAX_IMPLICIT_CAST_COST;
continue;
}
if (!TypeCastRules.isCastableWithNullHandling(argType, paramType, holder.getNullHandling())) {
return -1;
}
Integer paramVal = ResolverTypePrecedence.precedenceMap.get(paramType
.getMinorType());
Integer argVal = ResolverTypePrecedence.precedenceMap.get(argType
.getMinorType());
if (paramVal == null) {
throw new RuntimeException(String.format(
"Precedence for type %s is not defined", paramType.getMinorType().name()));
}
if (argVal == null) {
throw new RuntimeException(String.format(
"Precedence for type %s is not defined", argType.getMinorType().name()));
}
if (paramVal - argVal < 0) {
/* Precedence rules do not allow to implicit cast, however check
* if the secondary rules allow us to cast
*/
Set<MinorType> rules;
if ((rules = (ResolverTypePrecedence.secondaryImplicitCastRules.get(paramType.getMinorType()))) != null
&& rules.contains(argType.getMinorType())) {
secondaryCast = true;
} else {
return -1;
}
}
// Check null vs non-null, using same logic as that in Types.softEqual()
// Only when the function uses NULL_IF_NULL, nullable and non-nullable are interchangeable.
// Otherwise, the function implementation is not a match.
if (argType.getMode() != paramType.getMode()) {
// TODO - this does not seem to do what it is intended to
// if (!((holder.getNullHandling() == NullHandling.NULL_IF_NULL) &&
// (argType.getMode() == DataMode.OPTIONAL ||
// argType.getMode() == DataMode.REQUIRED ||
// paramType.getMode() == DataMode.OPTIONAL ||
// paramType.getMode() == DataMode.REQUIRED )))
// return -1;
// if the function is designed to take optional with custom null handling, and a required
// is being passed, increase the cost to account for a null check
// this allows for a non-nullable implementation to be preferred
if (holder.getNullHandling() == NullHandling.INTERNAL) {
// a function that expects required output, but nullable was provided
if (paramType.getMode() == DataMode.REQUIRED && argType.getMode() == DataMode.OPTIONAL) {
return -1;
} else if (paramType.getMode() == DataMode.OPTIONAL && argType.getMode() == DataMode.REQUIRED) {
cost+= DATAMODE_CAST_COST;
}
}
}
int castCost;
if ((castCost = (paramVal - argVal)) >= 0) {
nCasts++;
cost += castCost;
}
}
if (holder.isVarArg()) {
int varArgIndex = holder.getParamCount() - 1;
for (int i = varArgIndex; i < numOfArgs; i++) {
if (holder.isFieldReader(varArgIndex)) {
break;
} else if (holder.getParamMajorType(varArgIndex).getMode() != argumentTypes.get(i).getMode()) {
// prohibit using vararg functions for types with different nullability
return -1;
}
}
// increase cost for var arg functions to prioritize regular ones
Integer additionalCost = ResolverTypePrecedence.precedenceMap.get(holder.getParamMajorType(varArgIndex).getMinorType());
cost += additionalCost != null ? additionalCost : VARARG_COST;
cost += holder.getParamMajorType(varArgIndex).getMode() == DataMode.REQUIRED ? 0 : 1;
}
if (secondaryCast) {
// We have a secondary cast for one or more of the arguments, determine the cost associated
int secondaryCastCost = Integer.MAX_VALUE - 1;
// Subtract maximum possible implicit costs from the secondary cast cost
secondaryCastCost -= (nCasts * (ResolverTypePrecedence.MAX_IMPLICIT_CAST_COST + DATAMODE_CAST_COST));
// Add cost of implicitly casting the rest of the arguments that didn't use secondary casting
secondaryCastCost += cost;
return secondaryCastCost;
}
return cost;
}
/*
* Simple helper function to determine if input type is numeric
*/
public static boolean isNumericType(MinorType inputType) {
switch (inputType) {
case TINYINT:
case SMALLINT:
case INT:
case BIGINT:
case UINT1:
case UINT2:
case UINT4:
case UINT8:
case DECIMAL9:
case DECIMAL18:
case DECIMAL28SPARSE:
case DECIMAL38SPARSE:
case VARDECIMAL:
case FLOAT4:
case FLOAT8:
return true;
default:
return false;
}
}
}