Commit eaf72f23 by Konstantin Käfer

saving work

parent c09549d0
......@@ -16,273 +16,22 @@
var sqlite3 = module.exports = exports = require('./sqlite3_bindings');
var sys = require("sys");
function noop(err) {
if (err) throw err;
};
var Database = sqlite3.Database;
// var realClose = Database.prototype.close;
// sqlite3.Database.prototype.close = function(callback) {
// if (this.status === sqlite3.STATUS_IDLE) {
// return realClose.call(this, callback);
// } else {
// this.once('idle', function() {
// realClose.call(this, callback);
// });
// }
// function noop(err) {
// if (err) throw err;
// };
// var realClose = sqlite3.Database.prototype.close;
// sqlite3.Database.prototype.close = function() {
// var db = this;
// process.nextTick(function() {
// if (!db.idle) {
// db.on('idle', function fn() {
// realClose.call(db);
// db.removeListener('idle', fn);
// });
// } else {
// realClose.call(db);
// }
// });
// return this;
// };
/*
sqlite3.Database.prototype.query = function(sql, bindings, rowCallback) {
var self = this;
if (typeof(bindings) == "function") {
rowCallback = bindings;
bindings = undefined;
}
this.prepare(sql, function(error, statement) {
function next() {
_doStep(self, statement, rowCallback);
}
if (error) {
return rowCallback (error);
}
if (statement) {
if (Array.isArray(bindings)) {
statement.bindArray(bindings, next);
}
else if (typeof(bindings) === 'object') {
statement.bindObject(bindings, next);
}
else {
next();
}
}
else {
rowCallback();
}
});
}
function _doStep(db, statement, rowCallback) {
statement.step(function (error, row) {
if (error) {
return rowCallback(error);
}
if (!row) {
rowCallback();
statement.finalize(function(){});
return;
}
rowCallback(undefined, row);
_doStep(db, statement, rowCallback);
});
}
// Execute a single SQL query with the given optional parameters. Calls
// `callback` with all rows or an error on query completion.
sqlite3.Database.prototype.execute = function (sql /* , bindings, callback ) {
var self = this;
var bindings, callback;
var n = arguments.length;
var Database = sqlite3.Database;
var Statement = sqlite3.Statement;
switch (n) {
case 3:
callback = arguments[2];
bindings = arguments[1];
break;
case 2:
callback = arguments[1];
break;
default: throw new Error("Invalid number of arguments ("+n+")");
}
self.prepare(sql, function (error, statement) {
function next (error) {
if (error) return callback(new Error("Error binding: " + error.toString()));
fetchAll(statement);
}
// Database#prepare(sql, [bind1, bind2, ...], [callback])
Database.prototype.prepare = function(sql) {
var callback, params = Array.prototype.slice.call(arguments, 1);
if (error) {
return callback(error);
if (params.length && typeof params[params.length - 1] === 'function') {
callback = params.pop();
}
if (bindings) {
if (Array.isArray(bindings)) {
statement.bindArray(bindings, next);
}
else if (typeof(bindings) === 'object') {
statement.bindObject(bindings, next);
}
}
else {
next();
}
function fetchAll(statement) {
statement.fetchAll(function (error, rows) {
if (error) {
return callback(error);
}
statement.finalize(function () {
callback(undefined, rows);
});
});
}
});
}
// Execute SQL statements separated by semi-colons.
// SQL must contain no placeholders. Results are discarded.
sqlite3.Database.prototype.executeScript = function (script, callback) {
var self = this;
(function stepOverSQL(sql) {
self.prepare(sql, function(error, statement) {
if (error) {
return callback(error);
}
statement.step(function (error, row) {
var tail;
if (error) {
callback(error);
return;
}
if (!row) {
statement.finalize(function(){});
tail = statement.tail;
if (typeof tail == "string") {
tail = tail.trim();
}
if (tail) {
stepOverSQL(tail);
}
else {
callback();
}
}
});
});
})(script);
}
sqlite3.Database.prototype.insertMany = function (table, columns, rows, callback) {
var columnsFragment = columns.join(",");
var placeholdersFragment = [];
var i = columns.length;
if (!rows.length) {
callback();
return;
}
while (i--) {
placeholdersFragment.push('?');
}
placeholdersFragment = placeholdersFragment.join(", ");
var sql = [ 'INSERT INTO'
, table
, '('
, columnsFragment
, ')'
, 'VALUES'
, '('
, placeholdersFragment
, ')'
]
.join(" ");
var i = rows.length;
var statement;
function doStep(i) {
statement.bindArray(rows[i], function () {
statement.step(function (error, row) {
if (error) return callback(error);
statement.reset();
if (i) {
doStep(--i);
}
else {
statement.finalize(function () {
callback();
});
}
});
});
}
this.prepare(sql, function (error, stmt) {
if (error) return callback(error);
statement = stmt;
doStep(--i);
});
}
sqlite3.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";
}
return new Statement(this, sql, params, callback);
};
sqlite3.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;
};
*/
\ No newline at end of file
......@@ -19,8 +19,6 @@
#include <node.h>
#include <node_events.h>
#include "deferred_call.h"
#include <string>
#include <queue>
......@@ -29,34 +27,52 @@
using namespace v8;
using namespace node;
class Database;
static struct Baton {
Database* db;
Persistent<Function> callback;
int status;
std::string message;
~Baton() {
callback.Dispose();
}
};
static struct OpenBaton : Baton {
std::string filename;
int mode;
};
class Database : public EventEmitter {
public:
public:
static Persistent<FunctionTemplate> constructor_template;
static void Init(v8::Handle<Object> target);
static enum Status {
IsClosed = 1 << 0,
IsOpening = 1 << 1,
IsOpen = 1 << 2,
IsClosing = 1 << 3,
DoesntMatter = IsClosed | IsOpening | IsOpen | IsClosing
};
static inline bool HasInstance(Handle<Value> val) {
if (!val->IsObject()) return false;
Local<Object> obj = val->ToObject();
return constructor_template->HasInstance(obj);
}
typedef Deferred::Call<Status> Call;
typedef void (*EIO_Callback)(Baton* baton);
struct Baton {
Baton(Database* db_, Persistent<Function> callback_) :
db(db_), callback(callback_) {};
Database* db;
Persistent<Function> callback;
struct Call {
Call(EIO_Callback callback_, Baton* baton_, bool exclusive_ = false) :
callback(callback_), exclusive(exclusive_), baton(baton_) {};
EIO_Callback callback;
bool exclusive;
Baton* baton;
};
friend class Statement;
protected:
protected:
Database() : EventEmitter(),
handle(NULL),
pending(0),
status(IsClosed) {
open(false),
locked(false),
pending(0) {
}
......@@ -65,64 +81,32 @@ class Database : public EventEmitter {
}
static Handle<Value> New(const Arguments& args);
static void ProcessQueue(Database* db);
static Handle<Value> OpenSync(const Arguments& args);
static Handle<Value> Open(const Arguments& args);
static bool Open(Database* db);
static void EIO_BeginOpen(Baton* baton);
static int EIO_Open(eio_req *req);
static int EIO_AfterOpen(eio_req *req);
static Handle<Value> CloseSync(const Arguments& args);
static void Schedule(Database* db, EIO_Callback callback, Baton* baton,
bool exclusive);
static void Process(Database* db);
static Handle<Value> Close(const Arguments& args);
static bool Close(Database* db);
static void EIO_BeginClose(Baton* baton);
static int EIO_Close(eio_req *req);
static int EIO_AfterClose(eio_req *req);
static int EIO_AfterPrepareAndStep(eio_req *req);
static int EIO_PrepareAndStep(eio_req *req);
static Handle<Value> PrepareAndStep(const Arguments& args);
static int EIO_AfterPrepare(eio_req *req);
static int EIO_Prepare(eio_req *req);
static Handle<Value> Prepare(const Arguments& args);
void Wrap (Handle<Object> handle);
static void Destruct (Persistent<Value> value, void *data);
static int EIO_Destruct(eio_req *req);
static int EIO_AfterDestruct(eio_req *req);
protected:
protected:
sqlite3* handle;
std::string filename;
int open_mode;
std::string error_message;
int error_status;
bool open;
bool locked;
unsigned int pending;
int pending;
Status status;
std::queue<Call*> queue;
private:
};
enum ExecMode {
EXEC_EMPTY = 0,
EXEC_LAST_INSERT_ID = 1,
EXEC_AFFECTED_ROWS = 2
};
struct prepare_request {
Persistent<Function> cb;
Database *db;
sqlite3_stmt* stmt;
int mode;
sqlite3_int64 lastInsertId;
int affectedRows;
const char* tail;
char sql[1];
};
#endif
......@@ -121,7 +121,7 @@ const char* sqlite_code_string(int code);
String::NewSymbol(sqlite_code_string(errno)), \
String::NewSymbol(": ") \
), \
String::New(msg) \
(msg) \
) \
); \
Local<Object> name ##_obj = name->ToObject(); \
......@@ -129,30 +129,19 @@ const char* sqlite_code_string(int code);
name ##_obj->Set(NODE_PSYMBOL("code"), \
String::NewSymbol(sqlite_code_string(errno)));
#define EVENT_ONCE(event, callback) \
Local<Value> argv[2] = { \
String::NewSymbol(event), \
args.This()->Get(String::NewSymbol(callback)) \
}; \
v8::Local<v8::Value> fn_val = args.This()->Get(String::NewSymbol("once")); \
Local<Function> fn = Local<Function>::Cast(fn_val); \
fn->Call(args.This(), 2, argv);
#define SET_STRING(sym, str) \
Set(String::NewSymbol(#sym), String::New(str), ReadOnly)
#define SET_INTEGER(sym, i) \
Set(String::NewSymbol(#sym), Integer::New(i), ReadOnly)
#define EMIT_EVENT(obj, argc, argv) \
TRY_CATCH_CALL((obj), \
Local<Function>::Cast((obj)->Get(String::NewSymbol("emit"))), \
argc, argv \
);
#define TRY_CATCH_CALL(context, callback, argc, argv) \
{ \
TryCatch try_catch; \
{ TryCatch try_catch; \
(callback)->Call((context), (argc), (argv)); \
if (try_catch.HasCaught()) { \
FatalException(try_catch); \
} \
}
} }
#endif
// Copyright (c) 2010, Orlando Vazquez <ovazquez@gmail.com>
//
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
......@@ -18,139 +18,50 @@
#include <v8.h>
#include <node.h>
#include <node_events.h>
#include <sqlite3.h>
#include <stdlib.h>
#include <node_buffer.h>
extern "C" {
#include <mpool.h>
};
#include "database.h"
#include <string>
#include <queue>
#include <sqlite3.h>
using namespace v8;
using namespace node;
struct cell_node {
void *value;
int type;
struct cell_node *next;
int size;
};
class Statement;
struct row_node {
struct cell_node *cells;
struct row_node *next;
static struct PrepareBaton : Baton {
Statement* stmt;
std::string sql;
};
// represent strings with this struct
struct string_t {
size_t bytes;
char data[];
};
class Statement : public EventEmitter {
public:
public:
static Persistent<FunctionTemplate> constructor_template;
static void Init(v8::Handle<Object> target);
static void Init(Handle<Object> target);
static Handle<Value> New(const Arguments& args);
protected:
Statement(sqlite3_stmt* stmt, int first_rc = -1, int mode = 0)
: EventEmitter(), first_rc_(first_rc), mode_(mode), stmt_(stmt) {
column_count_ = -1;
column_names_ = NULL;
Statement(Database* db_) : EventEmitter() {
db = db_;
db->Ref();
}
~Statement() {
if (stmt_) sqlite3_finalize(stmt_);
if (column_names_) FreeColumnData();
db->Unref();
}
static Handle<Value> Bind(const Arguments &args);
static Handle<Value> BindObject(const Arguments &args);
static Handle<Value> BindArray(const Arguments &args);
static int EIO_BindArray(eio_req *req);
static int EIO_AfterBindArray(eio_req *req);
static int EIO_AfterFinalize(eio_req *req);
static int EIO_Finalize(eio_req *req);
static Handle<Value> Finalize(const Arguments &args);
static Handle<Value> Reset(const Arguments &args);
static Handle<Value> ClearBindings(const Arguments &args);
static int EIO_AfterStep(eio_req *req);
static int EIO_Step(eio_req *req);
static Handle<Value> Step(const Arguments &args);
static int EIO_AfterFetchAll(eio_req *req);
static int EIO_FetchAll(eio_req *req);
static Handle<Value> FetchAll(const Arguments &args);
void InitializeColumns(void);
void FreeColumnData(void);
bool HasCallback();
void SetCallback(Local<Function> cb);
protected:
static void EIO_BeginPrepare(Baton* baton);
static int EIO_Prepare(eio_req *req);
static int EIO_AfterPrepare(eio_req *req);
Local<Function> GetCallback();
private:
int column_count_;
char **column_names_;
int error_;
Local<String> error_msg_;
int first_rc_;
int mode_;
sqlite3_stmt* stmt_;
// for statment.step
cell_node *cells;
};
// indicates the key type (integer index or name string)
enum BindKeyType {
KEY_INT,
KEY_STRING
};
// indicate the parameter type
enum BindValueType {
VALUE_INT,
VALUE_DOUBLE,
VALUE_BLOB,
VALUE_STRING,
VALUE_NULL
};
struct bind_request {
Persistent<Function> cb;
Statement *sto;
struct bind_pair *pairs;
size_t len;
};
struct bind_pair {
enum BindKeyType key_type;
enum BindValueType value_type;
void *key; // char * | int *
void *value; // char * | int * | double * | 0
size_t value_size;
};
private:
Database* db;
struct fetchall_request {
Persistent<Function> cb;
Statement *sto;
mpool_t *pool;
char *error;
struct row_node *rows;
sqlite3_stmt* handle;
};
#endif
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