Commit 09e68144 by Konstantin Käfer

add blob support

parent 6e391c03
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#include <v8.h> #include <v8.h>
#include <node.h> #include <node.h>
#include <node_events.h> #include <node_events.h>
#include <node_buffer.h>
#include <node_version.h>
#include "macros.h" #include "macros.h"
#include "database.h" #include "database.h"
...@@ -186,6 +188,10 @@ template <class T> T* Statement::Bind(const Arguments& args, int start) { ...@@ -186,6 +188,10 @@ template <class T> T* Statement::Bind(const Arguments& args, int start) {
else if (args[i]->IsNull()) { else if (args[i]->IsNull()) {
baton->parameters.push_back(new Data::Null()); baton->parameters.push_back(new Data::Null());
} }
else if (Buffer::HasInstance(args[i])) {
Local<Object> buffer = args[i]->ToObject();
baton->parameters.push_back(new Data::Blob(Buffer::Length(buffer), Buffer::Data(buffer)));
}
else if (args[i]->IsUndefined()) { else if (args[i]->IsUndefined()) {
// Skip parameter position. // Skip parameter position.
baton->parameters.push_back(NULL); baton->parameters.push_back(NULL);
...@@ -219,19 +225,23 @@ bool Statement::Bind(const Data::Parameters parameters) { ...@@ -219,19 +225,23 @@ bool Statement::Bind(const Data::Parameters parameters) {
switch (field->type) { switch (field->type) {
case SQLITE_INTEGER: { case SQLITE_INTEGER: {
status = sqlite3_bind_int(handle, i, ((Data::Integer*)field)->value); status = sqlite3_bind_int(handle, i,
((Data::Integer*)field)->value);
} break; } break;
case SQLITE_FLOAT: { case SQLITE_FLOAT: {
status = sqlite3_bind_double(handle, i, ((Data::Float*)field)->value); status = sqlite3_bind_double(handle, i,
((Data::Float*)field)->value);
} break; } break;
case SQLITE_TEXT: { case SQLITE_TEXT: {
status = sqlite3_bind_text( status = sqlite3_bind_text(handle, i,
handle, i, ((Data::Text*)field)->value.c_str(), ((Data::Text*)field)->value.c_str(),
((Data::Text*)field)->value.size(), SQLITE_TRANSIENT); ((Data::Text*)field)->value.size(), SQLITE_TRANSIENT);
} break; } break;
// case SQLITE_BLOB: { case SQLITE_BLOB: {
// status = sqlite3_bind_blob(handle, i,
// } break; ((Data::Blob*)field)->value,
((Data::Blob*)field)->length, SQLITE_TRANSIENT);
} break;
case SQLITE_NULL: { case SQLITE_NULL: {
status = sqlite3_bind_null(handle, i); status = sqlite3_bind_null(handle, i);
} break; } break;
...@@ -566,9 +576,10 @@ Local<Array> Statement::RowToJS(Data::Row* row) { ...@@ -566,9 +576,10 @@ Local<Array> Statement::RowToJS(Data::Row* row) {
case SQLITE_TEXT: { case SQLITE_TEXT: {
result->Set(i, Local<String>(String::New(((Data::Text*)field)->value.c_str(), ((Data::Text*)field)->value.size()))); result->Set(i, Local<String>(String::New(((Data::Text*)field)->value.c_str(), ((Data::Text*)field)->value.size())));
} break; } break;
// case SQLITE_BLOB: { case SQLITE_BLOB: {
// result->Set(i, Local<String>(String::New(((Data::Text*)field)->value.c_str()))); Buffer *buffer = Buffer::New(((Data::Blob*)field)->value, ((Data::Blob*)field)->length);
// } break; result->Set(i, buffer->handle_);
} break;
case SQLITE_NULL: { case SQLITE_NULL: {
result->Set(i, Local<Value>::New(Null())); result->Set(i, Local<Value>::New(Null()));
} break; } break;
......
...@@ -42,14 +42,14 @@ namespace Data { ...@@ -42,14 +42,14 @@ namespace Data {
struct Blob : Field { struct Blob : Field {
Blob(size_t len, const void* val) : Field(SQLITE_BLOB), length(len) { Blob(size_t len, const void* val) : Field(SQLITE_BLOB), length(len) {
value = malloc(len); value = (char*)malloc(len);
memcpy(value, val, len); memcpy(value, val, len);
} }
~Blob() { ~Blob() {
free(value); free(value);
} }
int length; int length;
void* value; char* value;
}; };
typedef Field Null; typedef Field Null;
......
...@@ -5,71 +5,44 @@ var sqlite3 = require('sqlite3'), ...@@ -5,71 +5,44 @@ var sqlite3 = require('sqlite3'),
Buffer = require('buffer').Buffer; Buffer = require('buffer').Buffer;
// lots of elmo // lots of elmo
var elmo = fs.readFileSync(__dirname + '/support/elmo.png', 'binary'); var elmo = fs.readFileSync(__dirname + '/support/elmo.png');
var elmo_str = elmo.toString('binary');
exports['Blob overflow test'] = function(beforeExit) { exports['blob test'] = function(beforeExit) {
var db = new sqlite3.Database(''); var db = new sqlite3.Database(':memory:');
var total = 10; var total = 10;
var inserted = 0; var inserted = 0;
var retrieved = 0; var retrieved = 0;
Step( db.serialize(function() {
function() { db.run('CREATE TABLE elmos (id INT, image BLOB)');
var next = this;
db.prepare('CREATE TABLE elmos (image BLOB);').run(next);
},
function() {
var group = this.group();
for (var i = 0; i < total; i++) {
var next = group();
db.prepare('INSERT INTO elmos (image) VALUES (?)', function(err, statement) {
assert.isUndefined(err);
statement.bind(1, elmo, function() {
statement.step(function(err) {
assert.isUndefined(err);
inserted++;
next();
});
});
});
}
},
function() {
var next = this;
db.execute('SELECT COUNT(*) as amount FROM elmos', function(err, rows) {
assert.isUndefined(err);
assert.eql(rows[0].amount, total);
next();
});
},
function() {
var next = this;
db.prepare('SELECT image FROM elmos;', function(err, statement) {
assert.isUndefined(err);
fetch();
function fetch() { for (var i = 0; i < total; i++) {
statement.step(function(err, row) { db.run('INSERT INTO elmos (id, image) VALUES (?, ?)', i, elmo, function(err) {
assert.isUndefined(err); if (err) throw err;
if (row) { inserted++;
// Not using assert.equal here because it's image data
// and we don't want that in the command line.
assert.ok(elmo_str === row.image);
retrieved++;
fetch();
}
else {
next();
}
});
}
}); });
} }
);
db.all('SELECT id, image FROM elmos ORDER BY id', function(err, rows) {
if (err) throw err;
for (var i = 0; i < rows.length; i++) {
assert.ok(Buffer.isBuffer(rows[i][1]));
assert.ok(elmo.length, rows[i][1]);
for (var j = 0; j < elmo.length; j++) {
if (elmo[j] !== rows[i][1][j]) {
assert.ok(false, "Wrong byte");
}
}
retrieved++;
}
});
});
beforeExit(function() { beforeExit(function() {
assert.eql(inserted, total); assert.equal(inserted, total);
assert.eql(retrieved, total); assert.equal(retrieved, total);
}) })
} }
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