From e6c96a20759b2b50525875a0803f8bb59d79c0fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Thu, 10 Feb 2011 19:27:24 -0500 Subject: [PATCH] acquire proper error messages for .step() --- sqlite.js | 39 +++++++++++++++++++++++++++++++++++++++ src/statement.cc | 22 +++++++++++++++++----- src/statement.h | 3 ++- 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/sqlite.js b/sqlite.js index cb11df7..d53c5f6 100644 --- a/sqlite.js +++ b/sqlite.js @@ -225,3 +225,42 @@ Database.prototype.insertMany = function (table, columns, rows, callback) { }); } + +exports.fromErrorCode = function(code) { + switch (code) { + case 0: return "SQLITE_OK"; + case 1: return "SQLITE_ERROR"; + case 2: return "SQLITE_INTERNAL"; + case 3: return "SQLITE_PERM"; + case 4: return "SQLITE_ABORT"; + case 5: return "SQLITE_BUSY"; + case 6: return "SQLITE_LOCKED"; + case 7: return "SQLITE_NOMEM"; + case 8: return "SQLITE_READONLY"; + case 9: return "SQLITE_INTERRUPT"; + case 10: return "SQLITE_IOERR"; + case 11: return "SQLITE_CORRUPT"; + case 12: return "SQLITE_NOTFOUND"; + case 13: return "SQLITE_FULL"; + case 14: return "SQLITE_CANTOPEN"; + case 15: return "SQLITE_PROTOCOL"; + case 16: return "SQLITE_EMPTY"; + case 17: return "SQLITE_SCHEMA"; + case 18: return "SQLITE_TOOBIG"; + case 19: return "SQLITE_CONSTRAINT"; + case 20: return "SQLITE_MISMATCH"; + case 21: return "SQLITE_MISUSE"; + case 22: return "SQLITE_NOLFS"; + case 23: return "SQLITE_AUTH"; + case 24: return "SQLITE_FORMAT"; + case 25: return "SQLITE_RANGE"; + case 26: return "SQLITE_NOTADB"; + } +}; + +exports.sanitizeError = function(err, data) { + err.message = exports.fromErrorCode(err.errno) + ', ' + err.message + + ' in query "' + err.query + + '" with values ' + JSON.stringify(data, false, 4); + return err; +}; diff --git a/src/statement.cc b/src/statement.cc index 83b3c34..f09ec86 100644 --- a/src/statement.cc +++ b/src/statement.cc @@ -485,8 +485,11 @@ int Statement::EIO_AfterStep(eio_req *req) { Local argv[2]; if (sto->error_) { - argv[0] = Exception::Error( - String::New(sqlite3_errmsg(db))); + Local e = Exception::Error(sto->error_msg_); + Local obj = e->ToObject(); + obj->Set(NODE_PSYMBOL("errno"), Integer::New(sto->error_)); + obj->Set(NODE_PSYMBOL("query"), String::NewSymbol(sqlite3_sql(sto->stmt_))); + argv[0] = e; } else { argv[0] = Local::New(Undefined()); @@ -586,6 +589,7 @@ int Statement::EIO_Step(eio_req *req) { sqlite3_stmt *stmt = sto->stmt_; assert(stmt); int rc; + const char *msg; // check if we have already taken a step immediately after prepare if (sto->first_rc_ != -1) { @@ -597,10 +601,16 @@ int Statement::EIO_Step(eio_req *req) { sto->first_rc_ = -1; } else { - rc = req->result = sqlite3_step(stmt); + sqlite3* db = sqlite3_db_handle(stmt); + sqlite3_mutex* mtx = sqlite3_db_mutex(db); + sqlite3_mutex_enter(mtx); + rc = sqlite3_step(stmt); + if (rc != SQLITE_ROW && rc != SQLITE_DONE) msg = sqlite3_errmsg(db); + sqlite3_mutex_leave(mtx); + req->result = rc; } - sto->error_ = false; + sto->error_ = SQLITE_OK; if (rc == SQLITE_ROW) { // If this pointer is NULL, look up and store the columns names. @@ -667,7 +677,9 @@ int Statement::EIO_Step(eio_req *req) { // nothing to do in this case } else { - sto->error_ = true; + HandleScope scope; + sto->error_ = rc; + sto->error_msg_ = scope.Close(String::NewSymbol(msg)); sto->cells = NULL; } diff --git a/src/statement.h b/src/statement.h index e9f99aa..a4d21ea 100644 --- a/src/statement.h +++ b/src/statement.h @@ -102,7 +102,8 @@ class Statement : public EventEmitter { int column_count_; char **column_names_; - bool error_; + int error_; + Local error_msg_; int first_rc_; int mode_;