Dmitry Lychagin has uploaded a new change for review. https://asterix-gerrit.ics.uci.edu/2605
Change subject: [NO ISSUE][FUN] Implement reverse() function ...................................................................... [NO ISSUE][FUN] Implement reverse() function - user model changes: yes - storage format changes: no - interface changes: no Details: - Implement string reverse function: reverse() Change-Id: I4bc30217f160a5365fd4aa34bc09cce85e06230a --- A asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/reverse/reverse.1.query.sqlpp A asterixdb/asterix-app/src/test/resources/runtimets/results/string/reverse/reverse.1.adm M asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml M asterixdb/asterix-doc/src/main/markdown/builtins/2_string_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/StringReverseDescriptor.java M asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/functions/FunctionCollection.java M hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/UTF8StringPointable.java M hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/string/UTF8StringUtil.java 9 files changed, 158 insertions(+), 0 deletions(-) git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb refs/changes/05/2605/1 diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/reverse/reverse.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/reverse/reverse.1.query.sqlpp new file mode 100644 index 0000000..e127372 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/string/reverse/reverse.1.query.sqlpp @@ -0,0 +1,26 @@ +/* + * 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": [ reverse(missing) is missing, reverse(null) is null ], + "t2": reverse(""), + "t3": reverse("abcd"), + "t4": string_to_codepoint(reverse("a\u00D7\u2103\u00F7\u2109b")), + "t5": ( from ["ab", "abc", "abcd"] t select value reverse(t) order by t ) + } \ No newline at end of file diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/string/reverse/reverse.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/reverse/reverse.1.adm new file mode 100644 index 0000000..a2b8b2c --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/string/reverse/reverse.1.adm @@ -0,0 +1 @@ +{ "t1": [ true, true ], "t2": "", "t3": "dcba", "t4": [ 98, 8457, 247, 8451, 215, 97 ], "t5": [ "ba", "cba", "dcba" ] } \ 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 05382bc..7ba86c6 100644 --- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml +++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml @@ -6233,6 +6233,11 @@ </compilation-unit> </test-case> <test-case FilePath="string"> + <compilation-unit name="reverse"> + <output-dir compare="Text">reverse</output-dir> + </compilation-unit> + </test-case> + <test-case FilePath="string"> <compilation-unit name="rtrim"> <output-dir compare="Text">rtrim</output-dir> </compilation-unit> diff --git a/asterixdb/asterix-doc/src/main/markdown/builtins/2_string_common.md b/asterixdb/asterix-doc/src/main/markdown/builtins/2_string_common.md index 0e548a7..a733a84 100644 --- a/asterixdb/asterix-doc/src/main/markdown/builtins/2_string_common.md +++ b/asterixdb/asterix-doc/src/main/markdown/builtins/2_string_common.md @@ -414,6 +414,30 @@ "v2": "product-a and x-phone" } +### reverse ### + * Syntax: + + reverse(string) + + * Returns a string formed by reversing characters in the input `string`. + * Arguments: + * `string` : a `string` to be reversed + * Return Value: + * a string containing characters from the the input `string` in the reverse order, + * `missing` if any argument is a `missing` value, + * `null` if any argument is a `null` value but no argument is a `missing` value, + * a type error will be raised if: + * the first argument is any other non-string value + + * Example: + + reverse("hello"); + + + * The expected result is: + + "olleh" + ### rtrim ### * 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 6eeb6ab..dd199e7 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 @@ -324,6 +324,8 @@ new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "replace", 3); public static final FunctionIdentifier STRING_REPLACE_WITH_LIMIT = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "replace", 4); + public static final FunctionIdentifier STRING_REVERSE = + new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "reverse", 1); public static final FunctionIdentifier STRING_LENGTH = new FunctionIdentifier(FunctionConstants.ASTERIX_NS, "string-length", 1); public static final FunctionIdentifier STRING_LIKE = @@ -1186,6 +1188,7 @@ addFunction(STRING_REGEXP_REPLACE_WITH_FLAG, StringStringTypeComputer.INSTANCE, true); addFunction(STRING_REPLACE, StringStringTypeComputer.INSTANCE, true); addFunction(STRING_REPLACE_WITH_LIMIT, StringIntToStringTypeComputer.INSTANCE_TRIPLE_STRING, true); + addFunction(STRING_REVERSE, StringStringTypeComputer.INSTANCE, true); addFunction(SUBSTRING_BEFORE, StringStringTypeComputer.INSTANCE, true); addFunction(SUBSTRING_AFTER, StringStringTypeComputer.INSTANCE, true); addPrivateFunction(STRING_EQUAL, StringBooleanTypeComputer.INSTANCE, true); diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringReverseDescriptor.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringReverseDescriptor.java new file mode 100644 index 0000000..0095291 --- /dev/null +++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/StringReverseDescriptor.java @@ -0,0 +1,67 @@ +/* + * 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 java.io.IOException; + +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; +import org.apache.hyracks.data.std.primitive.UTF8StringPointable; + +public class StringReverseDescriptor extends AbstractScalarFunctionDynamicDescriptor { + private static final long serialVersionUID = 1L; + public static final IFunctionDescriptorFactory FACTORY = new IFunctionDescriptorFactory() { + @Override + public IFunctionDescriptor createFunctionDescriptor() { + return new StringReverseDescriptor(); + } + }; + + @Override + public IScalarEvaluatorFactory createEvaluatorFactory(final IScalarEvaluatorFactory[] args) { + return new IScalarEvaluatorFactory() { + private static final long serialVersionUID = 1L; + + @Override + public IScalarEvaluator createScalarEvaluator(final IHyracksTaskContext ctx) throws HyracksDataException { + return new AbstractUnaryStringStringEval(ctx, args[0], getIdentifier()) { + @Override + void process(UTF8StringPointable inputString, IPointable resultPointable) throws IOException { + UTF8StringPointable.reverse(inputString, resultBuilder, resultArray); + resultPointable.set(resultArray.getByteArray(), 0, resultArray.getLength()); + } + }; + } + }; + } + + @Override + public FunctionIdentifier getIdentifier() { + return BuiltinFunctions.STRING_REVERSE; + } +} 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 b05dbed..245eb25 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 @@ -230,6 +230,7 @@ import org.apache.asterix.runtime.evaluators.functions.StringRepeatDescriptor; import org.apache.asterix.runtime.evaluators.functions.StringReplaceDescriptor; import org.apache.asterix.runtime.evaluators.functions.StringReplaceWithLimitDescriptor; +import org.apache.asterix.runtime.evaluators.functions.StringReverseDescriptor; import org.apache.asterix.runtime.evaluators.functions.StringSplitDescriptor; import org.apache.asterix.runtime.evaluators.functions.StringStartsWithDescriptor; import org.apache.asterix.runtime.evaluators.functions.StringToCodePointDescriptor; @@ -561,6 +562,7 @@ fc.addGenerated(StringRepeatDescriptor.FACTORY); fc.addGenerated(StringReplaceDescriptor.FACTORY); fc.addGenerated(StringReplaceWithLimitDescriptor.FACTORY); + fc.addGenerated(StringReverseDescriptor.FACTORY); fc.addGenerated(StringSplitDescriptor.FACTORY); // Constructors diff --git a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/UTF8StringPointable.java b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/UTF8StringPointable.java index 8fdcd83..376307d 100644 --- a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/UTF8StringPointable.java +++ b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/UTF8StringPointable.java @@ -587,6 +587,31 @@ builder.finish(); } + /** + * Generates a reversed string from an input source string + * + * @param srcPtr + * , the input source string. + * @param builder + * , a builder for the resulting string. + * @param out + * , the storage for a result string. + * @throws IOException + */ + public static void reverse(UTF8StringPointable srcPtr, UTF8StringBuilder builder, GrowableArray out) + throws IOException { + builder.reset(out, srcPtr.getUTF8Length()); + int srcStart = srcPtr.getCharStartOffset(); + int srcEnd = srcPtr.getStartOffset() + srcPtr.getLength() - 1; + for (int cursorIndex = srcEnd; cursorIndex >= srcStart; cursorIndex--) { + if (UTF8StringUtil.isCharStart(srcPtr.bytes, cursorIndex)) { + int charSize = UTF8StringUtil.charSize(srcPtr.bytes, cursorIndex); + builder.appendUtf8StringPointable(srcPtr, cursorIndex, charSize); + } + } + builder.finish(); + } + public boolean findAndReplace(UTF8StringPointable searchPtr, UTF8StringPointable replacePtr, int replaceLimit, UTF8StringBuilder builder, GrowableArray out) throws IOException { return findAndReplace(this, searchPtr, replacePtr, replaceLimit, builder, out); diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/string/UTF8StringUtil.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/string/UTF8StringUtil.java index 78fdff1..cdb82bb 100644 --- a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/string/UTF8StringUtil.java +++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/string/UTF8StringUtil.java @@ -84,6 +84,11 @@ throw new IllegalStateException(); } + public static boolean isCharStart(byte[] b, int s) { + int c = b[s] & 0xff; + return (c >> 6) != 2; + } + public static int getModifiedUTF8Len(char c) { if (c >= 0x0001 && c <= 0x007F) { return 1; -- To view, visit https://asterix-gerrit.ics.uci.edu/2605 To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I4bc30217f160a5365fd4aa34bc09cce85e06230a Gerrit-PatchSet: 1 Gerrit-Project: asterixdb Gerrit-Branch: master Gerrit-Owner: Dmitry Lychagin <dmitry.lycha...@couchbase.com>