Xikui Wang has uploaded a new change for review. https://asterix-gerrit.ics.uci.edu/3270
Change subject: [NO ISSUE][FUN] Fix type inference and casting in UDFs ...................................................................... [NO ISSUE][FUN] Fix type inference and casting in UDFs - user model changes: no - storage format changes: no - interface changes: no Details: The current UDF framework handles the argument types in a sloppy way. It takes in the arguments and reads them as the expected data types in the configuration. This could cause exception at runtime when passing in arguments with unexpected datatypes. When setting the arguments, it did a type casting for numeric values only to make sure the int64 from query interface can be evaluated properly. However, this is not robust enough. This patch fixes the type inference for UDFs during the complation time. The ExternalTypeComputer is refactored to return defined data type, and meanwhile checks the argument data types. Also, the IntroduceDynamicTypeCastForExternalFunctionRule is modified to cover the type castings for data types besides record type. Change-Id: I40506fcca3cd8f14bbd6412359683433256c4c1f --- M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java C asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.1.ddl.sqlpp C asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.2.lib.sqlpp C asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.3.query.sqlpp C asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.6.lib.sqlpp C asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.7.ddl.sqlpp C asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.4.query.sqlpp C asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.5.query.sqlpp R asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.6.lib.sqlpp R asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.7.ddl.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/my_array_sum/my_array_sum.1.adm A asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/mysum/mysum.2.adm M asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/validate-default-library/validate-default-library.1.adm M asterixdb/asterix-app/src/test/resources/runtimets/testsuite_it_sqlpp.xml M asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/library/ExternalFunction.java C asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MyArraySumFactory.java C asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MyArraySumFunction.java R asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MySumFactory.java R asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MySumFunction.java M asterixdb/asterix-external-data/src/test/resources/library_descriptor.xml M asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalFunctionCompilerUtil.java M asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalTypeComputer.java A asterixdb/asterix-server/src/test/resources/integrationts/library/results/library-functions/my_array_sum/my_array_sum.1.adm A asterixdb/asterix-server/src/test/resources/integrationts/library/results/library-functions/mysum/mysum.2.adm M asterixdb/asterix-server/src/test/resources/integrationts/library/testsuite.xml 25 files changed, 115 insertions(+), 166 deletions(-) git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb refs/changes/70/3270/1 diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java index 97e2174..4041f44 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/IntroduceDynamicTypeCastForExternalFunctionRule.java @@ -21,11 +21,15 @@ import org.apache.asterix.lang.common.util.FunctionUtil; import org.apache.asterix.metadata.functions.ExternalScalarFunctionInfo; +import org.apache.asterix.om.base.ARecord; import org.apache.asterix.om.functions.BuiltinFunctions; import org.apache.asterix.om.typecomputer.base.TypeCastUtils; import org.apache.asterix.om.types.ARecordType; +import org.apache.asterix.om.types.ATypeTag; import org.apache.asterix.om.types.AUnionType; +import org.apache.asterix.om.types.BuiltinType; import org.apache.asterix.om.types.IAType; +import org.apache.asterix.om.types.hierachy.ATypeHierarchy; import org.apache.asterix.om.utils.NonTaggedFormatUtil; import org.apache.commons.lang3.mutable.Mutable; import org.apache.commons.lang3.mutable.MutableObject; @@ -71,35 +75,37 @@ if (BuiltinFunctions.getBuiltinFunctionIdentifier(funcCallExpr.getFunctionIdentifier()) != null) { return changed; } - IAType inputRecordType; - ARecordType requiredRecordType; + IAType inputType; + IAType reqArgType; + Boolean castFlag; for (int iter1 = 0; iter1 < funcCallExpr.getArguments().size(); iter1++) { Mutable<ILogicalExpression> argExpr = funcCallExpr.getArguments().get(iter1); - inputRecordType = (IAType) op.computeOutputTypeEnvironment(context).getType(argExpr.getValue()); - if (!(((ExternalScalarFunctionInfo) funcCallExpr.getFunctionInfo()).getArgumenTypes() - .get(iter1) instanceof ARecordType)) { - continue; + inputType = (IAType) op.computeOutputTypeEnvironment(context).getType(argExpr.getValue()); + reqArgType = ((ExternalScalarFunctionInfo) funcCallExpr.getFunctionInfo()).getArgumenTypes() + .get(iter1); + + if (reqArgType.getTypeTag() == ATypeTag.OBJECT) { + castFlag = !IntroduceDynamicTypeCastRule.compatible((ARecordType) reqArgType, inputType, + argExpr.getValue().getSourceLocation()); + } else { + castFlag = !reqArgType.equals(inputType); } - requiredRecordType = (ARecordType) ((ExternalScalarFunctionInfo) funcCallExpr.getFunctionInfo()) - .getArgumenTypes().get(iter1); /** * the input record type can be an union type * for the case when it comes from a subplan or left-outer join */ boolean checkUnknown = false; - while (NonTaggedFormatUtil.isOptional(inputRecordType)) { + while (NonTaggedFormatUtil.isOptional(inputType)) { /** while-loop for the case there is a nested multi-level union */ - inputRecordType = ((AUnionType) inputRecordType).getActualType(); + inputType = ((AUnionType) inputType).getActualType(); checkUnknown = true; } - boolean castFlag = !IntroduceDynamicTypeCastRule.compatible(requiredRecordType, inputRecordType, - argExpr.getValue().getSourceLocation()); if (castFlag || checkUnknown) { AbstractFunctionCallExpression castFunc = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.CAST_TYPE)); castFunc.setSourceLocation(argExpr.getValue().getSourceLocation()); castFunc.getArguments().add(argExpr); - TypeCastUtils.setRequiredAndInputTypes(castFunc, requiredRecordType, inputRecordType); + TypeCastUtils.setRequiredAndInputTypes(castFunc, reqArgType, inputType); funcCallExpr.getArguments().set(iter1, new MutableObject<>(castFunc)); changed = true; } diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.1.ddl.sqlpp similarity index 69% copy from asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.1.ddl.sqlpp index 5202093..76cc70d 100644 --- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.1.ddl.sqlpp @@ -16,16 +16,5 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.asterix.external.library; - -import org.apache.asterix.external.api.IExternalScalarFunction; -import org.apache.asterix.external.api.IFunctionFactory; - -public class SumFactory implements IFunctionFactory { - - @Override - public IExternalScalarFunction getExternalFunction() { - return new SumFunction(); - } - -} +DROP DATAVERSE externallibtest if exists; +CREATE DATAVERSE externallibtest; diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.2.lib.sqlpp similarity index 69% copy from asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.2.lib.sqlpp index 5202093..d1e0e87 100644 --- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.2.lib.sqlpp @@ -16,16 +16,4 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.asterix.external.library; - -import org.apache.asterix.external.api.IExternalScalarFunction; -import org.apache.asterix.external.api.IFunctionFactory; - -public class SumFactory implements IFunctionFactory { - - @Override - public IExternalScalarFunction getExternalFunction() { - return new SumFunction(); - } - -} +install externallibtest testlib target/data/externallib/asterix-external-data-testlib.zip \ No newline at end of file diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.3.query.sqlpp similarity index 69% copy from asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.3.query.sqlpp index 5202093..f9ebecd 100644 --- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.3.query.sqlpp @@ -16,16 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.asterix.external.library; +use externallibtest; -import org.apache.asterix.external.api.IExternalScalarFunction; -import org.apache.asterix.external.api.IFunctionFactory; - -public class SumFactory implements IFunctionFactory { - - @Override - public IExternalScalarFunction getExternalFunction() { - return new SumFunction(); - } - -} +testlib#my_array_sum([8.9, 9.7, 1]); diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.4.lib.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.6.lib.sqlpp similarity index 100% copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.4.lib.sqlpp copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.6.lib.sqlpp diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.5.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.7.ddl.sqlpp similarity index 100% copy from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.5.ddl.sqlpp copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/my_array_sum/my_array_sum.7.ddl.sqlpp diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.4.query.sqlpp similarity index 69% copy from asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.4.query.sqlpp index 5202093..9fd6f94 100644 --- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.4.query.sqlpp @@ -16,16 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.asterix.external.library; +use externallibtest; -import org.apache.asterix.external.api.IExternalScalarFunction; -import org.apache.asterix.external.api.IFunctionFactory; - -public class SumFactory implements IFunctionFactory { - - @Override - public IExternalScalarFunction getExternalFunction() { - return new SumFunction(); - } - -} +testlib#mysum(9.7, 4); diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.5.query.sqlpp similarity index 69% copy from asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.5.query.sqlpp index 5202093..776f976 100644 --- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.5.query.sqlpp @@ -16,16 +16,6 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.asterix.external.library; +use externallibtest; -import org.apache.asterix.external.api.IExternalScalarFunction; -import org.apache.asterix.external.api.IFunctionFactory; - -public class SumFactory implements IFunctionFactory { - - @Override - public IExternalScalarFunction getExternalFunction() { - return new SumFunction(); - } - -} +testlib#mysum("3",4); diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.4.lib.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.6.lib.sqlpp similarity index 100% rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.4.lib.sqlpp rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.6.lib.sqlpp diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.5.ddl.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.7.ddl.sqlpp similarity index 100% rename from asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.5.ddl.sqlpp rename to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/external-library/mysum/mysum.7.ddl.sqlpp diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/my_array_sum/my_array_sum.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/my_array_sum/my_array_sum.1.adm new file mode 100644 index 0000000..25bf17f --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/my_array_sum/my_array_sum.1.adm @@ -0,0 +1 @@ +18 \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/mysum/mysum.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/mysum/mysum.2.adm new file mode 100644 index 0000000..ca7bf83 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/mysum/mysum.2.adm @@ -0,0 +1 @@ +13 \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/validate-default-library/validate-default-library.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/validate-default-library/validate-default-library.1.adm index 13de599..ee90703 100644 --- a/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/validate-default-library/validate-default-library.1.adm +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/external-library/validate-default-library/validate-default-library.1.adm @@ -5,7 +5,8 @@ { "Function": { "DataverseName": "externallibtest", "Name": "testlib#fnameDetector", "Arity": "1", "Params": [ "InputRecordType" ], "ReturnType": "DetectResultType", "Definition": "org.apache.asterix.external.library.KeywordsDetectorFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ] ] } } { "Function": { "DataverseName": "externallibtest", "Name": "testlib#getCapital", "Arity": "1", "Params": [ "ASTRING" ], "ReturnType": "CountryCapitalType", "Definition": "org.apache.asterix.external.library.CapitalFinderFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ] ] } } { "Function": { "DataverseName": "externallibtest", "Name": "testlib#lnameDetector", "Arity": "1", "Params": [ "InputRecordType" ], "ReturnType": "DetectResultType", "Definition": "org.apache.asterix.external.library.KeywordsDetectorFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ] ] } } -{ "Function": { "DataverseName": "externallibtest", "Name": "testlib#mysum", "Arity": "2", "Params": [ "AINT32", "AINT32" ], "ReturnType": "AINT32", "Definition": "org.apache.asterix.external.library.SumFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ] ] } } +{ "Function": { "DataverseName": "externallibtest", "Name": "testlib#my_array_sum", "Arity": "1", "Params": [ "[AINT32]" ], "ReturnType": "AINT32", "Definition": "org.apache.asterix.external.library.MyArraySumFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ] ] } } +{ "Function": { "DataverseName": "externallibtest", "Name": "testlib#mysum", "Arity": "2", "Params": [ "AINT32", "AINT32" ], "ReturnType": "AINT32", "Definition": "org.apache.asterix.external.library.MySumFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ] ] } } { "Function": { "DataverseName": "externallibtest", "Name": "testlib#parseTweet", "Arity": "1", "Params": [ "TweetInputType" ], "ReturnType": "TweetOutputType", "Definition": "org.apache.asterix.external.library.ParseTweetFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ] ] } } { "Function": { "DataverseName": "externallibtest", "Name": "testlib#toUpper", "Arity": "1", "Params": [ "TextType" ], "ReturnType": "TextType", "Definition": "org.apache.asterix.external.library.UpperCaseFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ] ] } } { "Function": { "DataverseName": "externallibtest", "Name": "testlib#typeValidation", "Arity": "11", "Params": [ "AINT32", "AFLOAT", "ASTRING", "ADouble", "ABoolean", "APoint", "ADate", "ADatetime", "ALine", "ACircle", "ARectangle" ], "ReturnType": "AString", "Definition": "org.apache.asterix.external.library.TypeValidationFunctionFactory", "Language": "JAVA", "Kind": "SCALAR", "Dependencies": [ [ ], [ ] ] } } diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_it_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_it_sqlpp.xml index 2121aae..71d0503 100644 --- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_it_sqlpp.xml +++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_it_sqlpp.xml @@ -31,6 +31,12 @@ <test-case FilePath="external-library"> <compilation-unit name="mysum"> <output-dir compare="Text">mysum</output-dir> + <expected-error>Type mismatch: function testlib#mysum expects its 1st input parameter to be of type integer</expected-error> + </compilation-unit> + </test-case> + <test-case FilePath="external-library"> + <compilation-unit name="my_array_sum"> + <output-dir compare="Text">my_array_sum</output-dir> </compilation-unit> </test-case> <test-case FilePath="external-library"> diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/library/ExternalFunction.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/library/ExternalFunction.java index c5b9ad6..22783c2 100755 --- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/library/ExternalFunction.java +++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/library/ExternalFunction.java @@ -49,7 +49,6 @@ protected final IScalarEvaluatorFactory[] evaluatorFactories; protected final IPointable inputVal = new VoidPointable(); protected final ArrayBackedValueStorage resultBuffer = new ArrayBackedValueStorage(); - protected final ArrayBackedValueStorage castBuffer = new ArrayBackedValueStorage(); protected final IScalarEvaluator[] argumentEvaluators; protected final JavaFunctionHelper functionHelper; @@ -84,19 +83,7 @@ public void setArguments(IFrameTupleReference tuple) throws AlgebricksException, IOException { for (int i = 0; i < evaluatorFactories.length; i++) { argumentEvaluators[i].evaluate(tuple, inputVal); - - // Type-cast the source array based on the input type that this function wants to receive. - ATypeTag targetTypeTag = finfo.getArgumentList().get(i).getTypeTag(); - ATypeTag sourceTypeTag = EnumDeserializer.ATYPETAGDESERIALIZER - .deserialize(inputVal.getByteArray()[inputVal.getStartOffset()]); - if (sourceTypeTag != targetTypeTag) { - castBuffer.reset(); - ATypeHierarchy.convertNumericTypeByteArray(inputVal.getByteArray(), inputVal.getStartOffset(), - inputVal.getLength(), targetTypeTag, castBuffer.getDataOutput(), true); - functionHelper.setArgument(i, castBuffer); - } else { - functionHelper.setArgument(i, inputVal); - } + functionHelper.setArgument(i, inputVal); } } diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MyArraySumFactory.java similarity index 91% copy from asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java copy to asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MyArraySumFactory.java index 5202093..3f8c945 100644 --- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java +++ b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MyArraySumFactory.java @@ -21,11 +21,11 @@ import org.apache.asterix.external.api.IExternalScalarFunction; import org.apache.asterix.external.api.IFunctionFactory; -public class SumFactory implements IFunctionFactory { +public class MyArraySumFactory implements IFunctionFactory { @Override public IExternalScalarFunction getExternalFunction() { - return new SumFunction(); + return new MyArraySumFunction(); } } diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFunction.java b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MyArraySumFunction.java similarity index 78% copy from asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFunction.java copy to asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MyArraySumFunction.java index e16d779..67c2889 100644 --- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFunction.java +++ b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MyArraySumFunction.java @@ -21,8 +21,9 @@ import org.apache.asterix.external.api.IExternalScalarFunction; import org.apache.asterix.external.api.IFunctionHelper; import org.apache.asterix.external.library.java.base.JInt; +import org.apache.asterix.external.library.java.base.JOrderedList; -public class SumFunction implements IExternalScalarFunction { +public class MyArraySumFunction implements IExternalScalarFunction { private JInt result; @@ -33,9 +34,12 @@ @Override public void evaluate(IFunctionHelper functionHelper) throws Exception { - int arg0 = ((JInt) functionHelper.getArgument(0)).getValue(); - int arg1 = ((JInt) functionHelper.getArgument(1)).getValue(); - result.setValue(arg0 + arg1); + JOrderedList arg0 = (JOrderedList) (functionHelper.getArgument(0)); + int sum = 0; + for (int iter1 = 0; iter1 < arg0.size(); iter1++) { + sum += ((JInt) arg0.getValue().get(iter1)).getValue(); + } + result.setValue(sum); functionHelper.setResult(result); } diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MySumFactory.java similarity index 92% rename from asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java rename to asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MySumFactory.java index 5202093..0e071e4 100644 --- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFactory.java +++ b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MySumFactory.java @@ -21,11 +21,11 @@ import org.apache.asterix.external.api.IExternalScalarFunction; import org.apache.asterix.external.api.IFunctionFactory; -public class SumFactory implements IFunctionFactory { +public class MySumFactory implements IFunctionFactory { @Override public IExternalScalarFunction getExternalFunction() { - return new SumFunction(); + return new MySumFunction(); } } diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFunction.java b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MySumFunction.java similarity index 92% rename from asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFunction.java rename to asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MySumFunction.java index e16d779..82c52d3 100644 --- a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/SumFunction.java +++ b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/library/MySumFunction.java @@ -21,8 +21,9 @@ import org.apache.asterix.external.api.IExternalScalarFunction; import org.apache.asterix.external.api.IFunctionHelper; import org.apache.asterix.external.library.java.base.JInt; +import org.apache.asterix.external.library.java.base.JLong; -public class SumFunction implements IExternalScalarFunction { +public class MySumFunction implements IExternalScalarFunction { private JInt result; diff --git a/asterixdb/asterix-external-data/src/test/resources/library_descriptor.xml b/asterixdb/asterix-external-data/src/test/resources/library_descriptor.xml index acbc003..720c003 100644 --- a/asterixdb/asterix-external-data/src/test/resources/library_descriptor.xml +++ b/asterixdb/asterix-external-data/src/test/resources/library_descriptor.xml @@ -73,7 +73,15 @@ <function_type>SCALAR</function_type> <argument_type>AINT32,AINT32</argument_type> <return_type>AINT32</return_type> - <definition>org.apache.asterix.external.library.SumFactory + <definition>org.apache.asterix.external.library.MySumFactory + </definition> + </libraryFunction> + <libraryFunction> + <name>my_array_sum</name> + <function_type>SCALAR</function_type> + <argument_type>[AINT32]</argument_type> + <return_type>AINT32</return_type> + <definition>org.apache.asterix.external.library.MyArraySumFactory </definition> </libraryFunction> <libraryFunction> diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalFunctionCompilerUtil.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalFunctionCompilerUtil.java index 01d0af7..66b4ef7 100644 --- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalFunctionCompilerUtil.java +++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalFunctionCompilerUtil.java @@ -72,24 +72,27 @@ throws AlgebricksException { FunctionIdentifier fid = new FunctionIdentifier(function.getDataverseName(), function.getName(), function.getArity()); - IResultTypeComputer typeComputer = getResultTypeComputer(txnCtx, function); - List<IAType> arguments = new ArrayList<>(); - IAType returnType; - List<String> argumentTypes = function.getArguments(); - for (String argumentType : argumentTypes) { - arguments.add(getTypeInfo(argumentType, txnCtx, function)); + List<IAType> argumentTypes = new ArrayList<>(); + IAType returnType = getTypeInfo(function.getReturnType(), txnCtx, function);; + for (String argumentType : function.getArguments()) { + argumentTypes.add(getTypeInfo(argumentType, txnCtx, function)); } - - returnType = getTypeInfo(function.getReturnType(), txnCtx, function); + IResultTypeComputer typeComputer = new ExternalTypeComputer(returnType, argumentTypes); return new ExternalScalarFunctionInfo(fid.getNamespace(), fid.getName(), fid.getArity(), returnType, - function.getFunctionBody(), function.getLanguage(), arguments, typeComputer); + function.getFunctionBody(), function.getLanguage(), argumentTypes, typeComputer); } private static IAType getTypeInfo(String paramType, MetadataTransactionContext txnCtx, Function function) throws AlgebricksException { - if (paramType.equalsIgnoreCase(BuiltinType.AINT32.getDisplayName())) { + if (paramType.equalsIgnoreCase(BuiltinType.AINT8.getDisplayName())) { + return BuiltinType.AINT8; + } else if (paramType.equalsIgnoreCase(BuiltinType.AINT16.getDisplayName())) { + return BuiltinType.AINT16; + } else if (paramType.equalsIgnoreCase(BuiltinType.AINT32.getDisplayName())) { return BuiltinType.AINT32; + } else if (paramType.equalsIgnoreCase(BuiltinType.AINT64.getDisplayName())) { + return BuiltinType.AINT64; } else if (paramType.equalsIgnoreCase(BuiltinType.AFLOAT.getDisplayName())) { return BuiltinType.AFLOAT; } else if (paramType.equalsIgnoreCase(BuiltinType.ASTRING.getDisplayName())) { @@ -142,59 +145,6 @@ } } return null; - } - - private static IResultTypeComputer getResultTypeComputer(final MetadataTransactionContext txnCtx, - final Function function) throws AlgebricksException { - - final IAType type = getTypeInfo(function.getReturnType(), txnCtx, function); - switch (type.getTypeTag()) { - case INTEGER: - return AInt32TypeComputer.INSTANCE; - case FLOAT: - return AFloatTypeComputer.INSTANCE; - case DOUBLE: - return ADoubleTypeComputer.INSTANCE; - case BINARY: - return ABinaryTypeComputer.INSTANCE; - case STRING: - return AStringTypeComputer.INSTANCE; - case ARRAY: - return new ExternalTypeComputer() { - private static final long serialVersionUID = 1L; - - @Override - public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env, - IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException { - - return new AOrderedListType(((AOrderedListType) type).getItemType(), - ((AOrderedListType) type).getItemType().getTypeName()); - } - - }; - case MULTISET: - return new ExternalTypeComputer() { - private static final long serialVersionUID = 1L; - - @Override - public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env, - IMetadataProvider<?, ?> metadataProvider) throws AlgebricksException { - return new AUnorderedListType(((AUnorderedListType) type).getItemType(), type.getTypeName()); - } - - }; - default: - return new ExternalTypeComputer() { - private static final long serialVersionUID = 1L; - - @Override - public IAType computeType(ILogicalExpression expression, IVariableTypeEnvironment env, - IMetadataProvider<?, ?> mp) throws AlgebricksException { - return type; - } - }; - } - } private static IFunctionInfo getUnnestFunctionInfo(MetadataTransactionContext txnCtx, Function function) { diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalTypeComputer.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalTypeComputer.java index d50f4cb..ecb0ddd 100644 --- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalTypeComputer.java +++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/functions/ExternalTypeComputer.java @@ -18,10 +18,39 @@ */ package org.apache.asterix.metadata.functions; -import java.io.Serializable; +import java.util.List; -import org.apache.asterix.om.typecomputer.base.IResultTypeComputer; +import org.apache.asterix.om.exceptions.TypeMismatchException; +import org.apache.asterix.om.typecomputer.base.AbstractResultTypeComputer; +import org.apache.asterix.om.types.IAType; +import org.apache.asterix.om.types.hierachy.ATypeHierarchy; +import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException; +import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression; +import org.apache.hyracks.api.exceptions.SourceLocation; -public interface ExternalTypeComputer extends IResultTypeComputer, Serializable { +public class ExternalTypeComputer extends AbstractResultTypeComputer { + private IAType resultType; + private List<IAType> argTypes; + + @Override + protected void checkArgType(String funcName, int argIndex, IAType type, SourceLocation sourceLoc) + throws AlgebricksException { + IAType reqArgType = argTypes.get(argIndex); + if (!type.equals(argTypes.get(argIndex)) + && !ATypeHierarchy.isCompatible(type.getTypeTag(), reqArgType.getTypeTag())) { + throw new TypeMismatchException(sourceLoc, funcName, argIndex, type.getTypeTag(), + argTypes.get(argIndex).getTypeTag()); + } + } + + public ExternalTypeComputer(IAType resultType, List<IAType> argTypes) { + this.resultType = resultType; + this.argTypes = argTypes; + } + + @Override + protected IAType getResultType(ILogicalExpression expr, IAType... strippedInputTypes) { + return resultType; + } } diff --git a/asterixdb/asterix-server/src/test/resources/integrationts/library/results/library-functions/my_array_sum/my_array_sum.1.adm b/asterixdb/asterix-server/src/test/resources/integrationts/library/results/library-functions/my_array_sum/my_array_sum.1.adm new file mode 100644 index 0000000..25bf17f --- /dev/null +++ b/asterixdb/asterix-server/src/test/resources/integrationts/library/results/library-functions/my_array_sum/my_array_sum.1.adm @@ -0,0 +1 @@ +18 \ No newline at end of file diff --git a/asterixdb/asterix-server/src/test/resources/integrationts/library/results/library-functions/mysum/mysum.2.adm b/asterixdb/asterix-server/src/test/resources/integrationts/library/results/library-functions/mysum/mysum.2.adm new file mode 100644 index 0000000..ca7bf83 --- /dev/null +++ b/asterixdb/asterix-server/src/test/resources/integrationts/library/results/library-functions/mysum/mysum.2.adm @@ -0,0 +1 @@ +13 \ No newline at end of file diff --git a/asterixdb/asterix-server/src/test/resources/integrationts/library/testsuite.xml b/asterixdb/asterix-server/src/test/resources/integrationts/library/testsuite.xml index babf911..76b74ef 100644 --- a/asterixdb/asterix-server/src/test/resources/integrationts/library/testsuite.xml +++ b/asterixdb/asterix-server/src/test/resources/integrationts/library/testsuite.xml @@ -28,6 +28,12 @@ <test-case FilePath="library-functions"> <compilation-unit name="mysum"> <output-dir compare="Text">mysum</output-dir> + <expected-error>Type mismatch: function testlib#mysum expects its 1st input parameter to be of type integer</expected-error> + </compilation-unit> + </test-case> + <test-case FilePath="external-library"> + <compilation-unit name="my_array_sum"> + <output-dir compare="Text">my_array_sum</output-dir> </compilation-unit> </test-case> <test-case FilePath="library-functions"> -- To view, visit https://asterix-gerrit.ics.uci.edu/3270 To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I40506fcca3cd8f14bbd6412359683433256c4c1f Gerrit-PatchSet: 1 Gerrit-Project: asterixdb Gerrit-Branch: master Gerrit-Owner: Xikui Wang <xkk...@gmail.com>