diff --git ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeGenericFuncDesc.java ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeGenericFuncDesc.java index 7da5d6a..9aae02e 100644 --- ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeGenericFuncDesc.java +++ ql/src/java/org/apache/hadoop/hive/ql/plan/ExprNodeGenericFuncDesc.java @@ -36,6 +36,7 @@ import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; import org.apache.hadoop.hive.ql.udf.generic.GenericUDFBaseCompare; import org.apache.hadoop.hive.ql.udf.generic.GenericUDFBridge; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; +import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo; import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory; import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoUtils; @@ -60,16 +61,34 @@ public class ExprNodeGenericFuncDesc extends ExprNodeDesc implements */ private GenericUDF genericUDF; private List childExprs; - + /** + * This class uses a writableObjectInspector rather than a TypeInfo to store + * the canonical type information for this NodeDesc. + */ + private ObjectInspector writableObjectInspector; + public ExprNodeGenericFuncDesc() { } public ExprNodeGenericFuncDesc(TypeInfo typeInfo, GenericUDF genericUDF, List children) { - super(typeInfo); + this(TypeInfoUtils.getStandardWritableObjectInspectorFromTypeInfo(typeInfo), + genericUDF, children); + } + + public ExprNodeGenericFuncDesc(ObjectInspector oi, GenericUDF genericUDF, + List children) { + super(TypeInfoUtils.getTypeInfoFromObjectInspector(oi)); + this.writableObjectInspector = + ObjectInspectorUtils.getWritableObjectInspector(oi); assert (genericUDF != null); this.genericUDF = genericUDF; - childExprs = children; + this.childExprs = children; + } + + @Override + public ObjectInspector getWritableObjectInspector() { + return writableObjectInspector; } public GenericUDF getGenericUDF() { @@ -191,8 +210,7 @@ public class ExprNodeGenericFuncDesc extends ExprNodeDesc implements } ObjectInspector oi = genericUDF.initialize(childrenOIs); - return new ExprNodeGenericFuncDesc(TypeInfoUtils - .getTypeInfoFromObjectInspector(oi), genericUDF, children); + return new ExprNodeGenericFuncDesc(oi, genericUDF, children); } @Override diff --git ql/src/java/org/apache/hadoop/hive/ql/udf/generic/ConstantFoldableGenericUDF.java ql/src/java/org/apache/hadoop/hive/ql/udf/generic/ConstantFoldableGenericUDF.java new file mode 100644 index 0000000..c184b70 --- /dev/null +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/ConstantFoldableGenericUDF.java @@ -0,0 +1,103 @@ +/** + * 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.UDFArgumentException; +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.ObjectInspectorUtils; + +/** + * A user-defined function which will automatically cache and constant + * propagate its arguments if they are all constant. + */ +public abstract class ConstantFoldableGenericUDF extends GenericUDF { + + private boolean allConstant; + private Object constantValue; + + @Override + public ObjectInspector initialize(ObjectInspector[] arguments) + throws UDFArgumentException { + allConstant = true; + for (int ii = 0; ii < arguments.length; ++ii) { + if (!ObjectInspectorUtils.isConstantObjectInspector(arguments[ii])) { + allConstant = false; + break; + } + } + + if (allConstant) { + ObjectInspector returnOI = initializeUnfolded(arguments); + DeferredObject[] argumentValues = new DeferredJavaObject[arguments.length]; + for (int ii = 0; ii < arguments.length; ++ii) { + argumentValues[ii] = new DeferredJavaObject( + ((ConstantObjectInspector)arguments[ii]).getWritableConstantValue()); + } + try { + constantValue = evaluateUnfolded(argumentValues); + } catch (HiveException e) { + throw new UDFArgumentException(e); + } + return ObjectInspectorUtils.getConstantObjectInspector(returnOI, constantValue); + } else { + return initializeUnfolded(arguments); + } + } + + public static class DeferredJavaObject implements DeferredObject { + private Object value; + + public DeferredJavaObject(Object value) { + this.value = value; + } + + @Override + public Object get() throws HiveException { + return value; + } + } + + @Override + public Object evaluate(DeferredObject[] arguments) throws HiveException { + if (allConstant) { + return constantValue; + } else { + return evaluate(arguments); + } + } + + /** + * Like initialize() except that it is expected to be applied to unfolded + * arguments. Inheritors of this class should put the business logic of + * initialization here. + */ + public abstract ObjectInspector initializeUnfolded(ObjectInspector[] arguments) + throws UDFArgumentException; + + /** + * Like evaluate() except that it is expected to be applied to unfolded + * arguments. Inheritors of this class should put the business logic of + * evaluation here. + */ + public abstract Object evaluateUnfolded(DeferredObject[] arguments) + throws HiveException; + +} diff --git ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFArray.java ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFArray.java index 1cf97c8..974228b 100644 --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFArray.java +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFArray.java @@ -37,12 +37,12 @@ import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectIn */ @Description(name = "array", value = "_FUNC_(n0, n1...) - Creates an array with the given elements ") -public class GenericUDFArray extends GenericUDF { +public class GenericUDFArray extends ConstantFoldableGenericUDF { private Converter[] converters; private ArrayList ret = new ArrayList(); @Override - public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + public ObjectInspector initializeUnfolded(ObjectInspector[] arguments) throws UDFArgumentException { GenericUDFUtils.ReturnObjectInspectorResolver returnOIResolver; @@ -73,7 +73,7 @@ public class GenericUDFArray extends GenericUDF { } @Override - public Object evaluate(DeferredObject[] arguments) throws HiveException { + public Object evaluateUnfolded(DeferredObject[] arguments) throws HiveException { ret.clear(); for (int i = 0; i < arguments.length; i++) { ret.add(converters[i].convert(arguments[i].get())); diff --git ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFArrayContains.java ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFArrayContains.java index d60dc86..6a15d2b 100644 --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFArrayContains.java +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFArrayContains.java @@ -37,7 +37,7 @@ import org.apache.hadoop.io.BooleanWritable; extended="Example:\n" + " > SELECT _FUNC_(array(1, 2, 3), 2) FROM src LIMIT 1;\n" + " true") -public class GenericUDFArrayContains extends GenericUDF { +public class GenericUDFArrayContains extends ConstantFoldableGenericUDF { private static final int ARRAY_IDX = 0; private static final int VALUE_IDX = 1; @@ -50,7 +50,7 @@ public class GenericUDFArrayContains extends GenericUDF { private BooleanWritable result; @Override - public ObjectInspector initialize(ObjectInspector[] arguments) + public ObjectInspector initializeUnfolded(ObjectInspector[] arguments) throws UDFArgumentException { // Check if two arguments were passed @@ -99,7 +99,7 @@ public class GenericUDFArrayContains extends GenericUDF { @Override - public Object evaluate(DeferredObject[] arguments) throws HiveException { + public Object evaluateUnfolded(DeferredObject[] arguments) throws HiveException { result.set(false); diff --git ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFIf.java ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFIf.java index 9a6a7ff..b36e261 100644 --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFIf.java +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFIf.java @@ -33,12 +33,12 @@ import org.apache.hadoop.hive.serde2.objectinspector.primitive.BooleanObjectInsp * otherwise it returns expr3. IF() returns a numeric or string value, depending * on the context in which it is used. */ -public class GenericUDFIf extends GenericUDF { +public class GenericUDFIf extends ConstantFoldableGenericUDF { private ObjectInspector[] argumentOIs; private GenericUDFUtils.ReturnObjectInspectorResolver returnOIResolver; @Override - public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + public ObjectInspector initializeUnfolded(ObjectInspector[] arguments) throws UDFArgumentException { argumentOIs = arguments; returnOIResolver = new GenericUDFUtils.ReturnObjectInspectorResolver(true); @@ -72,7 +72,7 @@ public class GenericUDFIf extends GenericUDF { } @Override - public Object evaluate(DeferredObject[] arguments) throws HiveException { + public Object evaluateUnfolded(DeferredObject[] arguments) throws HiveException { Object condition = arguments[0].get(); if (condition != null && ((BooleanObjectInspector) argumentOIs[0]).get(condition)) { diff --git ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFMap.java ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFMap.java index 3b71c48..45be93a 100644 --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFMap.java +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFMap.java @@ -38,12 +38,12 @@ import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectIn */ @Description(name = "map", value = "_FUNC_(key0, value0, key1, value1...) - " + "Creates a map with the given key/value pairs ") -public class GenericUDFMap extends GenericUDF { +public class GenericUDFMap extends ConstantFoldableGenericUDF { Converter[] converters; HashMap ret = new HashMap(); @Override - public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { + public ObjectInspector initializeUnfolded(ObjectInspector[] arguments) throws UDFArgumentException { if (arguments.length % 2 != 0) { throw new UDFArgumentLengthException( @@ -105,7 +105,7 @@ public class GenericUDFMap extends GenericUDF { } @Override - public Object evaluate(DeferredObject[] arguments) throws HiveException { + public Object evaluateUnfolded(DeferredObject[] arguments) throws HiveException { ret.clear(); for (int i = 0; i < arguments.length; i += 2) { ret.put(converters[i].convert(arguments[i].get()), converters[i + 1] diff --git ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFMapKeys.java ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFMapKeys.java index b384717..73ab8cf 100644 --- ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFMapKeys.java +++ ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFMapKeys.java @@ -36,12 +36,12 @@ import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category; */ @Description(name = "map_keys", value = "_FUNC_(map) - " + "Returns an unordered array containing the keys of the input map.") -public class GenericUDFMapKeys extends GenericUDF { +public class GenericUDFMapKeys extends ConstantFoldableGenericUDF { private MapObjectInspector mapOI; private final ArrayList retArray = new ArrayList(); @Override - public ObjectInspector initialize(ObjectInspector[] arguments) + public ObjectInspector initializeUnfolded(ObjectInspector[] arguments) throws UDFArgumentException { if (arguments.length != 1) { throw new UDFArgumentLengthException("The function MAP_KEYS only accepts one argument."); @@ -58,7 +58,7 @@ public class GenericUDFMapKeys extends GenericUDF { } @Override - public Object evaluate(DeferredObject[] arguments) throws HiveException { + public Object evaluateUnfolded(DeferredObject[] arguments) throws HiveException { retArray.clear(); Object mapObj = arguments[0].get(); retArray.addAll(mapOI.getMap(mapObj).keySet()); diff --git ql/src/test/queries/clientpositive/constant_prop.q ql/src/test/queries/clientpositive/constant_prop.q new file mode 100644 index 0000000..ced72d6 --- /dev/null +++ ql/src/test/queries/clientpositive/constant_prop.q @@ -0,0 +1,20 @@ +EXPLAIN +SELECT NAMED_STRUCT( + IF(ARRAY_CONTAINS(ARRAY(1, 2), 3), "F1", "B1"), 1, + IF(ARRAY_CONTAINS(MAP_KEYS(MAP("b", "x")), "b"), "F2", "B2"), 2 + ), + NAMED_STRUCT( + IF(ARRAY_CONTAINS(ARRAY(1, 2), 3), "F1", "B1"), 1, + IF(ARRAY_CONTAINS(MAP_KEYS(MAP("b", "x")), "b"), "F2", "B2"), 2 + ).F2 + FROM src LIMIT 1; + +SELECT NAMED_STRUCT( + IF(ARRAY_CONTAINS(ARRAY(1, 2), 3), "F1", "B1"), 1, + IF(ARRAY_CONTAINS(MAP_KEYS(MAP("b", "x")), "b"), "F2", "B2"), 2 + ), + NAMED_STRUCT( + IF(ARRAY_CONTAINS(ARRAY(1, 2), 3), "F1", "B1"), 1, + IF(ARRAY_CONTAINS(MAP_KEYS(MAP("b", "x")), "b"), "F2", "B2"), 2 + ).F2 + FROM src LIMIT 1; diff --git ql/src/test/results/clientpositive/constant_prop.q.out ql/src/test/results/clientpositive/constant_prop.q.out new file mode 100644 index 0000000..bf4ecdb --- /dev/null +++ ql/src/test/results/clientpositive/constant_prop.q.out @@ -0,0 +1,81 @@ +PREHOOK: query: EXPLAIN +SELECT NAMED_STRUCT( + IF(ARRAY_CONTAINS(ARRAY(1, 2), 3), "F1", "B1"), 1, + IF(ARRAY_CONTAINS(MAP_KEYS(MAP("b", "x")), "b"), "F2", "B2"), 2 + ), + NAMED_STRUCT( + IF(ARRAY_CONTAINS(ARRAY(1, 2), 3), "F1", "B1"), 1, + IF(ARRAY_CONTAINS(MAP_KEYS(MAP("b", "x")), "b"), "F2", "B2"), 2 + ).F2 + FROM src LIMIT 1 +PREHOOK: type: QUERY +POSTHOOK: query: EXPLAIN +SELECT NAMED_STRUCT( + IF(ARRAY_CONTAINS(ARRAY(1, 2), 3), "F1", "B1"), 1, + IF(ARRAY_CONTAINS(MAP_KEYS(MAP("b", "x")), "b"), "F2", "B2"), 2 + ), + NAMED_STRUCT( + IF(ARRAY_CONTAINS(ARRAY(1, 2), 3), "F1", "B1"), 1, + IF(ARRAY_CONTAINS(MAP_KEYS(MAP("b", "x")), "b"), "F2", "B2"), 2 + ).F2 + FROM src LIMIT 1 +POSTHOOK: type: QUERY +ABSTRACT SYNTAX TREE: + (TOK_QUERY (TOK_FROM (TOK_TABREF (TOK_TABNAME src))) (TOK_INSERT (TOK_DESTINATION (TOK_DIR TOK_TMP_FILE)) (TOK_SELECT (TOK_SELEXPR (TOK_FUNCTION NAMED_STRUCT (TOK_FUNCTION IF (TOK_FUNCTION ARRAY_CONTAINS (TOK_FUNCTION ARRAY 1 2) 3) "F1" "B1") 1 (TOK_FUNCTION IF (TOK_FUNCTION ARRAY_CONTAINS (TOK_FUNCTION MAP_KEYS (TOK_FUNCTION MAP "b" "x")) "b") "F2" "B2") 2)) (TOK_SELEXPR (. (TOK_FUNCTION NAMED_STRUCT (TOK_FUNCTION IF (TOK_FUNCTION ARRAY_CONTAINS (TOK_FUNCTION ARRAY 1 2) 3) "F1" "B1") 1 (TOK_FUNCTION IF (TOK_FUNCTION ARRAY_CONTAINS (TOK_FUNCTION MAP_KEYS (TOK_FUNCTION MAP "b" "x")) "b") "F2" "B2") 2) F2))) (TOK_LIMIT 1))) + +STAGE DEPENDENCIES: + Stage-1 is a root stage + Stage-0 is a root stage + +STAGE PLANS: + Stage: Stage-1 + Map Reduce + Alias -> Map Operator Tree: + src + TableScan + alias: src + Select Operator + expressions: + expr: named_struct(if(array_contains(array(1,2), 3), 'F1', 'B1'),1,if(array_contains(map_keys(map('b':'x')), 'b'), 'F2', 'B2'),2) + type: struct + expr: named_struct(if(array_contains(array(1,2), 3), 'F1', 'B1'),1,if(array_contains(map_keys(map('b':'x')), 'b'), 'F2', 'B2'),2).F2 + type: int + outputColumnNames: _col0, _col1 + Limit + File Output Operator + compressed: false + GlobalTableId: 0 + table: + input format: org.apache.hadoop.mapred.TextInputFormat + output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat + + Stage: Stage-0 + Fetch Operator + limit: 1 + + +PREHOOK: query: SELECT NAMED_STRUCT( + IF(ARRAY_CONTAINS(ARRAY(1, 2), 3), "F1", "B1"), 1, + IF(ARRAY_CONTAINS(MAP_KEYS(MAP("b", "x")), "b"), "F2", "B2"), 2 + ), + NAMED_STRUCT( + IF(ARRAY_CONTAINS(ARRAY(1, 2), 3), "F1", "B1"), 1, + IF(ARRAY_CONTAINS(MAP_KEYS(MAP("b", "x")), "b"), "F2", "B2"), 2 + ).F2 + FROM src LIMIT 1 +PREHOOK: type: QUERY +PREHOOK: Input: default@src +PREHOOK: Output: file:/var/folders/C4/C40caRNsEM4C4yVangruonVUe7Y/-Tmp-/jonchang/hive_2011-09-27_14-38-28_158_1791133651106020479/-mr-10000 +POSTHOOK: query: SELECT NAMED_STRUCT( + IF(ARRAY_CONTAINS(ARRAY(1, 2), 3), "F1", "B1"), 1, + IF(ARRAY_CONTAINS(MAP_KEYS(MAP("b", "x")), "b"), "F2", "B2"), 2 + ), + NAMED_STRUCT( + IF(ARRAY_CONTAINS(ARRAY(1, 2), 3), "F1", "B1"), 1, + IF(ARRAY_CONTAINS(MAP_KEYS(MAP("b", "x")), "b"), "F2", "B2"), 2 + ).F2 + FROM src LIMIT 1 +POSTHOOK: type: QUERY +POSTHOOK: Input: default@src +POSTHOOK: Output: file:/var/folders/C4/C40caRNsEM4C4yVangruonVUe7Y/-Tmp-/jonchang/hive_2011-09-27_14-38-28_158_1791133651106020479/-mr-10000 +{"b1":1,"f2":2} 2 diff --git serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectInspectorFactory.java serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectInspectorFactory.java index a4689fb..b21755e 100644 --- serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectInspectorFactory.java +++ serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectInspectorFactory.java @@ -204,6 +204,12 @@ public final class ObjectInspectorFactory { return result; } + public static StandardConstantListObjectInspector getStandardConstantListObjectInspector( + ObjectInspector listElementObjectInspector, List constantValue) { + return new StandardConstantListObjectInspector(listElementObjectInspector, constantValue); + } + + static HashMap, StandardMapObjectInspector> cachedStandardMapObjectInspector = new HashMap, StandardMapObjectInspector>(); public static StandardMapObjectInspector getStandardMapObjectInspector( @@ -222,6 +228,14 @@ public final class ObjectInspectorFactory { return result; } + public static StandardConstantMapObjectInspector getStandardConstantMapObjectInspector( + ObjectInspector mapKeyObjectInspector, + ObjectInspector mapValueObjectInspector, + Map constantValue) { + return new StandardConstantMapObjectInspector(mapKeyObjectInspector, + mapValueObjectInspector, constantValue); + } + static HashMap, StandardUnionObjectInspector> cachedStandardUnionObjectInspector = new HashMap, StandardUnionObjectInspector>(); diff --git serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectInspectorUtils.java serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectInspectorUtils.java index 2c1a7e0..a965266 100644 --- serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectInspectorUtils.java +++ serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectInspectorUtils.java @@ -31,8 +31,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hive.serde.Constants; import org.apache.hadoop.hive.serde2.io.TimestampWritable; +import org.apache.hadoop.hive.serde2.objectinspector.ConstantObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory.ObjectInspectorOptions; +import org.apache.hadoop.hive.serde2.objectinspector.primitive.AbstractPrimitiveWritableObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.primitive.BooleanObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.primitive.ByteObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.primitive.DoubleObjectInspector; @@ -72,6 +74,21 @@ public final class ObjectInspectorUtils { } /** + * Ensures that an ObjectInspector is Writable. + */ + public static ObjectInspector getWritableObjectInspector(ObjectInspector oi) { + // All non-primitive OIs are writable so we need only check this case. + if (oi.getCategory() == Category.PRIMITIVE) { + PrimitiveObjectInspector poi = (PrimitiveObjectInspector) oi; + if (!(poi instanceof AbstractPrimitiveWritableObjectInspector)) { + return PrimitiveObjectInspectorFactory + .getPrimitiveWritableObjectInspector(poi.getPrimitiveCategory()); + } + } + return oi; + } + + /** * Get the corresponding standard ObjectInspector for an ObjectInspector. * * The returned ObjectInspector can be used to inspect the standard object. @@ -839,7 +856,36 @@ public final class ObjectInspectorUtils { throw new RuntimeException("Unknown category encountered: " + c1); } + public static ConstantObjectInspector getConstantObjectInspector(ObjectInspector oi, Object value) { + ObjectInspector writableOI = ObjectInspectorUtils + .getStandardObjectInspector(oi, ObjectInspectorCopyOption.WRITABLE); + Object writableValue = + ObjectInspectorConverters.getConverter(oi, writableOI).convert(value); + switch (writableOI.getCategory()) { + case PRIMITIVE: + PrimitiveObjectInspector poi = (PrimitiveObjectInspector) oi; + return PrimitiveObjectInspectorFactory.getPrimitiveWritableConstantObjectInspector( + poi.getPrimitiveCategory(), writableValue); + case LIST: + ListObjectInspector loi = (ListObjectInspector) oi; + return ObjectInspectorFactory.getStandardConstantListObjectInspector( + loi.getListElementObjectInspector(), (List)writableValue); + case MAP: + MapObjectInspector moi = (MapObjectInspector) oi; + return ObjectInspectorFactory.getStandardConstantMapObjectInspector( + moi.getMapKeyObjectInspector(), + moi.getMapValueObjectInspector(), + (Map)writableValue); + default: + throw new IllegalArgumentException( + writableOI.getCategory() + " not yet supported for constant OI"); + } + } + public static boolean isConstantObjectInspector(ObjectInspector oi) { + return (oi instanceof ConstantObjectInspector); + } + private ObjectInspectorUtils() { // prevent instantiation } diff --git serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/StandardConstantListObjectInspector.java serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/StandardConstantListObjectInspector.java new file mode 100644 index 0000000..6f164b0 --- /dev/null +++ serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/StandardConstantListObjectInspector.java @@ -0,0 +1,48 @@ +/** + * 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.serde2.objectinspector; + +import java.util.List; + +/** + * A StandardListObjectInspector which also implements the + * ConstantObjectInspector interface. + * + * Always use the ObjectInspectorFactory to create new ObjectInspector objects, + * instead of directly creating an instance of this class. + */ +public class StandardConstantListObjectInspector extends StandardListObjectInspector + implements ConstantObjectInspector { + + private List value; + + /** + * Call ObjectInspectorFactory.getStandardListObjectInspector instead. + */ + protected StandardConstantListObjectInspector( + ObjectInspector listElementObjectInspector, List value) { + super(listElementObjectInspector); + this.value = value; + } + + @Override + public List getWritableConstantValue() { + return value; + } +} diff --git serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/StandardConstantMapObjectInspector.java serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/StandardConstantMapObjectInspector.java new file mode 100644 index 0000000..ca6432e --- /dev/null +++ serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/StandardConstantMapObjectInspector.java @@ -0,0 +1,48 @@ +/** + * 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.serde2.objectinspector; + +import java.util.Map; + +/** + * A StandardMapObjectInspector which also implements the + * ConstantObjectInspector interface. + * + * Always use the ObjectInspectorFactory to create new ObjectInspector objects, + * instead of directly creating an instance of this class. + */ +public class StandardConstantMapObjectInspector extends StandardMapObjectInspector + implements ConstantObjectInspector { + + private Map value; + + /** + * Call ObjectInspectorFactory.getStandardMapObjectInspector instead. + */ + protected StandardConstantMapObjectInspector(ObjectInspector mapKeyObjectInspector, + ObjectInspector mapValueObjectInspector, Map value) { + super(mapKeyObjectInspector, mapValueObjectInspector); + this.value = value; + } + + @Override + public Map getWritableConstantValue() { + return value; + } +} -- 1.6.6