Skip to content

Commit 09e6814

Browse files
committed
add blob support
1 parent 6e391c0 commit 09e6814

3 files changed

Lines changed: 52 additions & 68 deletions

File tree

src/statement.cc

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#include <v8.h>
33
#include <node.h>
44
#include <node_events.h>
5+
#include <node_buffer.h>
6+
#include <node_version.h>
57

68
#include "macros.h"
79
#include "database.h"
@@ -186,6 +188,10 @@ template <class T> T* Statement::Bind(const Arguments& args, int start) {
186188
else if (args[i]->IsNull()) {
187189
baton->parameters.push_back(new Data::Null());
188190
}
191+
else if (Buffer::HasInstance(args[i])) {
192+
Local<Object> buffer = args[i]->ToObject();
193+
baton->parameters.push_back(new Data::Blob(Buffer::Length(buffer), Buffer::Data(buffer)));
194+
}
189195
else if (args[i]->IsUndefined()) {
190196
// Skip parameter position.
191197
baton->parameters.push_back(NULL);
@@ -219,19 +225,23 @@ bool Statement::Bind(const Data::Parameters parameters) {
219225

220226
switch (field->type) {
221227
case SQLITE_INTEGER: {
222-
status = sqlite3_bind_int(handle, i, ((Data::Integer*)field)->value);
228+
status = sqlite3_bind_int(handle, i,
229+
((Data::Integer*)field)->value);
223230
} break;
224231
case SQLITE_FLOAT: {
225-
status = sqlite3_bind_double(handle, i, ((Data::Float*)field)->value);
232+
status = sqlite3_bind_double(handle, i,
233+
((Data::Float*)field)->value);
226234
} break;
227235
case SQLITE_TEXT: {
228-
status = sqlite3_bind_text(
229-
handle, i, ((Data::Text*)field)->value.c_str(),
236+
status = sqlite3_bind_text(handle, i,
237+
((Data::Text*)field)->value.c_str(),
230238
((Data::Text*)field)->value.size(), SQLITE_TRANSIENT);
231239
} break;
232-
// case SQLITE_BLOB: {
233-
//
234-
// } break;
240+
case SQLITE_BLOB: {
241+
status = sqlite3_bind_blob(handle, i,
242+
((Data::Blob*)field)->value,
243+
((Data::Blob*)field)->length, SQLITE_TRANSIENT);
244+
} break;
235245
case SQLITE_NULL: {
236246
status = sqlite3_bind_null(handle, i);
237247
} break;
@@ -566,9 +576,10 @@ Local<Array> Statement::RowToJS(Data::Row* row) {
566576
case SQLITE_TEXT: {
567577
result->Set(i, Local<String>(String::New(((Data::Text*)field)->value.c_str(), ((Data::Text*)field)->value.size())));
568578
} break;
569-
// case SQLITE_BLOB: {
570-
// result->Set(i, Local<String>(String::New(((Data::Text*)field)->value.c_str())));
571-
// } break;
579+
case SQLITE_BLOB: {
580+
Buffer *buffer = Buffer::New(((Data::Blob*)field)->value, ((Data::Blob*)field)->length);
581+
result->Set(i, buffer->handle_);
582+
} break;
572583
case SQLITE_NULL: {
573584
result->Set(i, Local<Value>::New(Null()));
574585
} break;

src/statement.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,14 @@ namespace Data {
4242

4343
struct Blob : Field {
4444
Blob(size_t len, const void* val) : Field(SQLITE_BLOB), length(len) {
45-
value = malloc(len);
45+
value = (char*)malloc(len);
4646
memcpy(value, val, len);
4747
}
4848
~Blob() {
4949
free(value);
5050
}
5151
int length;
52-
void* value;
52+
char* value;
5353
};
5454

5555
typedef Field Null;

test/blob.test.js

Lines changed: 29 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5,71 +5,44 @@ var sqlite3 = require('sqlite3'),
55
Buffer = require('buffer').Buffer;
66

77
// lots of elmo
8-
var elmo = fs.readFileSync(__dirname + '/support/elmo.png', 'binary');
9-
var elmo_str = elmo.toString('binary');
8+
var elmo = fs.readFileSync(__dirname + '/support/elmo.png');
109

11-
exports['Blob overflow test'] = function(beforeExit) {
12-
var db = new sqlite3.Database('');
10+
exports['blob test'] = function(beforeExit) {
11+
var db = new sqlite3.Database(':memory:');
1312
var total = 10;
1413
var inserted = 0;
1514
var retrieved = 0;
1615

17-
Step(
18-
function() {
19-
var next = this;
20-
db.prepare('CREATE TABLE elmos (image BLOB);').run(next);
21-
},
22-
function() {
23-
var group = this.group();
24-
for (var i = 0; i < total; i++) {
25-
var next = group();
26-
db.prepare('INSERT INTO elmos (image) VALUES (?)', function(err, statement) {
27-
assert.isUndefined(err);
28-
statement.bind(1, elmo, function() {
29-
statement.step(function(err) {
30-
assert.isUndefined(err);
31-
inserted++;
32-
next();
33-
});
34-
});
35-
});
36-
}
37-
},
38-
function() {
39-
var next = this;
40-
db.execute('SELECT COUNT(*) as amount FROM elmos', function(err, rows) {
41-
assert.isUndefined(err);
42-
assert.eql(rows[0].amount, total);
43-
next();
44-
});
45-
},
46-
function() {
47-
var next = this;
48-
db.prepare('SELECT image FROM elmos;', function(err, statement) {
49-
assert.isUndefined(err);
50-
fetch();
16+
db.serialize(function() {
17+
db.run('CREATE TABLE elmos (id INT, image BLOB)');
5118

52-
function fetch() {
53-
statement.step(function(err, row) {
54-
assert.isUndefined(err);
55-
if (row) {
56-
// Not using assert.equal here because it's image data
57-
// and we don't want that in the command line.
58-
assert.ok(elmo_str === row.image);
59-
retrieved++;
60-
fetch();
61-
}
62-
else {
63-
next();
64-
}
65-
});
66-
}
19+
for (var i = 0; i < total; i++) {
20+
db.run('INSERT INTO elmos (id, image) VALUES (?, ?)', i, elmo, function(err) {
21+
if (err) throw err;
22+
inserted++;
6723
});
6824
}
69-
);
25+
26+
db.all('SELECT id, image FROM elmos ORDER BY id', function(err, rows) {
27+
if (err) throw err;
28+
for (var i = 0; i < rows.length; i++) {
29+
assert.ok(Buffer.isBuffer(rows[i][1]));
30+
assert.ok(elmo.length, rows[i][1]);
31+
32+
for (var j = 0; j < elmo.length; j++) {
33+
if (elmo[j] !== rows[i][1][j]) {
34+
assert.ok(false, "Wrong byte");
35+
}
36+
}
37+
38+
retrieved++;
39+
}
40+
});
41+
42+
});
7043

7144
beforeExit(function() {
72-
assert.eql(inserted, total);
73-
assert.eql(retrieved, total);
45+
assert.equal(inserted, total);
46+
assert.equal(retrieved, total);
7447
})
7548
}

0 commit comments

Comments
 (0)