Skip to content

Commit f01a6cb

Browse files
committed
feat(calcite): Register missing relevance functions in Calcite function table
Add SQL V2 relevance function aliases (match_query, matchquery, matchphrase, matchphrasequery, multimatch, multimatchquery) and new functions (query, wildcard_query, wildcardquery) to PPLFuncImpTable so CalciteRelNodeVisitor can resolve them when processing RelNodes generated by SQL V2 AstBuilder. Note: score/scorequery/score_query are not included as they use a special ScoreFunction AST node requiring separate visitor handling. PredicateAnalyzer pushdown handlers for these functions are not yet implemented (tracked separately). Signed-off-by: Chen Dai <daichen@amazon.com>
1 parent 022464a commit f01a6cb

4 files changed

Lines changed: 108 additions & 15 deletions

File tree

api/src/test/java/org/opensearch/sql/api/UnifiedRelevanceSearchSqlV2Test.java

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,104 @@ public void matchCombinedWithBooleanFilter() {
132132
LogicalTableScan(table=[[catalog, employees]])
133133
""");
134134
}
135+
136+
// Alias tests for single-field relevance functions
137+
138+
@Test
139+
public void matchQuery() {
140+
givenQuery("SELECT * FROM catalog.employees WHERE match_query(name, 'John')")
141+
.assertPlan(
142+
"""
143+
LogicalFilter(condition=[match_query(MAP('field', $1), MAP('query', 'John':VARCHAR))])
144+
LogicalTableScan(table=[[catalog, employees]])
145+
""");
146+
}
147+
148+
@Test
149+
public void matchquery() {
150+
givenQuery("SELECT * FROM catalog.employees WHERE matchquery(name, 'John')")
151+
.assertPlan(
152+
"""
153+
LogicalFilter(condition=[matchquery(MAP('field', $1), MAP('query', 'John':VARCHAR))])
154+
LogicalTableScan(table=[[catalog, employees]])
155+
""");
156+
}
157+
158+
@Test
159+
public void matchphrase() {
160+
givenQuery("SELECT * FROM catalog.employees WHERE matchphrase(name, 'John Doe')")
161+
.assertPlan(
162+
"""
163+
LogicalFilter(condition=[matchphrase(MAP('field', $1), MAP('query', 'John Doe':VARCHAR))])
164+
LogicalTableScan(table=[[catalog, employees]])
165+
""");
166+
}
167+
168+
@Test
169+
public void matchphrasequery() {
170+
givenQuery("SELECT * FROM catalog.employees WHERE matchphrasequery(name, 'John Doe')")
171+
.assertPlan(
172+
"""
173+
LogicalFilter(condition=[matchphrasequery(MAP('field', $1), MAP('query', 'John Doe':VARCHAR))])
174+
LogicalTableScan(table=[[catalog, employees]])
175+
""");
176+
}
177+
178+
@Test
179+
public void multimatch() {
180+
givenQuery("SELECT * FROM catalog.employees WHERE multimatch(['name', 'department'], 'John')")
181+
.assertPlan(
182+
"""
183+
LogicalFilter(condition=[multimatch(MAP('fields', MAP('name':VARCHAR, 1.0E0:DOUBLE, 'department':VARCHAR, 1.0E0:DOUBLE)), MAP('query', 'John':VARCHAR))])
184+
LogicalTableScan(table=[[catalog, employees]])
185+
""");
186+
}
187+
188+
@Test
189+
public void multimatchquery() {
190+
givenQuery(
191+
"SELECT * FROM catalog.employees WHERE multimatchquery(['name', 'department'], 'John')")
192+
.assertPlan(
193+
"""
194+
LogicalFilter(condition=[multimatchquery(MAP('fields', MAP('name':VARCHAR, 1.0E0:DOUBLE, 'department':VARCHAR, 1.0E0:DOUBLE)), MAP('query', 'John':VARCHAR))])
195+
LogicalTableScan(table=[[catalog, employees]])
196+
""");
197+
}
198+
199+
// No-field relevance function
200+
201+
@Test
202+
public void query() {
203+
givenQuery("SELECT * FROM catalog.employees WHERE query('name:John')")
204+
.assertPlan(
205+
"""
206+
LogicalFilter(condition=[query(MAP('query', 'name:John':VARCHAR))])
207+
LogicalTableScan(table=[[catalog, employees]])
208+
""");
209+
}
210+
211+
// Single-field: wildcard_query
212+
213+
@Test
214+
public void wildcardQuery() {
215+
givenQuery("SELECT * FROM catalog.employees WHERE wildcard_query(name, 'John*')")
216+
.assertPlan(
217+
"""
218+
LogicalFilter(condition=[wildcard_query(MAP('field', $1), MAP('query', 'John*':VARCHAR))])
219+
LogicalTableScan(table=[[catalog, employees]])
220+
""");
221+
}
222+
223+
@Test
224+
public void wildcardquery() {
225+
givenQuery("SELECT * FROM catalog.employees WHERE wildcardquery(name, 'John*')")
226+
.assertPlan(
227+
"""
228+
LogicalFilter(condition=[wildcardquery(MAP('field', $1), MAP('query', 'John*':VARCHAR))])
229+
LogicalTableScan(table=[[catalog, employees]])
230+
""");
231+
}
232+
233+
// Score wrapper function — requires special AstBuilder handling (wraps inner relevance function)
234+
// Not yet supported in the unified Calcite path; tracked separately.
135235
}

core/src/main/java/org/opensearch/sql/calcite/utils/UserDefinedFunctionUtils.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,23 @@ public class UserDefinedFunctionUtils {
8181
"match_phrase",
8282
"match_bool_prefix",
8383
"match_phrase_prefix",
84+
// TODO: Functions below are registered for SQL V2 AstBuilder compatibility but lack
85+
// PredicateAnalyzer pushdown handlers. Only reachable from SQL (not PPL grammar).
8486
"query",
8587
"wildcard_query",
8688
"wildcardquery",
87-
"score",
88-
"scorequery",
89-
"score_query",
9089
"match_query",
9190
"matchquery",
9291
"matchphrase",
9392
"matchphrasequery");
9493
public static Set<String> MULTI_FIELDS_RELEVANCE_FUNCTION_SET =
9594
ImmutableSet.of(
96-
"simple_query_string", "query_string", "multi_match", "multimatch", "multimatchquery");
95+
"simple_query_string",
96+
"query_string",
97+
"multi_match",
98+
// TODO: Same as above — registered for SQL V2 but lack pushdown handlers.
99+
"multimatch",
100+
"multimatchquery");
97101
public static String IP_FUNCTION_NAME = "IP";
98102

99103
/**

core/src/main/java/org/opensearch/sql/expression/function/PPLBuiltinOperators.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -429,11 +429,6 @@ public class PPLBuiltinOperators extends ReflectiveSqlOperatorTable {
429429
RELEVANCE_QUERY_FUNCTION_INSTANCE.toUDF("wildcard_query");
430430
public static final SqlOperator WILDCARDQUERY =
431431
RELEVANCE_QUERY_FUNCTION_INSTANCE.toUDF("wildcardquery");
432-
public static final SqlOperator SCORE = RELEVANCE_QUERY_FUNCTION_INSTANCE.toUDF("score");
433-
public static final SqlOperator SCOREQUERY =
434-
RELEVANCE_QUERY_FUNCTION_INSTANCE.toUDF("scorequery");
435-
public static final SqlOperator SCORE_QUERY =
436-
RELEVANCE_QUERY_FUNCTION_INSTANCE.toUDF("score_query");
437432
public static final SqlOperator MATCH_QUERY =
438433
RELEVANCE_QUERY_FUNCTION_INSTANCE.toUDF("match_query");
439434
public static final SqlOperator MATCHQUERY =

core/src/main/java/org/opensearch/sql/expression/function/PPLFuncImpTable.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,6 @@
205205
import static org.opensearch.sql.expression.function.BuiltinFunctionName.RTRIM;
206206
import static org.opensearch.sql.expression.function.BuiltinFunctionName.SCALAR_MAX;
207207
import static org.opensearch.sql.expression.function.BuiltinFunctionName.SCALAR_MIN;
208-
import static org.opensearch.sql.expression.function.BuiltinFunctionName.SCORE;
209-
import static org.opensearch.sql.expression.function.BuiltinFunctionName.SCOREQUERY;
210-
import static org.opensearch.sql.expression.function.BuiltinFunctionName.SCORE_QUERY;
211208
import static org.opensearch.sql.expression.function.BuiltinFunctionName.SECOND;
212209
import static org.opensearch.sql.expression.function.BuiltinFunctionName.SECOND_OF_MINUTE;
213210
import static org.opensearch.sql.expression.function.BuiltinFunctionName.SEC_TO_TIME;
@@ -923,9 +920,6 @@ void populate() {
923920
registerOperator(QUERY, PPLBuiltinOperators.QUERY);
924921
registerOperator(WILDCARD_QUERY, PPLBuiltinOperators.WILDCARD_QUERY);
925922
registerOperator(WILDCARDQUERY, PPLBuiltinOperators.WILDCARDQUERY);
926-
registerOperator(SCORE, PPLBuiltinOperators.SCORE);
927-
registerOperator(SCOREQUERY, PPLBuiltinOperators.SCOREQUERY);
928-
registerOperator(SCORE_QUERY, PPLBuiltinOperators.SCORE_QUERY);
929923
registerOperator(MATCH_QUERY, PPLBuiltinOperators.MATCH_QUERY);
930924
registerOperator(MATCHQUERY, PPLBuiltinOperators.MATCHQUERY);
931925
registerOperator(MATCHPHRASE, PPLBuiltinOperators.MATCHPHRASE);

0 commit comments

Comments
 (0)