Commit 482517de by Konstantin Käfer

add .reset()

parent 457146dd
......@@ -143,5 +143,20 @@ const char* sqlite_code_string(int code);
FatalException(try_catch); \
} }
#define EIO_DEFINITION(name) \
static Handle<Value> name(const Arguments& args); \
static void EIO_Begin##name(Baton* baton); \
static int EIO_##name(eio_req *req); \
static int EIO_After##name(eio_req *req);
#define STATEMENT_INIT(type) \
type* baton = static_cast<type*>(req->data); \
Statement* stmt = baton->stmt;
#define STATEMENT_END() \
stmt->locked = false; \
stmt->Process(); \
delete baton;
#endif
......@@ -36,6 +36,7 @@ void Statement::Init(v8::Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(constructor_template, "bind", Bind);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "get", Get);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "reset", Reset);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "finalize", Finalize);
target->Set(v8::String::NewSymbol("Statement"),
......@@ -128,17 +129,15 @@ void Statement::EIO_BeginPrepare(Database::Baton* baton) {
}
int Statement::EIO_Prepare(eio_req *req) {
PrepareBaton* baton = static_cast<PrepareBaton*>(req->data);
Database* db = baton->db;
Statement* stmt = baton->stmt;
STATEMENT_INIT(PrepareBaton);
// In case preparing fails, we use a mutex to make sure we get the associated
// error message.
sqlite3_mutex* mtx = sqlite3_db_mutex(db->handle);
sqlite3_mutex* mtx = sqlite3_db_mutex(baton->db->handle);
sqlite3_mutex_enter(mtx);
stmt->status = sqlite3_prepare_v2(
db->handle,
baton->db->handle,
baton->sql.c_str(),
baton->sql.size(),
&stmt->handle,
......@@ -146,7 +145,7 @@ int Statement::EIO_Prepare(eio_req *req) {
);
if (stmt->status != SQLITE_OK) {
stmt->message = std::string(sqlite3_errmsg(db->handle));
stmt->message = std::string(sqlite3_errmsg(baton->db->handle));
stmt->handle = NULL;
}
......@@ -157,10 +156,7 @@ int Statement::EIO_Prepare(eio_req *req) {
int Statement::EIO_AfterPrepare(eio_req *req) {
HandleScope scope;
PrepareBaton* baton = static_cast<PrepareBaton*>(req->data);
Database* db = baton->db;
Statement* stmt = baton->stmt;
STATEMENT_INIT(PrepareBaton);
if (stmt->status != SQLITE_OK) {
Error(baton);
......@@ -172,12 +168,10 @@ int Statement::EIO_AfterPrepare(eio_req *req) {
Local<Value> argv[] = { Local<Value>::New(Null()) };
TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv);
}
stmt->Process();
}
db->Process();
delete baton;
STATEMENT_END();
baton->db->Process();
return 0;
}
......@@ -230,11 +224,9 @@ void Statement::EIO_BeginBind(Baton* baton) {
}
int Statement::EIO_Bind(eio_req *req) {
BindBaton* baton = static_cast<BindBaton*>(req->data);
Statement* stmt = baton->stmt;
Database* db = stmt->db;
STATEMENT_INIT(BindBaton);
sqlite3_mutex* mtx = sqlite3_db_mutex(db->handle);
sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle);
sqlite3_mutex_enter(mtx);
Result::Row::iterator it = baton->values.begin();
......@@ -264,7 +256,7 @@ int Statement::EIO_Bind(eio_req *req) {
}
if (stmt->status != SQLITE_OK) {
stmt->message = std::string(sqlite3_errmsg(db->handle));
stmt->message = std::string(sqlite3_errmsg(stmt->db->handle));
break;
}
}
......@@ -276,8 +268,7 @@ int Statement::EIO_Bind(eio_req *req) {
int Statement::EIO_AfterBind(eio_req *req) {
HandleScope scope;
BindBaton* baton = static_cast<BindBaton*>(req->data);
Statement* stmt = baton->stmt;
STATEMENT_INIT(BindBaton);
if (stmt->status != SQLITE_OK) {
Error(baton);
......@@ -290,10 +281,7 @@ int Statement::EIO_AfterBind(eio_req *req) {
}
}
stmt->locked = false;
stmt->Process();
delete baton;
STATEMENT_END();
return 0;
}
......@@ -320,20 +308,18 @@ void Statement::EIO_BeginGet(Baton* baton) {
}
int Statement::EIO_Get(eio_req *req) {
RowBaton* baton = static_cast<RowBaton*>(req->data);
Statement* stmt = baton->stmt;
Database* db = stmt->db;
STATEMENT_INIT(RowBaton);
if (stmt->status != SQLITE_DONE) {
// In case preparing fails, we use a mutex to make sure we get the associated
// error message.
sqlite3_mutex* mtx = sqlite3_db_mutex(db->handle);
sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle);
sqlite3_mutex_enter(mtx);
stmt->status = sqlite3_step(stmt->handle);
if (!(stmt->status == SQLITE_ROW || stmt->status == SQLITE_DONE)) {
stmt->message = std::string(sqlite3_errmsg(db->handle));
stmt->message = std::string(sqlite3_errmsg(stmt->db->handle));
}
sqlite3_mutex_leave(mtx);
......@@ -349,8 +335,7 @@ int Statement::EIO_Get(eio_req *req) {
int Statement::EIO_AfterGet(eio_req *req) {
HandleScope scope;
RowBaton* baton = static_cast<RowBaton*>(req->data);
Statement* stmt = baton->stmt;
STATEMENT_INIT(RowBaton);
if (stmt->status != SQLITE_ROW && stmt->status != SQLITE_DONE) {
Error(baton);
......@@ -370,10 +355,50 @@ int Statement::EIO_AfterGet(eio_req *req) {
}
}
stmt->locked = false;
stmt->Process();
STATEMENT_END();
return 0;
}
delete baton;
Handle<Value> Statement::Reset(const Arguments& args) {
HandleScope scope;
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
OPTIONAL_ARGUMENT_FUNCTION(0, callback);
Baton* baton = new Baton(stmt, callback);
stmt->Schedule(EIO_BeginReset, baton);
return args.This();
}
void Statement::EIO_BeginReset(Baton* baton) {
assert(!baton->stmt->locked);
assert(!baton->stmt->finalized);
assert(baton->stmt->prepared);
baton->stmt->locked = true;
eio_custom(EIO_Reset, EIO_PRI_DEFAULT, EIO_AfterReset, baton);
}
int Statement::EIO_Reset(eio_req *req) {
STATEMENT_INIT(Baton);
sqlite3_reset(stmt->handle);
stmt->status = SQLITE_OK;
return 0;
}
int Statement::EIO_AfterReset(eio_req *req) {
HandleScope scope;
STATEMENT_INIT(Baton);
// Fire callbacks.
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
Local<Value> argv[] = { Local<Value>::New(Null()) };
TRY_CATCH_CALL(stmt->handle_, baton->callback, 1, argv);
}
STATEMENT_END();
return 0;
}
......
......@@ -143,23 +143,17 @@ public:
}
protected:
static Handle<Value> Bind(const Arguments& args);
static void EIO_BeginBind(Baton* baton);
static int EIO_Bind(eio_req *req);
static int EIO_AfterBind(eio_req *req);
static void EIO_BeginPrepare(Database::Baton* baton);
static int EIO_Prepare(eio_req *req);
static int EIO_AfterPrepare(eio_req *req);
static Handle<Value> Get(const Arguments& args);
static void EIO_BeginGet(Baton* baton);
static int EIO_Get(eio_req *req);
static int EIO_AfterGet(eio_req *req);
EIO_DEFINITION(Bind);
EIO_DEFINITION(Get);
EIO_DEFINITION(Reset);
static void GetRow(Result::Row* row, sqlite3_stmt* stmt);
static Local<Array> RowToJS(Result::Row* row);
static void EIO_BeginPrepare(Database::Baton* baton);
static int EIO_Prepare(eio_req *req);
static int EIO_AfterPrepare(eio_req *req);
void Schedule(EIO_Callback callback, Baton* baton);
void Process();
void CleanQueue();
......
......@@ -4,7 +4,7 @@ var Step = require('step');
exports['test simple prepared statement with invalid SQL'] = function(beforeExit) {
var error = false;
var db = new sqlite3.Database(':memory:')
var db = new sqlite3.Database(':memory:');
db.prepare('CRATE TALE foo text bar)', function(err, statement) {
if (err && err.errno == sqlite3.ERROR &&
err.message === 'SQLITE_ERROR: near "CRATE": syntax error') {
......@@ -42,7 +42,7 @@ exports['test inserting and retrieving rows'] = function(beforeExit) {
var retrieved = 0;
// We insert and retrieve that many rows.
var count = 5000;
var count = 1000;
Step(
function() {
......@@ -92,5 +92,37 @@ exports['test inserting and retrieving rows'] = function(beforeExit) {
beforeExit(function() {
assert.equal(count, inserted, "Didn't insert all rows");
assert.equal(count, retrieved, "Didn't retrieve all rows");
})
});
};
exports['test retrieving reset() function'] = function(beforeExit) {
var db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY);
var retrieved = 0;
Step(
function() {
var stmt = db.prepare("SELECT txt, num, flt, blb FROM foo ORDER BY num");
var group = this.group();
for (var i = 0; i < 10; i++) {
stmt.reset();
stmt.get(group());
}
},
function(err, rows) {
if (err) throw err;
for (var i = 0; i < rows.length; i++) {
assert.equal(rows[i][0], 'String 0');
assert.equal(rows[i][1], 0);
assert.equal(rows[i][2], 0.0);
assert.equal(rows[i][3], null);
retrieved++;
}
}
);
beforeExit(function() {
assert.equal(10, retrieved, "Didn't retrieve all rows");
});
};
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