Commit 400ff18a authored by JINMEI Tatuya's avatar JINMEI Tatuya

[1891] added bindXXX methods to StatementProcessor as sqlite_bind_xxx wrapper.

As suggested in review.

This will make the caller code simpler.  It's also safer in that the caller
doesn't have to manipulate the statement separetely (in the previous way
StatementProcessor and the caller could use different statements).

Also made naming more consistent: in the very initial version the class was
called "Executer" and then renamed to Processor.  Some variables of this class
were still named "exec", etc, but it's more consistent if they are named
like "proc".
parent e7c91fe7
......@@ -219,6 +219,10 @@ private:
// statement, which is completed with a single "step" (normally within a
// single call to an SQLite3Database method). In particular, it cannot be
// used for "SELECT" variants, which generally expect multiple matching rows.
//
// The bindXXX methods are straightforward wrappers for the corresponding
// sqlite3_bind_xxx functions that make bindings with the given parameters
// on the statement maintained in this class.
class StatementProcessor {
public:
// desc will be used on failure in the what() message of the resulting
......@@ -235,6 +239,33 @@ public:
sqlite3_reset(stmt_);
}
void bindInt(int index, int val) {
if (sqlite3_bind_int(stmt_, index, val) != SQLITE_OK) {
isc_throw(DataSourceError,
"failed to bind SQLite3 parameter: " <<
sqlite3_errmsg(dbparameters_.db_));
}
}
void bindInt64(int index, sqlite3_int64 val) {
if (sqlite3_bind_int64(stmt_, index, val) != SQLITE_OK) {
isc_throw(DataSourceError,
"failed to bind SQLite3 parameter: " <<
sqlite3_errmsg(dbparameters_.db_));
}
}
// For simplicity, we assume val is a NULL-terminated string, and the
// entire non NUL characters are to be bound. The destructor parameter
// is normally either SQLITE_TRANSIENT or SQLITE_STATIC.
void bindText(int index, const char* val, void(*destructor)(void*)) {
if (sqlite3_bind_text(stmt_, index, val, -1, destructor)
!= SQLITE_OK) {
isc_throw(DataSourceError, "failed to bind SQLite3 parameter: " <<
sqlite3_errmsg(dbparameters_.db_));
}
}
void exec() {
if (sqlite3_step(stmt_) != SQLITE_DONE) {
sqlite3_reset(stmt_);
......@@ -1040,18 +1071,11 @@ SQLite3Accessor::startUpdateZone(const string& zone_name, const bool replace) {
for (size_t i = 0;
i < sizeof(delzone_stmts) / sizeof(delzone_stmts[0]);
++i) {
StatementProcessor delzone_exec(*dbparameters_,
StatementProcessor delzone_proc(*dbparameters_,
delzone_stmts[i].first,
delzone_stmts[i].second);
sqlite3_stmt* stmt =
dbparameters_->getStatement(delzone_stmts[i].first);
sqlite3_clear_bindings(stmt);
if (sqlite3_bind_int(stmt, 1, zone_info.second) != SQLITE_OK) {
isc_throw(DataSourceError,
"failed to bind SQLite3 parameter: " <<
sqlite3_errmsg(dbparameters_->db_));
}
delzone_exec.exec();
delzone_proc.bindInt(1, zone_info.second);
delzone_proc.exec();
}
} catch (const DataSourceError&) {
// Once we start a transaction, if something unexpected happens
......@@ -1120,29 +1144,19 @@ void
doUpdate(SQLite3Parameters& dbparams, StatementID stmt_id,
COLUMNS_TYPE update_params, const char* exec_desc)
{
sqlite3_stmt* const stmt = dbparams.getStatement(stmt_id);
StatementProcessor executer(dbparams, stmt_id, exec_desc);
StatementProcessor proc(dbparams, stmt_id, exec_desc);
int param_id = 0;
if (sqlite3_bind_int(stmt, ++param_id, dbparams.updated_zone_id)
!= SQLITE_OK) {
isc_throw(DataSourceError, "failed to bind SQLite3 parameter: " <<
sqlite3_errmsg(dbparams.db_));
}
proc.bindInt(++param_id, dbparams.updated_zone_id);
const size_t column_count =
sizeof(update_params) / sizeof(update_params[0]);
for (int i = 0; i < column_count; ++i) {
// The old sqlite3 data source API assumes NULL for an empty column.
// We need to provide compatibility at least for now.
if (sqlite3_bind_text(stmt, ++param_id,
update_params[i].empty() ? NULL :
update_params[i].c_str(),
-1, SQLITE_TRANSIENT) != SQLITE_OK) {
isc_throw(DataSourceError, "failed to bind SQLite3 parameter: " <<
sqlite3_errmsg(dbparams.db_));
}
proc.bindText(++param_id, update_params[i].empty() ? NULL :
update_params[i].c_str(), SQLITE_TRANSIENT);
}
executer.exec();
proc.exec();
}
}
......@@ -1218,33 +1232,16 @@ SQLite3Accessor::addRecordDiff(int zone_id, uint32_t serial,
<< dbparameters_->updated_zone_id);
}
sqlite3_stmt* const stmt = dbparameters_->getStatement(ADD_RECORD_DIFF);
StatementProcessor executer(*dbparameters_, ADD_RECORD_DIFF,
"add record diff");
StatementProcessor proc(*dbparameters_, ADD_RECORD_DIFF,
"add record diff");
int param_id = 0;
if (sqlite3_bind_int(stmt, ++param_id, zone_id)
!= SQLITE_OK) {
isc_throw(DataSourceError, "failed to bind SQLite3 parameter: " <<
sqlite3_errmsg(dbparameters_->db_));
}
if (sqlite3_bind_int64(stmt, ++param_id, serial)
!= SQLITE_OK) {
isc_throw(DataSourceError, "failed to bind SQLite3 parameter: " <<
sqlite3_errmsg(dbparameters_->db_));
}
if (sqlite3_bind_int(stmt, ++param_id, operation)
!= SQLITE_OK) {
isc_throw(DataSourceError, "failed to bind SQLite3 parameter: " <<
sqlite3_errmsg(dbparameters_->db_));
}
proc.bindInt(++param_id, zone_id);
proc.bindInt64(++param_id, serial);
proc.bindInt(++param_id, operation);
for (int i = 0; i < DIFF_PARAM_COUNT; ++i) {
if (sqlite3_bind_text(stmt, ++param_id, params[i].c_str(),
-1, SQLITE_TRANSIENT) != SQLITE_OK) {
isc_throw(DataSourceError, "failed to bind SQLite3 parameter: " <<
sqlite3_errmsg(dbparameters_->db_));
}
proc.bindText(++param_id, params[i].c_str(), SQLITE_TRANSIENT);
}
executer.exec();
proc.exec();
}
std::string
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment