std::vector<std::string> titles={"Hare Brush", "Hare Tonic"}; std::pair<std::vector<double>, std::vector<x::sql::bitflag>> prices={ std::vector<double>({0.99, 0}), std::vector<x::sql::bitflag>({0, 1}) }; std::vector<x::sql::bitflag> status; status.resize(2); auto stmt=conn->prepare("insert into videos(titles, prices) values(?, ?)"); try { stmt->execute_vector(status, titles, prices); } catch (...) { // ... } if (!(status[0] & 1) || !(status[1] & 1)) // ...
execute_vector
()
executes the prepared statement with multiple sets of parameters.
This is usually used to bulk-insert rows into a table.
The parameter values are given as vectors. Each vector specifies the
value for the corresponding parameter in each row. It's a column vector.
All vectors, including the first parameter, must be of the same size.
The first parameter is a status vector, of
x::sql::bitflag
.
When execute_vector
() returns,
each x::sql::bitflag
reports what happened
to that row. The lowest bit indicates whether the row was processed,
with the entire value of the bitflag giving more detail.
The possible numerical values are:
Unspecified error. The SQL statement probably had an error in it.
This row was processed.
This row was not processed as a result of another error, some database drivers stop when an error occured processing one row, and will not process the remaining rows.
This row processed, with modifications (usually a truncated string value, with some database drivers, other database drivers truncate silently).
The numerical values are subject to change. An error is usually indicated by a thrown exception, but the status vector gets initialized in all cases.
The remaining parameters are any combination of:
std::vector
Specifies a non-NULL
value of this parameter in
each row.
std::pair
of two std::vectors
Specifies a non-NULL
value of this parameter in
each row from the first vector when the corresponding value in the
second vector is zero; or a NULL
value
for this row if the second vector's value for this row is non-zero.
std::list
of std::vector
s
This is equivalent to specifying each
std::vector
directly as a parameter to
execute_vector
().
std::list
of std::pair
of two std::vectors
This is equivalent to specifying each
std::pair
directly as a parameter to
execute_vector
().
When a std::pair
of vectors gets specified,
the second vector in the pair is always a vector of
x::sql::bitflag
s.
A non-zero value specifies a NULL
value for the corresponding row's value of its column parameter. A zero
takes the value for that row from the corresponding value in the first
vector. Specifying just a vector, instead of a
std::pair
of vectors, has the effect of
specifying non-NULL
values for all rows of that column.
The underlying ODBC
API is a C
API.
A vector of C++ std::string
s must be copied
into a single buffer which uses the same fixed size for each string
value. execute_vector
() automatically
takes the longest string in the vector, and allocates the appropriate
buffer.
But this means that if one of the strings in a 1000-element string vector is 100 characters long, this creates a char[100*1000] buffer, even if all other strings are only one character long.
x::sql::statement stmt=conn->prepare("INSERT INTO books(name, price) VALUES(?, ?)"); x::sql::bitflag result=stmt->execute("Around the world in 80 days", 9.99);
Technically, a non-vector execute is equivalent to a vector execute with
a one-row vector, with execute
() returning
the sole row's status. Since an error executing an SQL statement
usually results in a thrown exception, the expected return value
should always indicate a success.
x::sql::bitflag result; x::sql::statement stmt=conn->execute(result, "INSERT INTO books(name, price) VALUES(?, ?)", "Around the world in 80 days", 9.99);
A connection handle's execute
() optionally
takes an
x::sql::bitflag
lvalue parameter, before the SQL statement.
This sets the lvalue to the return value from the
real execute
(), with the same caveats.