diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java index 9ff010777e..1a412a3a86 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java @@ -284,6 +284,7 @@ system.registerUDF("replace", UDFReplace.class, false); system.registerUDF("regexp_extract", UDFRegExpExtract.class, false); system.registerUDF("parse_url", UDFParseUrl.class, false); + system.registerGenericUDF("quote", GenericUDFQuote.class); system.registerGenericUDF("nvl", GenericUDFCoalesce.class); //HIVE-20961 system.registerGenericUDF("split", GenericUDFSplit.class); system.registerGenericUDF("str_to_map", GenericUDFStringToMap.class); diff --git ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFQuote.java ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFQuote.java new file mode 100644 index 0000000000..78c52859dd --- /dev/null +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFQuote.java @@ -0,0 +1,72 @@ +/* + * 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.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.metadata.HiveException; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorConverter.TextConverter; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.apache.hadoop.io.Text; + +/** + * Source for GenericUDFQuote. + */ +@Description(name = "quote", value = "_FUNC_() - Returns the Quoted string" + "Example:\n " + + " > SELECT _FUNC_('Don't') FROM src LIMIT 1;\n" + " 'Don\'t'\n Including Single quotes\n") +public class GenericUDFQuote extends GenericUDF { + private transient TextConverter converter; + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + if (arguments.length != 1) { + throw new UDFArgumentException("QUOTE() requires one value argument. Found :" + arguments.length); + } + PrimitiveObjectInspector argumentOI; + if (arguments[0] instanceof PrimitiveObjectInspector) { + argumentOI = (PrimitiveObjectInspector) arguments[0]; + } else { + throw new UDFArgumentException("QUOTE() takes only primitive types. Found " + arguments[0].getTypeName()); + } + converter = new TextConverter(argumentOI); + return PrimitiveObjectInspectorFactory.writableStringObjectInspector; + } + + @Override + public Text evaluate(DeferredObject[] arguments) throws HiveException { + final String qtChar = "'"; + final String qtCharRep = "\\\\'"; + + Object valObject = arguments[0].get(); + if (valObject == null) { + return null; + } + String val = ((Text) converter.convert(valObject)).toString(); + String sp = (String) val.replaceAll(qtChar, qtCharRep); + sp = qtChar + sp + qtChar; + return new Text(sp); + } + + @Override + public String getDisplayString(String[] children) { + return getStandardDisplayString("quote", children); + } +} diff --git ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFQuote.java ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFQuote.java new file mode 100644 index 0000000000..4bb4215187 --- /dev/null +++ ql/src/test/org/apache/hadoop/hive/ql/udf/generic/TestGenericUDFQuote.java @@ -0,0 +1,57 @@ +/* + * 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.hadoop.hive.ql.udf.generic; + +import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF.DeferredJavaObject; +import org.apache.hadoop.hive.ql.udf.generic.GenericUDF.DeferredObject; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; +import org.apache.hadoop.io.Text; + +import junit.framework.TestCase; +/** + * Source for TestGenericUDFQuote. + */ +public class TestGenericUDFQuote extends TestCase { + public TestGenericUDFQuote() {} + public void testQuote() throws HiveException { + GenericUDFQuote udf = new GenericUDFQuote(); + ObjectInspector valueOI = PrimitiveObjectInspectorFactory.writableStringObjectInspector; + ObjectInspector[] arguments = {valueOI}; + + udf.initialize(arguments); + runAndVerify("", "''", udf); + runAndVerify(" ", "' '", udf); + runAndVerify("'", "'\\''", udf); + runAndVerify("DONT", "'DONT'", udf); + runAndVerify(" DON'T", "' DON\\'T'", udf); + runAndVerify("DON\\'T", "'DON\\\\'T'", udf); + } + + private void runAndVerify(String str, String expResult, GenericUDF udf) throws HiveException { + DeferredObject valueObj = new DeferredJavaObject(new Text(str)); + DeferredObject[] args = {valueObj}; + Text output = (Text) udf.evaluate(args); + if (expResult != null) { + assertEquals("quote() test ", expResult, output.toString()); + } else { + assertNull("quote() test ", output.toString()); + } + } +} diff --git ql/src/test/results/clientpositive/show_functions.q.out ql/src/test/results/clientpositive/show_functions.q.out index 1d2cb1cc40..4942fddbe0 100644 --- ql/src/test/results/clientpositive/show_functions.q.out +++ ql/src/test/results/clientpositive/show_functions.q.out @@ -200,6 +200,7 @@ pow power printf quarter +quote radians rand rank @@ -370,6 +371,7 @@ parse_url_tuple percentile posexplode positive +quote regexp_replace regr_slope replace