@@ -868,6 +868,27 @@ void FoldConstantScalarSubqueries(ClientContext &context, unique_ptr<LogicalOper
868868 plan->ResolveOperatorTypes ();
869869}
870870
871+ static ColumnBinding AppendProjectionPassthrough (LogicalProjection &proj, const ColumnBinding &binding,
872+ const LogicalType &type, const string &alias) {
873+ auto passthrough = make_uniq<BoundColumnRefExpression>(type, binding);
874+ passthrough->alias = alias;
875+ proj.expressions .push_back (std::move (passthrough));
876+ proj.ResolveOperatorTypes ();
877+ auto bindings = proj.GetColumnBindings ();
878+ if (bindings.empty ()) {
879+ throw InternalException (" OpenIVM: projection produced no bindings after appending hidden passthrough" );
880+ }
881+ return bindings.back ();
882+ }
883+
884+ static void PropagateHiddenBindingThroughProjectionPath (vector<LogicalProjection *> &projection_path,
885+ ColumnBinding binding, LogicalType type, const string &alias) {
886+ for (auto it = projection_path.rbegin (); it != projection_path.rend (); ++it) {
887+ binding = AppendProjectionPassthrough (**it, binding, type, alias);
888+ type = (*it)->types .back ();
889+ }
890+ }
891+
871892// / Inject a hidden COUNT(*) (alias `openivm_count_star`) into AGGREGATE_GROUP
872893// / aggregates that don't already have a reliable total-row-count aggregate.
873894// /
@@ -886,24 +907,37 @@ static void InjectGroupCountStar(unique_ptr<LogicalOperator> &plan) {
886907 // Only inject into the aggregate on the top-level output path. ORDER BY/LIMIT/TOP_N
887908 // preserve the projection schema; inner aggregates under joins or set operations
888909 // are handled by other refresh strategies.
910+ vector<LogicalProjection *> projection_path;
889911 LogicalOperator *node = plan.get ();
890- while (node && node->children .size () == 1 &&
891- (node->type == LogicalOperatorType::LOGICAL_ORDER_BY || node->type == LogicalOperatorType::LOGICAL_LIMIT ||
892- node->type == LogicalOperatorType::LOGICAL_TOP_N )) {
893- node = node->children [0 ].get ();
894- }
895- if (!node || node->type != LogicalOperatorType::LOGICAL_PROJECTION || node->children .empty ()) {
896- return ;
897- }
898- auto &projection = node->Cast <LogicalProjection>();
899- auto *agg_search = node->children [0 ].get ();
900- if (agg_search->type == LogicalOperatorType::LOGICAL_FILTER ) {
901- if (agg_search->children .empty ()) {
902- return ;
912+ LogicalOperator *agg_search = nullptr ;
913+ while (node) {
914+ switch (node->type ) {
915+ case LogicalOperatorType::LOGICAL_ORDER_BY :
916+ case LogicalOperatorType::LOGICAL_LIMIT :
917+ case LogicalOperatorType::LOGICAL_TOP_N :
918+ node = node->children .size () == 1 ? node->children [0 ].get () : nullptr ;
919+ continue ;
920+ case LogicalOperatorType::LOGICAL_PROJECTION :
921+ projection_path.push_back (&node->Cast <LogicalProjection>());
922+ node = node->children .size () == 1 ? node->children [0 ].get () : nullptr ;
923+ continue ;
924+ case LogicalOperatorType::LOGICAL_FILTER :
925+ if (node->children .size () == 1 &&
926+ node->children [0 ]->type == LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY ) {
927+ agg_search = node->children [0 ].get ();
928+ }
929+ node = nullptr ;
930+ continue ;
931+ case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY :
932+ agg_search = node;
933+ node = nullptr ;
934+ continue ;
935+ default :
936+ node = nullptr ;
937+ continue ;
903938 }
904- agg_search = agg_search->children [0 ].get ();
905939 }
906- if (agg_search-> type != LogicalOperatorType:: LOGICAL_AGGREGATE_AND_GROUP_BY ) {
940+ if (! agg_search || projection_path. empty () ) {
907941 return ;
908942 }
909943 auto &agg = agg_search->Cast <LogicalAggregate>();
@@ -954,10 +988,7 @@ static void InjectGroupCountStar(unique_ptr<LogicalOperator> &plan) {
954988 agg.ResolveOperatorTypes ();
955989
956990 ColumnBinding count_binding (agg.aggregate_index , new_agg_idx);
957- auto count_pt = make_uniq<BoundColumnRefExpression>(count_type, count_binding);
958- count_pt->alias = openivm::COUNT_STAR_COL ;
959- projection.expressions .push_back (std::move (count_pt));
960- projection.ResolveOperatorTypes ();
991+ PropagateHiddenBindingThroughProjectionPath (projection_path, count_binding, count_type, openivm::COUNT_STAR_COL );
961992 plan->ResolveOperatorTypes ();
962993
963994 OPENIVM_DEBUG_PRINT (" [PlanRewrite] Injected openivm_count_star for AGGREGATE_GROUP\n " );
@@ -1028,27 +1059,6 @@ void PropagateHiddenAggregateColumns(unique_ptr<LogicalOperator> &plan) {
10281059 }
10291060}
10301061
1031- static ColumnBinding AppendProjectionPassthrough (LogicalProjection &proj, const ColumnBinding &binding,
1032- const LogicalType &type, const string &alias) {
1033- auto passthrough = make_uniq<BoundColumnRefExpression>(type, binding);
1034- passthrough->alias = alias;
1035- proj.expressions .push_back (std::move (passthrough));
1036- proj.ResolveOperatorTypes ();
1037- auto bindings = proj.GetColumnBindings ();
1038- if (bindings.empty ()) {
1039- throw InternalException (" OpenIVM: projection produced no bindings after appending hidden passthrough" );
1040- }
1041- return bindings.back ();
1042- }
1043-
1044- static void PropagateHiddenBindingThroughProjectionPath (vector<LogicalProjection *> &projection_path,
1045- ColumnBinding binding, LogicalType type, const string &alias) {
1046- for (auto it = projection_path.rbegin (); it != projection_path.rend (); ++it) {
1047- binding = AppendProjectionPassthrough (**it, binding, type, alias);
1048- type = (*it)->types .back ();
1049- }
1050- }
1051-
10521062struct OuterJoinBindings {
10531063 bool found = false ;
10541064 bool is_full_outer = false ;
0 commit comments