Commits

Anonymous committed 8d76f97

sub-query support for IN functions in clause
cleanup, improved error message in as-clause, as-value-clause functions

Comments (0)

Files changed (2)

src/main/clj/org/bituf/sqlrat/clause.clj

   [\"?\" \"Anthony Pereira\"]
   etc"
   [value]
-  (if *assert-args* (assert (not (clause? value))))
+  (if *assert-args* (try
+                      (assert (not (clause? value)))
+                      (assert (not (nil?    value)))
+                      (catch AssertionError e
+                        (bad-arg!
+                          "Invalid input: nil and clauses are not allowed"))))
   (let [values (as-vector value)
+        _      (if *assert-args* (doseq [each values]
+                                   (try
+                                     (assert (not (nil?  each)))
+                                     (assert (not (coll? each)))
+                                     (assert (not (fn?   each)))
+                                     (catch AssertionError e
+                                       (bad-arg! "Invalid input: nil, collection and function are not allowed as clause elements"
+                                         )))))
         vcount (count values)
         cl-str (apply str
                  (interpose ", "
   [^String kw k v-coll]
   (assert k)
   (assert v-coll)
-  (let [v-vec (as-vector v-coll)
-        _     (if (empty? v-vec)
-                (throw (IllegalArgumentException. "Value collection is empty")))
-        v-cnt (count v-vec)
-        qexpr (apply str (str-name k) kw "("
-                (apply str
-                  (interpose ", " (take v-cnt (repeat \?)))) ")")]
-    (as-clause (into [qexpr] v-vec))))
+  (if (clause? v-coll) (merge-clauses (str-name k) kw
+                         (enclose v-coll)) ; sub-query
+    (let [v-vec (as-vector v-coll)
+          _     (if (empty? v-vec)
+                  (throw (IllegalArgumentException. "Value collection is empty")))
+          v-cnt (count v-vec)
+          qexpr (apply str (str-name k) kw "("
+                  (apply str
+                    (interpose ", " (take v-cnt (repeat \?)))) ")")]
+      (as-clause (into [qexpr] v-vec)))))
 
 
 (defn in?
 
 (defn ?
   "Smart value-parameter function. If you pass a map, a key=value pattern is
-  applied. For other collections a parameterized value clause is generated. 
+  applied. For other collections and single-value a parameterized value clause
+  is generated. 
   Arguments:
     coll  (Collection) of data. If it is a map then equivalent to (? in=? coll)
           else generates a parameterized SQL value clause
      [\"c IN (?, ?, ?)\" 10 20 30] [\"d IS NULL\"])
   See also:
     as-value-clause, map-to-clauses"
-  ([^IPersistentCollection coll]
-    (assert (coll? coll))
-    (if (map? coll) (? in=? coll)
-      (as-value-clause coll)))
+  ([value]
+    (if (map? value) (? in=? value)
+      (as-value-clause value)))
   ([^IFn op2fn ^IPersistentMap m]
-    (assert (fn? op2fn))
-    (assert (map? m))
+    (if *assert-args*
+      (assert (fn? op2fn))
+      (assert (map? m)))
     (map-to-clauses op2fn m)))
 
 

src/test/clj/org/bituf/sqlrat/test/clause.clj

         s>?  [(str "id>"  e) qp]
         s<?  [(str "id<"  e) qp]
         s>=? [(str "id>=" e) qp]
-        s<=? [(str "id<=" e) qp]]
+        s<=? [(str "id<=" e) qp]
+        sin? [(str "id IN " e) qp]]
     (testing "Equals"         (is (= s=?  (=?  k v))))
     (testing "Does not equal" (is (= s<>? (<>? k v))))
     (testing "Does not equal" (is (= s!=? (!=? k v))))
     (testing "Greater than"   (is (= s>?  (>? k v))))
     (testing "Less than"      (is (= s<?  (<? k v))))
     (testing "Greater than or equals" (is (= s>=? (>=? k v))))
-    (testing "Less than or equals"    (is (= s<=? (<=? k v))))))
+    (testing "Less than or equals"    (is (= s<=? (<=? k v))))
+    (testing "In" (is (= sin? (in? k v))))))
 
 
 (deftest test-multi-op