Skip to content

Commit 06fa7d7

Browse files
authored
Fix bug of missed analyzed node when pushdown filter for Search call (#4388)
Signed-off-by: Lantao Jin <[email protected]>
1 parent 877e6d5 commit 06fa7d7

File tree

3 files changed

+40
-13
lines changed

3 files changed

+40
-13
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,19 @@ public void testFilterFunctionScriptPushDownExplain() throws Exception {
238238
super.testFilterFunctionScriptPushDownExplain();
239239
}
240240

241+
@Test
242+
public void testFilterWithSearchCall() throws IOException {
243+
enabledOnlyWhenPushdownIsEnabled();
244+
String expected = loadExpectedPlan("explain_filter_with_search.yaml");
245+
assertYamlEqualsJsonIgnoreId(
246+
expected,
247+
explainQueryToString(
248+
String.format(
249+
"source=%s | where birthdate >= '2023-01-01 00:00:00' and birthdate < '2023-01-03"
250+
+ " 00:00:00' | stats count() by span(birthdate, 1d)",
251+
TEST_INDEX_BANK)));
252+
}
253+
241254
@Test
242255
public void testExplainWithReverse() throws IOException {
243256
String result =
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
calcite:
2+
logical: |
3+
LogicalSystemLimit(fetch=[10000], type=[QUERY_SIZE_LIMIT])
4+
LogicalProject(count()=[$1], span(birthdate,1d)=[$0])
5+
LogicalAggregate(group=[{0}], count()=[COUNT()])
6+
LogicalProject(span(birthdate,1d)=[SPAN($3, 1, 'd')])
7+
LogicalFilter(condition=[IS NOT NULL($3)])
8+
LogicalFilter(condition=[AND(>=($3, TIMESTAMP('2023-01-01 00:00:00':VARCHAR)), <($3, TIMESTAMP('2023-01-03 00:00:00':VARCHAR)))])
9+
CalciteLogicalIndexScan(table=[[OpenSearch, opensearch-sql_test_index_bank]])
10+
physical: |
11+
CalciteEnumerableIndexScan(table=[[OpenSearch, opensearch-sql_test_index_bank]], PushDownContext=[[PROJECT->[birthdate], FILTER->SEARCH($0, Sarg[['2023-01-01 00:00:00':VARCHAR..'2023-01-03 00:00:00':VARCHAR); NULL AS FALSE]:VARCHAR), AGGREGATION->rel#:LogicalAggregate.NONE.[](input=RelSubset#,group={0},count()=COUNT()), PROJECT->[count(), span(birthdate,1d)], LIMIT->10000], OpenSearchRequestBuilder(sourceBuilder={"from":0,"size":0,"timeout":"1m","query":{"bool":{"must":[{"range":{"birthdate":{"from":"2023-01-01T00:00:00.000Z","to":"2023-01-03T00:00:00.000Z","include_lower":true,"include_upper":false,"boost":1.0}}},{"exists":{"field":"birthdate","boost":1.0}}],"adjust_pure_negative":true,"boost":1.0}},"_source":{"includes":["birthdate"],"excludes":[]},"sort":[],"aggregations":{"composite_buckets":{"composite":{"size":1000,"sources":[{"span(birthdate,1d)":{"date_histogram":{"field":"birthdate","missing_bucket":false,"order":"asc","fixed_interval":"1d"}}}]}}}}, requestedTotalSize=2147483647, pageSize=null, startFrom=0)])

opensearch/src/main/java/org/opensearch/sql/opensearch/request/PredicateAnalyzer.java

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -656,17 +656,20 @@ private QueryExpression binary(RexCall call) {
656656
case SEARCH:
657657
QueryExpression expression = constructQueryExpressionForSearch(call, pair);
658658
RexUnknownAs nullAs = getNullAsForSearch(call);
659-
return switch (nullAs) {
660-
// e.g. where isNotNull(a) and (a = 1 or a = 2)
661-
// TODO: For this case, seems return `expression` should be equivalent
662-
case FALSE -> CompoundQueryExpression.and(
663-
false, expression, QueryExpression.create(pair.getKey()).exists());
664-
// e.g. where isNull(a) or a = 1 or a = 2
665-
case TRUE -> CompoundQueryExpression.or(
666-
expression, QueryExpression.create(pair.getKey()).notExists());
667-
// e.g. where a = 1 or a = 2
668-
case UNKNOWN -> expression;
669-
};
659+
QueryExpression finalExpression =
660+
switch (nullAs) {
661+
// e.g. where isNotNull(a) and (a = 1 or a = 2)
662+
// TODO: For this case, seems return `expression` should be equivalent
663+
case FALSE -> CompoundQueryExpression.and(
664+
false, expression, QueryExpression.create(pair.getKey()).exists());
665+
// e.g. where isNull(a) or a = 1 or a = 2
666+
case TRUE -> CompoundQueryExpression.or(
667+
expression, QueryExpression.create(pair.getKey()).notExists());
668+
// e.g. where a = 1 or a = 2
669+
case UNKNOWN -> expression;
670+
};
671+
finalExpression.updateAnalyzedNodes(call);
672+
return finalExpression;
670673
default:
671674
break;
672675
}
@@ -1220,7 +1223,7 @@ public List<RexNode> getUnAnalyzableNodes() {
12201223

12211224
@Override
12221225
public List<RexNode> getAnalyzedNodes() {
1223-
return List.of(analyzedRexNode);
1226+
return analyzedRexNode == null ? List.of() : List.of(analyzedRexNode);
12241227
}
12251228

12261229
@Override
@@ -1499,7 +1502,7 @@ public Script getScript() {
14991502

15001503
@Override
15011504
public List<RexNode> getAnalyzedNodes() {
1502-
return List.of(analyzedNode);
1505+
return analyzedNode == null ? List.of() : List.of(analyzedNode);
15031506
}
15041507

15051508
@Override

0 commit comments

Comments
 (0)