Index: ql/src/java/org/apache/hadoop/hive/ql/udf/generic/UDFSplitMapPrivs.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/UDFSplitMapPrivs.java (date 1587846935155) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/UDFSplitMapPrivs.java (date 1587846935155) @@ -0,0 +1,120 @@ +package org.apache.hadoop.hive.ql.udf.generic; + +import org.apache.hadoop.hive.ql.exec.Description; +import org.apache.hadoop.hive.ql.exec.UDFArgumentException; +import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.serde2.objectinspector.ConstantObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.apache.hadoop.io.Text; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.regex.Pattern; + +/** + * UDFSplitMapPrivs + * + */ + +@Description(name = "split_map_privs", value = "_FUNC_(str, regex) - Splits binary str and maps to privilege type " + + "regex", extended = "Example:\n" + + " > SELECT _FUNC_('0 1 1 0 1 1 0 0 0', ' ') FROM src LIMIT 1;\n" + + " [\"UPDATE\", \"CREATE\", \"ALTER\", \"INDEX\"]") + +class PrivilegeMap{ + private HashMap privilegeMap= new HashMap(); + + public HashMap getPrivilegeMap() { + + privilegeMap.put(0, "SELECT"); + privilegeMap.put(1, "UPDATE"); + privilegeMap.put(2, "CREATE"); + privilegeMap.put(3, "DROP"); + privilegeMap.put(4, "ALTER"); + privilegeMap.put(5, "INDEX"); + privilegeMap.put(6, "LOCK"); + privilegeMap.put(7, "READ"); + privilegeMap.put(8, "WRITE"); + privilegeMap.put(9, "ALL"); + + + return privilegeMap; + } +} + + + +public class UDFSplitMapPrivs extends GenericUDF { + private transient ObjectInspectorConverters.Converter[] converters; + private transient Pattern constPattern; + + private PrivilegeMap privsMap = new PrivilegeMap(); + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + if (arguments.length != 2) { + throw new UDFArgumentLengthException( + "The function split_map_privs(s, ' ') takes exactly 2 arguments."); + } + + converters = new ObjectInspectorConverters.Converter[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + converters[i] = ObjectInspectorConverters.getConverter(arguments[i], + PrimitiveObjectInspectorFactory.writableStringObjectInspector); + } + + ObjectInspector rightArg = arguments[1]; + if (rightArg instanceof ConstantObjectInspector) { + constPattern = Pattern.compile(((ConstantObjectInspector) rightArg). + getWritableConstantValue().toString()); + } + + return ObjectInspectorFactory + .getStandardListObjectInspector(PrimitiveObjectInspectorFactory + .writableStringObjectInspector); + } + + @Override + public Object evaluate(DeferredObject[] arguments) throws HiveException { + assert (arguments.length == 2); + + if (arguments[0].get() == null || arguments[1].get() == null) { + return null; + } + + Text s = (Text) converters[0].convert(arguments[0].get()); + ArrayList result = new ArrayList(); + int index = 0; + HashMap privs = privsMap.getPrivilegeMap(); + + + if (constPattern == null) { + Text regex = (Text) converters[1].convert(arguments[1].get()); + for (String str : s.toString().split(regex.toString(), -1)) { + if(str.equals("1")) { + result.add(new Text(privs.get(index))); + } + index++; + } + } else { + for (String str : constPattern.split(s.toString(), -1)) { + if(str.equals("1")) { + result.add(new Text(privs.get(index))); + } + index++; + } + } + return result; + } + + @Override + public String getDisplayString(String[] children) { + assert (children.length == 2); + return getStandardDisplayString("split", children); + } + +} \ No newline at end of file Index: ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestUDFSplitMapPrivs.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestUDFSplitMapPrivs.java (date 1587918489485) +++ ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestUDFSplitMapPrivs.java (date 1587918489485) @@ -0,0 +1,130 @@ +package org.apache.hadoop.hive.ql.udf.generic; + +import junit.framework.TestCase; + +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.apache.hadoop.io.Text; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; +import static org.apache.hadoop.hive.ql.udf.generic.GenericUDF.*; + + + +import static org.junit.Assert.*; +import static org.reflections.Reflections.log; + +public class TestUDFSplitMapPrivs extends TestCase { + private final UDFSplitMapPrivs udf = new UDFSplitMapPrivs(); + private Object p0 = new Text("SELECT"); + private Object p1 = new Text("UPDATE"); + private Object p2 = new Text("CREATE"); + private Object p3 = new Text("DROP"); + private Object p4 = new Text("ALTER"); + private Object p5 = new Text("INDEX"); + private Object p6 = new Text("LOCK"); + private Object p7 = new Text("READ"); + private Object p8 = new Text("WRITE"); + private Object p9 = new Text("All"); + + private DeferredObject splitDilimiter = new DeferredJavaObject(new Text(" ")); + + + + @Test + public void testBinaryStringSplitMapToPrivs() throws HiveException { + + ObjectInspector valueOI0 = PrimitiveObjectInspectorFactory.writableStringObjectInspector; + ObjectInspector valueOI1 = PrimitiveObjectInspectorFactory.writableStringObjectInspector; + ObjectInspector[] initArgs = {valueOI0, valueOI1}; + + udf.initialize(initArgs); + DeferredObject args; + DeferredObject[] evalArgs; + + args = new DeferredJavaObject(new Text("1 0 0 0 0 0 0 0 0 0")); + evalArgs = new DeferredObject[] { args, splitDilimiter }; + runAndVerify(asList(p0), evalArgs); + + args = new DeferredJavaObject(new Text("1 1 0 0 0 0 0 0 0 0")); + evalArgs = new DeferredObject[] { args, splitDilimiter }; + runAndVerify(asList(p0,p1),evalArgs); + + args = new DeferredJavaObject(new Text("1 1 1 0 0 0 0 0 0 0")); + evalArgs = new DeferredObject[] { args, splitDilimiter }; + runAndVerify(asList(p0,p1,p2), evalArgs); + + args = new DeferredJavaObject(new Text("1 1 1 1 0 0 0 0 0 0")); + evalArgs = new DeferredObject[] { args, splitDilimiter }; + runAndVerify(asList(p0,p1,p2,p3), evalArgs); + + args = new DeferredJavaObject(new Text("1 1 1 1 1 0 0 0 0 0")); + evalArgs = new DeferredObject[] { args, splitDilimiter }; + runAndVerify(asList(p0,p1,p2,p3,p4), evalArgs); + + args = new DeferredJavaObject(new Text("1 1 1 1 1 1 0 0 0 0")); + evalArgs = new DeferredObject[] { args, splitDilimiter }; + runAndVerify(asList(p0,p1,p2,p3,p4,p5), evalArgs); + + args = new DeferredJavaObject(new Text("1 1 1 1 1 1 1 0 0 0")); + evalArgs = new DeferredObject[] { args, splitDilimiter }; + runAndVerify(asList(p0,p1,p2,p3,p4,p5,p6), evalArgs); + + args = new DeferredJavaObject(new Text("1 1 1 1 1 1 1 1 0 0")); + evalArgs = new DeferredObject[] { args, splitDilimiter }; + runAndVerify(asList(p0,p1,p2,p3,p4,p5,p6,p7),evalArgs); + + args = new DeferredJavaObject(new Text("1 0 1 1 1 1 1 1 1 0")); + evalArgs = new DeferredObject[] { args, splitDilimiter }; + runAndVerify(asList(p0,p2,p3,p4,p5,p6,p7,p8), evalArgs); + + } + + @Test + public void BinaryStringMapingShouldFail() throws HiveException { + + ObjectInspector valueOI0 = PrimitiveObjectInspectorFactory.writableStringObjectInspector; + ObjectInspector valueOI1 = PrimitiveObjectInspectorFactory.writableStringObjectInspector; + ObjectInspector[] initArgs = {valueOI0, valueOI1}; + + udf.initialize(initArgs); + DeferredObject args; + DeferredObject[] evalArgs; + + args = new DeferredJavaObject(new Text("1 0 0 0 0 0 0 0 0 0")); + evalArgs = new DeferredObject[] { args, splitDilimiter }; + runAndVerifyNotTrue(asList(p1), evalArgs); + + args = new DeferredJavaObject(new Text("1 1 0 0 0 0 0 0 0 0")); + evalArgs = new DeferredObject[] { args, splitDilimiter }; + runAndVerifyNotTrue(asList(p0,p5),evalArgs); + + + + + } + + + + + + private void runAndVerify(List expResult, + DeferredObject[] evalArgs) throws HiveException { + + ArrayList output = (ArrayList) udf.evaluate(evalArgs); + assertEquals(expResult, output); + } + private void runAndVerifyNotTrue(List expResult, + DeferredObject[] evalArgs) throws HiveException { + + ArrayList output = (ArrayList) udf.evaluate(evalArgs); + assertNotSame(expResult, output); + } + +} \ No newline at end of file Index: ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java (revision 1ec275d3bf46ed36f4fc712bccba0ab9ce898a07) +++ ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java (date 1587846062561) @@ -285,6 +285,7 @@ system.registerGenericUDF("quote", GenericUDFQuote.class); system.registerGenericUDF("nvl", GenericUDFCoalesce.class); //HIVE-20961 system.registerGenericUDF("split", GenericUDFSplit.class); + system.registerGenericUDF("split_map_privs", UDFSplitMapPrivs.class); system.registerGenericUDF("str_to_map", GenericUDFStringToMap.class); system.registerGenericUDF("translate", GenericUDFTranslate.class); system.registerGenericUDF("validate_acid_sort_order", GenericUDFValidateAcidSortOrder.class);