seancorfield / next-jdbc

A modern low-level Clojure wrapper for JDBC-based access to databases.
https://cljdoc.org/d/com.github.seancorfield/next.jdbc/
Eclipse Public License 1.0
767 stars 90 forks source link

Spec for with-transaction is too strict #257

Closed seancorfield closed 1 year ago

seancorfield commented 1 year ago

Describe the bug Macros are spec-checked if an fdef spec exists, even without calling instrument. The spec for with-transaction requires a literal hash map for options so you cannot pass a variable.

To Reproduce

(~/oss/next-jdbc)-(!2007)-> clj -A:test
Clojure 1.11.1
user=> (require '[next.jdbc :as jdbc])
...
nil
user=> (require 'next.jdbc.specs)
nil
user=> (def db-spec {:dbtype "h2:mem" :dbname "with_t"})
#'user/db-spec
;; this is acceptable:
user=> (jdbc/with-transaction [s db-spec {:rollback-only true}] (jdbc/execute! s ["select * from mytable"]))
Execution error (JdbcSQLSyntaxErrorException) at org.h2.message.DbException/getJdbcSQLException (DbException.java:502).
Table "MYTABLE" not found (this database is empty); SQL statement:
select * from mytable [42104-214]
;; this should be acceptable too:
user=> (let [opts {:rollback-only true}] (jdbc/with-transaction [s db-spec opts] (jdbc/execute! s ["select * from mytable"])))
Syntax error macroexpanding next.jdbc/with-transaction at (REPL:1:35).
opts - failed: map? at: [:binding :opts] spec: :next.jdbc.specs/opts-map
user=>

Expected behavior with-transaction should allow arbitrary forms for the options map. The underlying transact function should trap non-hash-map options, if instrumentation is enabled.