The rules for determining which connection to use are as follows. These are tried in order until one returns non-nil:
The connectable specified in the function arguments.
The toucan2.connection/*current-connectable*, if bound. This is bound automatically when
using with-connection or with-transaction
The toucan2.model/default-connectable for the model resolved from the modelable in the function arguments;
The :default implementation of toucan2.connection/do-with-connection
You can define a 'named' connectable such as ::db by adding an implementation
of toucan2.connection/do-with-connection, or use things like JDBC URL connection strings or [[clojure.java.jdbc]]
connection properties maps directly.
IMPORTANT CAVEAT! Positional connectables will be used in preference to *current-connectable*, even when it was
bound by with-transaction -- this means your query will run OUTSIDE of the current transaction! Sometimes, this is
what you want, because maybe a certain query is meant to run against a different database! Usually, however, it is
not! So in that case you can either do something like
(t2/query (or conn/*current-connectable* ::my-db) ...)
to use the current connection if it exists, or define your named connectable method like
(m/defmethod conn/do-with-connection ::my-db
[_connectable f]
(conn/do-with-connection
(if (and conn/*current-connectable*
(not= conn/*current-connectable* ::my-db))
conn/*current-connectable*
"jdbc:postgresql://...")
f))
This, however, is super annoying! So I might reconsider this behavior in the future.
For reducible queries, the connection is not resolved until the query is executed, so you may create a reducible query
with no default connection available and execute it later with one bound. (This also means
that toucan2.execute/reducible-query does not capture dynamic bindings such
as toucan2.connection/*current-connectable* -- you probably wouldn't want it to, anyway, since we have no
guarantees and open connection will be around when we go to use the reducible query later.
The default JDBC implementations for methods here live in [[toucan2.jdbc.connection]].
#### Connection Resolution
The rules for determining which connection to use are as follows. These are tried in order until one returns
non-nil:
1. The connectable specified in the function arguments.
2. The [[toucan2.connection/*current-connectable*]], if bound. This is bound automatically when
using [[with-connection]] or [[with-transaction]]
3. The [[toucan2.model/default-connectable]] for the model resolved from the `modelable` in the function arguments;
4. The `:default` implementation of [[toucan2.connection/do-with-connection]]
You can define a 'named' connectable such as `::db` by adding an implementation
of [[toucan2.connection/do-with-connection]], or use things like JDBC URL connection strings or [[clojure.java.jdbc]]
connection properties maps directly.
IMPORTANT CAVEAT! Positional connectables will be used in preference to [[*current-connectable*]], even when it was
bound by [[with-transaction]] -- this means your query will run OUTSIDE of the current transaction! Sometimes, this is
what you want, because maybe a certain query is meant to run against a different database! Usually, however, it is
not! So in that case you can either do something like
```clj
(t2/query (or conn/*current-connectable* ::my-db) ...)
```
to use the current connection if it exists, or define your named connectable method like
```clj
(m/defmethod conn/do-with-connection ::my-db
[_connectable f]
(conn/do-with-connection
(if (and conn/*current-connectable*
(not= conn/*current-connectable* ::my-db))
conn/*current-connectable*
"jdbc:postgresql://...")
f))
```
This, however, is super annoying! So I might reconsider this behavior in the future.
For reducible queries, the connection is not resolved until the query is executed, so you may create a reducible query
with no default connection available and execute it later with one bound. (This also means
that [[toucan2.execute/reducible-query]] does not capture dynamic bindings such
as [[toucan2.connection/*current-connectable*]] -- you probably wouldn't want it to, anyway, since we have no
guarantees and open connection will be around when we go to use the reducible query later.
The default JDBC implementations for methods here live in [[toucan2.jdbc.connection]].The current connectable or connection. If you get a connection with with-connection or with-transaction, it
will be bound here. You can also bind this yourself to a connectable or connection, and Toucan methods called without
an explicit will connectable will use it rather than the :default connection.
The current connectable or connection. If you get a connection with [[with-connection]] or [[with-transaction]], it will be bound here. You can also bind this yourself to a connectable or connection, and Toucan methods called without an explicit will connectable will use it rather than the `:default` connection.
(connection-string-protocol connection-string)Extract the protocol part of a connection-string.
(connection-string-protocol "jdbc:postgresql:...")
=>
"jdbc"
Extract the protocol part of a `connection-string`. ```clj (connection-string-protocol "jdbc:postgresql:...") => "jdbc" ```
(do-with-connection connectable₁ f)Take a connectable, get a connection of some sort from it, and execute (f connection) with an open connection. A
normal implementation might look something like:
(m/defmethod t2.conn/do-with-connection ::my-connectable
[_connectable f]
(with-open [conn (get-connection)]
(f conn)))
Another common use case is to define a 'named' connectable that acts as an alias for another more complicated connectable, such as a JDBC connection string URL. You can do that like this:
(m/defmethod t2.conn/do-with-connection ::a-connectable
[_connectable f]
(t2.conn/do-with-connection
"jdbc:postgresql://localhost:5432/toucan2?user=cam&password=cam"
f))
do-with-connection is defined in toucan2.connection (toucan2/connection.clj:70).
It caches methods using a methodical.impl.cache.watching.WatchingCache.
It uses the method combination methodical.impl.combo.threaded.ThreadingMethodCombination
with the threading strategy :thread-last.
It uses the dispatcher methodical.impl.dispatcher.multi_default.MultiDefaultDispatcher
with hierarchy #'clojure.core/global-hierarchy
and prefs {javax.sql.DataSource #{clojure.lang.IPersistentMap}}.
The default value is :toucan2.connection/default.
It uses the method table methodical.impl.method_table.standard.StandardMethodTable.
These primary methods are known:
:toucan2.connection/default, defined in toucan2.connection (toucan2/connection.clj:174)
:default, defined in toucan2.connection (toucan2/connection.clj:184)
nil, defined in toucan2.connection (toucan2/connection.clj:194)
It has the following documentation:
nil means use the current connection.
The difference between nil and using *current-connectable* directly is that this waits until it gets resolved
by do-with-connection to get the value for *current-connectable*. For a reducible query this means you'll get
the value at the time you reduce the query rather than at the time you build the reducible query.
java.lang.String, defined in toucan2.connection (toucan2/connection.clj:229)
It has the following documentation:
Implementation for Strings. Hands off to do-with-connection-string.
java.sql.Connection, defined in [[toucan2.jdbc.connection]] (toucan2/jdbc/connection.clj:11)
javax.sql.DataSource, defined in [[toucan2.jdbc.connection]] (toucan2/jdbc/connection.clj:15)
clojure.lang.IPersistentMap, defined in [[toucan2.jdbc.connection]] (toucan2/jdbc/connection.clj:20)
It has the following documentation:
Implementation for map connectables. Treats them as a clojure.java.jdbc-style connection spec map, converting them to
a java.sql.DataSource with [[next.jdbc/get-datasource]].
These aux methods are known:
:around methods:
:toucan2.connection/default, defined in toucan2.connection (toucan2/connection.clj:106)
It has the following documentation:
Do some debug logging/context capture. Bind *current-connectable* to the connection f is called with inside of
f.
Take a *connectable*, get a connection of some sort from it, and execute `(f connection)` with an open connection. A
normal implementation might look something like:
```clj
(m/defmethod t2.conn/do-with-connection ::my-connectable
[_connectable f]
(with-open [conn (get-connection)]
(f conn)))
```
Another common use case is to define a 'named' connectable that acts as an alias for another more complicated
connectable, such as a JDBC connection string URL. You can do that like this:
```clj
(m/defmethod t2.conn/do-with-connection ::a-connectable
[_connectable f]
(t2.conn/do-with-connection
"jdbc:postgresql://localhost:5432/toucan2?user=cam&password=cam"
f))
```
do-with-connection is defined in [[toucan2.connection]] (toucan2/connection.clj:70).
It caches methods using a `methodical.impl.cache.watching.WatchingCache`.
It uses the method combination `methodical.impl.combo.threaded.ThreadingMethodCombination`
with the threading strategy `:thread-last`.
It uses the dispatcher `methodical.impl.dispatcher.multi_default.MultiDefaultDispatcher`
with hierarchy `#'clojure.core/global-hierarchy`
and prefs `{javax.sql.DataSource #{clojure.lang.IPersistentMap}}`.
The default value is `:toucan2.connection/default`.
It uses the method table `methodical.impl.method_table.standard.StandardMethodTable`.
These primary methods are known:
* `:toucan2.connection/default`, defined in [[toucan2.connection]] (toucan2/connection.clj:174)
* `:default`, defined in [[toucan2.connection]] (toucan2/connection.clj:184)
* `nil`, defined in [[toucan2.connection]] (toucan2/connection.clj:194)
It has the following documentation:
`nil` means use the current connection.
The difference between `nil` and using [[*current-connectable*]] directly is that this waits until it gets resolved
by [[do-with-connection]] to get the value for [[*current-connectable*]]. For a reducible query this means you'll get
the value at the time you reduce the query rather than at the time you build the reducible query.
* `java.lang.String`, defined in [[toucan2.connection]] (toucan2/connection.clj:229)
It has the following documentation:
Implementation for Strings. Hands off to [[do-with-connection-string]].
* `java.sql.Connection`, defined in [[toucan2.jdbc.connection]] (toucan2/jdbc/connection.clj:11)
* `javax.sql.DataSource`, defined in [[toucan2.jdbc.connection]] (toucan2/jdbc/connection.clj:15)
* `clojure.lang.IPersistentMap`, defined in [[toucan2.jdbc.connection]] (toucan2/jdbc/connection.clj:20)
It has the following documentation:
Implementation for map connectables. Treats them as a `clojure.java.jdbc`-style connection spec map, converting them to
a `java.sql.DataSource` with [[next.jdbc/get-datasource]].
These aux methods are known:
`:around` methods:
* `:toucan2.connection/default`, defined in [[toucan2.connection]] (toucan2/connection.clj:106)
It has the following documentation:
Do some debug logging/context capture. Bind [[*current-connectable*]] to the connection `f` is called with inside of
`f`.(do-with-connection-string connection-string f)Implementation of do-with-connection for strings. Dispatches on the connection-string-protocol of the string,
e.g. "jdbc" for "jdbc:postgresql://localhost:3000/toucan".
do-with-connection-string is defined in toucan2.connection (toucan2/connection.clj:220).
It caches methods using a methodical.impl.cache.watching.WatchingCache.
It uses the method combination methodical.impl.combo.threaded.ThreadingMethodCombination
with the threading strategy :thread-last.
It uses the dispatcher methodical.impl.dispatcher.multi_default.MultiDefaultDispatcher
with hierarchy #'clojure.core/global-hierarchy
and prefs {}.
The default value is :default.
It uses the method table methodical.impl.method_table.standard.StandardMethodTable.
These primary methods are known:
"jdbc", defined in [[toucan2.jdbc.connection]] (toucan2/jdbc/connection.clj:29)
It has the following documentation:
Implementation of do-with-connection-string (and thus do-with-connection) for all strings starting with jdbc:.
Calls java.sql.DriverManager/getConnection on the connection string.
Implementation of [[do-with-connection]] for strings. Dispatches on the [[connection-string-protocol]] of the string,
e.g. `"jdbc"` for `"jdbc:postgresql://localhost:3000/toucan"`.
do-with-connection-string is defined in [[toucan2.connection]] (toucan2/connection.clj:220).
It caches methods using a `methodical.impl.cache.watching.WatchingCache`.
It uses the method combination `methodical.impl.combo.threaded.ThreadingMethodCombination`
with the threading strategy `:thread-last`.
It uses the dispatcher `methodical.impl.dispatcher.multi_default.MultiDefaultDispatcher`
with hierarchy `#'clojure.core/global-hierarchy`
and prefs `{}`.
The default value is `:default`.
It uses the method table `methodical.impl.method_table.standard.StandardMethodTable`.
These primary methods are known:
* `"jdbc"`, defined in [[toucan2.jdbc.connection]] (toucan2/jdbc/connection.clj:29)
It has the following documentation:
Implementation of `do-with-connection-string` (and thus [[do-with-connection]]) for all strings starting with `jdbc:`.
Calls `java.sql.DriverManager/getConnection` on the connection string.(do-with-transaction connection₁ options f)options are options for determining what type of transaction we'll get. See dox for with-transaction for more
information.
do-with-transaction is defined in toucan2.connection (toucan2/connection.clj:236).
It caches methods using a methodical.impl.cache.watching.WatchingCache.
It uses the method combination methodical.impl.combo.threaded.ThreadingMethodCombination
with the threading strategy :thread-last.
It uses the dispatcher methodical.impl.dispatcher.multi_default.MultiDefaultDispatcher
with hierarchy #'clojure.core/global-hierarchy
and prefs {}.
The default value is :toucan2.connection/default.
It uses the method table methodical.impl.method_table.standard.StandardMethodTable.
These primary methods are known:
java.sql.Connection, defined in [[toucan2.jdbc.connection]] (toucan2/jdbc/connection.clj:36)These aux methods are known:
:around methods:
:toucan2.connection/default, defined in toucan2.connection (toucan2/connection.clj:245)
It has the following documentation:
Bind *current-connectable* to the connection f is called with inside of f.
`options` are options for determining what type of transaction we'll get. See dox for [[with-transaction]] for more
information.
do-with-transaction is defined in [[toucan2.connection]] (toucan2/connection.clj:236).
It caches methods using a `methodical.impl.cache.watching.WatchingCache`.
It uses the method combination `methodical.impl.combo.threaded.ThreadingMethodCombination`
with the threading strategy `:thread-last`.
It uses the dispatcher `methodical.impl.dispatcher.multi_default.MultiDefaultDispatcher`
with hierarchy `#'clojure.core/global-hierarchy`
and prefs `{}`.
The default value is `:toucan2.connection/default`.
It uses the method table `methodical.impl.method_table.standard.StandardMethodTable`.
These primary methods are known:
* `java.sql.Connection`, defined in [[toucan2.jdbc.connection]] (toucan2/jdbc/connection.clj:36)
These aux methods are known:
`:around` methods:
* `:toucan2.connection/default`, defined in [[toucan2.connection]] (toucan2/connection.clj:245)
It has the following documentation:
Bind [[*current-connectable*]] to the connection `f` is called with inside of `f`.(with-connection [connection-binding] & body)(with-connection [connection-binding connectable] & body)Execute body with an open connection. There are three ways to use this.
With no args in the bindings vector, with-connection will use the current connection -- *current-connectable*
if one is bound, or the default connectable if not. See docstring for toucan2.connection for more information.
(t2/with-connection []
...)
With one arg, with-connection still uses the current connection, but binds it to something (conn in the example
below):
(t2/with-connection [conn]
...)
If you're using the default JDBC backend, conn will be an instance of java.sql.Connection. Since Toucan 2 is also
written to work with other backend besides JDBC, conn does not include java.sql.Connection :tag metadata! If
you're doing Java interop with conn, make sure to tag it yourself:
(t2/with-connection [^java.sql.Connection conn]
(let [metadata (.getMetaData conn)]
...))
With a connection binding and a connectable:
(t2/with-connection [conn ::my-connectable]
...)
This example gets a connection by calling do-with-connection with ::my-connectable, ignoring the current
connection.
Execute `body` with an open connection. There are three ways to use this.
With no args in the bindings vector, `with-connection` will use the *current connection* -- [[*current-connectable*]]
if one is bound, or the *default connectable* if not. See docstring for [[toucan2.connection]] for more information.
```clj
(t2/with-connection []
...)
```
With one arg, `with-connection` still uses the *current connection*, but binds it to something (`conn` in the example
below):
```clj
(t2/with-connection [conn]
...)
```
If you're using the default JDBC backend, `conn` will be an instance of `java.sql.Connection`. Since Toucan 2 is also
written to work with other backend besides JDBC, `conn` does *not* include `java.sql.Connection` `:tag` metadata! If
you're doing Java interop with `conn`, make sure to tag it yourself:
```clj
(t2/with-connection [^java.sql.Connection conn]
(let [metadata (.getMetaData conn)]
...))
```
With a connection binding *and* a connectable:
```clj
(t2/with-connection [conn ::my-connectable]
...)
```
This example gets a connection by calling [[do-with-connection]] with `::my-connectable`, ignoring the *current
connection*.(with-transaction [conn-binding connectable options?] & body)Gets a connection with with-connection, and executes body within that transaction.
An options map, if specified, determine what sort of transaction we're asking for (stuff like the read isolation
level and what not). One key, :nested-transaction-rule, is handled directly in Toucan 2; other options are passed
directly to the underlying implementation, such as [[next.jdbc.transaction]].
:nested-transaction-rule must be one of #{:allow :ignore :prohibit}, a set of possibilities borrowed from
next.jdbc. For non-JDBC implementations, you should treat :allow as the default behavior if unspecified.
Gets a connection with [[with-connection]], and executes `body` within that transaction.
An `options` map, if specified, determine what sort of transaction we're asking for (stuff like the read isolation
level and what not). One key, `:nested-transaction-rule`, is handled directly in Toucan 2; other options are passed
directly to the underlying implementation, such as [[next.jdbc.transaction]].
`:nested-transaction-rule` must be one of `#{:allow :ignore :prohibit}`, a set of possibilities borrowed from
`next.jdbc`. For non-JDBC implementations, you should treat `:allow` as the default behavior if unspecified.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |