Dmitry Lychagin has submitted this change and it was merged. Change subject: [NO ISSUE][FUN] Implement numeric functions ......................................................................
[NO ISSUE][FUN] Implement numeric functions - user model changes: yes - storage format changes: no - interface changes: no Details: - Implement the following numeric functions: degrees(), e(), pi(), radians(), random() Change-Id: I3beb1f35979ec2e06222beb76e3c284b1259b4eb Reviewed-on: https://asterix-gerrit.ics.uci.edu/2610 Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Contrib: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Reviewed-by: Dmitry Lychagin <dmitry.lycha...@couchbase.com> --- M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/random/random.1.query.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/const/const.1.query.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/degrees/degrees.1.query.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/radians/radians.1.query.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/results/misc/random/random.1.adm A asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/const/const.1.adm A asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/degrees/degrees.1.adm A asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/radians/radians.1.adm M asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml M asterixdb/asterix-doc/src/main/markdown/builtins/12_misc.md M asterixdb/asterix-doc/src/main/markdown/builtins/1_numeric_common.md M asterixdb/asterix-om/src/main/java/org/apache/asterix/om/functions/BuiltinFunctions.java A asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericDegreesDescriptor.java A asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRadiansDescriptor.java A asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/RandomDescriptor.java A asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/RandomWithSeedDescriptor.java A asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/utils/RandomHelper.java M asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java 19 files changed, 639 insertions(+), 0 deletions(-) Approvals: Anon. E. Moose #1000171: Jenkins: Verified; ; Verified Dmitry Lychagin: Looks good to me, approved Objections: Jenkins: Violations found diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java index 29a8e77..7110dbb 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/ConstantFoldingRule.java @@ -22,6 +22,7 @@ import java.io.DataInputStream; import java.nio.ByteBuffer; import java.util.List; +import java.util.Map; import org.apache.asterix.common.config.GlobalConfig; import org.apache.asterix.common.dataflow.ICcApplicationContext; @@ -37,6 +38,7 @@ import org.apache.asterix.formats.nontagged.TypeTraitProvider; import org.apache.asterix.jobgen.QueryLogicalExpressionJobGen; import org.apache.asterix.metadata.declared.MetadataProvider; +import org.apache.asterix.om.base.ADouble; import org.apache.asterix.om.base.IAObject; import org.apache.asterix.om.constants.AsterixConstantValue; import org.apache.asterix.om.functions.BuiltinFunctions; @@ -78,6 +80,7 @@ import org.apache.hyracks.data.std.primitive.VoidPointable; import org.apache.hyracks.dataflow.common.comm.util.ByteBufferInputStream; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; public class ConstantFoldingRule implements IAlgebraicRewriteRule { @@ -94,6 +97,9 @@ BuiltinFunctions.FIELD_ACCESS_BY_INDEX, BuiltinFunctions.CAST_TYPE, BuiltinFunctions.META, BuiltinFunctions.META_KEY, BuiltinFunctions.RECORD_CONCAT, BuiltinFunctions.RECORD_CONCAT_STRICT, BuiltinFunctions.TO_ATOMIC, BuiltinFunctions.TO_ARRAY); + + private static final Map<FunctionIdentifier, IAObject> FUNC_ID_TO_CONSTANT = ImmutableMap + .of(BuiltinFunctions.NUMERIC_E, new ADouble(Math.E), BuiltinFunctions.NUMERIC_PI, new ADouble(Math.PI)); /** * Throws exceptions in substituiteProducedVariable, setVarType, and one getVarType method. @@ -220,6 +226,10 @@ return new Pair<>(changed, expr); } } + IAObject c = FUNC_ID_TO_CONSTANT.get(expr.getFunctionIdentifier()); + if (c != null) { + return new Pair<>(true, new ConstantExpression(new AsterixConstantValue(c))); + } IScalarEvaluatorFactory fact = jobGenCtx.getExpressionRuntimeProvider().createEvaluatorFactory(expr, _emptyTypeEnv, _emptySchemas, jobGenCtx); diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/random/random.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/random/random.1.query.sqlpp new file mode 100644 index 0000000..bf35f87 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/misc/random/random.1.query.sqlpp @@ -0,0 +1,42 @@ +/* + * 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. + */ + +{ + "t1": array_length(( + from range(1, 6) t + select distinct value random() + )), + + "t2": array_length(( + from range(1, 6) t + select distinct value random(t) + )), + + "t3": array_length(( + from range(1, 6) t + select distinct value random(unix_time_from_datetime_in_ms(current_datetime())) + )), + + "t4": array_length(( + from [ tinyint("1"), smallint("2"), integer("3"), bigint("4"), float("5"), double("6") ] t + select distinct value random(t) + )), + + "t5": [ random(missing) is missing, random(null) is null ] +} \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/const/const.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/const/const.1.query.sqlpp new file mode 100644 index 0000000..fe67901 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/const/const.1.query.sqlpp @@ -0,0 +1,23 @@ +/* + * 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. + */ + +{ + "e": trunc(e(), 2), + "pi": trunc(pi(), 2) +} \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/degrees/degrees.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/degrees/degrees.1.query.sqlpp new file mode 100644 index 0000000..80e002e --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/degrees/degrees.1.query.sqlpp @@ -0,0 +1,22 @@ +/* + * 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. + */ + +{ + "t1": tobigint(degrees(pi())) +} \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/radians/radians.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/radians/radians.1.query.sqlpp new file mode 100644 index 0000000..6d04878 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/numeric/radians/radians.1.query.sqlpp @@ -0,0 +1,22 @@ +/* + * 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. + */ + +{ + "t1": trunc(radians(180), 2) +} \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/random/random.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/random/random.1.adm new file mode 100644 index 0000000..4be3e9a --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/misc/random/random.1.adm @@ -0,0 +1 @@ +{ "t1": 6, "t2": 6, "t3": 6, "t4": 6, "t5": [ true, true ] } \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/const/const.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/const/const.1.adm new file mode 100644 index 0000000..abab248 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/const/const.1.adm @@ -0,0 +1 @@ +{ "e": 2.71, "pi": 3.14 } \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/degrees/degrees.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/degrees/degrees.1.adm new file mode 100644 index 0000000..e1310b6 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/degrees/degrees.1.adm @@ -0,0 +1 @@ +{ "t1": 180 } \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/radians/radians.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/radians/radians.1.adm new file mode 100644 index 0000000..6091a8c --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/numeric/radians/radians.1.adm @@ -0,0 +1 @@ +{ "t1": 3.14 } \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml index 6118d29..278f3f5 100644 --- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml +++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml @@ -3683,6 +3683,11 @@ </compilation-unit> </test-case> <test-case FilePath="misc"> + <compilation-unit name="random"> + <output-dir compare="Text">random</output-dir> + </compilation-unit> + </test-case> + <test-case FilePath="misc"> <compilation-unit name="stable_sort"> <output-dir compare="Text">stable_sort</output-dir> </compilation-unit> @@ -4839,6 +4844,16 @@ </compilation-unit> </test-case> <test-case FilePath="numeric"> + <compilation-unit name="const"> + <output-dir compare="Text">const</output-dir> + </compilation-unit> + </test-case> + <test-case FilePath="numeric"> + <compilation-unit name="degrees"> + <output-dir compare="Text">degrees</output-dir> + </compilation-unit> + </test-case> + <test-case FilePath="numeric"> <compilation-unit name="divide_double"> <output-dir compare="Text">divide_double</output-dir> </compilation-unit> @@ -4949,6 +4964,11 @@ </compilation-unit> </test-case> <test-case FilePath="numeric"> + <compilation-unit name="radians"> + <output-dir compare="Text">radians</output-dir> + </compilation-unit> + </test-case> + <test-case FilePath="numeric"> <compilation-unit name="round-half-to-even0"> <output-dir compare="Text">round-half-to-even0</output-dir> </compilation-unit> diff --git a/asterixdb/asterix-doc/src/main/markdown/builtins/12_misc.md b/asterixdb/asterix-doc/src/main/markdown/builtins/12_misc.md index ac2a465..dfb1b0b 100644 --- a/asterixdb/asterix-doc/src/main/markdown/builtins/12_misc.md +++ b/asterixdb/asterix-doc/src/main/markdown/builtins/12_misc.md @@ -76,6 +76,28 @@ { "v1": false, "v2": true, "v3": null } +### random ### + * Syntax: + + random( [seed_value] ) + + * Returns a random number, accepting an optional seed value + * Arguments: + * `seed_value`: an optional `tinyint`/`smallint`/`integer`/`bigint`/`float`/`double` value representing the seed number. + * Return Value: + * A random number of type `double` between 0 and 1, + * `missing` if the argument is a `missing` value, + * `null` if the argument is a `null` value, + * any other non-numeric input value will cause a type error. + + * Example: + + { + "v1": random(), + "v2": random(unix_time_from_datetime_in_ms(current_datetime())) + }; + + ### range ### * Syntax: diff --git a/asterixdb/asterix-doc/src/main/markdown/builtins/1_numeric_common.md b/asterixdb/asterix-doc/src/main/markdown/builtins/1_numeric_common.md index c058d10..b95e778c 100644 --- a/asterixdb/asterix-doc/src/main/markdown/builtins/1_numeric_common.md +++ b/asterixdb/asterix-doc/src/main/markdown/builtins/1_numeric_common.md @@ -198,6 +198,47 @@ { "v1": 0.5403023058681398, "v2": -0.4161468365471424, "v3": 1.0, "v4": 0.8775825618903728, "v5": 0.562379076290703 } +### degrees ### + * Syntax: + + degrees(numeric_value) + + * Converts radians to degrees + * Arguments: + * `numeric_value`: a `tinyint`/`smallint`/`integer`/`bigint`/`float`/`double` value. + * Return Value: + * The degrees value for the given radians value. The returned value has type `double`, + * `missing` if the argument is a `missing` value, + * `null` if the argument is a `null` value, + * any other non-numeric input value will cause a type error. + + * Example: + + { "v1": degrees(pi()) }; + + + * The expected result is: + + { "v1": 180.0 } + + +### e ### + * Syntax: + + e() + + * Return Value: + * e (base of the natural logarithm) + + * Example: + + { "v1": e() }; + + * The expected result is: + + { "v1": 2.718281828459045 } + + ### exp ### * Syntax: @@ -301,6 +342,22 @@ { "v1": 0.0, "v2": 0.3010299956639812, "v3": "-Infinity", "v4": -0.3010299956639812, "v5": 3.0 } +### pi ### + * Syntax: + + pi() + + * Return Value: + * Pi + + * Example: + + { "v1": pi() }; + + * The expected result is: + + { "v1": 3.141592653589793 } + ### power ### * Syntax: @@ -327,6 +384,30 @@ { "v1": 1, "v3": 0, "v4": 1.4142135623730951 } +### radians ### + * Syntax: + + radians(numeric_value) + + * Converts degrees to radians + * Arguments: + * `numeric_value`: a `tinyint`/`smallint`/`integer`/`bigint`/`float`/`double` value. + * Return Value: + * The radians value for the given degrees value. The returned value has type `double`, + * `missing` if the argument is a `missing` value, + * `null` if the argument is a `null` value, + * any other non-numeric input value will cause a type error. + + * Example: + + { "v1": radians(180) }; + + + * The expected result is: + + { "v1": 3.141592653589793 } + + ### round ### * Syntax: 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 8071967..222b539 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 @@ -243,6 +243,10 @@ new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "atan", 1); public static final FunctionIdentifier NUMERIC_ATAN2 = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "atan2", 2); + public static final FunctionIdentifier NUMERIC_DEGREES = + new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "degrees", 1); + public static final FunctionIdentifier NUMERIC_RADIANS = + new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "radians", 1); public static final FunctionIdentifier NUMERIC_COS = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "cos", 1); public static final FunctionIdentifier NUMERIC_SIN = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "sin", 1); public static final FunctionIdentifier NUMERIC_TAN = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "tan", 1); @@ -253,6 +257,8 @@ new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "sqrt", 1); public static final FunctionIdentifier NUMERIC_SIGN = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "sign", 1); + public static final FunctionIdentifier NUMERIC_E = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "e", 0); + public static final FunctionIdentifier NUMERIC_PI = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "pi", 0); public static final FunctionIdentifier NUMERIC_CEILING = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "ceiling", 1); @@ -741,6 +747,9 @@ public static final FunctionIdentifier UUID = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "uuid", 0); public static final FunctionIdentifier CREATE_QUERY_UID = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "create-query-uid", 0); + public static final FunctionIdentifier RANDOM = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "random", 0); + public static final FunctionIdentifier RANDOM_WITH_SEED = + new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "random", 1); //Geo public static final FunctionIdentifier ST_AREA = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "st-area", 1); @@ -1097,6 +1106,8 @@ addFunction(UUID, AUUIDTypeComputer.INSTANCE, false); addFunction(CREATE_QUERY_UID, ABinaryTypeComputer.INSTANCE, false); addFunction(UUID_CONSTRUCTOR, AUUIDTypeComputer.INSTANCE, true); + addFunction(RANDOM, ADoubleTypeComputer.INSTANCE, false); + addFunction(RANDOM_WITH_SEED, ADoubleTypeComputer.INSTANCE, false); addFunction(DATE_CONSTRUCTOR, ADateTypeComputer.INSTANCE, true); addFunction(DATETIME_CONSTRUCTOR, ADateTimeTypeComputer.INSTANCE, true); @@ -1140,12 +1151,16 @@ addFunction(NUMERIC_ASIN, NumericDoubleOutputFunctionTypeComputer.INSTANCE, true); addFunction(NUMERIC_ATAN, NumericDoubleOutputFunctionTypeComputer.INSTANCE, true); addFunction(NUMERIC_ATAN2, NumericDoubleOutputFunctionTypeComputer.INSTANCE, true); + addFunction(NUMERIC_DEGREES, NumericDoubleOutputFunctionTypeComputer.INSTANCE, true); + addFunction(NUMERIC_RADIANS, NumericDoubleOutputFunctionTypeComputer.INSTANCE, true); addFunction(NUMERIC_COS, NumericDoubleOutputFunctionTypeComputer.INSTANCE, true); addFunction(NUMERIC_SIN, NumericDoubleOutputFunctionTypeComputer.INSTANCE, true); addFunction(NUMERIC_TAN, NumericDoubleOutputFunctionTypeComputer.INSTANCE, true); + addFunction(NUMERIC_E, ADoubleTypeComputer.INSTANCE, true); addFunction(NUMERIC_EXP, NumericDoubleOutputFunctionTypeComputer.INSTANCE, true); addFunction(NUMERIC_LN, NumericDoubleOutputFunctionTypeComputer.INSTANCE, true); addFunction(NUMERIC_LOG, NumericDoubleOutputFunctionTypeComputer.INSTANCE, true); + addFunction(NUMERIC_PI, ADoubleTypeComputer.INSTANCE, true); addFunction(NUMERIC_SQRT, NumericDoubleOutputFunctionTypeComputer.INSTANCE, true); addFunction(NUMERIC_SIGN, NumericInt8OutputFunctionTypeComputer.INSTANCE, true); addFunction(NUMERIC_CEILING, NumericUnaryFunctionTypeComputer.INSTANCE, true); diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericDegreesDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericDegreesDescriptor.java new file mode 100644 index 0000000..dbb4737 --- /dev/null +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericDegreesDescriptor.java @@ -0,0 +1,64 @@ +/* + * 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.IFunctionDescriptor; +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.IScalarEvaluator; +import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory; +import org.apache.hyracks.api.context.IHyracksTaskContext; +import org.apache.hyracks.api.exceptions.HyracksDataException; +import org.apache.hyracks.data.std.api.IPointable; + +public class NumericDegreesDescriptor extends AbstractScalarFunctionDynamicDescriptor { + private static final long serialVersionUID = 1L; + public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() { + @Override + public IFunctionDescriptor createFunctionDescriptor() { + return new NumericDegreesDescriptor(); + } + }; + + @Override + public IScalarEvaluatorFactory createEvaluatorFactory(IScalarEvaluatorFactory[] args) { + return new IScalarEvaluatorFactory() { + private static final long serialVersionUID = 1L; + + @Override + public IScalarEvaluator createScalarEvaluator(IHyracksTaskContext ctx) throws HyracksDataException { + return new AbstractUnaryNumericDoubleFunctionEval(ctx, args[0], getIdentifier()) { + @Override + protected void processDouble(double arg, IPointable resultPointable) throws HyracksDataException { + aDouble.setValue(Math.toDegrees(arg)); + serialize(aDouble, doubleSerde, resultPointable); + } + }; + } + }; + } + + @Override + public FunctionIdentifier getIdentifier() { + return BuiltinFunctions.NUMERIC_DEGREES; + } +} diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRadiansDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRadiansDescriptor.java new file mode 100644 index 0000000..51352cb --- /dev/null +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/NumericRadiansDescriptor.java @@ -0,0 +1,64 @@ +/* + * 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.IFunctionDescriptor; +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.IScalarEvaluator; +import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory; +import org.apache.hyracks.api.context.IHyracksTaskContext; +import org.apache.hyracks.api.exceptions.HyracksDataException; +import org.apache.hyracks.data.std.api.IPointable; + +public class NumericRadiansDescriptor extends AbstractScalarFunctionDynamicDescriptor { + private static final long serialVersionUID = 1L; + public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() { + @Override + public IFunctionDescriptor createFunctionDescriptor() { + return new NumericRadiansDescriptor(); + } + }; + + @Override + public IScalarEvaluatorFactory createEvaluatorFactory(IScalarEvaluatorFactory[] args) { + return new IScalarEvaluatorFactory() { + private static final long serialVersionUID = 1L; + + @Override + public IScalarEvaluator createScalarEvaluator(IHyracksTaskContext ctx) throws HyracksDataException { + return new AbstractUnaryNumericDoubleFunctionEval(ctx, args[0], getIdentifier()) { + @Override + protected void processDouble(double arg, IPointable resultPointable) throws HyracksDataException { + aDouble.setValue(Math.toRadians(arg)); + serialize(aDouble, doubleSerde, resultPointable); + } + }; + } + }; + } + + @Override + public FunctionIdentifier getIdentifier() { + return BuiltinFunctions.NUMERIC_RADIANS; + } +} diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/RandomDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/RandomDescriptor.java new file mode 100644 index 0000000..fb99438 --- /dev/null +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/RandomDescriptor.java @@ -0,0 +1,68 @@ +/* + * 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.IFunctionDescriptor; +import org.apache.asterix.om.functions.IFunctionDescriptorFactory; +import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor; +import org.apache.asterix.runtime.evaluators.functions.utils.RandomHelper; +import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier; +import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator; +import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory; +import org.apache.hyracks.api.context.IHyracksTaskContext; +import org.apache.hyracks.api.exceptions.HyracksDataException; +import org.apache.hyracks.data.std.api.IPointable; +import org.apache.hyracks.dataflow.common.data.accessors.IFrameTupleReference; + +public class RandomDescriptor extends AbstractScalarFunctionDynamicDescriptor { + private static final long serialVersionUID = 1L; + + public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() { + @Override + public IFunctionDescriptor createFunctionDescriptor() { + return new RandomDescriptor(); + } + }; + + @Override + public IScalarEvaluatorFactory createEvaluatorFactory(IScalarEvaluatorFactory[] args) { + return new IScalarEvaluatorFactory() { + private static final long serialVersionUID = 1L; + + @Override + public IScalarEvaluator createScalarEvaluator(IHyracksTaskContext ctx) throws HyracksDataException { + return new IScalarEvaluator() { + private final RandomHelper randomHelper = new RandomHelper(false); + + @Override + public void evaluate(IFrameTupleReference tuple, IPointable result) throws HyracksDataException { + randomHelper.nextDouble(result); + } + }; + } + }; + } + + @Override + public FunctionIdentifier getIdentifier() { + return BuiltinFunctions.RANDOM; + } +} diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/RandomWithSeedDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/RandomWithSeedDescriptor.java new file mode 100644 index 0000000..6dd5eac --- /dev/null +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/RandomWithSeedDescriptor.java @@ -0,0 +1,92 @@ +/* + * 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.IFunctionDescriptor; +import org.apache.asterix.om.functions.IFunctionDescriptorFactory; +import org.apache.asterix.om.types.ATypeTag; +import org.apache.asterix.runtime.evaluators.base.AbstractScalarFunctionDynamicDescriptor; +import org.apache.asterix.runtime.evaluators.functions.utils.RandomHelper; +import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier; +import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluator; +import org.apache.hyracks.algebricks.runtime.base.IScalarEvaluatorFactory; +import org.apache.hyracks.api.context.IHyracksTaskContext; +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 class RandomWithSeedDescriptor extends AbstractScalarFunctionDynamicDescriptor { + private static final long serialVersionUID = 1L; + + public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() { + @Override + public IFunctionDescriptor createFunctionDescriptor() { + return new RandomWithSeedDescriptor(); + } + }; + + @Override + public IScalarEvaluatorFactory createEvaluatorFactory(IScalarEvaluatorFactory[] args) { + return new IScalarEvaluatorFactory() { + private static final long serialVersionUID = 1L; + + @Override + public IScalarEvaluator createScalarEvaluator(IHyracksTaskContext ctx) throws HyracksDataException { + return new IScalarEvaluator() { + private final IScalarEvaluator eval0 = args[0].createScalarEvaluator(ctx); + private final IPointable arg0 = new VoidPointable(); + + private final RandomHelper randomHelper = new RandomHelper(true); + + @Override + public void evaluate(IFrameTupleReference tuple, IPointable resultPointable) + throws HyracksDataException { + eval0.evaluate(tuple, arg0); + + byte[] bytes = arg0.getByteArray(); + int offset = arg0.getStartOffset(); + ATypeTag tt = ATypeTag.VALUE_TYPE_MAPPING[bytes[offset]]; + switch (tt) { + case TINYINT: + case SMALLINT: + case INTEGER: + case BIGINT: + case FLOAT: + case DOUBLE: + randomHelper.setSeed(bytes, offset + 1, arg0.getLength() - 1); + randomHelper.nextDouble(resultPointable); + break; + default: + PointableHelper.setNull(resultPointable); + break; + } + } + }; + } + }; + } + + @Override + public FunctionIdentifier getIdentifier() { + return BuiltinFunctions.RANDOM_WITH_SEED; + } +} diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/utils/RandomHelper.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/utils/RandomHelper.java new file mode 100644 index 0000000..7ed1ce5 --- /dev/null +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/utils/RandomHelper.java @@ -0,0 +1,80 @@ +/* + * 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.utils; + +import java.io.DataOutput; +import java.io.IOException; +import java.security.SecureRandom; + +import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider; +import org.apache.asterix.om.base.AMutableDouble; +import org.apache.asterix.om.types.BuiltinType; +import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer; +import org.apache.hyracks.api.exceptions.HyracksDataException; +import org.apache.hyracks.data.std.api.IPointable; +import org.apache.hyracks.data.std.util.ArrayBackedValueStorage; +import org.apache.hyracks.data.std.util.DataUtils; +import org.apache.hyracks.data.std.util.GrowableArray; + +public final class RandomHelper { + + private final SecureRandom random = new SecureRandom(); + + private final GrowableArray seed; + + private final AMutableDouble aDouble = new AMutableDouble(0); + + @SuppressWarnings("rawtypes") + private ISerializerDeserializer doubleSerde = + SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ADOUBLE); + + private final ArrayBackedValueStorage resultStorage = new ArrayBackedValueStorage(); + private final DataOutput dataOutput = resultStorage.getDataOutput(); + + public RandomHelper(boolean withSeed) { + seed = withSeed ? new GrowableArray(8) : null; + } + + public void setSeed(byte[] bytes, int offset, int length) throws HyracksDataException { + if (seed == null) { + throw new IllegalStateException(); + } + + boolean sameSeed = + seed.getLength() == length && DataUtils.equalsInRange(seed.getByteArray(), 0, bytes, offset, length); + + if (!sameSeed) { + try { + seed.reset(); + seed.append(bytes, offset, length); + random.setSeed(seed.getByteArray()); + } catch (IOException e) { + throw HyracksDataException.create(e); + } + } + } + + public void nextDouble(IPointable resultPointable) throws HyracksDataException { + aDouble.setValue(random.nextDouble()); + resultStorage.reset(); + doubleSerde.serialize(aDouble, dataOutput); + resultPointable.set(resultStorage); + } +} 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 32b7b7f..9a09184 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 @@ -188,6 +188,7 @@ import org.apache.asterix.runtime.evaluators.functions.NumericCaretDescriptor; import org.apache.asterix.runtime.evaluators.functions.NumericCeilingDescriptor; import org.apache.asterix.runtime.evaluators.functions.NumericCosDescriptor; +import org.apache.asterix.runtime.evaluators.functions.NumericDegreesDescriptor; import org.apache.asterix.runtime.evaluators.functions.NumericDivideDescriptor; import org.apache.asterix.runtime.evaluators.functions.NumericExpDescriptor; import org.apache.asterix.runtime.evaluators.functions.NumericFloorDescriptor; @@ -195,6 +196,7 @@ import org.apache.asterix.runtime.evaluators.functions.NumericLogDescriptor; import org.apache.asterix.runtime.evaluators.functions.NumericModuloDescriptor; import org.apache.asterix.runtime.evaluators.functions.NumericMultiplyDescriptor; +import org.apache.asterix.runtime.evaluators.functions.NumericRadiansDescriptor; import org.apache.asterix.runtime.evaluators.functions.NumericRoundDescriptor; import org.apache.asterix.runtime.evaluators.functions.NumericRoundHalfToEven2Descriptor; import org.apache.asterix.runtime.evaluators.functions.NumericRoundHalfToEvenDescriptor; @@ -206,6 +208,8 @@ import org.apache.asterix.runtime.evaluators.functions.NumericTruncDescriptor; import org.apache.asterix.runtime.evaluators.functions.NumericUnaryMinusDescriptor; import org.apache.asterix.runtime.evaluators.functions.OrDescriptor; +import org.apache.asterix.runtime.evaluators.functions.RandomDescriptor; +import org.apache.asterix.runtime.evaluators.functions.RandomWithSeedDescriptor; import org.apache.asterix.runtime.evaluators.functions.SleepDescriptor; import org.apache.asterix.runtime.evaluators.functions.SpatialAreaDescriptor; import org.apache.asterix.runtime.evaluators.functions.SpatialCellDescriptor; @@ -466,6 +470,7 @@ fc.add(CreateUUIDDescriptor.FACTORY); fc.add(UUIDDescriptor.FACTORY); fc.add(CreateQueryUIDDescriptor.FACTORY); + fc.add(RandomDescriptor.FACTORY); fc.add(CurrentDateDescriptor.FACTORY); fc.add(CurrentTimeDescriptor.FACTORY); fc.add(CurrentDateTimeDescriptor.FACTORY); @@ -502,6 +507,8 @@ fc.addGenerated(NumericACosDescriptor.FACTORY); fc.addGenerated(NumericASinDescriptor.FACTORY); fc.addGenerated(NumericATanDescriptor.FACTORY); + fc.addGenerated(NumericDegreesDescriptor.FACTORY); + fc.addGenerated(NumericRadiansDescriptor.FACTORY); fc.addGenerated(NumericCosDescriptor.FACTORY); fc.addGenerated(NumericSinDescriptor.FACTORY); fc.addGenerated(NumericTanDescriptor.FACTORY); @@ -728,6 +735,9 @@ // Record function fc.addGenerated(RecordPairsDescriptor.FACTORY); + // Other functions + fc.addGenerated(RandomWithSeedDescriptor.FACTORY); + ServiceLoader.load(IFunctionRegistrant.class).iterator().forEachRemaining(c -> c.register(fc)); return fc; } -- To view, visit https://asterix-gerrit.ics.uci.edu/2610 To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings Gerrit-MessageType: merged Gerrit-Change-Id: I3beb1f35979ec2e06222beb76e3c284b1259b4eb Gerrit-PatchSet: 6 Gerrit-Project: asterixdb Gerrit-Branch: master Gerrit-Owner: Dmitry Lychagin <dmitry.lycha...@couchbase.com> Gerrit-Reviewer: Anon. E. Moose #1000171 Gerrit-Reviewer: Dmitry Lychagin <dmitry.lycha...@couchbase.com> Gerrit-Reviewer: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Gerrit-Reviewer: Till Westmann <ti...@apache.org>