diff --git a/lib/active_record_extended/query_methods/with_cte.rb b/lib/active_record_extended/query_methods/with_cte.rb index e46652b..da56117 100644 --- a/lib/active_record_extended/query_methods/with_cte.rb +++ b/lib/active_record_extended/query_methods/with_cte.rb @@ -54,6 +54,8 @@ def pipe_cte_with!(value) # Ensure we follow FIFO pattern. # If the parent has similar CTE alias keys, we want to favor the parent's expressions over its children's. if expression.is_a?(ActiveRecord::Relation) && expression.with_values? + expression.cte = expression.cte.dup if expression.cte + # Add child's materialized keys to the parent @materialized_keys += expression.cte.materialized_keys @not_materialized_keys += expression.cte.not_materialized_keys diff --git a/spec/query_methods/with_cte_spec.rb b/spec/query_methods/with_cte_spec.rb index a584c89..7c5e294 100644 --- a/spec/query_methods/with_cte_spec.rb +++ b/spec/query_methods/with_cte_spec.rb @@ -67,5 +67,20 @@ expect(query).to contain_exactly(user_two) end end + + context "when the relation uses itself as a second CTE" do + it "works without a SystemStackError" do + user_relation = User.all + + # Add first CTE to User Relation + group_relation = Group.all + user_relation_with_cte = user_relation.with('first_cte' => group_relation) + + # User Relation with a CTE adds itself as another CTE + user_relation_with_self_cte = user_relation_with_cte.with('self_cte' => user_relation_with_cte) + + expect(user_relation_with_self_cte).to contain_exactly(user_one,user_two) + end + end end end