| 734 | } |
| 735 | |
| 736 | bool optimizePlanForExists(QueryPlan & query_plan) |
| 737 | { |
| 738 | auto * node = query_plan.getRootNode(); |
| 739 | while (true) |
| 740 | { |
| 741 | if (typeid_cast<ExpressionStep *>(node->step.get())) |
| 742 | { |
| 743 | node = node->children[0]; |
| 744 | continue; |
| 745 | } |
| 746 | if (auto * aggregation = typeid_cast<AggregatingStep *>(node->step.get())) |
| 747 | { |
| 748 | const auto & params = aggregation->getParams(); |
| 749 | if (params.keys_size == 0 && !params.empty_result_for_aggregation_by_empty_set) |
| 750 | { |
| 751 | /// Subquery will always produce at least one row |
| 752 | return true; |
| 753 | } |
| 754 | node = node->children[0]; |
| 755 | continue; |
| 756 | } |
| 757 | if (auto * limit_step = typeid_cast<LimitStep *>(node->step.get())) |
| 758 | { |
| 759 | if (limit_step->getOffset() == 0 && limit_step->getLimit() > 0) |
| 760 | { |
| 761 | /// TODO: Support LimitStep in decorrelation process. |
| 762 | /// For now, we just remove it, because it only increases the number of rows in the result. |
| 763 | /// It doesn't affect the result of correlated subquery. |
| 764 | node = node->children[0]; |
| 765 | continue; |
| 766 | } |
| 767 | break; |
| 768 | } |
| 769 | break; |
| 770 | } |
| 771 | |
| 772 | if (node != query_plan.getRootNode()) |
| 773 | { |
| 774 | query_plan = query_plan.extractSubplan(node); |
| 775 | } |
| 776 | return false; |
| 777 | } |
| 778 | |
| 779 | QueryPlanStepPtr projectOnlyUsedColumns( |
| 780 | const SharedHeader & stream_header, |
no test coverage detected