From f94e343f31fd935498e2f5f8bf32c595df41db34 Mon Sep 17 00:00:00 2001 From: Brandon Adams Date: Tue, 27 Jun 2017 15:01:43 -0500 Subject: [PATCH] Reprioritize WITH wrt UNION and UNION ALL WITH needs to come before clauses that are part of a UNION or UNION ALL.[1][2][3][4] [1] "A CTE must be followed by a single SELECT, INSERT, UPDATE, or DELETE statement that references some or all the CTE columns." https://docs.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql [2] "the WITH clause itself is attached to a primary statement that can also be a SELECT, INSERT, UPDATE, or DELETE" https://www.postgresql.org/docs/9.6/static/queries-with.html [3] https://mariadb.com/kb/en/mariadb/with/ [4] "All common table expressions (ordinary and recursive) are created by prepending a WITH clause in front of a SELECT, INSERT, DELETE, or UPDATE statement." https://sqlite.org/lang_with.html Added a test case demonstrating the expected behavior for each of UNION and UNION ALL. --- src/honeysql/format.cljc | 8 ++++---- test/honeysql/format_test.cljc | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/honeysql/format.cljc b/src/honeysql/format.cljc index c0974b3..e7e323e 100644 --- a/src/honeysql/format.cljc +++ b/src/honeysql/format.cljc @@ -183,10 +183,10 @@ (def default-clause-priorities "Determines the order that clauses will be placed within generated SQL" - {:union 20 - :union-all 25 - :with 30 - :with-recursive 40 + {:with 20 + :with-recursive 30 + :union 40 + :union-all 45 :select 50 :insert-into 60 :update 70 diff --git a/test/honeysql/format_test.cljc b/test/honeysql/format_test.cljc index 3e6faf7..acc9cb3 100644 --- a/test/honeysql/format_test.cljc +++ b/test/honeysql/format_test.cljc @@ -121,3 +121,18 @@ (format {:select [:foo] :from [:bar] :where [:= [:mod :col1 4] [:+ :col2 4]]}))))) + +(deftest union-with-cte + (is (= (format {:union [{:select [:foo] :from [:bar1]} + {:select [:foo] :from [:bar2]}] + :with [[[:bar {:columns [:spam :eggs]}] + {:values [[1 2] [3 4] [5 6]]}]]}) + ["WITH bar (spam, eggs) AS (VALUES (?, ?), (?, ?), (?, ?)) SELECT foo FROM bar1 UNION SELECT foo FROM bar2" 1 2 3 4 5 6]))) + + +(deftest union-all-with-cte + (is (= (format {:union-all [{:select [:foo] :from [:bar1]} + {:select [:foo] :from [:bar2]}] + :with [[[:bar {:columns [:spam :eggs]}] + {:values [[1 2] [3 4] [5 6]]}]]}) + ["WITH bar (spam, eggs) AS (VALUES (?, ?), (?, ?), (?, ?)) SELECT foo FROM bar1 UNION ALL SELECT foo FROM bar2" 1 2 3 4 5 6])))