This is an automated email from the ASF dual-hosted git repository. timothyfarkas pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/drill.git
commit 4124b41a09ba2197957539a35dd8ae4c52ad2e15 Author: Volodymyr Vysotskyi <[email protected]> AuthorDate: Thu Nov 1 18:31:16 2018 +0200 DRILL-4456: Add Hive translate UDF closes #1527 --- .../drill/exec/expr/fn/HiveFunctionRegistry.java | 45 ++++++++++++++-------- .../drill/exec/fn/hive/TestInbuiltHiveUDFs.java | 13 +++++++ 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/expr/fn/HiveFunctionRegistry.java b/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/expr/fn/HiveFunctionRegistry.java index cb00ede..0ec9778 100644 --- a/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/expr/fn/HiveFunctionRegistry.java +++ b/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/expr/fn/HiveFunctionRegistry.java @@ -20,9 +20,12 @@ package org.apache.drill.exec.expr.fn; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.stream.Stream; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.sql.SqlOperatorBinding; +import org.apache.calcite.sql.fun.OracleSqlOperatorTable; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.type.SqlReturnTypeInference; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.drill.common.config.DrillConfig; @@ -38,6 +41,7 @@ import org.apache.drill.exec.planner.sql.DrillOperatorTable; import org.apache.drill.exec.planner.sql.HiveUDFOperator; import org.apache.drill.exec.planner.sql.HiveUDFOperatorWithoutInference; import org.apache.drill.exec.planner.sql.TypeInferenceUtils; +import org.apache.drill.shaded.guava.com.google.common.collect.ImmutableMap; import org.apache.hadoop.hive.ql.exec.Description; import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.hive.ql.udf.UDFType; @@ -48,8 +52,18 @@ import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.drill.shaded.guava.com.google.common.collect.ArrayListMultimap; import org.apache.drill.shaded.guava.com.google.common.collect.Sets; -public class HiveFunctionRegistry implements PluggableFunctionRegistry{ - static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(HiveFunctionRegistry.class); +public class HiveFunctionRegistry implements PluggableFunctionRegistry { + private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(HiveFunctionRegistry.class); + + /** + * Map for renaming UDFs. Keys of the map represent UDF names which should be replaced + * and its values represent target UDF names. + */ + private static final Map<String, String> FUNCTION_REPLACE_MAP = ImmutableMap.<String, String> builder() + // renames Hive's TRANSLATE UDF to TRANSLATE3 due to CALCITE-1115 + .put(SqlStdOperatorTable.TRANSLATE.getName().toLowerCase(), + OracleSqlOperatorTable.TRANSLATE3.getName().toLowerCase()) + .build(); private ArrayListMultimap<String, Class<? extends GenericUDF>> methodsGenericUDF = ArrayListMultimap.create(); private ArrayListMultimap<String, Class<? extends UDF>> methodsUDF = ArrayListMultimap.create(); @@ -102,27 +116,28 @@ public class HiveFunctionRegistry implements PluggableFunctionRegistry{ } } - private <C,I> void register(Class<? extends I> clazz, ArrayListMultimap<String,Class<? extends I>> methods) { + private <I> void register(Class<? extends I> clazz, ArrayListMultimap<String, Class<? extends I>> methods) { Description desc = clazz.getAnnotation(Description.class); - String[] names; + Stream<String> namesStream; if (desc != null) { - names = desc.name().split(","); - for (int i=0; i<names.length; i++) { - names[i] = names[i].trim(); - } - }else{ - names = new String[]{clazz.getName().replace('.', '_')}; + namesStream = Stream.of(desc.name().split(",")) + .map(String::trim); + } else { + namesStream = Stream.of(clazz) + .map(Class::getName) + .map(name -> name.replace('.', '_')); } + // Checks specified array of function names whether they should be replaced + // using FUNCTION_REPLACE_MAP map. + namesStream.map(String::toLowerCase) + .map(functionName -> FUNCTION_REPLACE_MAP.getOrDefault(functionName, functionName)) + .forEach(name -> methods.put(name, clazz)); + UDFType type = clazz.getAnnotation(UDFType.class); if (type != null && !type.deterministic()) { nonDeterministicUDFs.add(clazz); } - - - for(int i=0; i<names.length;i++) { - methods.put(names[i].toLowerCase(), clazz); - } } /** diff --git a/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/fn/hive/TestInbuiltHiveUDFs.java b/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/fn/hive/TestInbuiltHiveUDFs.java index c74a7c4..43c3e3f 100644 --- a/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/fn/hive/TestInbuiltHiveUDFs.java +++ b/contrib/storage-hive/core/src/test/java/org/apache/drill/exec/fn/hive/TestInbuiltHiveUDFs.java @@ -184,4 +184,17 @@ public class TestInbuiltHiveUDFs extends HiveTestBase { .go(); } + @Test // DRILL-4456 + public void testTranslate3() throws Exception { + testBuilder() + .sqlQuery("SELECT translate(string_field, 's', 'S') as ts," + + "translate(varchar_field, 'v', 'V') as tv,\n" + + "translate('literal', 'l', 'L') as tl from hive.readtest") + .unOrdered() + .baselineColumns("ts", "tv", "tl") + .baselineValues("Stringfield", "Varcharfield", "LiteraL") + .baselineValues(null, null, "LiteraL") + .go(); + } + }
