@@ -53,7 +53,6 @@ macro prepare(getDB, sql)
5353 key = gensym ()
5454 return quote
5555 get! (DBInterface. PREPARED_STMTS, $ (QuoteNode (key))) do
56- println (" preparing stmt" )
5756 DBInterface. prepare ($ (esc (getDB)), $ sql)
5857 end
5958 end
6362abstract type Cursor end
6463
6564"""
66- DBInterface.execute!(conn::DBInterface.Connection, sql::AbstractString, args...; kw... ) => DBInterface.Cursor
67- DBInterface.execute!(stmt::DBInterface.Statement, args...; kw... ) => DBInterface.Cursor
65+ DBInterface.execute!(conn::DBInterface.Connection, sql::AbstractString, [params] ) => DBInterface.Cursor
66+ DBInterface.execute!(stmt::DBInterface.Statement, [params] ) => DBInterface.Cursor
6867
6968Database packages should overload `DBInterface.execute!` for a valid, prepared `DBInterface.Statement` subtype (the first method
70- signature is defined in DBInterface.jl using `DBInterface.prepare`), which takes zero or more `args` or `kw` arguments that should
71- be bound against the `stmt` (`args` as positional parameters, `kw` as named parameters, but not mixed) before executing the query
72- against the database. `DBInterface.execute!` should return a valid `DBInterface.Cursor` object, which is any iterator of "rows",
69+ signature is defined in DBInterface.jl using `DBInterface.prepare`), which takes an optional `params` argument, which should be
70+ an indexable collection (`Vector` or `Tuple`) for positional parameters, or a `NamedTuple` for named parameters.
71+ `DBInterface.execute!` should return a valid `DBInterface.Cursor` object, which is any iterator of "rows",
7372which themselves must be property-accessible (i.e. implement `propertynames` and `getproperty` for value access by name),
7473and indexable (i.e. implement `length` and `getindex` for value access by index). These "result" objects do not need
7574to subtype `DBInterface.Cursor` explicitly as long as they satisfy the interface. For DDL/DML SQL statements, which typically
7675do not return results, an iterator is still expected to be returned that just iterates `nothing`, i.e. an "empty" iterator.
7776"""
7877function execute! end
7978
80- execute! (stmt:: Statement , args ... ; kw ... ) = throw (NotImplementedError (" `DBInterface.execute!` not implemented for `$(typeof (stmt)) `" ))
79+ execute! (stmt:: Statement , params = () ) = throw (NotImplementedError (" `DBInterface.execute!` not implemented for `$(typeof (stmt)) `" ))
8180
82- execute! (conn:: Connection , sql:: AbstractString , args... ; kw... ) = execute! (prepare (conn, sql), args... ; kw... )
81+ execute! (conn:: Connection , sql:: AbstractString , params= ()) = execute! (prepare (conn, sql), params)
82+
83+ struct LazyIndex{T} <: AbstractVector{Any}
84+ x:: T
85+ i:: Int
86+ end
87+
88+ Base. IndexStyle (:: Type{<:LazyIndex} ) = Base. IndexLinear ()
89+ Base. IteratorSize (:: Type{<:LazyIndex} ) = Base. HasLength ()
90+ Base. size (x:: LazyIndex ) = (length (x. x),)
91+ Base. getindex (x:: LazyIndex , i:: Int ) = x. x[i][x. i]
8392
8493"""
85- DBInterface.executemany!(conn::DBInterface.Connect, sql::AbstractString, args...; kw... ) => Nothing
86- DBInterface.executemany!(stmt::DBInterface.Statement, args...; kw... ) => Nothing
94+ DBInterface.executemany!(conn::DBInterface.Connect, sql::AbstractString, [params] ) => Nothing
95+ DBInterface.executemany!(stmt::DBInterface.Statement, [params] ) => Nothing
8796
88- Similar to
97+ Similar in usage to `DBInterface.execute!`, but allows passing multiple sets of parameters to be executed in sequence.
98+ `params`, like for `DBInterface.execute!`, should be an indexable collection (`Vector` or `Tuple`) or `NamedTuple`, but instead
99+ of a single scalar value per parameter, an indexable collection should be passed for each parameter. By default, each set of
100+ parameters will be looped over and `DBInterface.execute!` will be called for each. Note that no result sets or cursors are returned
101+ for any execution, so the usage is mainly intended for bulk INSERT statements.
89102"""
90- function executemany! (stmt:: Statement , args... ; kw... )
91- if ! isempty (args)
92- arg = args[1 ]
93- len = length (arg)
94- all (x -> length (x) == len, args) || throw (ParameterError (" positional parameters provided to `DBInterface.executemany!` do not all have the same number of parameters" ))
95- for i = 1 : len
96- xargs = map (x -> x[i], args)
97- execute! (stmt, xargs... )
98- end
99- elseif ! isempty (kw)
100- k = kw[1 ]
101- len = length (k)
102- all (x -> length (x) == len, kw) || throw (ParameterError (" named parameters provided to `DBInterface.executemany!` do not all have the same number of parameters" ))
103+ function executemany! (stmt:: Statement , params= ())
104+ if ! isempty (params)
105+ param = params[1 ]
106+ len = length (param)
107+ all (x -> length (x) == len, params) || throw (ParameterError (" parameters provided to `DBInterface.executemany!` do not all have the same number of parameters" ))
103108 for i = 1 : len
104- xargs = collect (k => v[i] for (k, v) in kw )
105- execute! (stmt; xargs... )
109+ xargs = LazyIndex (params, i )
110+ execute! (stmt, xargs)
106111 end
107112 else
108113 execute! (stmt)
109114 end
110115 return
111116end
112117
113- executemany! (conn:: Connection , sql:: AbstractString , args... ; kw... ) = executemany! (prepare (conn, sql), args... ; kw... )
118+ executemany! (conn:: Connection , sql:: AbstractString , params= ()) = executemany! (prepare (conn, sql), params)
119+
120+ """
121+ DBInterface.close!(stmt::DBInterface.Statement)
122+
123+ Close a prepared statement so further queries cannot be executed.
124+ """
125+ function close! end
114126
115127"""
116128 DBInterface.lastrowid(x::Cursor) => Int
0 commit comments