Commit bd56d6ca by Konstantin Käfer

add .all() function to retrieve all rows in the result

parent 416ffb25
...@@ -16,14 +16,10 @@ ...@@ -16,14 +16,10 @@
var sqlite3 = module.exports = exports = require('./sqlite3_bindings'); var sqlite3 = module.exports = exports = require('./sqlite3_bindings');
var sys = require("sys"); var sys = require("sys");
// function noop(err) {
// if (err) throw err;
// };
var Database = sqlite3.Database; var Database = sqlite3.Database;
var Statement = sqlite3.Statement; var Statement = sqlite3.Statement;
// Database#prepare(sql, [bind1, bind2, ...], [callback]) // Database#prepare(sql, [bind1, bind2, ...], [callback])
Database.prototype.prepare = function(sql) { Database.prototype.prepare = function(sql) {
var callback, params = Array.prototype.slice.call(arguments, 1); var callback, params = Array.prototype.slice.call(arguments, 1);
...@@ -39,4 +35,3 @@ Database.prototype.prepare = function(sql) { ...@@ -39,4 +35,3 @@ Database.prototype.prepare = function(sql) {
return new Statement(this, sql, params.pop()); return new Statement(this, sql, params.pop());
} }
}; };
...@@ -39,6 +39,7 @@ void Statement::Init(v8::Handle<Object> target) { ...@@ -39,6 +39,7 @@ void Statement::Init(v8::Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(constructor_template, "bind", Bind); NODE_SET_PROTOTYPE_METHOD(constructor_template, "bind", Bind);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "get", Get); NODE_SET_PROTOTYPE_METHOD(constructor_template, "get", Get);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "run", Run); NODE_SET_PROTOTYPE_METHOD(constructor_template, "run", Run);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "all", All);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "reset", Reset); NODE_SET_PROTOTYPE_METHOD(constructor_template, "reset", Reset);
NODE_SET_PROTOTYPE_METHOD(constructor_template, "finalize", Finalize); NODE_SET_PROTOTYPE_METHOD(constructor_template, "finalize", Finalize);
...@@ -446,6 +447,89 @@ int Statement::EIO_AfterRun(eio_req *req) { ...@@ -446,6 +447,89 @@ int Statement::EIO_AfterRun(eio_req *req) {
return 0; return 0;
} }
Handle<Value> Statement::All(const Arguments& args) {
HandleScope scope;
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
Baton* baton = stmt->Bind<RowsBaton>(args);
stmt->Schedule(EIO_BeginAll, baton);
return args.This();
}
void Statement::EIO_BeginAll(Baton* baton) {
assert(!baton->stmt->locked);
assert(!baton->stmt->finalized);
assert(baton->stmt->prepared);
baton->stmt->locked = true;
eio_custom(EIO_All, EIO_PRI_DEFAULT, EIO_AfterAll, baton);
}
int Statement::EIO_All(eio_req *req) {
STATEMENT_INIT(RowsBaton);
sqlite3_mutex* mtx = sqlite3_db_mutex(stmt->db->handle);
sqlite3_mutex_enter(mtx);
// Make sure that we also reset when there are no parameters.
if (!baton->parameters.size()) {
sqlite3_reset(stmt->handle);
}
if (stmt->Bind(baton->parameters)) {
while ((stmt->status = sqlite3_step(stmt->handle)) == SQLITE_ROW) {
Data::Row* row = new Data::Row();
GetRow(row, stmt->handle);
baton->rows.push_back(row);
}
if (stmt->status != SQLITE_DONE) {
stmt->message = std::string(sqlite3_errmsg(stmt->db->handle));
}
}
sqlite3_mutex_leave(mtx);
return 0;
}
int Statement::EIO_AfterAll(eio_req *req) {
HandleScope scope;
STATEMENT_INIT(RowsBaton);
if (stmt->status != SQLITE_DONE) {
Error(baton);
}
else {
// Fire callbacks.
if (!baton->callback.IsEmpty() && baton->callback->IsFunction()) {
if (baton->rows.size()) {
// Create the result array from the data we acquired.
Local<Array> result(Array::New(baton->rows.size()));
Data::Rows::const_iterator it = baton->rows.begin();
Data::Rows::const_iterator end = baton->rows.end();
for (int i = 0; it < end; it++, i++) {
result->Set(i, RowToJS(*it));
}
Local<Value> argv[] = { Local<Value>::New(Null()), result };
TRY_CATCH_CALL(stmt->handle_, baton->callback, 2, argv);
}
else {
// There were no result rows.
Local<Value> argv[] = {
Local<Value>::New(Null()),
Local<Value>::New(Array::New(0))
};
TRY_CATCH_CALL(stmt->handle_, baton->callback, 2, argv);
}
}
}
STATEMENT_END();
return 0;
}
Handle<Value> Statement::Reset(const Arguments& args) { Handle<Value> Statement::Reset(const Arguments& args) {
HandleScope scope; HandleScope scope;
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This()); Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
...@@ -492,8 +576,9 @@ int Statement::EIO_AfterReset(eio_req *req) { ...@@ -492,8 +576,9 @@ int Statement::EIO_AfterReset(eio_req *req) {
Local<Array> Statement::RowToJS(Data::Row* row) { Local<Array> Statement::RowToJS(Data::Row* row) {
Local<Array> result(Array::New(row->size())); Local<Array> result(Array::New(row->size()));
Data::Row::iterator it = row->begin(); Data::Row::const_iterator it = row->begin();
for (int i = 0; it < row->end(); it++, i++) { Data::Row::const_iterator end = row->end();
for (int i = 0; it < end; it++, i++) {
Data::Field* field = *it; Data::Field* field = *it;
switch (field->type) { switch (field->type) {
case SQLITE_INTEGER: { case SQLITE_INTEGER: {
......
...@@ -105,6 +105,12 @@ public: ...@@ -105,6 +105,12 @@ public:
Data::Row row; Data::Row row;
}; };
static struct RowsBaton : Baton {
RowsBaton(Statement* stmt_, Handle<Function> cb_) :
Baton(stmt_, cb_) {}
Data::Rows rows;
};
static struct PrepareBaton : Database::Baton { static struct PrepareBaton : Database::Baton {
Statement* stmt; Statement* stmt;
std::string sql; std::string sql;
......
...@@ -128,7 +128,7 @@ exports['test retrieving reset() function'] = function(beforeExit) { ...@@ -128,7 +128,7 @@ exports['test retrieving reset() function'] = function(beforeExit) {
}); });
}; };
exports['test multiple get() function binding'] = function(beforeExit) { exports['test multiple get() parameter binding'] = function(beforeExit) {
var db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY); var db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY);
var retrieved = 0; var retrieved = 0;
...@@ -161,7 +161,7 @@ exports['test multiple get() function binding'] = function(beforeExit) { ...@@ -161,7 +161,7 @@ exports['test multiple get() function binding'] = function(beforeExit) {
}; };
exports['test prepare() function binding'] = function(beforeExit) { exports['test prepare() parameter binding'] = function(beforeExit) {
var db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY); var db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY);
var retrieved = 0; var retrieved = 0;
...@@ -182,7 +182,7 @@ exports['test prepare() function binding'] = function(beforeExit) { ...@@ -182,7 +182,7 @@ exports['test prepare() function binding'] = function(beforeExit) {
}; };
exports['test get() function binding'] = function(beforeExit) { exports['test get() parameter binding'] = function(beforeExit) {
var db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY); var db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY);
var retrieved = 0; var retrieved = 0;
...@@ -201,3 +201,51 @@ exports['test get() function binding'] = function(beforeExit) { ...@@ -201,3 +201,51 @@ exports['test get() function binding'] = function(beforeExit) {
assert.equal(1, retrieved, "Didn't retrieve all rows"); assert.equal(1, retrieved, "Didn't retrieve all rows");
}); });
}; };
exports['test all()'] = function(beforeExit) {
var db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY);
var retrieved = 0;
var count = 1000;
db.prepare("SELECT txt, num, flt, blb FROM foo WHERE num < ? ORDER BY num", count)
.all(function(err, rows) {
if (err) throw err;
for (var i = 0; i < rows.length; i++) {
assert.equal(rows[i][0], 'String ' + i);
assert.equal(rows[i][1], i);
assert.equal(rows[i][2], i * Math.PI);
assert.equal(rows[i][3], null);
retrieved++;
}
});
beforeExit(function() {
assert.equal(count, retrieved, "Didn't retrieve all rows");
});
};
exports['test all() parameter binding'] = function(beforeExit) {
var db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY);
var retrieved = 0;
var count = 1000;
db.prepare("SELECT txt, num, flt, blb FROM foo WHERE num < ? ORDER BY num")
.all(count, function(err, rows) {
if (err) throw err;
for (var i = 0; i < rows.length; i++) {
assert.equal(rows[i][0], 'String ' + i);
assert.equal(rows[i][1], i);
assert.equal(rows[i][2], i * Math.PI);
assert.equal(rows[i][3], null);
retrieved++;
}
});
beforeExit(function() {
assert.equal(count, 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