Skip to content

Commit 24bcb66

Browse files
committed
pushdown match when only one equal in search command
Signed-off-by: xinyual <xinyual@amazon.com>
1 parent 2cb2048 commit 24bcb66

7 files changed

Lines changed: 48 additions & 17 deletions

File tree

core/src/main/java/org/opensearch/sql/ast/expression/SearchComparison.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55

66
package org.opensearch.sql.ast.expression;
77

8+
import static org.opensearch.sql.ast.expression.SearchComparison.Operator.EQUALS;
9+
810
import java.util.Arrays;
911
import java.util.List;
1012
import lombok.EqualsAndHashCode;
1113
import lombok.Getter;
1214
import lombok.RequiredArgsConstructor;
1315
import lombok.ToString;
16+
import org.opensearch.sql.ast.dsl.AstDSL;
1417
import org.opensearch.sql.utils.QueryStringUtils;
1518

1619
/** Search expression for field comparisons. */
@@ -63,6 +66,23 @@ public String toQueryString() {
6366
}
6467
}
6568

69+
@Override
70+
public Function toDSLFunction() {
71+
String fieldName = QueryStringUtils.escapeFieldName(field.getField().toString());
72+
String valueStr = value.toQueryString();
73+
switch (operator) {
74+
case EQUALS:
75+
return AstDSL.function(
76+
"match",
77+
AstDSL.unresolvedArg("field_name", AstDSL.qualifiedName(fieldName)),
78+
AstDSL.unresolvedArg("value", AstDSL.stringLiteral(valueStr)));
79+
default:
80+
return AstDSL.function(
81+
"query_string",
82+
AstDSL.unresolvedArg("query", AstDSL.stringLiteral(this.toQueryString())));
83+
}
84+
}
85+
6686
@Override
6787
public String toAnonymizedString() {
6888
return "identifier " + operator.symbol + " ***";

core/src/main/java/org/opensearch/sql/ast/expression/SearchExpression.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package org.opensearch.sql.ast.expression;
77

88
import org.opensearch.sql.ast.AbstractNodeVisitor;
9+
import org.opensearch.sql.ast.dsl.AstDSL;
910

1011
/** Base class for search expressions that get converted to query_string syntax. */
1112
public abstract class SearchExpression extends UnresolvedExpression {
@@ -17,6 +18,14 @@ public abstract class SearchExpression extends UnresolvedExpression {
1718
*/
1819
public abstract String toQueryString();
1920

21+
public Function toDSLFunction() {
22+
Function queryStringFunc =
23+
AstDSL.function(
24+
"query_string",
25+
AstDSL.unresolvedArg("query", AstDSL.stringLiteral(this.toQueryString())));
26+
return queryStringFunc;
27+
}
28+
2029
/**
2130
* Convert the search expression to anonymized string
2231
*

core/src/main/java/org/opensearch/sql/calcite/CalciteRelNodeVisitor.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,7 @@ public RelNode visitSearch(Search node, CalcitePlanContext context) {
210210
// Visit the Relation child to get the scan
211211
node.getChild().get(0).accept(this, context);
212212
// Create query_string function
213-
Function queryStringFunc =
214-
AstDSL.function(
215-
"query_string",
216-
AstDSL.unresolvedArg("query", AstDSL.stringLiteral(node.getQueryString())));
213+
Function queryStringFunc = node.getOriginalExpression().toDSLFunction();
217214
RexNode queryStringRex = rexVisitor.analyze(queryStringFunc, context);
218215

219216
context.relBuilder.filter(queryStringRex);

integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteExplainIT.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,15 @@ public void supportSearchSargPushDown_timeRange() throws IOException {
7878
assertYamlEqualsIgnoreId(expected, result);
7979
}
8080

81+
@Test
82+
public void supportSearchMatchPushDown() throws IOException {
83+
String query =
84+
"source=opensearch-sql_test_index_bank birthdate = '2016-12-08 00:00:00.000000000'";
85+
var result = explainQueryToString(query);
86+
String expected = loadExpectedPlan("explain_search_with_match_pushdown.json");
87+
assertJsonEqualsIgnoreId(expected, result);
88+
}
89+
8190
// Only for Calcite
8291
@Ignore("https://github.com/opensearch-project/OpenSearch/issues/3725")
8392
public void testJoinWithCriteriaAndMaxOption() throws IOException {

integ-test/src/test/java/org/opensearch/sql/calcite/standalone/CalcitePPLDateTimeBuiltinFunctionIT.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,6 @@ public void init() throws IOException {
4949
initRelativeDocs();
5050
}
5151

52-
@Test
53-
public void test() {
54-
JSONObject actual =
55-
executeQuery(
56-
String.format(
57-
"source=%s age=2",
58-
TEST_INDEX_BANK));
59-
}
60-
6152
private static String getFormattedLocalDate() {
6253
return LocalDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
6354
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"calcite":{
3+
"logical":"LogicalSystemLimit(fetch=[10000], type=[QUERY_SIZE_LIMIT])\n LogicalProject(account_number=[$0], firstname=[$1], address=[$2], birthdate=[$3], gender=[$4], city=[$5], lastname=[$6], balance=[$7], employer=[$8], state=[$9], age=[$10], email=[$11], male=[$12])\n LogicalFilter(condition=[match(MAP('field_name', $3), MAP('value', '\"2016\\-12\\-08 00\\:00\\:00.000000000\"':VARCHAR))])\n CalciteLogicalIndexScan(table=[[OpenSearch, opensearch-sql_test_index_bank]])\n",
4+
"physical":"CalciteEnumerableIndexScan(table=[[OpenSearch, opensearch-sql_test_index_bank]], PushDownContext=[[PROJECT->[account_number, firstname, address, birthdate, gender, city, lastname, balance, employer, state, age, email, male], FILTER->match(MAP('field_name', $3), MAP('value', '\"2016\\-12\\-08 00\\:00\\:00.000000000\"':VARCHAR)), LIMIT->10000], OpenSearchRequestBuilder(sourceBuilder={\"from\":0,\"size\":10000,\"timeout\":\"1m\",\"query\":{\"match\":{\"birthdate\":{\"query\":\"\\\"2016\\\\-12\\\\-08 00\\\\:00\\\\:00.000000000\\\"\",\"operator\":\"OR\",\"prefix_length\":0,\"max_expansions\":50,\"fuzzy_transpositions\":true,\"lenient\":false,\"zero_terms_query\":\"NONE\",\"auto_generate_synonyms_phrase_query\":true,\"boost\":1.0}}},\"_source\":{\"includes\":[\"account_number\",\"firstname\",\"address\",\"birthdate\",\"gender\",\"city\",\"lastname\",\"balance\",\"employer\",\"state\",\"age\",\"email\",\"male\"],\"excludes\":[]}}, requestedTotalSize=10000, pageSize=null, startFrom=0)])\n"
5+
}
6+
}

ppl/src/main/java/org/opensearch/sql/ppl/utils/PPLQueryDataAnonymizer.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
import org.opensearch.sql.ast.expression.Not;
4242
import org.opensearch.sql.ast.expression.Or;
4343
import org.opensearch.sql.ast.expression.ParseMethod;
44-
import org.opensearch.sql.ast.expression.SearchExpression;
4544
import org.opensearch.sql.ast.expression.Span;
4645
import org.opensearch.sql.ast.expression.UnresolvedExpression;
4746
import org.opensearch.sql.ast.expression.When;
@@ -251,10 +250,10 @@ public String visitTableFunction(TableFunction node, String context) {
251250
@Override
252251
public String visitSearch(Search node, String context) {
253252
String source = node.getChild().get(0).accept(this, context);
254-
//SearchExpression expression = node.getOriginalExpression();
253+
// SearchExpression expression = node.getOriginalExpression();
255254

256-
//String queryString = node.getQueryString();
257-
//String anonymized = queryString.replaceAll(":\\S+", ":" + MASK_LITERAL);
255+
// String queryString = node.getQueryString();
256+
// String anonymized = queryString.replaceAll(":\\S+", ":" + MASK_LITERAL);
258257
return StringUtils.format("%s %s", source, node.getOriginalExpression().toAnonymizedString());
259258
}
260259

0 commit comments

Comments
 (0)