[ASTERIXDB-3446][RT] Do not use pools in CastTypeEvaluator
- user model changes: no
- storage format changes: no
- interface changes: no
Details:
Do not use pools in CastTypeEvaluator since that is not
needed.
- Use separate caster that uses pool for array functions.
Ext-ref: MB-62691
Change-Id: I0df95d19e652b97a86144ee5d56ca92596ab5c95
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18466
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
Reviewed-by: Murtadha Hubail <mhubail@apache.org>
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.1.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.1.ddl.sqlpp
index 1c55a9a..e2ea074 100755
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.1.ddl.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.1.ddl.sqlpp
@@ -52,5 +52,10 @@
compType: t1
};
+create type t3 AS {
+id: int
+};
+
create dataset TweetMessages(TweetMessageType) primary key tweetid hints (`CARDINALITY`=`100`);
-create dataset d1(t2) primary key id;
\ No newline at end of file
+create dataset d1(t2) primary key id;
+create dataset d3(t3) primary key id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.2.update.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.2.update.sqlpp
index 1c4bad0..e320513 100755
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.2.update.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.2.update.sqlpp
@@ -24,4 +24,9 @@
insert into d1([
{"id":1, "compType":{"sth":33}},
{"id":2, "compType":{"sth":44}, "followers":["John Green", "Emily Jones"]}
+]);
+
+insert into d3([
+{"id":1, "list_f": [99], "compType":{"sth":33}, "s": 1},
+{"id":2, "list_f": [88, {"a": 8}], "compType":[{"sth":44}, {"sth2": [1,2]}], "s": 2}
]);
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.4.query.sqlpp
new file mode 100755
index 0000000..061dd7f
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.4.query.sqlpp
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+USE TinySocial;
+
+FROM d3 AS d
+SELECT array_append(d.list_f, d.compType, d.s) AS append_result
+ORDER BY d.id;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.4.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.9.ddl.sqlpp
similarity index 100%
rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.4.ddl.sqlpp
rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/array_fun/array_append/array_append.9.ddl.sqlpp
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/array_fun/array_append/array_append.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/array_fun/array_append/array_append.4.adm
new file mode 100644
index 0000000..b7e6002
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/array_fun/array_append/array_append.4.adm
@@ -0,0 +1,2 @@
+{ "append_result": [ 99, { "sth": 33 }, 1 ] }
+{ "append_result": [ 88, { "a": 8 }, [ { "sth": 44 }, { "sth2": [ 1, 2 ] } ], 2 ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractArrayAddRemoveEval.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractArrayAddRemoveEval.java
index f65bf30..95c062c 100755
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractArrayAddRemoveEval.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractArrayAddRemoveEval.java
@@ -52,7 +52,7 @@
private final IPointable[] valuesArgs;
private final IScalarEvaluator listArgEval;
private final IScalarEvaluator[] valuesEval;
- private final CastTypeEvaluator caster;
+ private final TypeCaster caster;
private final ListAccessor listAccessor;
private final int listOffset;
private final int valuesOffset;
@@ -71,7 +71,7 @@
orderedListBuilder = null;
unorderedListBuilder = null;
listAccessor = new ListAccessor();
- caster = new CastTypeEvaluator(null);
+ caster = new TypeCaster(null);
storage = new ArrayBackedValueStorage();
listArg = new VoidPointable();
tempList = new VoidPointable();
@@ -130,8 +130,10 @@
// cast val to open if needed. don't cast if function will return null anyway, e.g. list arg not list
defaultOpenType = DefaultOpenFieldType.getDefaultOpenFieldType(argTypes[i + valuesOffset].getTypeTag());
if (defaultOpenType != null && !returnNull && makeOpen) {
- caster.resetAndAllocate(defaultOpenType, argTypes[i + valuesOffset], valuesEval[i]);
- caster.evaluate(tuple, valuesArgs[i]);
+ valuesEval[i].evaluate(tuple, tempItem);
+ if (!PointableHelper.checkAndSetMissingOrNull(valuesArgs[i], tempItem)) {
+ caster.allocateAndCast(tempItem, argTypes[i + valuesOffset], valuesArgs[i], defaultOpenType);
+ }
} else {
valuesEval[i].evaluate(tuple, valuesArgs[i]);
}
@@ -162,8 +164,7 @@
if (makeOpen || argTypes[listOffset].getTypeTag() != ATypeTag.ARRAY) {
listType = DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE;
// TODO(ali): maybe casting isn't needed if compile-time type=ANY if guaranteed input list is open
- caster.resetAndAllocate(listType, argTypes[listOffset], listArgEval);
- caster.cast(tempList, listArg);
+ caster.allocateAndCast(tempList, argTypes[listOffset], listArg, listType);
} else {
listType = (AbstractCollectionType) argTypes[listOffset];
listArg.set(tempList);
@@ -175,8 +176,7 @@
listBuilder = unorderedListBuilder;
if (makeOpen || argTypes[listOffset].getTypeTag() != ATypeTag.MULTISET) {
listType = DefaultOpenFieldType.NESTED_OPEN_AUNORDERED_LIST_TYPE;
- caster.resetAndAllocate(listType, argTypes[listOffset], listArgEval);
- caster.cast(tempList, listArg);
+ caster.allocateAndCast(tempList, argTypes[listOffset], listArg, listType);
} else {
listType = (AbstractCollectionType) argTypes[listOffset];
listArg.set(tempList);
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractArrayProcessArraysEval.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractArrayProcessArraysEval.java
index 052b79d..401f9fc 100755
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractArrayProcessArraysEval.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/AbstractArrayProcessArraysEval.java
@@ -56,7 +56,7 @@
private final IObjectPool<IPointable, Void> pointablePool;
private final IObjectPool<IMutableValueStorage, Void> storageAllocator;
private final IAType[] argTypes;
- private final CastTypeEvaluator caster;
+ private final TypeCaster caster;
private OrderedListBuilder orderedListBuilder;
private UnorderedListBuilder unorderedListBuilder;
@@ -68,7 +68,7 @@
storageAllocator = new ListObjectPool<>(ObjectFactories.STORAGE_FACTORY);
finalResult = new ArrayBackedValueStorage();
listAccessor = new ListAccessor();
- caster = new CastTypeEvaluator(null);
+ caster = new TypeCaster(sourceLoc);
tempList = new VoidPointable();
listsArgs = new IPointable[args.length];
listsEval = new IScalarEvaluator[args.length];
@@ -111,9 +111,7 @@
if (outList == null) {
outList = (AbstractCollectionType) DefaultOpenFieldType.getDefaultOpenFieldType(listTag);
}
-
- caster.resetAndAllocate(outList, argTypes[i], listsEval[i]);
- caster.cast(tempList, listsArgs[i]);
+ caster.allocateAndCast(tempList, argTypes[i], listsArgs[i], outList);
}
}
}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayFlattenDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayFlattenDescriptor.java
index 72d6c3d..67c0da9 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayFlattenDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayFlattenDescriptor.java
@@ -127,7 +127,7 @@
private final TaggedValuePointable depthArg;
private final IObjectPool<IMutableValueStorage, ATypeTag> storageAllocator;
private final IObjectPool<ListAccessor, ATypeTag> listAccessorAllocator;
- private final CastTypeEvaluator caster;
+ private final TypeCaster caster;
private final ArrayBackedValueStorage finalStorage;
private ArrayBackedValueStorage storage;
private IAsterixListBuilder orderedListBuilder;
@@ -141,7 +141,7 @@
depthEval = args[1].createScalarEvaluator(ctx);
list = new VoidPointable();
pointable = new VoidPointable();
- caster = new CastTypeEvaluator(null);
+ caster = new TypeCaster(sourceLoc);
depthArg = new TaggedValuePointable();
orderedListBuilder = null;
unorderedListBuilder = null;
@@ -172,9 +172,8 @@
}
try {
- caster.resetAndAllocate(DefaultOpenFieldType.getDefaultOpenFieldType(listType), inputListType,
- listEval);
- caster.cast(pointable, list);
+ caster.allocateAndCast(pointable, inputListType, list,
+ DefaultOpenFieldType.getDefaultOpenFieldType(listType));
int depthInt = (int) depth;
// create list
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayIntersectDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayIntersectDescriptor.java
index c33222d..25a01ca 100755
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayIntersectDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayIntersectDescriptor.java
@@ -179,7 +179,7 @@
private final IObjectPool<List<ValueListIndex>, ATypeTag> arrayListAllocator;
private final IObjectPool<ValueListIndex, ATypeTag> valueListIndexAllocator;
private final ArrayBackedValueStorage finalResult;
- private final CastTypeEvaluator caster;
+ private final TypeCaster caster;
private final IBinaryComparator comp;
private IAsterixListBuilder orderedListBuilder;
private IAsterixListBuilder unorderedListBuilder;
@@ -194,7 +194,7 @@
hashes = new Int2ObjectOpenHashMap<>();
finalResult = new ArrayBackedValueStorage();
listAccessor = new ListAccessor();
- caster = new CastTypeEvaluator(null);
+ caster = new TypeCaster(sourceLoc);
// for functions that accept multiple lists arguments, they will be casted to open, hence item is ANY
comp = BinaryComparatorFactoryProvider.INSTANCE
.getBinaryComparatorFactory(BuiltinType.ANY, BuiltinType.ANY, true).createBinaryComparator();
@@ -247,8 +247,7 @@
(AbstractCollectionType) DefaultOpenFieldType.getDefaultOpenFieldType(listTag);
}
- caster.resetAndAllocate(outList, argTypes[i], listsEval[i]);
- caster.cast(pointable, listsArgs[i]);
+ caster.allocateAndCast(pointable, argTypes[i], listsArgs[i], outList);
nextSize = getNumItems(outList, listsArgs[i].getByteArray(), listsArgs[i].getStartOffset());
if (nextSize < minSize || minSize == -1) {
minSize = nextSize;
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceEvaluator.java
index aeda168..74eb3e1 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayReplaceEvaluator.java
@@ -86,7 +86,7 @@
private final ListAccessor listAccessor;
private final IBinaryComparator comp;
private final ArrayBackedValueStorage storage;
- private final CastTypeEvaluator caster;
+ private final TypeCaster caster;
private IAsterixListBuilder orderedListBuilder;
private IAsterixListBuilder unorderedListBuilder;
@@ -108,7 +108,7 @@
tempVal = new VoidPointable();
item = new VoidPointable();
listAccessor = new ListAccessor();
- caster = new CastTypeEvaluator(null);
+ caster = new TypeCaster(sourceLocation);
orderedListBuilder = null;
unorderedListBuilder = null;
@@ -157,12 +157,10 @@
}
try {
IAType defaultOpenType = DefaultOpenFieldType.getDefaultOpenFieldType(listType);
- caster.resetAndAllocate(defaultOpenType, inputListType, listEval);
- caster.cast(tempList, list);
+ caster.allocateAndCast(tempList, inputListType, list, defaultOpenType);
defaultOpenType = DefaultOpenFieldType.getDefaultOpenFieldType(newValTag);
if (defaultOpenType != null) {
- caster.resetAndAllocate(defaultOpenType, newValueType, newValEval);
- caster.cast(tempVal, newVal);
+ caster.allocateAndCast(tempVal, newValueType, newVal, defaultOpenType);
} else {
newVal.set(tempVal);
}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayStarDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayStarDescriptor.java
index 78d8d36..ae11178 100755
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayStarDescriptor.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/ArrayStarDescriptor.java
@@ -182,7 +182,7 @@
private final IPointable list;
private final IPointable tempList;
private final IPointable object;
- private final CastTypeEvaluator caster;
+ private final TypeCaster caster;
private final ListAccessor listAccessor;
private final RecordBuilder recordBuilder;
private final IAsterixListBuilder listBuilder;
@@ -198,7 +198,7 @@
list = new VoidPointable();
tempList = new VoidPointable();
listEval = args[0].createScalarEvaluator(ctx);
- caster = new CastTypeEvaluator(null);
+ caster = new TypeCaster(sourceLoc);
listAccessor = new ListAccessor();
recordBuilder = new RecordBuilder();
listBuilder = new OrderedListBuilder();
@@ -225,8 +225,8 @@
}
try {
- caster.resetAndAllocate(DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE, inputListType, listEval);
- caster.cast(tempList, list);
+ caster.allocateAndCast(tempList, inputListType, list,
+ DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE);
tempMinHeap.clear();
fieldNameToValuesList.clear();
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastTypeEvaluator.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastTypeEvaluator.java
index 50f6417..6be4483 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastTypeEvaluator.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CastTypeEvaluator.java
@@ -30,8 +30,6 @@
import org.apache.asterix.om.types.EnumDeserializer;
import org.apache.asterix.om.types.IAType;
import org.apache.asterix.om.types.TypeTagUtil;
-import org.apache.asterix.om.util.container.IObjectPool;
-import org.apache.asterix.om.util.container.ListObjectPool;
import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.api.exceptions.SourceLocation;
@@ -42,34 +40,27 @@
public class CastTypeEvaluator implements IScalarEvaluator {
private final IPointable argPointable = new VoidPointable();
- private final IObjectPool<AFlatValueCastingPointable, IAType> flatValuePool =
- new ListObjectPool<>(AFlatValueCastingPointable.FACTORY);
- private final IObjectPool<ARecordCastingPointable, IAType> recordValuePool =
- new ListObjectPool<>(ARecordCastingPointable.FACTORY);
- private final IObjectPool<AListCastingPointable, IAType> listValuePool =
- new ListObjectPool<>(AListCastingPointable.FACTORY);
- private IScalarEvaluator argEvaluator;
+ private final IScalarEvaluator argEvaluator;
protected final SourceLocation sourceLoc;
private ICastingPointable inputPointable;
+ private ICastingPointable record;
+ private ICastingPointable list;
+ private ICastingPointable flat;
private final ACastingPointableVisitor castVisitor = createCastVisitor();
private final CastResult castResult = new CastResult(new VoidPointable(), null);
- private boolean inputTypeIsAny;
-
- public CastTypeEvaluator(SourceLocation sourceLoc) {
- this.sourceLoc = sourceLoc;
- // reset() should be called after using this constructor before calling any method
- }
+ private final boolean inputTypeIsAny;
public CastTypeEvaluator(IAType reqType, IAType inputType, IScalarEvaluator argEvaluator,
SourceLocation sourceLoc) {
this.sourceLoc = sourceLoc;
- resetAndAllocate(reqType, inputType, argEvaluator);
- }
-
- public void resetAndAllocate(IAType reqType, IAType inputType, IScalarEvaluator argEvaluator) {
this.argEvaluator = argEvaluator;
- this.inputPointable = allocatePointable(inputType);
this.castResult.setOutType(reqType);
+ if (!inputType.equals(BuiltinType.ANY)) {
+ this.inputPointable = createPointable(inputType);
+ this.inputTypeIsAny = false;
+ } else {
+ this.inputTypeIsAny = true;
+ }
}
protected ACastingPointableVisitor createCastVisitor() {
@@ -79,20 +70,11 @@
@Override
public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException {
argEvaluator.evaluate(tuple, argPointable);
-
if (PointableHelper.checkAndSetMissingOrNull(result, argPointable)) {
return;
}
-
- cast(argPointable, result);
- }
-
- // TODO(ali): refactor in a better way
- protected void cast(IPointable argPointable, IPointable result) throws HyracksDataException {
if (inputTypeIsAny) {
- ATypeTag inTag = EnumDeserializer.ATYPETAGDESERIALIZER
- .deserialize(argPointable.getByteArray()[argPointable.getStartOffset()]);
- inputPointable = allocateForInput(TypeTagUtil.getBuiltinTypeByTag(inTag));
+ inputPointable = getPointable(argPointable);
}
inputPointable.set(argPointable);
castInto(result);
@@ -103,35 +85,37 @@
result.set(castResult.getOutPointable());
}
- private ICastingPointable allocatePointable(IAType inputType) {
- if (!inputType.equals(BuiltinType.ANY)) {
- inputTypeIsAny = false;
- return allocateForInput(inputType);
- } else {
- inputTypeIsAny = true;
- return null;
- }
- }
-
- private ICastingPointable allocateForInput(IAType inputType) {
- ICastingPointable pointable;
- switch (inputType.getTypeTag()) {
+ private static ICastingPointable createPointable(IAType type) {
+ switch (type.getTypeTag()) {
case OBJECT:
- pointable = recordValuePool.allocate(inputType);
- break;
+ return ARecordCastingPointable.FACTORY.create(type);
case ARRAY:
case MULTISET:
- pointable = listValuePool.allocate(inputType);
- break;
+ return AListCastingPointable.FACTORY.create(type);
default:
- pointable = flatValuePool.allocate(null);
+ return AFlatValueCastingPointable.FACTORY.create(type);
}
- return pointable;
}
- public void deallocatePointables() {
- flatValuePool.reset();
- listValuePool.reset();
- recordValuePool.reset();
+ private ICastingPointable getPointable(IPointable arg) throws HyracksDataException {
+ ATypeTag tag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(arg.getByteArray()[arg.getStartOffset()]);
+ switch (tag) {
+ case OBJECT:
+ if (record == null) {
+ record = ARecordCastingPointable.FACTORY.create(TypeTagUtil.getBuiltinTypeByTag(tag));
+ }
+ return record;
+ case ARRAY:
+ case MULTISET:
+ if (list == null) {
+ list = AListCastingPointable.FACTORY.create(TypeTagUtil.getBuiltinTypeByTag(tag));
+ }
+ return list;
+ default:
+ if (flat == null) {
+ flat = AFlatValueCastingPointable.FACTORY.create(null);
+ }
+ return flat;
+ }
}
}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/TypeCaster.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/TypeCaster.java
new file mode 100644
index 0000000..670b44d
--- /dev/null
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/TypeCaster.java
@@ -0,0 +1,96 @@
+/*
+ * 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.asterix.runtime.evaluators.functions;
+
+import org.apache.asterix.om.pointables.AFlatValueCastingPointable;
+import org.apache.asterix.om.pointables.AListCastingPointable;
+import org.apache.asterix.om.pointables.ARecordCastingPointable;
+import org.apache.asterix.om.pointables.base.ICastingPointable;
+import org.apache.asterix.om.pointables.cast.ACastingPointableVisitor;
+import org.apache.asterix.om.pointables.cast.CastResult;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.EnumDeserializer;
+import org.apache.asterix.om.types.IAType;
+import org.apache.asterix.om.types.TypeTagUtil;
+import org.apache.asterix.om.util.container.IObjectPool;
+import org.apache.asterix.om.util.container.ListObjectPool;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.api.exceptions.SourceLocation;
+import org.apache.hyracks.data.std.api.IPointable;
+import org.apache.hyracks.data.std.primitive.VoidPointable;
+
+public class TypeCaster {
+
+ private final IObjectPool<AFlatValueCastingPointable, IAType> flatValuePool =
+ new ListObjectPool<>(AFlatValueCastingPointable.FACTORY);
+ private final IObjectPool<ARecordCastingPointable, IAType> recordValuePool =
+ new ListObjectPool<>(ARecordCastingPointable.FACTORY);
+ private final IObjectPool<AListCastingPointable, IAType> listValuePool =
+ new ListObjectPool<>(AListCastingPointable.FACTORY);
+ private final CastResult castResult = new CastResult(new VoidPointable(), null);
+ private final ACastingPointableVisitor castVisitor;
+
+ public TypeCaster(SourceLocation sourceLoc) {
+ this.castVisitor = new ACastingPointableVisitor(true, sourceLoc);
+ }
+
+ protected void allocateAndCast(IPointable argPointable, IAType argType, IPointable result, IAType reqType)
+ throws HyracksDataException {
+ castResult.setOutType(reqType);
+ ICastingPointable inputPointable = allocate(argPointable, argType);
+ inputPointable.accept(castVisitor, castResult);
+ result.set(castResult.getOutPointable());
+ }
+
+ private ICastingPointable allocate(IPointable arg, IAType argType) throws HyracksDataException {
+ ICastingPointable p;
+ if (!argType.equals(BuiltinType.ANY)) {
+ p = allocate(argType);
+ } else {
+ ATypeTag tag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(arg.getByteArray()[arg.getStartOffset()]);
+ p = allocate(TypeTagUtil.getBuiltinTypeByTag(tag));
+ }
+ p.set(arg);
+ return p;
+ }
+
+ private ICastingPointable allocate(IAType inputType) {
+ ICastingPointable pointable;
+ switch (inputType.getTypeTag()) {
+ case OBJECT:
+ pointable = recordValuePool.allocate(inputType);
+ break;
+ case ARRAY:
+ case MULTISET:
+ pointable = listValuePool.allocate(inputType);
+ break;
+ default:
+ pointable = flatValuePool.allocate(null);
+ }
+ return pointable;
+ }
+
+ public void deallocatePointables() {
+ flatValuePool.reset();
+ listValuePool.reset();
+ recordValuePool.reset();
+ }
+}