|
5 | 5 |
|
6 | 6 | package org.opensearch.sql.calcite.remote; |
7 | 7 |
|
| 8 | +import static org.opensearch.sql.legacy.TestUtils.getResponseBody; |
8 | 9 | import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_ACCOUNT; |
9 | 10 | import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_ALIAS; |
10 | 11 | import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_BANK; |
|
25 | 26 |
|
26 | 27 | import java.io.IOException; |
27 | 28 | import java.util.Locale; |
| 29 | +import org.junit.Assert; |
28 | 30 | import org.junit.Ignore; |
29 | 31 | import org.junit.Test; |
| 32 | +import org.opensearch.client.Request; |
| 33 | +import org.opensearch.client.RequestOptions; |
| 34 | +import org.opensearch.client.Response; |
30 | 35 | import org.opensearch.sql.ast.statement.ExplainMode; |
31 | 36 | import org.opensearch.sql.common.setting.Settings; |
32 | 37 | import org.opensearch.sql.common.setting.Settings.Key; |
@@ -2497,4 +2502,68 @@ public void testExplainMvCombine() throws IOException { |
2497 | 2502 | String expected = loadExpectedPlan("explain_mvcombine.yaml"); |
2498 | 2503 | assertYamlEqualsIgnoreId(expected, actual); |
2499 | 2504 | } |
| 2505 | + |
| 2506 | + // ==================== fetch_size explain tests ==================== |
| 2507 | + |
| 2508 | + @Test |
| 2509 | + public void testExplainFetchSizePushDown() throws IOException { |
| 2510 | + // fetch_size=5 injects Head(5, 0) on top of the plan |
| 2511 | + // Logical plan: LogicalSort(fetch=[5]) wraps the Project |
| 2512 | + String expected = loadExpectedPlan("explain_fetch_size_push.yaml"); |
| 2513 | + assertYamlEqualsIgnoreId( |
| 2514 | + expected, |
| 2515 | + explainQueryWithFetchSizeYaml( |
| 2516 | + String.format("source=%s | fields age", TEST_INDEX_ACCOUNT), 5)); |
| 2517 | + } |
| 2518 | + |
| 2519 | + @Test |
| 2520 | + public void testExplainFetchSizeWithSmallerHead() throws IOException { |
| 2521 | + // fetch_size=10 with user's | head 3 |
| 2522 | + // Two LogicalSort nodes: inner fetch=[3] from user head, outer fetch=[10] from fetch_size |
| 2523 | + // Effective limit = min(3, 10) = 3 |
| 2524 | + String expected = loadExpectedPlan("explain_fetch_size_with_head_push.yaml"); |
| 2525 | + assertYamlEqualsIgnoreId( |
| 2526 | + expected, |
| 2527 | + explainQueryWithFetchSizeYaml( |
| 2528 | + String.format("source=%s | head 3 | fields age", TEST_INDEX_ACCOUNT), 10)); |
| 2529 | + } |
| 2530 | + |
| 2531 | + @Test |
| 2532 | + public void testExplainFetchSizeSmallerThanHead() throws IOException { |
| 2533 | + // fetch_size=5 with user's | head 100 |
| 2534 | + // Two LogicalSort nodes: inner fetch=[100] from user head, outer fetch=[5] from fetch_size |
| 2535 | + // Effective limit = min(100, 5) = 5 |
| 2536 | + String expected = loadExpectedPlan("explain_fetch_size_smaller_than_head_push.yaml"); |
| 2537 | + assertYamlEqualsIgnoreId( |
| 2538 | + expected, |
| 2539 | + explainQueryWithFetchSizeYaml( |
| 2540 | + String.format("source=%s | head 100 | fields age", TEST_INDEX_ACCOUNT), 5)); |
| 2541 | + } |
| 2542 | + |
| 2543 | + /** |
| 2544 | + * Send an explain request with fetch_size in the JSON body and return YAML output. |
| 2545 | + * |
| 2546 | + * @param query the PPL query string |
| 2547 | + * @param fetchSize the fetch_size parameter value |
| 2548 | + * @return the explain output as YAML string |
| 2549 | + */ |
| 2550 | + private String explainQueryWithFetchSizeYaml(String query, int fetchSize) throws IOException { |
| 2551 | + Request request = |
| 2552 | + new Request( |
| 2553 | + "POST", |
| 2554 | + String.format( |
| 2555 | + "/_plugins/_ppl/_explain?format=%s&mode=%s", Format.YAML, ExplainMode.STANDARD)); |
| 2556 | + String jsonBody = |
| 2557 | + String.format( |
| 2558 | + Locale.ROOT, "{\n \"query\": \"%s\",\n \"fetch_size\": %d\n}", query, fetchSize); |
| 2559 | + request.setJsonEntity(jsonBody); |
| 2560 | + |
| 2561 | + RequestOptions.Builder restOptionsBuilder = RequestOptions.DEFAULT.toBuilder(); |
| 2562 | + restOptionsBuilder.addHeader("Content-Type", "application/json"); |
| 2563 | + request.setOptions(restOptionsBuilder); |
| 2564 | + |
| 2565 | + Response response = client().performRequest(request); |
| 2566 | + Assert.assertEquals(200, response.getStatusLine().getStatusCode()); |
| 2567 | + return getResponseBody(response, true); |
| 2568 | + } |
2500 | 2569 | } |
0 commit comments