Skip to content

Commit 7712414

Browse files
committed
Add getconnection/transaction
In `DBInterface.executemany`, it's much more efficient for databases to wrap multiple `execute` invocations in transactions, so we add `transaction` for individual database packages to overload and we need `getconnection` in order to get the `Connection` for a `Statement`.
1 parent 91e208a commit 7712414

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

docs/src/index.md

+2
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ across various database packages.
88
## Functions
99
```@docs
1010
DBInterface.connect
11+
DBInterface.getconnection
1112
DBInterface.prepare
1213
DBInterface.@prepare
1314
DBInterface.execute
15+
DBInterface.transaction
1416
DBInterface.executemany
1517
DBInterface.executemultiple
1618
DBInterface.close!

src/DBInterface.jl

+25-3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,14 @@ close!(conn::Connection)
3636
"Database packages should provide a `DBInterface.Statement` subtype which represents a valid, prepared SQL statement that can be executed repeatedly"
3737
abstract type Statement end
3838

39+
"""
40+
DBInterface.getconnection(::DBInterface.Statement)
41+
42+
For a valid `DBInterface.Statement`, return the `DBInterface.Connection` the statement
43+
is associated with.
44+
"""
45+
function getconnection end
46+
3947
"""
4048
DBInterface.prepare(conn::DBInterface.Connection, sql::AbstractString) => DBInterface.Statement
4149
DBInterface.prepare(f::Function, sql::AbstractString) => DBInterface.Statement
@@ -145,6 +153,18 @@ execute(conn::Connection, sql::AbstractString; kwargs...) = execute(conn, sql, v
145153
execute(f::Base.Callable, conn::Connection, sql::AbstractString; kwargs...) = execute(f, conn, sql, values(kwargs))
146154
execute(f::Base.Callable, stmt::Statement; kwargs...) = execute(f, stmt, values(kwargs))
147155

156+
"""
157+
DBInterface.transaction(f, conn::DBInterface.Connection)
158+
159+
Open a transaction against a database connection `conn`, execute a closure `f`,
160+
then "commit" the transaction after executing the closure function. The default
161+
definition in DBInterface.jl is a no-op in that it just executes the closure
162+
function with no transaction. Used in `DBInterface.executemany` to wrap the
163+
individual execute calls in a transaction since this often leads to much better
164+
performance in database systems.
165+
"""
166+
transaction(f, ::Connection) = f()
167+
148168
struct LazyIndex{T} <: AbstractVector{Any}
149169
x::T
150170
i::Int
@@ -170,9 +190,11 @@ function executemany(stmt::Statement, params)
170190
param = params[1]
171191
len = length(param)
172192
all(x -> length(x) == len, params) || throw(ParameterError("parameters provided to `DBInterface.executemany!` do not all have the same number of parameters"))
173-
for i = 1:len
174-
xargs = LazyIndex(params, i)
175-
execute(stmt, xargs)
193+
transaction(getconnection(stmt)) do
194+
for i = 1:len
195+
xargs = LazyIndex(params, i)
196+
execute(stmt, xargs)
197+
end
176198
end
177199
else
178200
execute(stmt)

0 commit comments

Comments
 (0)