diff --git a/core/src/main/java/org/opensearch/sql/calcite/CalciteRexNodeVisitor.java b/core/src/main/java/org/opensearch/sql/calcite/CalciteRexNodeVisitor.java index d14f2d07c8a..a9a32a707b6 100644 --- a/core/src/main/java/org/opensearch/sql/calcite/CalciteRexNodeVisitor.java +++ b/core/src/main/java/org/opensearch/sql/calcite/CalciteRexNodeVisitor.java @@ -676,6 +676,13 @@ public RexNode visitRelevanceFieldList(RelevanceFieldList node, CalcitePlanConte @Override public RexNode visitUnresolvedArgument(UnresolvedArgument node, CalcitePlanContext context) { RexNode value = analyze(node.getValue(), context); - return context.relBuilder.alias(value, node.getArgName()); + /* + * Calcite SqlStdOperatorTable.AS doesn't have implementor registration in RexImpTable. + * To not block ReduceExpressionsRule constants reduction optimization, use MAP_VALUE_CONSTRUCTOR instead to achieve the same effect. + */ + return context.rexBuilder.makeCall( + SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, + context.rexBuilder.makeLiteral(node.getArgName()), + value); } } diff --git a/core/src/main/java/org/opensearch/sql/calcite/utils/PlanUtils.java b/core/src/main/java/org/opensearch/sql/calcite/utils/PlanUtils.java index 9da326fc078..42d0addb53e 100644 --- a/core/src/main/java/org/opensearch/sql/calcite/utils/PlanUtils.java +++ b/core/src/main/java/org/opensearch/sql/calcite/utils/PlanUtils.java @@ -20,6 +20,7 @@ import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.RelShuttle; import org.apache.calcite.rel.core.TableScan; +import org.apache.calcite.rex.RexCall; import org.apache.calcite.rex.RexInputRef; import org.apache.calcite.rex.RexNode; import org.apache.calcite.rex.RexVisitorImpl; @@ -330,4 +331,20 @@ public Void visitChildren(Node node, Object context) { }; node.accept(leafVisitor, null); } + + /** + * Return the first value RexNode of the valid map RexCall structure + * + * @param rexNode RexNode that expects type of MAP_VALUE_CONSTRUCTOR RexCall + * @return first value of the valid map RexCall + */ + static RexNode derefMapCall(RexNode rexNode) { + if (rexNode instanceof RexCall) { + RexCall call = (RexCall) rexNode; + if (call.getOperator() == SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR) { + return call.getOperands().get(1); + } + } + return rexNode; + } } diff --git a/core/src/main/java/org/opensearch/sql/expression/function/PPLBuiltinOperators.java b/core/src/main/java/org/opensearch/sql/expression/function/PPLBuiltinOperators.java index 966a5ee2e22..3da366da827 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/PPLBuiltinOperators.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/PPLBuiltinOperators.java @@ -338,11 +338,11 @@ public class PPLBuiltinOperators extends ReflectiveSqlOperatorTable { public static final SqlOperator MATCH_PHRASE_PREFIX = RELEVANCE_QUERY_FUNCTION_INSTANCE.toUDF("match_phrase_prefix"); public static final SqlOperator SIMPLE_QUERY_STRING = - RELEVANCE_QUERY_FUNCTION_INSTANCE.toUDF("simple_query_string"); + RELEVANCE_QUERY_FUNCTION_INSTANCE.toUDF("simple_query_string", false); public static final SqlOperator QUERY_STRING = - RELEVANCE_QUERY_FUNCTION_INSTANCE.toUDF("query_string"); + RELEVANCE_QUERY_FUNCTION_INSTANCE.toUDF("query_string", false); public static final SqlOperator MULTI_MATCH = - RELEVANCE_QUERY_FUNCTION_INSTANCE.toUDF("multi_match"); + RELEVANCE_QUERY_FUNCTION_INSTANCE.toUDF("multi_match", false); /** * Invoking an implementor registered in {@link RexImpTable}, need to use reflection since they're diff --git a/core/src/main/java/org/opensearch/sql/expression/function/PPLFuncImpTable.java b/core/src/main/java/org/opensearch/sql/expression/function/PPLFuncImpTable.java index 84e11d170f1..363baff3e4c 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/PPLFuncImpTable.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/PPLFuncImpTable.java @@ -252,6 +252,7 @@ import org.opensearch.sql.calcite.udf.udaf.PercentileApproxFunction; import org.opensearch.sql.calcite.udf.udaf.TakeAggFunction; import org.opensearch.sql.calcite.utils.OpenSearchTypeFactory; +import org.opensearch.sql.calcite.utils.PlanUtils; import org.opensearch.sql.calcite.utils.UserDefinedFunctionUtils; import org.opensearch.sql.exception.ExpressionEvaluationException; import org.opensearch.sql.executor.QueryType; @@ -1033,19 +1034,23 @@ void populate() { register( TAKE, - (distinct, field, argList, ctx) -> - TransferUserDefinedAggFunction( - TakeAggFunction.class, - "TAKE", - UserDefinedFunctionUtils.getReturnTypeInferenceForArray(), - List.of(field), - argList, - ctx.relBuilder)); + (distinct, field, argList, ctx) -> { + List newArgList = + argList.stream().map(PlanUtils::derefMapCall).collect(Collectors.toList()); + return TransferUserDefinedAggFunction( + TakeAggFunction.class, + "TAKE", + UserDefinedFunctionUtils.getReturnTypeInferenceForArray(), + List.of(field), + newArgList, + ctx.relBuilder); + }); register( PERCENTILE_APPROX, (distinct, field, argList, ctx) -> { - List newArgList = new ArrayList<>(argList); + List newArgList = + argList.stream().map(PlanUtils::derefMapCall).collect(Collectors.toList()); newArgList.add(ctx.rexBuilder.makeFlag(field.getType().getSqlTypeName())); return TransferUserDefinedAggFunction( PercentileApproxFunction.class, diff --git a/core/src/main/java/org/opensearch/sql/expression/function/UserDefinedFunctionBuilder.java b/core/src/main/java/org/opensearch/sql/expression/function/UserDefinedFunctionBuilder.java index a74f1555071..30dd644fc76 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/UserDefinedFunctionBuilder.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/UserDefinedFunctionBuilder.java @@ -33,6 +33,19 @@ public interface UserDefinedFunctionBuilder { UDFOperandMetadata getOperandMetadata(); default SqlUserDefinedFunction toUDF(String functionName) { + return toUDF(functionName, true); + } + + /** + * In some rare cases, we need to call out the UDF to be not deterministic to avoid Volcano + * planner over-optimization. For example, we don't need ReduceExpressionsRule to optimize + * relevance query UDF. + * + * @param functionName UDF name to be registered + * @param isDeterministic Specified isDeterministic flag + * @return Calcite SqlUserDefinedFunction + */ + default SqlUserDefinedFunction toUDF(String functionName, boolean isDeterministic) { SqlIdentifier udfLtrimIdentifier = new SqlIdentifier(Collections.singletonList(functionName), null, SqlParserPos.ZERO, null); return new SqlUserDefinedFunction( @@ -41,6 +54,11 @@ default SqlUserDefinedFunction toUDF(String functionName) { getReturnTypeInference(), InferTypes.ANY_NULLABLE, getOperandMetadata(), - getFunction()); + getFunction()) { + @Override + public boolean isDeterministic() { + return isDeterministic; + } + }; } } diff --git a/core/src/main/java/org/opensearch/sql/expression/function/udf/RelevanceQueryFunction.java b/core/src/main/java/org/opensearch/sql/expression/function/udf/RelevanceQueryFunction.java index c7adf5f73b0..6bc54f26242 100644 --- a/core/src/main/java/org/opensearch/sql/expression/function/udf/RelevanceQueryFunction.java +++ b/core/src/main/java/org/opensearch/sql/expression/function/udf/RelevanceQueryFunction.java @@ -41,49 +41,49 @@ public UDFOperandMetadata getOperandMetadata() { (CompositeOperandTypeChecker) OperandTypes.family( ImmutableList.of( - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING), + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP), i -> i > 1 && i < 14) // Parameters 3-14 are optional .or( OperandTypes.family( ImmutableList.of( SqlTypeFamily.MAP, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING, - SqlTypeFamily.STRING), + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP, + SqlTypeFamily.MAP), i -> i > 1 && i < 25))); // Parameters 3-25 are optional } diff --git a/integ-test/src/test/java/org/opensearch/sql/ppl/RelevanceFunctionIT.java b/integ-test/src/test/java/org/opensearch/sql/ppl/RelevanceFunctionIT.java index 86228c53acc..04880901490 100644 --- a/integ-test/src/test/java/org/opensearch/sql/ppl/RelevanceFunctionIT.java +++ b/integ-test/src/test/java/org/opensearch/sql/ppl/RelevanceFunctionIT.java @@ -144,13 +144,38 @@ public void test_mixed_relevance_function_and_normal_filter() throws IOException assertEquals(8, result2.getInt("total")); } + @Test + public void test_single_field_relevance_function_and_implicit_timestamp_filter() + throws IOException { + String query1 = + "SOURCE=" + + TEST_INDEX_BEER + + " | WHERE match('Tags', 'brewing taste', operator='AND') and CreationDate >" + + " '2014-01-20 00:00:00.000' and CreationDate < '2018-01-20 00:00:00.000' | fields" + + " Tags"; + var result1 = executeQuery(query1); + assertEquals(2, result1.getInt("total")); + } + + @Test + public void test_multi_fields_relevance_function_and_implicit_timestamp_filter() + throws IOException { + String query1 = + "SOURCE=" + + TEST_INDEX_BEER + + " | WHERE query_string(['Tags'], 'brewing AND taste') and CreationDate > '2014-01-20" + + " 00:00:00.000' and CreationDate < '2018-01-20 00:00:00.000' | fields Tags"; + var result1 = executeQuery(query1); + assertEquals(2, result1.getInt("total")); + } + @Test public void not_pushdown_throws_exception() throws IOException { String query1 = "SOURCE=" + TEST_INDEX_BEER - + " | STATS count(AcceptedAnswerId) as idCount" - + " | WHERE simple_query_string(['Tags'], 'taste') and idCount > 200"; + + " | EVAL answerId = AcceptedAnswerId + 1" + + " | WHERE simple_query_string(['Tags'], 'taste') and answerId > 200"; assertThrows(Exception.class, () -> executeQuery(query1)); } } diff --git a/integ-test/src/test/resources/expectedOutput/calcite/explain_multi_fields_relevance_push.json b/integ-test/src/test/resources/expectedOutput/calcite/explain_multi_fields_relevance_push.json index 254b22b34b1..65860397457 100644 --- a/integ-test/src/test/resources/expectedOutput/calcite/explain_multi_fields_relevance_push.json +++ b/integ-test/src/test/resources/expectedOutput/calcite/explain_multi_fields_relevance_push.json @@ -1,6 +1,6 @@ { "calcite": { - "logical": "LogicalProject(account_number=[$0], firstname=[$1], address=[$2], balance=[$3], gender=[$4], city=[$5], employer=[$6], state=[$7], age=[$8], email=[$9], lastname=[$10])\n LogicalFilter(condition=[simple_query_string(AS(MAP('name':VARCHAR, 4.0E0:DOUBLE, 'email':VARCHAR, 1.0E0:DOUBLE), 'fields'), AS('gmail':VARCHAR, 'query'), AS('or':VARCHAR, 'default_operator'), AS('english':VARCHAR, 'analyzer'))])\n CalciteLogicalIndexScan(table=[[OpenSearch, opensearch-sql_test_index_account]])\n", - "physical": "CalciteEnumerableIndexScan(table=[[OpenSearch, opensearch-sql_test_index_account]], PushDownContext=[[PROJECT->[account_number, firstname, address, balance, gender, city, employer, state, age, email, lastname], FILTER->simple_query_string(AS(MAP('name':VARCHAR, 4.0E0:DOUBLE, 'email':VARCHAR, 1.0E0:DOUBLE), 'fields'), AS('gmail':VARCHAR, 'query'), AS('or':VARCHAR, 'default_operator'), AS('english':VARCHAR, 'analyzer'))], OpenSearchRequestBuilder(sourceBuilder={\"from\":0,\"timeout\":\"1m\",\"query\":{\"simple_query_string\":{\"query\":\"gmail\",\"fields\":[\"name^4.0\",\"email^1.0\"],\"analyzer\":\"english\",\"flags\":-1,\"default_operator\":\"or\",\"analyze_wildcard\":false,\"auto_generate_synonyms_phrase_query\":true,\"fuzzy_prefix_length\":0,\"fuzzy_max_expansions\":50,\"fuzzy_transpositions\":true,\"boost\":1.0}},\"_source\":{\"includes\":[\"account_number\",\"firstname\",\"address\",\"balance\",\"gender\",\"city\",\"employer\",\"state\",\"age\",\"email\",\"lastname\"],\"excludes\":[]},\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}, requestedTotalSize=2147483647, pageSize=null, startFrom=0)])\n" + "logical": "LogicalProject(account_number=[$0], firstname=[$1], address=[$2], balance=[$3], gender=[$4], city=[$5], employer=[$6], state=[$7], age=[$8], email=[$9], lastname=[$10])\n LogicalFilter(condition=[simple_query_string(MAP('fields', MAP('name':VARCHAR, 4.0E0:DOUBLE, 'email':VARCHAR, 1.0E0:DOUBLE)), MAP('query', 'gmail':VARCHAR), MAP('default_operator', 'or':VARCHAR), MAP('analyzer', 'english':VARCHAR))])\n CalciteLogicalIndexScan(table=[[OpenSearch, opensearch-sql_test_index_account]])\n", + "physical": "CalciteEnumerableIndexScan(table=[[OpenSearch, opensearch-sql_test_index_account]], PushDownContext=[[PROJECT->[account_number, firstname, address, balance, gender, city, employer, state, age, email, lastname], FILTER->simple_query_string(MAP('fields', MAP('name':VARCHAR, 4.0E0:DOUBLE, 'email':VARCHAR, 1.0E0:DOUBLE)), MAP('query', 'gmail':VARCHAR), MAP('default_operator', 'or':VARCHAR), MAP('analyzer', 'english':VARCHAR))], OpenSearchRequestBuilder(sourceBuilder={\"from\":0,\"timeout\":\"1m\",\"query\":{\"simple_query_string\":{\"query\":\"gmail\",\"fields\":[\"name^4.0\",\"email^1.0\"],\"analyzer\":\"english\",\"flags\":-1,\"default_operator\":\"or\",\"analyze_wildcard\":false,\"auto_generate_synonyms_phrase_query\":true,\"fuzzy_prefix_length\":0,\"fuzzy_max_expansions\":50,\"fuzzy_transpositions\":true,\"boost\":1.0}},\"_source\":{\"includes\":[\"account_number\",\"firstname\",\"address\",\"balance\",\"gender\",\"city\",\"employer\",\"state\",\"age\",\"email\",\"lastname\"],\"excludes\":[]},\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}, requestedTotalSize=2147483647, pageSize=null, startFrom=0)])\n" } } \ No newline at end of file diff --git a/integ-test/src/test/resources/expectedOutput/calcite/explain_single_field_relevance_push.json b/integ-test/src/test/resources/expectedOutput/calcite/explain_single_field_relevance_push.json index 6ad7b285050..c31c841c23a 100644 --- a/integ-test/src/test/resources/expectedOutput/calcite/explain_single_field_relevance_push.json +++ b/integ-test/src/test/resources/expectedOutput/calcite/explain_single_field_relevance_push.json @@ -1,6 +1,6 @@ { "calcite": { - "logical": "LogicalProject(account_number=[$0], firstname=[$1], address=[$2], balance=[$3], gender=[$4], city=[$5], employer=[$6], state=[$7], age=[$8], email=[$9], lastname=[$10])\n LogicalFilter(condition=[match(AS($9, 'field'), AS('*@gmail.com':VARCHAR, 'query'), AS('1.0':VARCHAR, 'boost'))])\n CalciteLogicalIndexScan(table=[[OpenSearch, opensearch-sql_test_index_account]])\n", - "physical": "CalciteEnumerableIndexScan(table=[[OpenSearch, opensearch-sql_test_index_account]], PushDownContext=[[PROJECT->[account_number, firstname, address, balance, gender, city, employer, state, age, email, lastname], FILTER->match(AS($9, 'field'), AS('*@gmail.com':VARCHAR, 'query'), AS('1.0':VARCHAR, 'boost'))], OpenSearchRequestBuilder(sourceBuilder={\"from\":0,\"timeout\":\"1m\",\"query\":{\"match\":{\"email\":{\"query\":\"*@gmail.com\",\"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\",\"balance\",\"gender\",\"city\",\"employer\",\"state\",\"age\",\"email\",\"lastname\"],\"excludes\":[]},\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}, requestedTotalSize=2147483647, pageSize=null, startFrom=0)])\n" + "logical": "LogicalProject(account_number=[$0], firstname=[$1], address=[$2], balance=[$3], gender=[$4], city=[$5], employer=[$6], state=[$7], age=[$8], email=[$9], lastname=[$10])\n LogicalFilter(condition=[match(MAP('field', $9), MAP('query', '*@gmail.com':VARCHAR), MAP('boost', '1.0':VARCHAR))])\n CalciteLogicalIndexScan(table=[[OpenSearch, opensearch-sql_test_index_account]])\n", + "physical": "CalciteEnumerableIndexScan(table=[[OpenSearch, opensearch-sql_test_index_account]], PushDownContext=[[PROJECT->[account_number, firstname, address, balance, gender, city, employer, state, age, email, lastname], FILTER->match(MAP('field', $9), MAP('query', '*@gmail.com':VARCHAR), MAP('boost', '1.0':VARCHAR))], OpenSearchRequestBuilder(sourceBuilder={\"from\":0,\"timeout\":\"1m\",\"query\":{\"match\":{\"email\":{\"query\":\"*@gmail.com\",\"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\",\"balance\",\"gender\",\"city\",\"employer\",\"state\",\"age\",\"email\",\"lastname\"],\"excludes\":[]},\"sort\":[{\"_doc\":{\"order\":\"asc\"}}]}, requestedTotalSize=2147483647, pageSize=null, startFrom=0)])\n" } } \ No newline at end of file diff --git a/opensearch/src/main/java/org/opensearch/sql/opensearch/request/PredicateAnalyzer.java b/opensearch/src/main/java/org/opensearch/sql/opensearch/request/PredicateAnalyzer.java index a29e148783d..fcc6079d016 100644 --- a/opensearch/src/main/java/org/opensearch/sql/opensearch/request/PredicateAnalyzer.java +++ b/opensearch/src/main/java/org/opensearch/sql/opensearch/request/PredicateAnalyzer.java @@ -401,8 +401,8 @@ private static class AliasPair { final RexNode alias; static AliasPair from(RexNode node, String funcName) { - RexCall as = expectCall(node, SqlStdOperatorTable.AS, funcName); - return new AliasPair(as.getOperands().get(0), as.getOperands().get(1)); + RexCall mapCall = expectCall(node, SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, funcName); + return new AliasPair(mapCall.getOperands().get(1), mapCall.getOperands().get(0)); } private AliasPair(RexNode value, RexNode alias) { diff --git a/opensearch/src/test/java/org/opensearch/sql/opensearch/request/PredicateAnalyzerTest.java b/opensearch/src/test/java/org/opensearch/sql/opensearch/request/PredicateAnalyzerTest.java index 29c0452d429..a7a84acad16 100644 --- a/opensearch/src/test/java/org/opensearch/sql/opensearch/request/PredicateAnalyzerTest.java +++ b/opensearch/src/test/java/org/opensearch/sql/opensearch/request/PredicateAnalyzerTest.java @@ -62,9 +62,11 @@ public class PredicateAnalyzerTest { final RexLiteral numericLiteral = builder.makeExactLiteral(new BigDecimal(12)); final RexLiteral stringLiteral = builder.makeLiteral("Hi"); final RexNode aliasedField2 = - builder.makeCall(SqlStdOperatorTable.AS, field2, builder.makeLiteral("field")); + builder.makeCall( + SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, builder.makeLiteral("field"), field2); final RexNode aliasedStringLiteral = - builder.makeCall(SqlStdOperatorTable.AS, stringLiteral, builder.makeLiteral("query")); + builder.makeCall( + SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, builder.makeLiteral("query"), stringLiteral); @Test void equals_generatesTermQuery() throws ExpressionNotAnalyzableException { @@ -336,7 +338,9 @@ void matchPhraseRelevanceQueryFunction_generatesMatchPhraseQuery() aliasedField2, aliasedStringLiteral, builder.makeCall( - SqlStdOperatorTable.AS, builder.makeLiteral("2"), builder.makeLiteral("slop"))); + SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, + builder.makeLiteral("slop"), + builder.makeLiteral("2"))); RexNode call = PPLFuncImpTable.INSTANCE.resolve( builder, "match_phrase", arguments.toArray(new RexNode[0])); @@ -365,9 +369,9 @@ void matchBoolPrefixRelevanceQueryFunction_generatesMatchBoolPrefixQuery() aliasedField2, aliasedStringLiteral, builder.makeCall( - SqlStdOperatorTable.AS, - builder.makeLiteral("1"), - builder.makeLiteral("minimum_should_match"))); + SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, + builder.makeLiteral("minimum_should_match"), + builder.makeLiteral("1"))); RexNode call = PPLFuncImpTable.INSTANCE.resolve( builder, "match_bool_prefix", arguments.toArray(new RexNode[0])); @@ -399,9 +403,9 @@ void matchPhrasePrefixRelevanceQueryFunction_generatesMatchPhrasePrefixQuery() aliasedField2, aliasedStringLiteral, builder.makeCall( - SqlStdOperatorTable.AS, - builder.makeLiteral("standard"), - builder.makeLiteral("analyzer"))); + SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, + builder.makeLiteral("analyzer"), + builder.makeLiteral("standard"))); RexNode call = PPLFuncImpTable.INSTANCE.resolve( builder, "match_phrase_prefix", arguments.toArray(new RexNode[0])); @@ -430,7 +434,8 @@ void queryStringRelevanceQueryFunction_generatesQueryStringQuery() List arguments = Arrays.asList( builder.makeCall( - SqlStdOperatorTable.AS, + SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, + builder.makeLiteral("fields"), builder.makeCall( SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, builder.makeLiteral("b"), @@ -438,13 +443,12 @@ void queryStringRelevanceQueryFunction_generatesQueryStringQuery() 1.0, builder.getTypeFactory().createSqlType(SqlTypeName.DOUBLE), true), builder.makeLiteral("c"), builder.makeLiteral( - 2.5, builder.getTypeFactory().createSqlType(SqlTypeName.DOUBLE), true)), - builder.makeLiteral("fields")), + 2.5, builder.getTypeFactory().createSqlType(SqlTypeName.DOUBLE), true))), aliasedStringLiteral, builder.makeCall( - SqlStdOperatorTable.AS, - builder.makeLiteral("1"), - builder.makeLiteral("fuzziness"))); + SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, + builder.makeLiteral("fuzziness"), + builder.makeLiteral("1"))); RexNode call = PPLFuncImpTable.INSTANCE.resolve( builder, "query_string", arguments.toArray(new RexNode[0])); @@ -482,13 +486,13 @@ void simpleQueryStringRelevanceQueryFunction_generatesSimpleQueryStringQuery() List arguments = Arrays.asList( builder.makeCall( - SqlStdOperatorTable.AS, + SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, + builder.makeLiteral("fields"), builder.makeCall( SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, builder.makeLiteral("b*"), builder.makeLiteral( - 1.0, builder.getTypeFactory().createSqlType(SqlTypeName.DOUBLE), true)), - builder.makeLiteral("fields")), + 1.0, builder.getTypeFactory().createSqlType(SqlTypeName.DOUBLE), true))), aliasedStringLiteral); RexNode call = PPLFuncImpTable.INSTANCE.resolve( @@ -522,18 +526,18 @@ void multiMatchRelevanceQueryFunction_generatesMultiMatchQuery() List arguments = Arrays.asList( builder.makeCall( - SqlStdOperatorTable.AS, + SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, + builder.makeLiteral("fields"), builder.makeCall( SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, builder.makeLiteral("b*"), builder.makeLiteral( - 1.0, builder.getTypeFactory().createSqlType(SqlTypeName.DOUBLE), true)), - builder.makeLiteral("fields")), + 1.0, builder.getTypeFactory().createSqlType(SqlTypeName.DOUBLE), true))), aliasedStringLiteral, builder.makeCall( - SqlStdOperatorTable.AS, - builder.makeLiteral("25"), - builder.makeLiteral("max_expansions"))); + SqlStdOperatorTable.MAP_VALUE_CONSTRUCTOR, + builder.makeLiteral("max_expansions"), + builder.makeLiteral("25"))); RexNode call = PPLFuncImpTable.INSTANCE.resolve(builder, "multi_match", arguments.toArray(new RexNode[0])); QueryBuilder result = PredicateAnalyzer.analyze(call, schema, fieldTypes); diff --git a/ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLAggregationTest.java b/ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLAggregationTest.java index cbb1de8dd45..dc3abdc3007 100644 --- a/ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLAggregationTest.java +++ b/ppl/src/test/java/org/opensearch/sql/ppl/calcite/CalcitePPLAggregationTest.java @@ -37,9 +37,8 @@ public void testTakeAgg() { String ppl = "source=EMP | stats take(JOB, 2) as c"; RelNode root = getRelNode(ppl); String expectedLogical = - "" - + "LogicalAggregate(group=[{}], c=[TAKE($0, $1)])\n" - + " LogicalProject(JOB=[$2], size=[2])\n" + "LogicalAggregate(group=[{}], c=[TAKE($0, $1)])\n" + + " LogicalProject(JOB=[$2], $f1=[2])\n" + " LogicalTableScan(table=[[scott, EMP]])\n"; verifyLogical(root, expectedLogical); String expectedResult = "c=[CLERK, SALESMAN]\n";