From 8799014635f4b6b71f58c568f1f5ab4ddce15e8d Mon Sep 17 00:00:00 2001 From: Leon Mergen Date: Tue, 31 May 2016 15:10:18 +0200 Subject: [PATCH 1/2] Implement dsl/exists and dsl/array subquery clauses --- src/suricatta/dsl.clj | 17 ++++++++++++++--- test/suricatta/dsl_test.clj | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/suricatta/dsl.clj b/src/suricatta/dsl.clj index 0b588f1..eef102c 100644 --- a/src/suricatta/dsl.clj +++ b/src/suricatta/dsl.clj @@ -40,6 +40,7 @@ org.jooq.impl.DefaultConfiguration org.jooq.impl.DefaultDataType org.jooq.impl.SQLDataType + org.jooq.util.postgres.PostgresDSL org.jooq.util.postgres.PostgresDataType org.jooq.util.mariadb.MariaDBDataType org.jooq.util.mysql.MySQLDataType @@ -283,7 +284,11 @@ params (rest v)] (->> (map -unwrap params) (into-array Object) - (DSL/condition sql))))) + (DSL/condition sql)))) + + suricatta.types.Deferred + (-condition [s] + (-condition @s))) (extend-protocol IVal Object @@ -476,11 +481,17 @@ (into-array org.jooq.Condition) (.where @q)))) +(defn array + "Convert an expression to an array." + [q] + (defer + (PostgresDSL/array @q))) + (defn exists "Create an exists condition." - [select'] + [q] (defer - (DSL/exists select'))) + (DSL/exists @q))) (defn group-by [q & fields] diff --git a/test/suricatta/dsl_test.clj b/test/suricatta/dsl_test.clj index 3b73f6a..4e7a241 100644 --- a/test/suricatta/dsl_test.clj +++ b/test/suricatta/dsl_test.clj @@ -252,6 +252,24 @@ (dsl/from :author))] (is (= (fmt/sql q) "select fullname, (select count(*) from book where (book.authorid = author.id)) \"books\" from author")))) + + (testing "Nested select returned as array" + (let [sq (-> (dsl/select (dsl/field :id)) + (dsl/from :book) + (dsl/where "book.authorid = author.id")) + q (-> (dsl/select :fullname, (dsl/field (dsl/array sq) "books")) + (dsl/from :author))] + (is (= (fmt/sql q) + "select fullname, array(select id from book where (book.authorid = author.id)) \"books\" from author")))) + + (testing "Nested select in where clause using exists" + (let [q (-> (dsl/select :fullname) + (dsl/from :author) + (dsl/where (dsl/exists (-> (dsl/select :id) + (dsl/from :table) + (dsl/where ["table.author_id = author.id"])))))] + (is (= (fmt/sql q) + "select fullname from author where exists (select id from table where (table.author_id = author.id))")))) ) (deftest dsl-insert From c4ae4a086661fdfb84ab748a42c7eed46938a767 Mon Sep 17 00:00:00 2001 From: Leon Mergen Date: Wed, 1 Jun 2016 14:14:38 +0200 Subject: [PATCH 2/2] Moves PostgreSQL DSL extensions to dsl/pgsql --- src/suricatta/dsl.clj | 7 ----- src/suricatta/dsl/pgsql.clj | 60 +++++++++++++++++++++++++++++++++++++ test/suricatta/dsl_test.clj | 3 +- 3 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 src/suricatta/dsl/pgsql.clj diff --git a/src/suricatta/dsl.clj b/src/suricatta/dsl.clj index eef102c..6166f0a 100644 --- a/src/suricatta/dsl.clj +++ b/src/suricatta/dsl.clj @@ -40,7 +40,6 @@ org.jooq.impl.DefaultConfiguration org.jooq.impl.DefaultDataType org.jooq.impl.SQLDataType - org.jooq.util.postgres.PostgresDSL org.jooq.util.postgres.PostgresDataType org.jooq.util.mariadb.MariaDBDataType org.jooq.util.mysql.MySQLDataType @@ -481,12 +480,6 @@ (into-array org.jooq.Condition) (.where @q)))) -(defn array - "Convert an expression to an array." - [q] - (defer - (PostgresDSL/array @q))) - (defn exists "Create an exists condition." [q] diff --git a/src/suricatta/dsl/pgsql.clj b/src/suricatta/dsl/pgsql.clj new file mode 100644 index 0000000..56b95ca --- /dev/null +++ b/src/suricatta/dsl/pgsql.clj @@ -0,0 +1,60 @@ +;; Copyright (c) 2014-2015, Andrey Antukh +;; All rights reserved. +;; +;; Redistribution and use in source and binary forms, with or without +;; modification, are permitted provided that the following conditions are met: +;; +;; * Redistributions of source code must retain the above copyright notice, this +;; list of conditions and the following disclaimer. +;; +;; * Redistributions in binary form must reproduce the above copyright notice, +;; this list of conditions and the following disclaimer in the documentation +;; and/or other materials provided with the distribution. +;; +;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +;; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +;; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +;; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +;; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +(ns suricatta.dsl.pgsql + "PostgreSQL-specific DSL extensions" + (:require [suricatta.proto :as proto] + [suricatta.types :as types :refer [defer]]) + (:import org.jooq.util.postgres.PostgresDSL)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Protocol Implementations +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(extend-protocol proto/ISQLType + (Class/forName "[Ljava.lang.String;") + (-convert [self] + (into [] self))) + +(extend-protocol proto/ISQLType + (Class/forName "[Ljava.lang.Long;") + (-convert [self] + (into [] self))) + +(extend-protocol proto/ISQLType + java.sql.Array + (-convert [self] + (into [] (.getArray self)))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Common DSL functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defn array + "Convert an expression to an array." + [q] + (defer + (PostgresDSL/array @q))) + diff --git a/test/suricatta/dsl_test.clj b/test/suricatta/dsl_test.clj index 4e7a241..485baaa 100644 --- a/test/suricatta/dsl_test.clj +++ b/test/suricatta/dsl_test.clj @@ -2,6 +2,7 @@ (:require [clojure.test :refer :all] [suricatta.core :refer :all] [suricatta.dsl :as dsl] + [suricatta.dsl.pgsql :as pgsql] [suricatta.format :as fmt])) (def dbspec {:subprotocol "h2" @@ -257,7 +258,7 @@ (let [sq (-> (dsl/select (dsl/field :id)) (dsl/from :book) (dsl/where "book.authorid = author.id")) - q (-> (dsl/select :fullname, (dsl/field (dsl/array sq) "books")) + q (-> (dsl/select :fullname, (dsl/field (pgsql/array sq) "books")) (dsl/from :author))] (is (= (fmt/sql q) "select fullname, array(select id from book where (book.authorid = author.id)) \"books\" from author"))))