Commit d1a750dc by Will White Committed by Konstantin Käfer

Add blob read/write support.

parent 46eb3b2f
...@@ -147,6 +147,10 @@ int Statement::EIO_BindArray(eio_req *req) { ...@@ -147,6 +147,10 @@ int Statement::EIO_BindArray(eio_req *req) {
rc = sqlite3_bind_text(sto->stmt_, index, (char*)(pair->value), rc = sqlite3_bind_text(sto->stmt_, index, (char*)(pair->value),
pair->value_size, SQLITE_TRANSIENT); pair->value_size, SQLITE_TRANSIENT);
break; break;
case VALUE_BLOB:
rc = sqlite3_bind_blob(sto->stmt_, index, (char*)(pair->value),
pair->value_size, SQLITE_TRANSIENT);
break;
case VALUE_NULL: case VALUE_NULL:
rc = sqlite3_bind_null(sto->stmt_, index); rc = sqlite3_bind_null(sto->stmt_, index);
break; break;
...@@ -388,6 +392,12 @@ Handle<Value> Statement::Bind(const Arguments& args) { ...@@ -388,6 +392,12 @@ Handle<Value> Statement::Bind(const Arguments& args) {
pair->value = value; pair->value = value;
pair->value_size = text.length(); pair->value_size = text.length();
} }
else if (Buffer::HasInstance(args[1])) {
pair->value_type = VALUE_BLOB;
Buffer* buffer = Buffer::Unwrap<Buffer>(args[1]->ToObject());
pair->value = buffer->data();
pair->value_size = buffer->length();
}
else if (args[1]->IsNull() || args[1]->IsUndefined()) { else if (args[1]->IsNull() || args[1]->IsUndefined()) {
pair->value_type = VALUE_NULL; pair->value_type = VALUE_NULL;
pair->value = NULL; pair->value = NULL;
...@@ -525,6 +535,14 @@ int Statement::EIO_AfterStep(eio_req *req) { ...@@ -525,6 +535,14 @@ int Statement::EIO_AfterStep(eio_req *req) {
} }
break; break;
case SQLITE_BLOB: {
node::Buffer *buf = Buffer::New(cell->size);
memcpy(buf->data(), cell->value, cell->size);
row->Set(String::New(sto->column_names_[i]), buf->handle_);
free(cell->value);
}
break;
case SQLITE_NULL: case SQLITE_NULL:
row->Set(String::New(sto->column_names_[i]), row->Set(String::New(sto->column_names_[i]),
Local<Value>::New(Null())); Local<Value>::New(Null()));
...@@ -644,6 +662,16 @@ int Statement::EIO_Step(eio_req *req) { ...@@ -644,6 +662,16 @@ int Statement::EIO_Step(eio_req *req) {
} }
break; break;
case SQLITE_BLOB: {
const void* blob = sqlite3_column_blob(stmt, i);
int size = sqlite3_column_bytes(stmt, i);
cell->size = size;
unsigned char *pzBlob = (unsigned char *)malloc(size);
memcpy(pzBlob, blob, size);
cell->value = pzBlob;
}
break;
case SQLITE_NULL: case SQLITE_NULL:
cell->value = NULL; cell->value = NULL;
break; break;
......
...@@ -22,6 +22,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ...@@ -22,6 +22,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <node_events.h> #include <node_events.h>
#include <sqlite3.h> #include <sqlite3.h>
#include <stdlib.h> #include <stdlib.h>
#include <node_buffer.h>
extern "C" { extern "C" {
#include <mpool.h> #include <mpool.h>
...@@ -34,6 +35,7 @@ struct cell_node { ...@@ -34,6 +35,7 @@ struct cell_node {
void *value; void *value;
int type; int type;
struct cell_node *next; struct cell_node *next;
int size;
}; };
struct row_node { struct row_node {
...@@ -122,6 +124,7 @@ enum BindKeyType { ...@@ -122,6 +124,7 @@ enum BindKeyType {
enum BindValueType { enum BindValueType {
VALUE_INT, VALUE_INT,
VALUE_DOUBLE, VALUE_DOUBLE,
VALUE_BLOB,
VALUE_STRING, VALUE_STRING,
VALUE_NULL VALUE_NULL
}; };
......
require.paths.push(__dirname + '/..');
sys = require('sys');
fs = require('fs');
path = require('path');
TestSuite = require('async-testing/async_testing').TestSuite;
sqlite = require('sqlite');
var db = new sqlite.Database();
var name = "Reading and writing blobs";
var suite = exports[name] = new TestSuite(name);
var fixture_path = path.join(__dirname, 'fixtures/principia_mathematica.jpg');
function createTestTable(db, callback) {
db.prepare('CREATE TABLE [images] (name text,image blob);',
function (error, createStatement) {
if (error) throw error;
createStatement.step(function (error, row) {
if (error) throw error;
callback();
});
});
}
var tests = [
{ "Blob read/write":
function(assert, finished) {
var that = this;
this.db.open(':memory:', function() {
createTestTable(that.db, function() {
that.db.prepare(
'INSERT INTO images (name, image) VALUES ("principia_mathematica", ?);',
function(err, statement) {
if (err) throw err;
fs.readFile(fixture_path, function(err, data) {
if (err) throw err;
assert.equal(data.length, 48538);
statement.bind(1, data, function(err) {
if (err) throw err;
statement.step(function(err, row) {
if (err) throw err;
that.db.prepare(
'SELECT image FROM images WHERE name = "principia_mathematica";',
function(err, statement) {
if (err) throw err;
statement.step(function(err, row) {
if (err) throw err;
assert.equal(row.image.length, 48538);
finished();
});
}
);
});
});
});
}
);
});
});
}
},
{ "Close database after blob query":
function(assert, finished) {
this.db.close(function (err) {
if (err) throw err;
finished();
});
}
}
];
for (var i=0,il=tests.length; i < il; i++) {
suite.addTests(tests[i]);
}
var currentTest = 0;
var testCount = tests.length;
suite.db = new sqlite.Database();
suite.setup(function(finished, test) {
this.db = suite.db;
finished();
});
suite.teardown(function(finished) {
finished();
++currentTest == testCount;
});
if (module == require.main) {
suite.runTests();
}
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