Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Add UNION and UNION ALL support #2678
This PR adds support of UNION and UNION ALL:
customer_city_query = from c in Customer, select: c.city from s in Supplier, select: s.city, union: customer_city_query
customer_city_query = Customer |> select([c], c.city) Supplier |> select([s], s.city) |> union_all(customer_query)
Both can be used as keyword or expression versions. Multiple unions are also supported.
I made this because I had to optimize a complex query that had some OR conditions which made the optimizer unable to use indexes. This could be optimized by rewriting it with UNION ALL but Ecto didn't have such an ability. Rewriting the query as plain SQL was impossible because it was constructed of different subqueries spreaded all accross of my app's domain logic.
This is my first contribution here. Hope I got it correctly how Ecto.Query works under the hood, especially the Planner module. If anything is wrong please let me know and I'll update the PR.
Thank you! I really like the approach here. We do however need tests where both queries contain parameters interpolated to make sure we are taking them into account properly. In particular, in the query planner, you need to make sure you process the unions in the same order as you process the union in MySQL / Postgres. So instead of adding your own normalize_unions, you need to hook into the existing union. I also think we can get rid of Ecto.Query.Builder.Union. We can implement everything at runtime, similar to Ecto.Query.exclude. -- *José Valim* www.plataformatec.com.br Skype: jv.ptec Founder and Director of R&D