kayak / pypika

PyPika is a python SQL query builder that exposes the full richness of the SQL language using a syntax that reflects the resulting query. PyPika excels at all sorts of SQL queries but is especially useful for data analysis.
http://pypika.readthedocs.io/en/latest/
Apache License 2.0
2.43k stars 292 forks source link

MySQL queries should wrap set operations #773

Closed pandaxtc closed 2 months ago

pandaxtc commented 7 months ago

The MySQLQuery dialect doesn't wrap set operations in parens, but UNION queries that have LIMITs and ORDERs in the subqueries fail without parens. The documentation states:

You cannot have a query block with a trailing ORDER BY or LIMIT without wrapping it in parentheses...

For example, this fails:

SELECT 1 LIMIT 1 UNION SELECT 2 LIMIT 1;

but this does not:

(SELECT 1 LIMIT 1) UNION (SELECT 2 LIMIT 1);
wd60622 commented 7 months ago

Are you trying to recreate that specific example?

I'm seeing that

from pypika.dialects import MSSQLQuery

query = MSSQLQuery.from_("table").select("id").union(MSSQLQuery.from_("another_table").select("id"))
query.get_sql() # or str(query)

does indeed use the parens


(SELECT "id" FROM "table") UNION (SELECT "id" FROM "another_table")
pandaxtc commented 6 months ago

The example you provided uses MSSQLQuery instead of MySQLQuery. Here's an example:

from pypika.dialects import MySQLQuery

query = MySQLQuery.from_("table").select("id").union(MSSQLQuery.from_("another_table").select("id"))
query.get_sql() # or str(query)

results in

SELECT `id` FROM `table` UNION SELECT `id` FROM `another_table`
wd60622 commented 6 months ago

I misread that then. Here in the code, the wrap_set_operation_queries is set to False. https://github.com/kayak/pypika/blob/8841520e906970d76c5ed81c7dd5d154f0d5259d/pypika/dialects.py#L90

Would you want to make a PR to change?

In the meantime, you might be able to set the wrap_set_operation_queries attribute of your query to True. But I'm not sure about that temporary solution

pandaxtc commented 6 months ago

The temporary solution works, thanks. I opened a PR: https://github.com/kayak/pypika/pull/782