diff --git a/doc/special-syntax.md b/doc/special-syntax.md index d5affe6..4e0638c 100644 --- a/doc/special-syntax.md +++ b/doc/special-syntax.md @@ -8,15 +8,19 @@ The first group are used for SQL expressions. The second (last group) are used p ## array -Accepts a single argument, which is expected to evaluate to -a sequence, and produces `ARRAY[?, ?, ..]` for the elements -of that sequence (as SQL parameters): +Accepts a single argument, which is expected to evaluate to a sequence, +with an optional second argument specifying the type of the array, +and produces `ARRAY[?, ?, ..]` for the elements of that sequence (as SQL parameters): ```clojure (require '[honey.sql :as sql]) (sql/format-expr [:array (range 5)]) ;;=> ["ARRAY[?, ?, ?, ?, ?]" 0 1 2 3 4] +(sql/format-expr [:array (range 3) :text]) +;;=> ["ARRAY[?, ?, ?]::TEXT[]" 0 1 2] +(sql/format-expr [:array [] :integer]) +;;=> ["ARRAY[]::INTEGER[]"] ``` > Note: you cannot provide a named parameter as the argument for `:array` because the generated SQL depends on the number of elements in the sequence, so the following throws an exception: diff --git a/src/honey/sql.cljc b/src/honey/sql.cljc index ffc0ecd..bfa405b 100644 --- a/src/honey/sql.cljc +++ b/src/honey/sql.cljc @@ -1437,10 +1437,11 @@ (str/join ", " (map format-single-column spec)) ">")]) :array - (fn [_ [arr]] + (fn [_ [arr type]] ;; allow for (unwrap arr) here? - (let [[sqls params] (format-expr-list arr)] - (into [(str "ARRAY[" (str/join ", " sqls) "]")] params))) + (let [[sqls params] (format-expr-list arr) + type-str (when type (str "::" (sql-kw type) "[]"))] + (into [(str "ARRAY[" (str/join ", " sqls) "]" type-str)] params))) :between (fn [_ [x a b]] (let [[sql-x & params-x] (format-expr x {:nested true}) diff --git a/test/honey/sql_test.cljc b/test/honey/sql_test.cljc index 14b21fb..2ff04d7 100644 --- a/test/honey/sql_test.cljc +++ b/test/honey/sql_test.cljc @@ -278,7 +278,12 @@ :columns [:baz] :values [[[:array :?vals]]]} {:params {:vals [1 2 3 4]}}) - ["INSERT INTO foo (baz) VALUES (ARRAY[?, ?, ?, ?])" 1 2 3 4]))) + ["INSERT INTO foo (baz) VALUES (ARRAY[?, ?, ?, ?])" 1 2 3 4])) + (testing "typed array" + (is (= (format {:select [[[:array [] :integer]]]}) + ["SELECT ARRAY[]::INTEGER[]"])) + (is (= (format {:select [[[:array [1 2] :text]]]}) + ["SELECT ARRAY[?, ?]::TEXT[]" 1 2])))) (deftest union-test ;; UNION and INTERSECT subexpressions should not be parenthesized.