Index: data/files/posexplode_data.txt =================================================================== --- data/files/posexplode_data.txt (revision 0) +++ data/files/posexplode_data.txt (revision 0) @@ -0,0 +1,4 @@ +John Doe100000.0Mary SmithTodd JonesFederal Taxes.2State Taxes.05Insurance.11 Michigan Ave.ChicagoIL60600 +Mary Smith80000.0Jeremy KingFederal Taxes.2State Taxes. 05Insurance.1100 Ontario St.ChicagoIL60601 +Todd Jones70000.0Federal Taxes.15State Taxes.03Insurance. 1200 Chicago Ave.Oak ParkIL60700 +Jeremy King60000.0Federal Taxes.15State Taxes.03Insurance. 1300 Obscure Dr.ObscuriaIL60100 Index: ql/src/test/results/clientpositive/udtf_posexplode.q.out =================================================================== --- ql/src/test/results/clientpositive/udtf_posexplode.q.out (revision 0) +++ ql/src/test/results/clientpositive/udtf_posexplode.q.out (revision 0) @@ -0,0 +1,42 @@ +PREHOOK: query: CREATE TABLE employees ( +name STRING, +salary FLOAT, +subordinates ARRAY, +deductions MAP, +address STRUCT) +PREHOOK: type: CREATETABLE +POSTHOOK: query: CREATE TABLE employees ( +name STRING, +salary FLOAT, +subordinates ARRAY, +deductions MAP, +address STRUCT) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: default@employees +PREHOOK: query: LOAD DATA LOCAL INPATH '../data/files/posexplode_data.txt' INTO TABLE employees +PREHOOK: type: LOAD +PREHOOK: Output: default@employees +POSTHOOK: query: LOAD DATA LOCAL INPATH '../data/files/posexplode_data.txt' INTO TABLE employees +POSTHOOK: type: LOAD +POSTHOOK: Output: default@employees +PREHOOK: query: SELECT + name, pos, sub +FROM + employees +LATERAL VIEW + posexplode(subordinates) subView AS pos, sub +PREHOOK: type: QUERY +PREHOOK: Input: default@employees +#### A masked pattern was here #### +POSTHOOK: query: SELECT + name, pos, sub +FROM + employees +LATERAL VIEW + posexplode(subordinates) subView AS pos, sub +POSTHOOK: type: QUERY +POSTHOOK: Input: default@employees +#### A masked pattern was here #### +John Doe 0 Mary Smith +John Doe 1 Todd Jones +Mary Smith 0 Jeremy King Index: ql/src/test/results/clientpositive/show_functions.q.out =================================================================== --- ql/src/test/results/clientpositive/show_functions.q.out (revision 1515738) +++ ql/src/test/results/clientpositive/show_functions.q.out (working copy) @@ -127,6 +127,7 @@ percentile_approx pi pmod +posexplode positive pow power @@ -240,6 +241,7 @@ ntile parse_url_tuple percentile +posexplode positive regexp_replace reverse Index: ql/src/test/queries/clientpositive/udtf_posexplode.q =================================================================== --- ql/src/test/queries/clientpositive/udtf_posexplode.q (revision 0) +++ ql/src/test/queries/clientpositive/udtf_posexplode.q (revision 0) @@ -0,0 +1,15 @@ +CREATE TABLE employees ( +name STRING, +salary FLOAT, +subordinates ARRAY, +deductions MAP, +address STRUCT); + +LOAD DATA LOCAL INPATH '../data/files/posexplode_data.txt' INTO TABLE employees; + +SELECT + name, pos, sub +FROM + employees +LATERAL VIEW + posexplode(subordinates) subView AS pos, sub; Index: ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java (revision 1515738) +++ ql/src/java/org/apache/hadoop/hive/ql/exec/FunctionRegistry.java (working copy) @@ -429,6 +429,7 @@ registerGenericUDTF("inline", GenericUDTFInline.class); registerGenericUDTF("json_tuple", GenericUDTFJSONTuple.class); registerGenericUDTF("parse_url_tuple", GenericUDTFParseUrlTuple.class); + registerGenericUDTF("posexplode", GenericUDTFPosExplode.class); registerGenericUDTF("stack", GenericUDTFStack.class); //PTF declarations Index: ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDTFPosExplode.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDTFPosExplode.java (revision 0) +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDTFPosExplode.java (revision 0) @@ -0,0 +1,87 @@ +/** + * 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 java.util.ArrayList; +import java.util.List; + +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.ListObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory; +import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory; +import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; + +/** + * PosExplode. + * + */ +@Description( + name = "posexplode", + value = "_FUNC_(a) - behaves like explode for arrays, " + + "but includes the position of items in the original array") +public class GenericUDTFPosExplode extends GenericUDTF { + private ListObjectInspector listOI = null; + private final Object[] forwardObj = new Object[2]; + + @Override + public void close() throws HiveException { + } + + @Override + public StructObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException { + + if (args.length != 1) { + throw new UDFArgumentException("posexplode() takes only one argument"); + } + + if (args[0].getCategory() != ObjectInspector.Category.LIST) { + throw new UDFArgumentException("posexplode() takes an array as a parameter"); + } + listOI = (ListObjectInspector) args[0]; + + ArrayList fieldNames = new ArrayList(); + ArrayList fieldOIs = new ArrayList(); + fieldNames.add("pos"); + fieldNames.add("val"); + fieldOIs.add(PrimitiveObjectInspectorFactory + .getPrimitiveJavaObjectInspector(PrimitiveCategory.INT)); + fieldOIs.add(listOI.getListElementObjectInspector()); + return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs); + } + + @Override + public void process(Object[] o) throws HiveException { + List list = listOI.getList(o[0]); + for (int i = 0; i < list.size(); i++) { + Object r = list.get(i); + forwardObj[0] = new Integer(i); + forwardObj[1] = r; + forward(forwardObj); + } + } + + @Override + public String toString() { + return "posexplode"; + } +}