Commit bd56d6ca by Konstantin Käfer

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

parent 416ffb25
......@@ -16,14 +16,10 @@
var sqlite3 = module.exports = exports = require('./sqlite3_bindings');
var sys = require("sys");
// function noop(err) {
// if (err) throw err;
// };
var Database = sqlite3.Database;
var Statement = sqlite3.Statement;
// Database#prepare(sql, [bind1, bind2, ...], [callback])
Database.prototype.prepare = function(sql) {
var callback, params = Array.prototype.slice.call(arguments, 1);
......@@ -39,4 +35,3 @@ Database.prototype.prepare = function(sql) {
return new Statement(this, sql, params.pop());
}
};
......@@ -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, "get", Get);
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, "finalize", Finalize);
......@@ -446,6 +447,89 @@ int Statement::EIO_AfterRun(eio_req *req) {
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) {
HandleScope scope;
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
......@@ -492,8 +576,9 @@ int Statement::EIO_AfterReset(eio_req *req) {
Local<Array> Statement::RowToJS(Data::Row* row) {
Local<Array> result(Array::New(row->size()));
Data::Row::iterator it = row->begin();
for (int i = 0; it < row->end(); it++, i++) {
Data::Row::const_iterator it = row->begin();
Data::Row::const_iterator end = row->end();
for (int i = 0; it < end; it++, i++) {
Data::Field* field = *it;
switch (field->type) {
case SQLITE_INTEGER: {
......
......@@ -105,6 +105,12 @@ public:
Data::Row row;
};
static struct RowsBaton : Baton {
RowsBaton(Statement* stmt_, Handle<Function> cb_) :
Baton(stmt_, cb_) {}
Data::Rows rows;
};
static struct PrepareBaton : Database::Baton {
Statement* stmt;
std::string sql;
......
......@@ -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 retrieved = 0;
......@@ -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 retrieved = 0;
......@@ -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 retrieved = 0;
......@@ -201,3 +201,51 @@ exports['test get() function binding'] = function(beforeExit) {
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