Commit f3663bdf by Orlando Vazquez

get statement.step() ready to work

parent 23df298e
-- Used to create mydatabase.db -- Used to create mydatabase.db
CREATE TABlE foo ( CREATE TABLE foo (
bar TEXT, bar TEXT,
baz INT baz INT
); );
INSERT INTO foo (bar, baz) VALUES ('hello', 420); INSERT INTO foo (bar, baz) VALUES ('hello', 0);
INSERT INTO foo (bar, baz) VALUES ('world', 42); INSERT INTO foo (bar, baz) VALUES ('world', 1);
INSERT INTO foo (bar, baz) VALUES ('shazbot', 2);
INSERT INTO foo (bar, baz) VALUES ('shazbot', 3);
INSERT INTO foo (bar, baz) VALUES ('shazbot', 4);
INSERT INTO foo (bar, baz) VALUES ('shazbot', 5);
INSERT INTO foo (bar, baz) VALUES ('shazbot', 6);
INSERT INTO foo (bar, baz) VALUES ('shazbot', 7);
INSERT INTO foo (bar, baz) VALUES ('shazbot', 8);
INSERT INTO foo (bar, baz) VALUES ('shazbot', 9);
INSERT INTO foo (bar, baz) VALUES ('shazbot', 10);
/* /*
Copyright (c) 2009, Eric Fredricksen <e@fredricksen.net> Copyright (c) 2009, Eric Fredricksen <e@fredricksen.net>
Copyright (c) 2010, Orlando Vazquez <ovazquez@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
...@@ -67,11 +68,9 @@ using namespace node; ...@@ -67,11 +68,9 @@ using namespace node;
String::New("Argument " #I " must be an integer"))); \ String::New("Argument " #I " must be an integer"))); \
} }
class Sqlite3Db : public EventEmitter class Sqlite3Db : public EventEmitter {
{
public: public:
static void Init(v8::Handle<Object> target) static void Init(v8::Handle<Object> target) {
{
HandleScope scope; HandleScope scope;
Local<FunctionTemplate> t = FunctionTemplate::New(New); Local<FunctionTemplate> t = FunctionTemplate::New(New);
...@@ -659,8 +658,175 @@ protected: ...@@ -659,8 +658,175 @@ protected:
return Undefined(); return Undefined();
} }
struct step_request {
Persistent<Function> cb;
Statement *sto;
// Populate two arrays: one will be the types of columns for the result,
// the second will be the data for the row.
int column_count;
int *column_types;
void **column_data;
};
static int EIO_AfterStep(eio_req *req) {
HandleScope scope;
struct step_request *step_req = (struct step_request *)(req->data);
ev_unref(EV_DEFAULT_UC);
void **data = step_req->column_data;
printf("column_data addr was %p\n", ((void**)data)+1);
printf("there were %d columns\n", step_req->column_count);
for (int i = 0; i < step_req->column_count; i++) {
printf("value addr was %p\n", (step_req->column_data[i]));
switch(step_req->column_types[i]) {
case SQLITE_INTEGER:
printf("type was an integer\n");
printf("value was %d\n", *(int*)(step_req->column_data[i]));
break;
case SQLITE_TEXT:
printf("type was as string\n");
printf("value was %s\n", (char*)(step_req->column_data[i]));
break;
default:
printf("dunno\n");
}
}
step_req->cb.Dispose();
free(step_req);
step_req->sto->Unref();
return 0;
}
static int EIO_Step(eio_req *req) {
struct step_request *step_req = (struct step_request *)(req->data);
Statement *sto = step_req->sto;
// int rc = sqlite3_step(*stmt);
// if (rc == SQLITE_ROW) {
// Local<Object> row = Object::New();
// for (int c = 0; c < sqlite3_column_count(*stmt); ++c) {
// Handle<Value> value;
// switch (sqlite3_column_type(*stmt, c)) {
// case SQLITE_INTEGER:
// value = Integer::New(sqlite3_column_int(*stmt, c));
// break;
// case SQLITE_FLOAT:
// value = Number::New(sqlite3_column_double(*stmt, c));
// break;
// case SQLITE_TEXT:
// value = String::New((const char*) sqlite3_column_text(*stmt, c));
// break;
// case SQLITE_NULL:
// default: // We don't handle any other types just now
// value = Undefined();
// break;
// }
// row->Set(String::NewSymbol(sqlite3_column_name(*stmt, c)),
// value);
// }
// return row;
// } else if (rc == SQLITE_DONE) {
// return Null();
// } else {
// return ThrowException(Exception::Error(String::New(
// sqlite3_errmsg(sqlite3_db_handle(*stmt)))));
// }
sqlite3_stmt *stmt = *sto;
int rc = sqlite3_step(stmt);
printf("result of step %d\n", rc);
if (rc == SQLITE_ROW) {
// would be nice to not have to fetch and return the columns always
step_req->column_count = sqlite3_column_count(stmt);
step_req->column_types =
(int *) calloc(step_req->column_count, sizeof(int));
step_req->column_data =
(void **) calloc(step_req->column_count, sizeof(void *));
for (int i = 0; i < step_req->column_count; i++) {
int type = step_req->column_types[i] = sqlite3_column_type(stmt, i);
switch(type) {
case SQLITE_INTEGER: {
int *value = (int*) malloc(sizeof(int));
*value = sqlite3_column_int(stmt, i);
step_req->column_data[i] = value;
printf("serialized int %d\n", *(int*)(step_req->column_data[i]));
}
break;
case SQLITE_FLOAT: {
double *value = (double*) malloc(sizeof(double));
*value = sqlite3_column_double(stmt, i);
step_req->column_data[i] = value;
printf("serialized float\n");
}
break;
case SQLITE_TEXT: {
// It shouldn't be necessary to copy or free() this value,
// according to http://www.sqlite.org/c3ref/column_blob.html
// it will be reclaimed on the next step, reset, or finalize.
// I'm going to assume it's okay to keep this pointer around
// until it is used in `EIO_AfterStep`
char *value = (char *)sqlite3_column_text(stmt, i);
step_req->column_data[i] = value;
printf("serialized text %s\n", step_req->column_data[i]);
}
break;
default: {
// unsupported type
printf("default, not serialized\n");
}
}
}
}
else if (rc == SQLITE_DONE) {
// done case
}
else {
// error case
}
req->result = 0;
return 0;
}
static Handle<Value> Step(const Arguments& args) { static Handle<Value> Step(const Arguments& args) {
HandleScope scope; HandleScope scope;
REQ_FUN_ARG(0, cb);
Statement* sto = ObjectWrap::Unwrap<Statement>(args.This());
struct step_request *step_req = (struct step_request *)
calloc(1, sizeof(struct step_request));
if (!step_req) {
V8::LowMemoryNotification();
return ThrowException(Exception::Error(
String::New("Could not allocate enough memory")));
}
step_req->cb = Persistent<Function>::New(cb);
step_req->sto = sto;
eio_custom(EIO_Step, EIO_PRI_DEFAULT, EIO_AfterStep, step_req);
ev_ref(EV_DEFAULT_UC);
sto->Ref();
return Undefined();
}
static Handle<Value> Step2(const Arguments& args) {
HandleScope scope;
Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This()); Statement* stmt = ObjectWrap::Unwrap<Statement>(args.This());
int rc = sqlite3_step(*stmt); int rc = sqlite3_step(*stmt);
if (rc == SQLITE_ROW) { if (rc == SQLITE_ROW) {
...@@ -677,7 +843,7 @@ protected: ...@@ -677,7 +843,7 @@ protected:
case SQLITE_TEXT: case SQLITE_TEXT:
value = String::New((const char*) sqlite3_column_text(*stmt, c)); value = String::New((const char*) sqlite3_column_text(*stmt, c));
break; break;
case SQLITE_NULL:
default: // We don't handle any other types just now default: // We don't handle any other types just now
value = Undefined(); value = Undefined();
break; break;
......
...@@ -18,7 +18,8 @@ throws(function () { ...@@ -18,7 +18,8 @@ throws(function () {
db.open("foo.db"); db.open("foo.db");
}); });
db.open("mydatabase.db", function (err) { function testBinds() {
db.open("mydatabase.db", function (err) {
puts(inspect(arguments)); puts(inspect(arguments));
if (err) { if (err) {
puts("There was an error"); puts("There was an error");
...@@ -31,6 +32,9 @@ db.open("mydatabase.db", function (err) { ...@@ -31,6 +32,9 @@ db.open("mydatabase.db", function (err) {
db.prepare("SELECT bar FROM foo; SELECT baz FROM foo;", function (error, statement) { db.prepare("SELECT bar FROM foo; SELECT baz FROM foo;", function (error, statement) {
puts("prepare callback"); puts("prepare callback");
db.prepare("SELECT bar FROM foo WHERE bar = $x and (baz = $y or baz = $z)", function (error, statement) { db.prepare("SELECT bar FROM foo WHERE bar = $x and (baz = $y or baz = $z)", function (error, statement) {
});
db.prepare("SELECT bar FROM foo WHERE bar = $x and (baz = $y or baz = $z)", function (error, statement) {
puts("prepare callback"); puts("prepare callback");
statement.bind(0, 666, function () { statement.bind(0, 666, function () {
...@@ -45,9 +49,13 @@ db.open("mydatabase.db", function (err) { ...@@ -45,9 +49,13 @@ db.open("mydatabase.db", function (err) {
statement.bind('$z', 3.141, function () { statement.bind('$z', 3.141, function () {
puts("bind callback"); puts("bind callback");
statement.bind('$a', 'no such param', function (err) { // statement.bind('$a', 'no such param', function (err) {
puts(inspect(arguments)); // puts(inspect(arguments));
puts("bind callback"); puts("bind callback");
statement.step(function () {
puts("step callback");
});
// });
}); });
}); });
}); });
...@@ -55,6 +63,16 @@ db.open("mydatabase.db", function (err) { ...@@ -55,6 +63,16 @@ db.open("mydatabase.db", function (err) {
}); });
}); });
}); });
}
db.open("mydatabase.db", function () {
db.prepare("SELECT bar, baz FROM foo WHERE baz > 5", function (error, statement) {
puts(inspect(arguments));
statement.step(function () {
puts('query callback');
});
});
}); });
puts("done"); puts("done");
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