diff --git a/doc/special-syntax.md b/doc/special-syntax.md index e17fa5f..cf6bf0b 100644 --- a/doc/special-syntax.md +++ b/doc/special-syntax.md @@ -93,7 +93,7 @@ and a time zone name or identifier (can be a string, a symbol, or a keyword): The time zone name or identifier will be inlined (as a string) and therefore cannot be an expression. -## between +## between and not-between Accepts three arguments: an expression, a lower bound, and an upper bound: @@ -101,6 +101,9 @@ an upper bound: ```clojure (sql/format-expr [:between :id 1 100]) ;;=> ["id BETWEEN ? AND ?" 1 100] + +(sql/format-expr [:not-between :id 1 100]) +;;=> ["id NOT BETWEEN ? AND ?" 1 100] ``` ## case diff --git a/src/honey/sql.cljc b/src/honey/sql.cljc index 4d986ab..ab8311d 100644 --- a/src/honey/sql.cljc +++ b/src/honey/sql.cljc @@ -1877,6 +1877,19 @@ (into paramsx) (into params)))) +(defn- between-fn + "For both :between and :not-between" + [k [x a b]] + (let [[sql-x & params-x] (format-expr x {:nested true}) + [sql-a & params-a] (format-expr a {:nested true}) + [sql-b & params-b] (format-expr b {:nested true}) + add-not? (str/starts-with? (name k) "not") + between-type (if add-not? " NOT BETWEEN " " BETWEEN ")] + (-> [(str sql-x between-type sql-a " AND " sql-b)] + (into params-x) + (into params-a) + (into params-b)))) + (defn ignore-respect-nulls [k [x]] (let [[sql & params] (format-expr x)] (into [(str sql " " (sql-kw k))] params))) @@ -1938,15 +1951,8 @@ (binding [*inline* true] (format-expr (if (ident? tz) (name tz) tz)))] (into [(str sql " AT TIME ZONE " tz-sql)] params))) - :between - (fn [_ [x a b]] - (let [[sql-x & params-x] (format-expr x {:nested true}) - [sql-a & params-a] (format-expr a {:nested true}) - [sql-b & params-b] (format-expr b {:nested true})] - (-> [(str sql-x " BETWEEN " sql-a " AND " sql-b)] - (into params-x) - (into params-a) - (into params-b)))) + :between #'between-fn + :not-between #'between-fn :case #'case-clauses :case-expr #'case-clauses :cast