|
12 | 12 | import org.elasticsearch.common.logging.LoggerMessageFormat; |
13 | 13 | import org.elasticsearch.common.lucene.BytesRefs; |
14 | 14 | import org.elasticsearch.compute.aggregation.QuantileStates; |
15 | | -import org.elasticsearch.compute.data.Block; |
16 | | -import org.elasticsearch.compute.data.LongVectorBlock; |
17 | 15 | import org.elasticsearch.compute.test.TestBlockFactory; |
18 | 16 | import org.elasticsearch.core.Tuple; |
19 | 17 | import org.elasticsearch.dissect.DissectParser; |
|
176 | 174 | import static org.elasticsearch.xpack.esql.core.type.DataType.GEO_POINT; |
177 | 175 | import static org.elasticsearch.xpack.esql.core.type.DataType.INTEGER; |
178 | 176 | import static org.elasticsearch.xpack.esql.core.type.DataType.KEYWORD; |
179 | | -import static org.elasticsearch.xpack.esql.core.type.DataType.LONG; |
180 | 177 | import static org.elasticsearch.xpack.esql.core.type.DataType.TEXT; |
181 | 178 | import static org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.EsqlBinaryComparison.BinaryComparisonOperation.EQ; |
182 | 179 | import static org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.EsqlBinaryComparison.BinaryComparisonOperation.GT; |
|
199 | 196 | import static org.hamcrest.Matchers.instanceOf; |
200 | 197 | import static org.hamcrest.Matchers.is; |
201 | 198 | import static org.hamcrest.Matchers.not; |
202 | | -import static org.hamcrest.Matchers.nullValue; |
203 | 199 | import static org.hamcrest.Matchers.startsWith; |
204 | 200 |
|
205 | 201 | //@TestLogging(value = "org.elasticsearch.xpack.esql:TRACE", reason = "debug") |
@@ -536,349 +532,6 @@ public void testStatsWithFilteringDefaultAliasing() { |
536 | 532 | assertThat(Expressions.names(agg.aggregates()), contains("sum(salary)", "sum(salary) WheRe last_name == \"Doe\"")); |
537 | 533 | } |
538 | 534 |
|
539 | | - /** |
540 | | - * <pre>{@code |
541 | | - * Limit[1000[INTEGER]] |
542 | | - * \_LocalRelation[[sum(salary) where false{r}#26],[ConstantNullBlock[positions=1]]] |
543 | | - * }</pre> |
544 | | - */ |
545 | | - public void testReplaceStatsFilteredAggWithEvalSingleAgg() { |
546 | | - var plan = plan(""" |
547 | | - from test |
548 | | - | stats sum(salary) where false |
549 | | - """); |
550 | | - |
551 | | - var project = as(plan, Limit.class); |
552 | | - var source = as(project.child(), LocalRelation.class); |
553 | | - assertThat(Expressions.names(source.output()), contains("sum(salary) where false")); |
554 | | - Block[] blocks = source.supplier().get(); |
555 | | - assertThat(blocks.length, is(1)); |
556 | | - assertThat(blocks[0].getPositionCount(), is(1)); |
557 | | - assertTrue(blocks[0].areAllValuesNull()); |
558 | | - } |
559 | | - |
560 | | - /** |
561 | | - * <pre>{@code |
562 | | - * Project[[sum(salary) + 1 where false{r}#68]] |
563 | | - * \_Eval[[$$SUM$sum(salary)_+_1$0{r$}#79 + 1[INTEGER] AS sum(salary) + 1 where false]] |
564 | | - * \_Limit[1000[INTEGER]] |
565 | | - * \_LocalRelation[[$$SUM$sum(salary)_+_1$0{r$}#79],[ConstantNullBlock[positions=1]]] |
566 | | - * }</pre> |
567 | | - */ |
568 | | - public void testReplaceStatsFilteredAggWithEvalSingleAggWithExpression() { |
569 | | - var plan = plan(""" |
570 | | - from test |
571 | | - | stats sum(salary) + 1 where false |
572 | | - """); |
573 | | - |
574 | | - var project = as(plan, Project.class); |
575 | | - assertThat(Expressions.names(project.projections()), contains("sum(salary) + 1 where false")); |
576 | | - |
577 | | - var eval = as(project.child(), Eval.class); |
578 | | - assertThat(eval.fields().size(), is(1)); |
579 | | - var alias = as(eval.fields().getFirst(), Alias.class); |
580 | | - assertThat(alias.name(), is("sum(salary) + 1 where false")); |
581 | | - var add = as(alias.child(), Add.class); |
582 | | - var literal = as(add.right(), Literal.class); |
583 | | - assertThat(literal.value(), is(1)); |
584 | | - |
585 | | - var limit = as(eval.child(), Limit.class); |
586 | | - var source = as(limit.child(), LocalRelation.class); |
587 | | - |
588 | | - Block[] blocks = source.supplier().get(); |
589 | | - assertThat(blocks.length, is(1)); |
590 | | - assertThat(blocks[0].getPositionCount(), is(1)); |
591 | | - assertTrue(blocks[0].areAllValuesNull()); |
592 | | - } |
593 | | - |
594 | | - /** |
595 | | - * <pre>{@code |
596 | | - * Project[[sum(salary) + 1 where false{r}#4, sum(salary) + 2{r}#6, emp_no{f}#7]] |
597 | | - * \_Eval[[null[LONG] AS sum(salary) + 1 where false, $$SUM$sum(salary)_+_2$1{r$}#18 + 2[INTEGER] AS sum(salary) + 2]] |
598 | | - * \_Limit[1000[INTEGER]] |
599 | | - * \_Aggregate[STANDARD,[emp_no{f}#7],[SUM(salary{f}#12,true[BOOLEAN]) AS $$SUM$sum(salary)_+_2$1, emp_no{f}#7]] |
600 | | - * \_EsRelation[test][_meta_field{f}#13, emp_no{f}#7, first_name{f}#8, ge..] |
601 | | - * }</pre> |
602 | | - */ |
603 | | - public void testReplaceStatsFilteredAggWithEvalMixedFilterAndNoFilter() { |
604 | | - var plan = plan(""" |
605 | | - from test |
606 | | - | stats sum(salary) + 1 where false, |
607 | | - sum(salary) + 2 |
608 | | - by emp_no |
609 | | - """); |
610 | | - |
611 | | - var project = as(plan, Project.class); |
612 | | - assertThat(Expressions.names(project.projections()), contains("sum(salary) + 1 where false", "sum(salary) + 2", "emp_no")); |
613 | | - var eval = as(project.child(), Eval.class); |
614 | | - assertThat(eval.fields().size(), is(2)); |
615 | | - |
616 | | - var alias = as(eval.fields().getFirst(), Alias.class); |
617 | | - assertTrue(alias.child().foldable()); |
618 | | - assertThat(alias.child().fold(FoldContext.small()), nullValue()); |
619 | | - assertThat(alias.child().dataType(), is(LONG)); |
620 | | - |
621 | | - alias = as(eval.fields().getLast(), Alias.class); |
622 | | - assertThat(Expressions.name(alias.child()), containsString("sum(salary) + 2")); |
623 | | - |
624 | | - var limit = as(eval.child(), Limit.class); |
625 | | - var aggregate = as(limit.child(), Aggregate.class); |
626 | | - var source = as(aggregate.child(), EsRelation.class); |
627 | | - } |
628 | | - |
629 | | - /** |
630 | | - * <pre>{@code |
631 | | - * Project[[sum(salary) + 1 where false{r}#3, sum(salary) + 3{r}#5, sum(salary) + 2 where null{r}#7, |
632 | | - * sum(salary) + 4 where not true{r}#9]] |
633 | | - * \_Eval[[null[LONG] AS sum(salary) + 1 where false#3, $$SUM$sum(salary)_+_3$1{r$}#22 + 3[INTEGER] AS sum(salary) + 3#5 |
634 | | - * , null[LONG] AS sum(salary) + 2 where null#7, null[LONG] AS sum(salary) + 4 where not true#9]] |
635 | | - * \_Limit[1000[INTEGER],false] |
636 | | - * \_Aggregate[[],[SUM(salary{f}#15,true[BOOLEAN],compensated[KEYWORD]) AS $$SUM$sum(salary)_+_3$1#22]] |
637 | | - * \_EsRelation[test][_meta_field{f}#16, emp_no{f}#10, first_name{f}#11, ..] |
638 | | - * }</pre> |
639 | | - * |
640 | | - */ |
641 | | - public void testReplaceStatsFilteredAggWithEvalFilterFalseAndNull() { |
642 | | - var plan = plan(""" |
643 | | - from test |
644 | | - | stats sum(salary) + 1 where false, |
645 | | - sum(salary) + 3, |
646 | | - sum(salary) + 2 where null, |
647 | | - sum(salary) + 4 where not true |
648 | | - """); |
649 | | - |
650 | | - var project = as(plan, Project.class); |
651 | | - assertThat( |
652 | | - Expressions.names(project.projections()), |
653 | | - contains("sum(salary) + 1 where false", "sum(salary) + 3", "sum(salary) + 2 where null", "sum(salary) + 4 where not true") |
654 | | - ); |
655 | | - var eval = as(project.child(), Eval.class); |
656 | | - assertThat(eval.fields().size(), is(4)); |
657 | | - |
658 | | - var alias = as(eval.fields().getFirst(), Alias.class); |
659 | | - assertTrue(alias.child().foldable()); |
660 | | - assertThat(alias.child().fold(FoldContext.small()), nullValue()); |
661 | | - assertThat(alias.child().dataType(), is(LONG)); |
662 | | - |
663 | | - alias = as(eval.fields().get(0), Alias.class); |
664 | | - assertThat(Expressions.name(alias.child()), containsString("sum(salary) + 1")); |
665 | | - |
666 | | - alias = as(eval.fields().get(1), Alias.class); |
667 | | - assertThat(Expressions.name(alias.child()), containsString("sum(salary) + 3")); |
668 | | - |
669 | | - alias = as(eval.fields().get(2), Alias.class); |
670 | | - assertThat(Expressions.name(alias.child()), containsString("sum(salary) + 2")); |
671 | | - |
672 | | - alias = as(eval.fields().get(3), Alias.class); |
673 | | - assertThat(Expressions.name(alias.child()), containsString("sum(salary) + 4")); |
674 | | - |
675 | | - alias = as(eval.fields().getLast(), Alias.class); |
676 | | - assertTrue(alias.child().foldable()); |
677 | | - assertThat(alias.child().fold(FoldContext.small()), nullValue()); |
678 | | - assertThat(alias.child().dataType(), is(LONG)); |
679 | | - |
680 | | - var limit = as(eval.child(), Limit.class); |
681 | | - var aggregate = as(limit.child(), Aggregate.class); |
682 | | - var source = as(aggregate.child(), EsRelation.class); |
683 | | - } |
684 | | - |
685 | | - /* |
686 | | - * Limit[1000[INTEGER]] |
687 | | - * \_LocalRelation[[count(salary) where false{r}#3],[LongVectorBlock[vector=ConstantLongVector[positions=1, value=0]]]] |
688 | | - */ |
689 | | - public void testReplaceStatsFilteredAggWithEvalNotTrue() { |
690 | | - var plan = plan(""" |
691 | | - from test |
692 | | - | stats count(salary) where not true |
693 | | - """); |
694 | | - |
695 | | - var limit = as(plan, Limit.class); |
696 | | - var source = as(limit.child(), LocalRelation.class); |
697 | | - assertThat(Expressions.names(source.output()), contains("count(salary) where not true")); |
698 | | - Block[] blocks = source.supplier().get(); |
699 | | - assertThat(blocks.length, is(1)); |
700 | | - var block = as(blocks[0], LongVectorBlock.class); |
701 | | - assertThat(block.getPositionCount(), is(1)); |
702 | | - assertThat(block.asVector().getLong(0), is(0L)); |
703 | | - } |
704 | | - |
705 | | - /* |
706 | | - * Limit[1000[INTEGER],false] |
707 | | - * \_Aggregate[[],[COUNT(salary{f}#10,true[BOOLEAN]) AS m1#4]] |
708 | | - * \_EsRelation[test][_meta_field{f}#11, emp_no{f}#5, first_name{f}#6, ge..] |
709 | | - */ |
710 | | - public void testReplaceStatsFilteredAggWithEvalNotFalse() { |
711 | | - var plan = plan(""" |
712 | | - from test |
713 | | - | stats m1 = count(salary) where not false |
714 | | - """); |
715 | | - var limit = as(plan, Limit.class); |
716 | | - var aggregate = as(limit.child(), Aggregate.class); |
717 | | - assertEquals(1, aggregate.aggregates().size()); |
718 | | - assertEquals(1, aggregate.aggregates().get(0).children().size()); |
719 | | - assertTrue(aggregate.aggregates().get(0).children().get(0) instanceof Count); |
720 | | - assertEquals("true", (((Count) aggregate.aggregates().get(0).children().get(0)).filter().toString())); |
721 | | - assertThat(Expressions.names(aggregate.aggregates()), contains("m1")); |
722 | | - var source = as(aggregate.child(), EsRelation.class); |
723 | | - } |
724 | | - |
725 | | - /** |
726 | | - * <pre>{@code |
727 | | - * Limit[1000[INTEGER]] |
728 | | - * \_LocalRelation[[count(salary) where false{r}#3],[LongVectorBlock[vector=ConstantLongVector[positions=1, value=0]]]] |
729 | | - * }</pre> |
730 | | - */ |
731 | | - public void testReplaceStatsFilteredAggWithEvalCount() { |
732 | | - var plan = plan(""" |
733 | | - from test |
734 | | - | stats count(salary) where false |
735 | | - """); |
736 | | - |
737 | | - var limit = as(plan, Limit.class); |
738 | | - var source = as(limit.child(), LocalRelation.class); |
739 | | - assertThat(Expressions.names(source.output()), contains("count(salary) where false")); |
740 | | - Block[] blocks = source.supplier().get(); |
741 | | - assertThat(blocks.length, is(1)); |
742 | | - var block = as(blocks[0], LongVectorBlock.class); |
743 | | - assertThat(block.getPositionCount(), is(1)); |
744 | | - assertThat(block.asVector().getLong(0), is(0L)); |
745 | | - } |
746 | | - |
747 | | - /** |
748 | | - * <pre>{@code |
749 | | - * Project[[count_distinct(salary + 2) + 3 where false{r}#3]] |
750 | | - * \_Eval[[$$COUNTDISTINCT$count_distinct(>$0{r$}#15 + 3[INTEGER] AS count_distinct(salary + 2) + 3 where false]] |
751 | | - * \_Limit[1000[INTEGER]] |
752 | | - * \_LocalRelation[[$$COUNTDISTINCT$count_distinct(>$0{r$}#15],[LongVectorBlock[vector=ConstantLongVector[positions=1, value=0]]]] |
753 | | - * }</pre> |
754 | | - */ |
755 | | - public void testReplaceStatsFilteredAggWithEvalCountDistinctInExpression() { |
756 | | - var plan = plan(""" |
757 | | - from test |
758 | | - | stats count_distinct(salary + 2) + 3 where false |
759 | | - """); |
760 | | - |
761 | | - var project = as(plan, Project.class); |
762 | | - assertThat(Expressions.names(project.projections()), contains("count_distinct(salary + 2) + 3 where false")); |
763 | | - |
764 | | - var eval = as(project.child(), Eval.class); |
765 | | - assertThat(eval.fields().size(), is(1)); |
766 | | - var alias = as(eval.fields().getFirst(), Alias.class); |
767 | | - assertThat(alias.name(), is("count_distinct(salary + 2) + 3 where false")); |
768 | | - var add = as(alias.child(), Add.class); |
769 | | - var literal = as(add.right(), Literal.class); |
770 | | - assertThat(literal.value(), is(3)); |
771 | | - |
772 | | - var limit = as(eval.child(), Limit.class); |
773 | | - var source = as(limit.child(), LocalRelation.class); |
774 | | - |
775 | | - Block[] blocks = source.supplier().get(); |
776 | | - assertThat(blocks.length, is(1)); |
777 | | - var block = as(blocks[0], LongVectorBlock.class); |
778 | | - assertThat(block.getPositionCount(), is(1)); |
779 | | - assertThat(block.asVector().getLong(0), is(0L)); |
780 | | - } |
781 | | - |
782 | | - /** |
783 | | - * <pre>{@code |
784 | | - * Project[[max{r}#91, max_a{r}#94, min{r}#97, min_a{r}#100, emp_no{f}#101]] |
785 | | - * \_Eval[[null[INTEGER] AS max_a, null[INTEGER] AS min_a]] |
786 | | - * \_Limit[1000[INTEGER]] |
787 | | - * \_Aggregate[STANDARD,[emp_no{f}#101],[MAX(salary{f}#106,true[BOOLEAN]) AS max, MIN(salary{f}#106,true[BOOLEAN]) AS min, emp_ |
788 | | - * no{f}#101]] |
789 | | - * \_EsRelation[test][_meta_field{f}#107, emp_no{f}#101, first_name{f}#10..] |
790 | | - * }</pre> |
791 | | - */ |
792 | | - public void testReplaceStatsFilteredAggWithEvalSameAggWithAndWithoutFilter() { |
793 | | - var plan = plan(""" |
794 | | - from test |
795 | | - | stats max = max(salary), max_a = max(salary) where null, |
796 | | - min = min(salary), min_a = min(salary) where to_string(null) == "abc" |
797 | | - by emp_no |
798 | | - """); |
799 | | - |
800 | | - var project = as(plan, Project.class); |
801 | | - assertThat(Expressions.names(project.projections()), contains("max", "max_a", "min", "min_a", "emp_no")); |
802 | | - var eval = as(project.child(), Eval.class); |
803 | | - assertThat(eval.fields().size(), is(2)); |
804 | | - |
805 | | - var alias = as(eval.fields().getFirst(), Alias.class); |
806 | | - assertThat(Expressions.name(alias), containsString("max_a")); |
807 | | - assertTrue(alias.child().foldable()); |
808 | | - assertThat(alias.child().fold(FoldContext.small()), nullValue()); |
809 | | - assertThat(alias.child().dataType(), is(INTEGER)); |
810 | | - |
811 | | - alias = as(eval.fields().getLast(), Alias.class); |
812 | | - assertThat(Expressions.name(alias), containsString("min_a")); |
813 | | - assertTrue(alias.child().foldable()); |
814 | | - assertThat(alias.child().fold(FoldContext.small()), nullValue()); |
815 | | - assertThat(alias.child().dataType(), is(INTEGER)); |
816 | | - |
817 | | - var limit = as(eval.child(), Limit.class); |
818 | | - |
819 | | - var aggregate = as(limit.child(), Aggregate.class); |
820 | | - assertThat(Expressions.names(aggregate.aggregates()), contains("max", "min", "emp_no")); |
821 | | - |
822 | | - var source = as(aggregate.child(), EsRelation.class); |
823 | | - } |
824 | | - |
825 | | - /** |
826 | | - * <pre>{@code |
827 | | - * Limit[1000[INTEGER]] |
828 | | - * \_LocalRelation[[count{r}#7],[LongVectorBlock[vector=ConstantLongVector[positions=1, value=0]]]] |
829 | | - * }</pre> |
830 | | - */ |
831 | | - @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/100634") // i.e. PropagateEvalFoldables applicability to Aggs |
832 | | - public void testReplaceStatsFilteredAggWithEvalFilterUsingEvaledValue() { |
833 | | - var plan = plan(""" |
834 | | - from test |
835 | | - | eval my_length = length(concat(first_name, null)) |
836 | | - | stats count = count(my_length) where my_length > 0 |
837 | | - """); |
838 | | - |
839 | | - var limit = as(plan, Limit.class); |
840 | | - var source = as(limit.child(), LocalRelation.class); |
841 | | - assertThat(Expressions.names(source.output()), contains("count")); |
842 | | - Block[] blocks = source.supplier().get(); |
843 | | - assertThat(blocks.length, is(1)); |
844 | | - var block = as(blocks[0], LongVectorBlock.class); |
845 | | - assertThat(block.getPositionCount(), is(1)); |
846 | | - assertThat(block.asVector().getLong(0), is(0L)); |
847 | | - } |
848 | | - |
849 | | - /** |
850 | | - * |
851 | | - * <pre>{@code |
852 | | - * Project[[c{r}#67, emp_no{f}#68]] |
853 | | - * \_Eval[[0[LONG] AS c]] |
854 | | - * \_Limit[1000[INTEGER]] |
855 | | - * \_Aggregate[STANDARD,[emp_no{f}#68],[emp_no{f}#68]] |
856 | | - * \_EsRelation[test][_meta_field{f}#74, emp_no{f}#68, first_name{f}#69, ..] |
857 | | - * }</pre> |
858 | | - */ |
859 | | - public void testReplaceStatsFilteredAggWithEvalSingleAggWithGroup() { |
860 | | - var plan = plan(""" |
861 | | - from test |
862 | | - | stats c = count(emp_no) where false |
863 | | - by emp_no |
864 | | - """); |
865 | | - |
866 | | - var project = as(plan, Project.class); |
867 | | - assertThat(Expressions.names(project.projections()), contains("c", "emp_no")); |
868 | | - |
869 | | - var eval = as(project.child(), Eval.class); |
870 | | - assertThat(eval.fields().size(), is(1)); |
871 | | - var alias = as(eval.fields().getFirst(), Alias.class); |
872 | | - assertThat(Expressions.name(alias), containsString("c")); |
873 | | - |
874 | | - var limit = as(eval.child(), Limit.class); |
875 | | - |
876 | | - var aggregate = as(limit.child(), Aggregate.class); |
877 | | - assertThat(Expressions.names(aggregate.aggregates()), contains("emp_no")); |
878 | | - |
879 | | - var source = as(aggregate.child(), EsRelation.class); |
880 | | - } |
881 | | - |
882 | 535 | public void testExtractStatsCommonFilter() { |
883 | 536 | var plan = plan(""" |
884 | 537 | from test |
|
0 commit comments