-
Notifications
You must be signed in to change notification settings - Fork 0
Add position() to V2 engine #177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
441b997
8025fdb
0950e7d
8609e8b
e254462
07637e9
c8cd1bb
9a6b7b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,6 +33,7 @@ | |
| import org.opensearch.sql.ast.expression.Not; | ||
| import org.opensearch.sql.ast.expression.Or; | ||
| import org.opensearch.sql.ast.expression.ParseMethod; | ||
| import org.opensearch.sql.ast.expression.PositionFunction; | ||
| import org.opensearch.sql.ast.expression.QualifiedName; | ||
| import org.opensearch.sql.ast.expression.Span; | ||
| import org.opensearch.sql.ast.expression.SpanUnit; | ||
|
|
@@ -288,6 +289,10 @@ public UnresolvedExpression highlight(UnresolvedExpression fieldName, | |
| return new HighlightFunction(fieldName, arguments); | ||
| } | ||
|
|
||
| public UnresolvedExpression position(UnresolvedExpression left, UnresolvedExpression right) { | ||
| return new PositionFunction(left, right); | ||
|
||
| } | ||
|
|
||
| public UnresolvedExpression window(UnresolvedExpression function, | ||
| List<UnresolvedExpression> partitionByList, | ||
| List<Pair<SortOption, UnresolvedExpression>> sortList) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.ast.expression; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.List; | ||
| import lombok.AllArgsConstructor; | ||
| import lombok.EqualsAndHashCode; | ||
| import lombok.Getter; | ||
| import lombok.ToString; | ||
| import org.opensearch.sql.ast.AbstractNodeVisitor; | ||
|
|
||
|
|
||
| /** | ||
| * Expression node of Highlight function. | ||
acarbonetto marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| */ | ||
| @AllArgsConstructor | ||
| @EqualsAndHashCode(callSuper = false) | ||
| @Getter | ||
| @ToString | ||
| public class PositionFunction extends UnresolvedExpression { | ||
| @Getter | ||
| private UnresolvedExpression left; | ||
|
||
| @Getter | ||
| private UnresolvedExpression right; | ||
|
|
||
| @Override | ||
| public List<UnresolvedExpression> getChild() { | ||
| return Arrays.asList(left, right); | ||
| } | ||
|
|
||
| @Override | ||
| public <R, C> R accept(AbstractNodeVisitor<R, C> nodeVisitor, C context) { | ||
| return nodeVisitor.visitPositionFunction(this, context); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -55,6 +55,7 @@ public void register(BuiltinFunctionRepository repository) { | |
| repository.register(ascii()); | ||
| repository.register(locate()); | ||
| repository.register(replace()); | ||
| repository.register(position()); | ||
acarbonetto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| /** | ||
|
|
@@ -241,6 +242,18 @@ private DefaultFunctionResolver locate() { | |
| TextFunction::exprLocate), INTEGER, STRING, STRING, INTEGER)); | ||
| } | ||
|
|
||
| /** | ||
| * Returns the position of the first occurrence of a substring in a string. | ||
|
||
| * Returns 0 if substring is not in string. | ||
| * Returns NULL if any argument is NULL. | ||
| * Supports following signature: | ||
| * (STRING IN STRING) -> INTEGER | ||
| */ | ||
| private DefaultFunctionResolver position() { | ||
| return define(BuiltinFunctionName.POSITION.getName(), | ||
| impl(nullMissingHandling(TextFunction::exprPosition), INTEGER, STRING, STRING)); | ||
| } | ||
|
|
||
| /** | ||
| * REPLACE(str, from_str, to_str) returns the string str with all occurrences of | ||
| * the string from_str replaced by the string to_str. | ||
|
|
@@ -313,6 +326,10 @@ private static ExprValue exprLocate(ExprValue subStr, ExprValue str, ExprValue p | |
| str.stringValue().indexOf(subStr.stringValue(), pos.integerValue() - 1) + 1); | ||
| } | ||
|
|
||
| private static ExprValue exprPosition(ExprValue subStr, ExprValue str) { | ||
| return exprLocate(subStr, str); | ||
| } | ||
|
|
||
| private static ExprValue exprReplace(ExprValue str, ExprValue from, ExprValue to) { | ||
| return new ExprStringValue(str.stringValue().replaceAll(from.stringValue(), to.stringValue())); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -377,6 +377,20 @@ void locate() { | |
| DSL.locate(missingRef, DSL.literal("hello"), DSL.literal(1)))); | ||
| } | ||
|
|
||
| @Test | ||
| void position() { | ||
| FunctionExpression expression = DSL.position( | ||
| DSL.literal("world"), | ||
| DSL.literal("helloworld")); | ||
|
||
| assertEquals(INTEGER, expression.type()); | ||
| assertEquals(6, eval(expression).integerValue()); | ||
acarbonetto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| when(nullRef.type()).thenReturn(STRING); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we split these out into |
||
| assertEquals(nullValue(), eval(DSL.position(nullRef, DSL.literal("hello")))); | ||
| when(missingRef.type()).thenReturn(STRING); | ||
| assertEquals(missingValue(), eval(DSL.position(missingRef, DSL.literal("hello")))); | ||
| } | ||
|
|
||
| @Test | ||
| void replace() { | ||
| FunctionExpression expression = DSL.replace( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.sql; | ||
|
|
||
| import org.json.JSONObject; | ||
| import org.junit.Test; | ||
| import org.opensearch.sql.legacy.SQLIntegTestCase; | ||
| import org.opensearch.sql.legacy.TestsConstants; | ||
|
|
||
| import static org.opensearch.sql.util.MatcherUtils.rows; | ||
| import static org.opensearch.sql.util.MatcherUtils.schema; | ||
| import static org.opensearch.sql.util.MatcherUtils.verifyDataRows; | ||
| import static org.opensearch.sql.util.MatcherUtils.verifySchema; | ||
|
|
||
| public class PositionFunctionIT extends SQLIntegTestCase { | ||
|
|
||
| @Override | ||
| protected void init() throws Exception { | ||
| loadIndex(Index.PEOPLE2); | ||
| loadIndex(Index.CALCS); | ||
| } | ||
|
|
||
| @Test | ||
| public void position_function_test() { | ||
| String query = "SELECT firstname, position('a' IN firstname) FROM %s"; | ||
| JSONObject response = executeJdbcRequest(String.format(query, TestsConstants.TEST_INDEX_PEOPLE2)); | ||
|
|
||
| verifySchema(response, schema("firstname", null, "keyword"), | ||
| schema("position('a' IN firstname)", null, "integer")); | ||
| assertEquals(12, response.getInt("total")); | ||
|
|
||
| verifyDataRows(response, | ||
| rows("Daenerys", 2), rows("Hattie", 2), | ||
| rows("Nanette", 2), rows("Dale", 2), | ||
| rows("Elinor", 0), rows("Virginia", 8), | ||
| rows("Dillard", 5), rows("Mcgee", 0), | ||
| rows("Aurelia", 7), rows("Fulton", 0), | ||
| rows("Burton", 0), rows("Josie", 0)); | ||
| } | ||
|
|
||
| @Test | ||
| public void position_function_with_nulls_test() { | ||
| String query = "SELECT str2, position('ee' IN str2) FROM %s"; | ||
| JSONObject response = executeJdbcRequest(String.format(query, TestsConstants.TEST_INDEX_CALCS)); | ||
|
|
||
| verifySchema(response, schema("str2", null, "keyword"), | ||
| schema("position('ee' IN str2)", null, "integer")); | ||
| assertEquals(17, response.getInt("total")); | ||
|
|
||
| verifyDataRows(response, | ||
| rows("one", 0), rows("two", 0), | ||
| rows("three", 4), rows(null, null), | ||
| rows("five", 0), rows("six", 0), | ||
| rows(null, null), rows("eight", 0), | ||
| rows("nine", 0), rows("ten", 0), | ||
| rows("eleven", 0), rows("twelve", 0), | ||
| rows(null, null), rows("fourteen", 6), | ||
| rows("fifteen", 5), rows("sixteen", 5), | ||
| rows(null, null)); | ||
| } | ||
|
|
||
| @Test | ||
| public void position_function_with_string_literals_test() { | ||
| String query = "SELECT position('world' IN 'hello world')"; | ||
| JSONObject response = executeJdbcRequest(query); | ||
|
|
||
| verifySchema(response, schema("position('world' IN 'hello world')", null, "integer")); | ||
| assertEquals(1, response.getInt("total")); | ||
|
|
||
| verifyDataRows(response, rows(7)); | ||
| } | ||
|
|
||
| @Test | ||
| public void position_function_with_only_fields_as_args_test() { | ||
| String query = "SELECT position(str3 IN str2) FROM %s WHERE str2 IN ('one', 'two', 'three')"; | ||
| JSONObject response = executeJdbcRequest(String.format(query, TestsConstants.TEST_INDEX_CALCS)); | ||
|
|
||
| verifySchema(response, schema("position(str3 IN str2)", null, "integer")); | ||
| assertEquals(3, response.getInt("total")); | ||
|
|
||
| verifyDataRows(response, rows(3), rows(0), rows(4)); | ||
| } | ||
|
|
||
| @Test | ||
| public void position_function_with_function_as_arg_test() { | ||
| String query = "SELECT position(upper(str3) IN str1) FROM %s WHERE str1 LIKE 'BINDING SUPPLIES'"; | ||
| JSONObject response = executeJdbcRequest(String.format(query, TestsConstants.TEST_INDEX_CALCS)); | ||
|
|
||
| verifySchema(response, schema("position(upper(str3) IN str1)", null, "integer")); | ||
| assertEquals(1, response.getInt("total")); | ||
|
|
||
| verifyDataRows(response, rows(15)); | ||
| } | ||
GumpacG marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| @Test | ||
| public void position_function_in_where_clause_test() { | ||
| String query = "SELECT str2 FROM %s WHERE position(str3 IN str2)=1"; | ||
| JSONObject response = executeJdbcRequest(String.format(query, TestsConstants.TEST_INDEX_CALCS)); | ||
|
|
||
| verifySchema(response, schema("str2", null, "keyword")); | ||
| assertEquals(2, response.getInt("total")); | ||
|
|
||
| verifyDataRows(response, rows("eight"), rows("eleven")); | ||
| } | ||
acarbonetto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.