This is an automated email from the ASF dual-hosted git repository. mblow pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/asterixdb.git
commit 907c769582d3646b6d30056158277f08383d87de Author: Ali Alsuliman <[email protected]> AuthorDate: Mon May 12 13:03:15 2025 -0700 [ASTERIXDB-3607][FUN] Add function to handle failures when evaluating functions - user model changes: no - storage format changes: no - interface changes: no Details: Such a function will be helpful when we need to identify the documents causing query failure due to function evaluation errors. Ext-ref: MB-66662 Change-Id: I7568f80059742788d1a9cc8286e1f242b0bfebbf Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19766 Tested-by: Ali Alsuliman <[email protected]> Reviewed-by: Ali Alsuliman <[email protected]> Reviewed-by: Ian Maxon <[email protected]> --- .../InjectTypeCastForFunctionArgumentsRule.java | 1 + .../handle_error_fun.01.query.sqlpp | 25 ++++++++ .../misc/handle_error_fun/handle_error_fun.01.adm | 1 + .../src/test/resources/runtimets/sqlpp_queries.xml | 5 ++ .../asterix/om/functions/BuiltinFunctions.java | 3 + .../evaluators/functions/IfErrorDescriptor.java | 70 ++++++++++++++++++++++ .../runtime/functions/FunctionCollection.java | 2 + 7 files changed, 107 insertions(+) diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForFunctionArgumentsRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForFunctionArgumentsRule.java index f78aa59f2e..98c54e6005 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForFunctionArgumentsRule.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/InjectTypeCastForFunctionArgumentsRule.java @@ -61,6 +61,7 @@ public class InjectTypeCastForFunctionArgumentsRule implements IAlgebraicRewrite addFunctionAndArgChecker(BuiltinFunctions.IF_NULL, null); addFunctionAndArgChecker(BuiltinFunctions.IF_MISSING_OR_NULL, null); addFunctionAndArgChecker(BuiltinFunctions.IF_SYSTEM_NULL, null); + addFunctionAndArgChecker(BuiltinFunctions.IF_ERROR, null); } // allows the rule to check other functions in addition to the ones specified here diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/handle_error_fun/handle_error_fun.01.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/handle_error_fun/handle_error_fun.01.query.sqlpp new file mode 100644 index 0000000000..c47e3f5663 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/handle_error_fun/handle_error_fun.01.query.sqlpp @@ -0,0 +1,25 @@ +/* + * 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. + */ +SET `import-private-functions` `true`; +SELECT VALUE t +FROM [ +{"id": 1, "f": "fine doc"}, +{"id": 2, "f": "problematic doc"} +] AS t +WHERE if_error(inject_failure("", t.id = 2), true) = true; \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/handle_error_fun/handle_error_fun.01.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/handle_error_fun/handle_error_fun.01.adm new file mode 100644 index 0000000000..b9a7cb51e7 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/handle_error_fun/handle_error_fun.01.adm @@ -0,0 +1 @@ +{ "id": 2, "f": "problematic doc" } \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml index 8dfc136924..2701f152dd 100644 --- a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml +++ b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml @@ -7290,6 +7290,11 @@ <output-dir compare="Text">serialized_size_fun</output-dir> </compilation-unit> </test-case> + <test-case FilePath="misc"> + <compilation-unit name="handle_error_fun"> + <output-dir compare="Text">handle_error_fun</output-dir> + </compilation-unit> + </test-case> <test-case FilePath="misc"> <compilation-unit name="query-ASTERIXDB-3334"> <output-dir compare="Text">query-ASTERIXDB-3334</output-dir> diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java index bb05ba6d49..bc7f81763e 100644 --- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java +++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java @@ -1716,6 +1716,8 @@ public class BuiltinFunctions { public static final FunctionIdentifier SERIALIZED_SIZE = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "serialized-size", 1); + public static final FunctionIdentifier IF_ERROR = + new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "if-error", 2); static { // first, take care of Algebricks builtin functions @@ -2556,6 +2558,7 @@ public class BuiltinFunctions { addPrivateFunction(COLLECTION_TO_SEQUENCE, CollectionToSequenceTypeComputer.INSTANCE, true); addPrivateFunction(SERIALIZED_SIZE, AInt64TypeComputer.INSTANCE, true); + addPrivateFunction(IF_ERROR, AnyTypeComputer.INSTANCE, true); // external lookup addPrivateFunction(EXTERNAL_LOOKUP, AnyTypeComputer.INSTANCE, false); diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfErrorDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfErrorDescriptor.java new file mode 100644 index 0000000000..a4e830f824 --- /dev/null +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/IfErrorDescriptor.java @@ -0,0 +1,70 @@ +/* + * 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.functions.BuiltinFunctions; +import org.apache.asterix.om.functions.IFunctionDescriptorFactory; +import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor; +import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier; +import org.apache.hyracks.algebricks.runtime.base.IEvaluatorContext; +import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator; +import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory; +import org.apache.hyracks.api.exceptions.HyracksDataException; +import org.apache.hyracks.data.std.api.IPointable; +import org.apache.hyracks.data.std.primitive.VoidPointable; +import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference; + +public final class IfErrorDescriptor extends AbstractScalarFunctionDynamicDescriptor { + private static final long serialVersionUID = 1L; + + public static final IFunctionDescriptorFactory FACTORY = IfErrorDescriptor::new; + + @Override + public IScalarEvaluatorFactory createEvaluatorFactory(IScalarEvaluatorFactory[] args) { + return new IScalarEvaluatorFactory() { + private static final long serialVersionUID = 1L; + + @Override + public IScalarEvaluator createScalarEvaluator(IEvaluatorContext ctx) throws HyracksDataException { + return new AbstractScalarEval(sourceLoc, getIdentifier()) { + private final IScalarEvaluator eval0 = args[0].createScalarEvaluator(ctx); + private final IScalarEvaluator eval1 = args[1].createScalarEvaluator(ctx); + private final VoidPointable arg = VoidPointable.FACTORY.createPointable(); + + @Override + public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException { + try { + eval0.evaluate(tuple, arg); + result.set(arg); + } catch (Throwable th) { + eval1.evaluate(tuple, arg); + result.set(arg); + } + } + }; + } + }; + } + + @Override + public FunctionIdentifier getIdentifier() { + return BuiltinFunctions.IF_ERROR; + } +} diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java index 2b8d4e2eee..36dc469028 100644 --- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java @@ -377,6 +377,7 @@ import org.apache.asterix.runtime.evaluators.functions.GetIntersectionDescriptor import org.apache.asterix.runtime.evaluators.functions.GetItemDescriptor; import org.apache.asterix.runtime.evaluators.functions.GetJobParameterByNameDescriptor; import org.apache.asterix.runtime.evaluators.functions.GetTypeDescriptor; +import org.apache.asterix.runtime.evaluators.functions.IfErrorDescriptor; import org.apache.asterix.runtime.evaluators.functions.IfInfDescriptor; import org.apache.asterix.runtime.evaluators.functions.IfMissingDescriptor; import org.apache.asterix.runtime.evaluators.functions.IfMissingOrNullDescriptor; @@ -1329,6 +1330,7 @@ public final class FunctionCollection implements IFunctionCollection { fc.add(DecodeDataverseNameDescriptor.FACTORY); fc.add(RandomWithSeedDescriptor.FACTORY); fc.add(SerializedSizeDescriptor.FACTORY); + fc.add(IfErrorDescriptor.FACTORY); ServiceLoader.load(IFunctionRegistrant.class).iterator().forEachRemaining(c -> c.register(fc)); return fc;
