|
8 | 8 | import org.elasticsearch.test.ESTestCase;
|
9 | 9 | import org.elasticsearch.xpack.ql.expression.Expressions;
|
10 | 10 | import org.elasticsearch.xpack.ql.expression.ReferenceAttribute;
|
| 11 | +import org.elasticsearch.xpack.ql.expression.function.aggregate.AggregateFunction; |
11 | 12 | import org.elasticsearch.xpack.ql.index.EsIndex;
|
12 | 13 | import org.elasticsearch.xpack.ql.index.IndexResolution;
|
13 | 14 | import org.elasticsearch.xpack.ql.type.EsField;
|
|
20 | 21 | import org.elasticsearch.xpack.sql.plan.physical.EsQueryExec;
|
21 | 22 | import org.elasticsearch.xpack.sql.plan.physical.LocalExec;
|
22 | 23 | import org.elasticsearch.xpack.sql.plan.physical.PhysicalPlan;
|
| 24 | +import org.elasticsearch.xpack.sql.querydsl.container.QueryContainer; |
23 | 25 | import org.elasticsearch.xpack.sql.session.EmptyExecutable;
|
24 | 26 | import org.elasticsearch.xpack.sql.session.SingletonExecutable;
|
25 | 27 | import org.elasticsearch.xpack.sql.stats.Metrics;
|
26 | 28 | import org.elasticsearch.xpack.sql.types.SqlTypesTests;
|
27 | 29 | import org.junit.AfterClass;
|
28 | 30 | import org.junit.BeforeClass;
|
29 | 31 |
|
30 |
| -import java.util.Arrays; |
| 32 | +import java.util.List; |
31 | 33 | import java.util.Map;
|
32 | 34 |
|
| 35 | +import static java.util.Arrays.asList; |
| 36 | +import static java.util.stream.Collectors.toList; |
33 | 37 | import static org.hamcrest.Matchers.containsString;
|
34 | 38 | import static org.hamcrest.Matchers.endsWith;
|
35 | 39 | import static org.hamcrest.Matchers.startsWith;
|
@@ -449,15 +453,15 @@ public void testSelectLiteralWithGroupBy() {
|
449 | 453 | assertEquals(EsQueryExec.class, p.getClass());
|
450 | 454 | EsQueryExec ee = (EsQueryExec) p;
|
451 | 455 | assertEquals(2, ee.output().size());
|
452 |
| - assertEquals(Arrays.asList("1", "MAX(int)"), Expressions.names(ee.output())); |
| 456 | + assertEquals(asList("1", "MAX(int)"), Expressions.names(ee.output())); |
453 | 457 | assertThat(ee.queryContainer().aggs().asAggBuilder().toString().replaceAll("\\s+", ""),
|
454 | 458 | containsString("\"max\":{\"field\":\"int\""));
|
455 | 459 |
|
456 | 460 | p = plan("SELECT 1, count(*) FROM test GROUP BY int");
|
457 | 461 | assertEquals(EsQueryExec.class, p.getClass());
|
458 | 462 | ee = (EsQueryExec) p;
|
459 | 463 | assertEquals(2, ee.output().size());
|
460 |
| - assertEquals(Arrays.asList("1", "count(*)"), Expressions.names(ee.output())); |
| 464 | + assertEquals(asList("1", "count(*)"), Expressions.names(ee.output())); |
461 | 465 | assertThat(ee.queryContainer().aggs().asAggBuilder().toString().replaceAll("\\s+", ""),
|
462 | 466 | containsString("\"terms\":{\"field\":\"int\""));
|
463 | 467 | }
|
@@ -495,14 +499,39 @@ public void testFoldingOfPivot() {
|
495 | 499 | assertEquals(EsQueryExec.class, p.getClass());
|
496 | 500 | EsQueryExec ee = (EsQueryExec) p;
|
497 | 501 | assertEquals(3, ee.output().size());
|
498 |
| - assertEquals(Arrays.asList("bool", "'A'", "'B'"), Expressions.names(ee.output())); |
| 502 | + assertEquals(asList("bool", "'A'", "'B'"), Expressions.names(ee.output())); |
499 | 503 | String q = ee.toString().replaceAll("\\s+", "");
|
500 | 504 | assertThat(q, containsString("\"query\":{\"terms\":{\"keyword\":[\"A\",\"B\"]"));
|
501 | 505 | String a = ee.queryContainer().aggs().asAggBuilder().toString().replaceAll("\\s+", "");
|
502 | 506 | assertThat(a, containsString("\"terms\":{\"field\":\"bool\""));
|
503 | 507 | assertThat(a, containsString("\"terms\":{\"field\":\"keyword\""));
|
504 | 508 | assertThat(a, containsString("{\"avg\":{\"field\":\"int\"}"));
|
505 | 509 | }
|
| 510 | + |
| 511 | + public void testPivotHasSameQueryAsGroupBy() { |
| 512 | + final Map<String, String> aggFnsWithMultipleArguments = Map.of( |
| 513 | + "PERCENTILE", "PERCENTILE(int, 0)", |
| 514 | + "PERCENTILE_RANK", "PERCENTILE_RANK(int, 0)" |
| 515 | + ); |
| 516 | + List<String> aggregations = new SqlFunctionRegistry().listFunctions() |
| 517 | + .stream() |
| 518 | + .filter(def -> AggregateFunction.class.isAssignableFrom(def.clazz())) |
| 519 | + .map(def -> aggFnsWithMultipleArguments.getOrDefault(def.name(), def.name() + "(int)")) |
| 520 | + .collect(toList()); |
| 521 | + for (String aggregationStr : aggregations) { |
| 522 | + PhysicalPlan pivotPlan = plan("SELECT * FROM (SELECT some.dotted.field, bool, keyword, int FROM test) " + |
| 523 | + "PIVOT(" + aggregationStr + " FOR keyword IN ('A', 'B'))"); |
| 524 | + PhysicalPlan groupByPlan = plan("SELECT some.dotted.field, bool, keyword, " + aggregationStr + " " + |
| 525 | + "FROM test WHERE keyword IN ('A', 'B') GROUP BY some.dotted.field, bool, keyword"); |
| 526 | + assertEquals(EsQueryExec.class, pivotPlan.getClass()); |
| 527 | + assertEquals(EsQueryExec.class, groupByPlan.getClass()); |
| 528 | + QueryContainer pivotQueryContainer = ((EsQueryExec) pivotPlan).queryContainer(); |
| 529 | + QueryContainer groupByQueryContainer = ((EsQueryExec) groupByPlan).queryContainer(); |
| 530 | + assertEquals(pivotQueryContainer.query(), groupByQueryContainer.query()); |
| 531 | + assertEquals(pivotQueryContainer.aggs(), groupByQueryContainer.aggs()); |
| 532 | + assertEquals(pivotPlan.toString(), groupByPlan.toString()); |
| 533 | + } |
| 534 | + } |
506 | 535 |
|
507 | 536 | private static String randomOrderByAndLimit(int noOfSelectArgs) {
|
508 | 537 | return SqlTestUtils.randomOrderByAndLimit(noOfSelectArgs, random());
|
|
0 commit comments