diff --git a/integ-test/src/test/java/org/opensearch/sql/sql/TextFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/sql/TextFunctionIT.java index 314132fed0..e5472eec24 100644 --- a/integ-test/src/test/java/org/opensearch/sql/sql/TextFunctionIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/sql/TextFunctionIT.java @@ -5,6 +5,7 @@ package org.opensearch.sql.sql; +import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_STRINGS; import static org.opensearch.sql.legacy.plugin.RestSqlAction.QUERY_API_ENDPOINT; import static org.opensearch.sql.util.MatcherUtils.rows; import static org.opensearch.sql.util.MatcherUtils.schema; @@ -25,7 +26,7 @@ public class TextFunctionIT extends SQLIntegTestCase { @Override public void init() throws Exception { - super.init(); + loadIndex(Index.BANK_WITH_STRING_VALUES); } void verifyQuery(String query, String type, String output) throws IOException { @@ -52,6 +53,15 @@ public void testRegexp() throws IOException { verifyQuery("'a' regexp '.*'", "integer", 1); } + @Test + public void testRegexpAgainstIndex() throws IOException { + JSONObject result = + executeQuery( + String.format("select * from %s where name regexp 'hel.*'", TEST_INDEX_STRINGS)); + verifySchema(result, schema("name", "text")); + verifyDataRows(result, rows("hello"), rows("helloworld")); + } + @Test public void testReverse() throws IOException { verifyQuery("reverse('hello')", "keyword", "olleh"); diff --git a/opensearch/src/main/java/org/opensearch/sql/opensearch/storage/script/filter/ExpressionFilterScript.java b/opensearch/src/main/java/org/opensearch/sql/opensearch/storage/script/filter/ExpressionFilterScript.java index 557cbbe4c9..43ec16407f 100644 --- a/opensearch/src/main/java/org/opensearch/sql/opensearch/storage/script/filter/ExpressionFilterScript.java +++ b/opensearch/src/main/java/org/opensearch/sql/opensearch/storage/script/filter/ExpressionFilterScript.java @@ -14,7 +14,9 @@ import org.opensearch.sql.data.model.ExprValue; import org.opensearch.sql.data.type.ExprCoreType; import org.opensearch.sql.expression.Expression; +import org.opensearch.sql.expression.FunctionExpression; import org.opensearch.sql.expression.env.Environment; +import org.opensearch.sql.expression.function.BuiltinFunctionName; import org.opensearch.sql.opensearch.storage.script.core.ExpressionScript; /** @@ -48,6 +50,16 @@ private ExprValue evaluateExpression( return ExprBooleanValue.of(false); } + // refer to https://github.com/opensearch-project/sql/issues/2796 + if (isRegexpExpression(expression)) { + assert result.type() == ExprCoreType.INTEGER; + if (result.integerValue() == 0) { + result = ExprBooleanValue.of(false); + } else if (result.integerValue() == 1) { + result = ExprBooleanValue.of(true); + } + } + if (result.type() != ExprCoreType.BOOLEAN) { throw new IllegalStateException( String.format( @@ -57,4 +69,11 @@ private ExprValue evaluateExpression( } return result; } + + private boolean isRegexpExpression(Expression expression) { + return expression instanceof FunctionExpression + && ((FunctionExpression) expression) + .getFunctionName() + .equals(BuiltinFunctionName.REGEXP.getName()); + } } diff --git a/opensearch/src/test/java/org/opensearch/sql/opensearch/storage/script/filter/ExpressionFilterScriptTest.java b/opensearch/src/test/java/org/opensearch/sql/opensearch/storage/script/filter/ExpressionFilterScriptTest.java index df754887cf..43df7e8895 100644 --- a/opensearch/src/test/java/org/opensearch/sql/opensearch/storage/script/filter/ExpressionFilterScriptTest.java +++ b/opensearch/src/test/java/org/opensearch/sql/opensearch/storage/script/filter/ExpressionFilterScriptTest.java @@ -22,6 +22,7 @@ import static org.opensearch.sql.data.type.ExprCoreType.TIMESTAMP; import static org.opensearch.sql.expression.DSL.literal; import static org.opensearch.sql.expression.DSL.ref; +import static org.opensearch.sql.expression.DSL.regexp; import com.google.common.collect.ImmutableMap; import java.time.ZonedDateTime; @@ -164,6 +165,19 @@ void cannot_execute_non_predicate_expression() { .filterBy(literal(10)); } + @Test + void can_execute_regexp_expression() { + assertThat() + .docValues("text", "test search") + .filterBy(regexp(ref("text", STRING), literal("test.*"))) + .shouldMatch(); + + assertThat() + .docValues("text", "test search") + .filterBy(regexp(ref("text", STRING), literal("search.*"))) + .shouldNotMatch(); + } + private ExprScriptAssertion assertThat() { return new ExprScriptAssertion(lookup, leafLookup, context); }