Commit cd623f4c by Artem Kustikov

Implemented last inserted ID/affected rows count loading

parent ecaa5831
......@@ -18,6 +18,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
var sys = require("sys");
var sqlite = require("./sqlite3_bindings");
// load numeric constants from sqlite3_bindings
for (prop in sqlite) {
var obj = sqlite[prop];
if ((obj === +obj) || (toString.call(obj) === '[object Number]') ) {
exports[prop] = sqlite[prop];
}
}
var Database = exports.Database = function () {
var self = this;
......@@ -59,7 +67,6 @@ function _queryDone(db, statement) {
}
statement.finalize(function () {
db.currentQuery = undefined;
// if there are any queries queued, let them know it's safe to go
db.emit("ready");
});
......@@ -67,15 +74,16 @@ function _queryDone(db, statement) {
function _doStep(db, statement, rowCallback) {
statement.step(function (error, row) {
if (error) throw error;
if (error)
return rowCallback (error);
if (!row) {
// rows.rowsAffected = this.changes();
// rows.insertId = this.lastInsertRowid();
rowCallback();
_queryDone(db, statement);
return;
}
rowCallback(row);
rowCallback(undefined, row);
_doStep(db, statement, rowCallback);
});
}
......@@ -94,21 +102,36 @@ function _onPrepare(db, statement, bindings, rowCallback) {
}
}
Database.prototype.query = function(sql, bindings, rowCallback) {
Database.prototype.query = function(sql, bindings, rowCallback, prepareMode) {
var self = this;
if (typeof(bindings) == "function") {
prepareMode = rowCallback || sqlite.EXEC_EMPTY;
rowCallback = bindings;
bindings = [];
}
if (typeof(prepareMode) == "undefined")
prepareMode = sqlite.EXEC_EMPTY;
this.prepare(sql, function(error, statement) {
if (error) throw error;
if (error)
return rowCallback (error);
if (statement) {
_onPrepare(self, statement, bindings, rowCallback)
_onPrepare(self, statement, bindings, rowCallback);
} else {
rowCallback();
self.currentQuery = undefined;
}
});
}, prepareMode);
}
Database.prototype.insert = function(sql, insertCallback) {
var self = this;
this.prepare(sql, function(error, info) {
if (error)
return insertCallback (error);
insertCallback (undefined, (info ? info.last_inserted_id : 0));
}, sqlite.EXEC_LAST_INSERT_ID);
}
......@@ -73,6 +73,13 @@ static Persistent<String> callback_sym;
String::New("Argument " #I " must be an integer"))); \
}
enum ExecMode
{
EXEC_EMPTY = 0,
EXEC_LAST_INSERT_ID = 1,
EXEC_AFFECTED_ROWS = 2
};
class Sqlite3Db : public EventEmitter {
public:
static Persistent<FunctionTemplate> constructor_template;
......@@ -95,6 +102,11 @@ public:
target->Set(v8::String::NewSymbol("Database"),
constructor_template->GetFunction());
// insert/update execution result mask
NODE_DEFINE_CONSTANT (target, EXEC_EMPTY);
NODE_DEFINE_CONSTANT (target, EXEC_LAST_INSERT_ID);
NODE_DEFINE_CONSTANT (target, EXEC_AFFECTED_ROWS);
Statement::Init(target);
}
......@@ -298,7 +310,7 @@ protected:
Sqlite3Db* dbo = ObjectWrap::Unwrap<Sqlite3Db>(args.This());
Local<Number> result = Integer::New(sqlite3_last_insert_rowid(dbo->db_));
return scope.Close(result);
}
};
// Hooks
......@@ -329,6 +341,9 @@ protected:
Persistent<Function> cb;
Sqlite3Db *dbo;
sqlite3_stmt* stmt;
int mode;
sqlite3_int64 lastInsertId;
int affectedRows;
const char* tail;
char sql[1];
};
......@@ -346,10 +361,30 @@ protected:
argv[0] = Exception::Error(
String::New(sqlite3_errmsg(prep_req->dbo->db_)));
argc = 1;
}
else {
} else {
if (req->int1 == SQLITE_DONE) {
argc = 0;
if (prep_req->mode != EXEC_EMPTY) {
argv[0] = Local<Value>::New(Undefined()); // no error
Local<Object> info = Object::New();
if (prep_req->mode & EXEC_LAST_INSERT_ID) {
info->Set(String::NewSymbol("last_inserted_id"),
Integer::NewFromUnsigned (prep_req->lastInsertId));
}
if (prep_req->mode & EXEC_AFFECTED_ROWS) {
info->Set(String::NewSymbol("affected_rows"),
Integer::New (prep_req->affectedRows));
}
argv[1] = info;
argc = 2;
} else {
argc = 0;
}
} else {
argv[0] = External::New(prep_req->stmt);
argv[1] = Integer::New(req->int1);
......@@ -410,6 +445,15 @@ protected:
}
}
prep_req->lastInsertId = 0;
prep_req->affectedRows = 0;
// load custom properties
if (prep_req->mode & EXEC_LAST_INSERT_ID)
prep_req->lastInsertId = sqlite3_last_insert_rowid(db);
if (prep_req->mode & EXEC_AFFECTED_ROWS)
prep_req->affectedRows = sqlite3_changes(db);
return 0;
}
......@@ -417,6 +461,7 @@ protected:
HandleScope scope;
REQ_STR_ARG(0, sql);
REQ_FUN_ARG(1, cb);
OPT_INT_ARG(2, mode, EXEC_EMPTY);
Sqlite3Db* dbo = ObjectWrap::Unwrap<Sqlite3Db>(args.This());
......@@ -432,6 +477,7 @@ protected:
strcpy(prep_req->sql, *sql);
prep_req->cb = Persistent<Function>::New(cb);
prep_req->dbo = dbo;
prep_req->mode = mode;
eio_custom(EIO_Prepare, EIO_PRI_DEFAULT, EIO_AfterPrepare, prep_req);
......
var sqlite = require('../sqlite3_bindings');
var sys = require('sys');
var assert = require('assert');
var puts = sys.puts;
var inspect = sys.inspect;
......@@ -34,7 +35,7 @@ function getRows() {
}
function createTable(db, callback) {
db.prepare("CREATE TABLE t1 (alpha INTEGER)", function (error, statement) {
db.prepare("CREATE TABLE t1 (id INTEGER PRIMARY KEY, alpha INTEGER)", function (error, statement) {
if (error) throw error;
callback();
});
......@@ -42,10 +43,12 @@ function createTable(db, callback) {
var count = 0;
function onPrepare(error, statement) {
function onInsert(error, info) {
var d;
if (error) throw error;
assert.ok (info && info.last_inserted_id > 0, 'Last inserted ID loading failed');
if (++rows == total) {
d = ((new Date)-t0)/1000;
puts("**** " + d + "s to insert " + rows + " rows (" + (rows/d) + "/s)");
......@@ -57,7 +60,9 @@ db.open(':memory:', function () {
createTable(db, function () {
t0 = new Date();
for (var i = 0; i < total; i++) {
db.prepare("INSERT INTO t1 VALUES (1)", onPrepare);
db.prepare("INSERT INTO t1 (alpha) VALUES (1)",
onInsert,
sqlite.EXEC_LAST_INSERT_ID);
}
});
});
var sqlite = require('./sqlite3_bindings');
var sqlite = require('../sqlite3_bindings');
var sys = require('sys');
var puts = sys.puts;
......
......@@ -10,14 +10,14 @@ var db = new sqlite.Database();
function readTest(db, callback) {
var t0 = new Date;
var rows = 0;
db.query("SELECT * FROM t1", function(row) {
db.query("SELECT * FROM t1", function(error, row) {
if (!row) {
var d = ((new Date)-t0)/1000;
puts("**** " + rows + " rows in " + d + "s (" + (rows/d) + "/s)");
if (callback) callback(db);
}
else {
} else {
// puts("got a row" + inspect(arguments));
rows++;
}
......@@ -25,15 +25,15 @@ function readTest(db, callback) {
}
function writeTest(db, i, callback) {
db.query("INSERT INTO t1 VALUES (1)", function (row) {
db.insert("INSERT INTO t1 VALUES (1)", function (error, id) {
if (!i--) {
// end of results
var dt = ((new Date)-t0)/1000;
puts("**** " + count + " insertions in " + dt + "s (" + (count/dt) + "/s)");
if (callback) callback(db);
}
else {
} else {
writeTest(db, i--, callback);
}
});
......
var fs = require("fs"),
sys = require("sys"),
sqlite = require("./sqlite");
sqlite = require("../sqlite");
var puts = sys.puts;
var inspect = sys.inspect;
var sqlite = require("./sqlite");
var db = new sqlite.Database();
function readTest(db, callback) {
var t0 = new Date;
var rows = 0;
db.query("SELECT * FROM t1", function(row) {
db.query("SELECT * FROM t1", function(error, row) {
if (!row) {
var d = ((new Date)-t0)/1000;
puts("**** " + rows + " rows in " + d + "s (" + (rows/d) + "/s)");
......@@ -27,7 +26,7 @@ function readTest(db, callback) {
}
function writeTest(db, i, callback) {
db.query("INSERT INTO t1 VALUES (1, 'hello', 3.141)", function (row) {
db.insert("INSERT INTO t1 VALUES (1, 'hello', 3.141)", function (error, id) {
if (!i--) {
// end of results
var dt = ((new Date)-t0)/1000;
......
var fs = require("fs");
var sys = require("sys");
var assert = require("assert");
var puts = sys.puts
var inspect = sys.inspect
var sqlite = require("../sqlite3_bindings");
var sqlite = require("./sqlite3_bindings");
var puts = sys.puts;
var inspect = sys.inspect;
var db = new sqlite.Database();
throws(function () {
assert.throws(function () {
db.open();
});
throws(function () {
assert.throws(function () {
db.open("my.db");
});
throws(function () {
assert.throws(function () {
db.open("foo.db");
});
......@@ -74,9 +75,11 @@ function test_simple() {
db.open("mydatabase.db", function () {
db.prepare("SELECT bar, baz FROM foo WHERE baz > 5", function (error, statement) {
puts('prepare callback');
if (error) throw (error);
puts(inspect(arguments));
statement.step(function () {
statement.step(function (error) {
puts('query callback');
puts(inspect(arguments));
statement.step(function () {
......
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