Skip to content

Commit affb7a3

Browse files
committed
added .run tests
1 parent f9e5552 commit affb7a3

File tree

11 files changed

+146
-84
lines changed

11 files changed

+146
-84
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
},
2424
"scripts": {
2525
"install": "if [ \"$CI\" = \"true\" ]; then node-gyp rebuild --debug; else node-gyp rebuild; fi;",
26-
"test": "$(npm bin)/mocha --timeout 5000 --slow 5000",
26+
"test": "$(npm bin)/mocha --bail --timeout 5000 --slow 5000",
2727
"pretest": "rm -r ./temp/ || true && mkdir ./temp/",
2828
"posttest": "rm -r ./temp/",
2929
"benchmark": "node benchmark"

src/binder/bind-array-like.cc

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/binder/bind-array.cc

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,18 @@
55
// parameters that were bound.
66

77
int Binder::BindArray(v8::Local<v8::Array> arr) {
8-
return BindArrayLike(v8::Local<v8::Object>::Cast(arr), arr->Length());
8+
unsigned int length = arr->Length();
9+
int len = length > 0x7ffffffeU ? 0x7ffffffe : static_cast<int>(length);
10+
for (int i=0; i<len; ++i) {
11+
Nan::MaybeLocal<v8::Value> maybeValue = Nan::Get(arr, i);
12+
if (maybeValue.IsEmpty()) {
13+
error = "An error was thrown while trying to get values from the given array.";
14+
return i;
15+
}
16+
BindValue(maybeValue.ToLocalChecked());
17+
if (error) {
18+
return i;
19+
}
20+
}
21+
return len;
922
}

src/binder/bind.cc

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,8 @@ void Binder::Bind(Nan::NAN_METHOD_ARGS_TYPE info, int len, Query* query) {
2222
}
2323

2424
// Objects
25-
if (arg->IsObject() && !arg->IsFunction() && !arg->IsArrayBufferView()) {
25+
if (arg->IsObject() && !arg->IsArrayBufferView()) {
2626
v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(arg);
27-
28-
// Plain objects
2927
if (IsPlainObject(obj)) {
3028
if (bound_object) {
3129
error = "You cannot specify named parameters in two different objects.";
@@ -39,19 +37,6 @@ void Binder::Bind(Nan::NAN_METHOD_ARGS_TYPE info, int len, Query* query) {
3937
}
4038
continue;
4139
}
42-
43-
// Array-like objects
44-
double array_like_length = GetArrayLikeLength(obj);
45-
if (error) {
46-
return;
47-
}
48-
if (array_like_length >= 0) {
49-
count += BindArrayLike(obj, static_cast<unsigned int>(array_like_length));
50-
if (error) {
51-
return;
52-
}
53-
continue;
54-
}
5540
}
5641

5742
// All other values

src/binder/binder.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include "../util/macros.h"
1111

1212
#include "next-anon-index.cc"
13-
#include "get-array-like-length.cc"
1413
#include "is-plain-object.cc"
1514
#include "set-binding-error.cc"
1615
#include "get-error.cc"
@@ -21,7 +20,6 @@
2120
#include "bind-null.cc"
2221
#include "bind-value.cc"
2322
#include "bind-array.cc"
24-
#include "bind-array-like.cc"
2523
#include "bind-object.cc"
2624
#include "bind.cc"
2725

src/binder/binder.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,8 @@ class Binder {
2424
void BindValue(v8::Local<v8::Value>, int = 0);
2525

2626
int BindArray(v8::Local<v8::Array>);
27-
int BindArrayLike(v8::Local<v8::Object>, unsigned int);
2827
virtual int BindObject(v8::Local<v8::Object>, v8::Local<v8::Object>); // This should only be invoked once
2928

30-
double GetArrayLikeLength(v8::Local<v8::Object>);
3129
static bool IsPlainObject(v8::Local<v8::Object>);
3230

3331
sqlite3_stmt* handle;

src/binder/get-array-like-length.cc

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/multi-binder/bind.cc

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,8 @@ void MultiBinder::Bind(Nan::NAN_METHOD_ARGS_TYPE info, int len, Query* query) {
2222
}
2323

2424
// Objects
25-
if (arg->IsObject() && !arg->IsFunction() && !arg->IsArrayBufferView()) {
25+
if (arg->IsObject() && !arg->IsArrayBufferView()) {
2626
v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(arg);
27-
28-
// Plain objects
2927
if (IsPlainObject(obj)) {
3028
if (bound_object) {
3129
error = "You cannot specify named parameters in two different objects.";
@@ -39,19 +37,6 @@ void MultiBinder::Bind(Nan::NAN_METHOD_ARGS_TYPE info, int len, Query* query) {
3937
}
4038
continue;
4139
}
42-
43-
// Array-like objects
44-
double array_like_length = GetArrayLikeLength(obj);
45-
if (error) {
46-
return;
47-
}
48-
if (array_like_length >= 0) {
49-
count += BindArrayLike(obj, static_cast<unsigned int>(array_like_length));
50-
if (error) {
51-
return;
52-
}
53-
continue;
54-
}
5540
}
5641

5742
// All other values

src/util/macros.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ inline char* C_STRING(v8::Local<v8::String> string) {
2727
return str;
2828
}
2929

30-
// Given a double, returns whether the number is a valid 32-bit unsigned integer.
31-
inline bool IS_32BIT_UINT(double num) {
32-
return floor(num) == num && num < 4294967296 && num >= 0;
33-
}
34-
3530
// Given a double, returns whether the number is a valid 32-bit signed integer.
3631
inline bool IS_32BIT_INT(double num) {
3732
return floor(num) == num && num < 2147483648 && num >= -2147483648;

test/20.statement.run.js

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
'use strict';
2+
var expect = require('chai').expect;
3+
var Database = require('../.');
4+
var util = require('../tools/test-util.js');
5+
var db;
6+
7+
before(function (done) {
8+
db = new Database(util.next());
9+
db.on('open', done);
10+
});
11+
12+
describe('Statement#run()', function () {
13+
it('should throw an exception when used on a read-only statement', function () {
14+
var stmt = db.prepare('SELECT 555');
15+
expect(function () {stmt.run();}).to.throw(TypeError);
16+
});
17+
it('should work with CREATE TABLE', function () {
18+
var stmt = db.prepare('CREATE TABLE entries (a TEXT, b INTEGER, c REAL, d BLOB)');
19+
var info = stmt.run();
20+
expect(info.changes).to.equal(0);
21+
expect(info.lastInsertROWID).to.equal(0);
22+
});
23+
it('should work with INSERT INTO', function () {
24+
var stmt = db.prepare("INSERT INTO entries VALUES ('foo', 25, 3.14, x'1133ddff')");
25+
var info = stmt.run();
26+
expect(info.changes).to.equal(1);
27+
expect(info.lastInsertROWID).to.equal(1);
28+
29+
info = stmt.run();
30+
expect(info.changes).to.equal(1);
31+
expect(info.lastInsertROWID).to.equal(2);
32+
33+
stmt = db.prepare("INSERT INTO entries VALUES ('foo', 25, 3.14, x'1133ddff'), ('foo', 25, 3.14, x'1133ddff')");
34+
info = stmt.run();
35+
expect(info.changes).to.equal(2);
36+
expect(info.lastInsertROWID).to.equal(4);
37+
});
38+
it('should work with UPDATE', function () {
39+
var stmt = db.prepare("UPDATE entries SET a='bar' WHERE rowid=1");
40+
expect(stmt.run().changes).to.equal(1);
41+
});
42+
it('should work with DELETE FROM', function () {
43+
var stmt = db.prepare("DELETE FROM entries WHERE a='foo'");
44+
expect(stmt.run().changes).to.equal(3);
45+
46+
stmt = db.prepare("INSERT INTO entries VALUES ('foo', 25, 3.14, x'1133ddff')");
47+
var info = stmt.run();
48+
expect(info.changes).to.equal(1);
49+
expect(info.lastInsertROWID).to.equal(2);
50+
});
51+
it('should work with DROP TABLE', function () {
52+
var stmt = db.prepare("DROP TABLE entries");
53+
expect(stmt.run().changes).to.equal(0);
54+
});
55+
it('should throw an exception for failed constraints', function () {
56+
db.prepare('CREATE TABLE people (id INTEGER PRIMARY KEY, name TEXT)').run();
57+
db.prepare('CREATE TABLE ages (age INTEGER, person INTEGER NOT NULL REFERENCES people ON DELETE CASCADE ON UPDATE CASCADE)').run();
58+
db.prepare("INSERT INTO people VALUES (NULL, 'bob')").run();
59+
db.prepare("INSERT INTO people VALUES (NULL, 'sarah')").run();
60+
db.prepare("INSERT INTO ages VALUES (25, 1)").run();
61+
db.prepare("INSERT INTO ages VALUES (30, 2)").run();
62+
db.prepare("INSERT INTO ages VALUES (35, 2)").run();
63+
var stmt = db.prepare("INSERT INTO ages VALUES (30, 3)");
64+
expect(function () {stmt.run();}).to.throw(Error);
65+
stmt = db.prepare("INSERT INTO ages VALUES (30, NULL)");
66+
expect(function () {stmt.run();}).to.throw(Error);
67+
});
68+
it('should not count changes from indirect mechanisms', function () {
69+
var stmt = db.prepare("UPDATE people SET id=55 WHERE id=2");
70+
expect(stmt.run().changes).to.equal(1);
71+
});
72+
it('should count accurate DELETE changes when a dropped table has side effects', function () {
73+
var stmt = db.prepare("DROP TABLE people");
74+
expect(stmt.run().changes).to.equal(2);
75+
});
76+
it('should accept bind parameters', function () {
77+
db.prepare("CREATE TABLE entries (a TEXT CHECK(typeof(a)=='text'), b INTEGER CHECK(typeof(b)=='integer' OR typeof(b)=='real'), c REAL CHECK(typeof(c)=='real' OR typeof(c)=='integer'), d BLOB CHECK(typeof(d)=='blob'))").run();
78+
db.prepare('INSERT INTO entries VALUES (?, ?, ?, ?)').run('foo', 25, 25, Buffer.alloc(8).fill(0xdd));
79+
db.prepare('INSERT INTO entries VALUES (?, ?, ?, ?)').run(['foo', 25, 25, Buffer.alloc(8).fill(0xdd)]);
80+
db.prepare('INSERT INTO entries VALUES (?, ?, ?, ?)').run(['foo', 25], [25], Buffer.alloc(8).fill(0xdd));
81+
db.prepare('INSERT INTO entries VALUES (@a, @b, @c, @d)').run({a: 'foo', b: 25, c: 25, d: Buffer.alloc(8).fill(0xdd)});
82+
db.prepare('INSERT INTO entries VALUES ($a, $b, $c, $d)').run({a: 'foo', b: 25, c: 25, d: Buffer.alloc(8).fill(0xdd)});
83+
db.prepare('INSERT INTO entries VALUES (:a, :b, :c, :d)').run({a: 'foo', b: 25, c: 25, d: Buffer.alloc(8).fill(0xdd)});
84+
db.prepare('INSERT INTO entries VALUES (?, @a, @a, ?)').run({a: 25}, ['foo'], Buffer.alloc(8).fill(0xdd));
85+
expect(function () {
86+
db.prepare('INSERT INTO entries VALUES (?, @a, @a, ?)').run({a: 25}, ['foo'], Buffer.alloc(8).fill(0xdd), Buffer.alloc(8).fill(0xdd));
87+
}).to.throw(Error);
88+
expect(function () {
89+
db.prepare('INSERT INTO entries VALUES (?, @a, @a, ?)').run({a: 25}, ['foo']);
90+
}).to.throw(Error);
91+
expect(function () {
92+
db.prepare('INSERT INTO entries VALUES (?, @a, @a, ?)').run({a: 25, c: 25}, ['foo'], Buffer.alloc(8).fill(0xdd));
93+
}).to.throw(Error);
94+
expect(function () {
95+
db.prepare('INSERT INTO entries VALUES (?, @a, @a, ?)').run({}, ['foo'], Buffer.alloc(8).fill(0xdd));
96+
}).to.throw(Error);
97+
expect(function () {
98+
db.prepare('INSERT INTO entries VALUES (?, ?, ?, ?)').run(25, 'foo', 25, Buffer.alloc(8).fill(0xdd));
99+
}).to.throw(Error);
100+
expect(function () {
101+
db.prepare('INSERT INTO entries VALUES (?, ?, ?, ?)').run('foo', 25, 25, Buffer.alloc(8).fill(0xdd), {foo: 'foo'});
102+
}).to.throw(Error);
103+
db.prepare('INSERT INTO entries VALUES (?, ?, ?, ?)').run('foo', 25, 25, Buffer.alloc(8).fill(0xdd), {});
104+
expect(function () {
105+
db.prepare('INSERT INTO entries VALUES (?, ?, ?, ?)').run('foo', 25, 25, {4: Buffer.alloc(8).fill(0xdd)});
106+
}).to.throw(Error);
107+
expect(function () {
108+
db.prepare('INSERT INTO entries VALUES (?, ?, ?, ?)').run();
109+
}).to.throw(Error);
110+
expect(function () {
111+
db.prepare('INSERT INTO entries VALUES (?, ?, ?, ?)').run({length: 4, 0: 'foo', 1: 25, 2: 25, 3: Buffer.alloc(8).fill(0xdd)});
112+
}).to.throw(Error);
113+
expect(function () {
114+
db.prepare('INSERT INTO entries VALUES (?, ?, ?, ?)').run('foo', 25, new Number(25), Buffer.alloc(8).fill(0xdd));
115+
}).to.throw(Error);
116+
expect(function () {
117+
db.prepare('INSERT INTO entries VALUES (?, ?, ?, ?)').run('foo', {low: 25, high: 25}, 25, Buffer.alloc(8).fill(0xdd));
118+
}).to.throw(Error);
119+
function Foo() {
120+
this.a = 'foo';
121+
this.b = 25;
122+
this.c = 25;
123+
this.d = Buffer.alloc(8).fill(0xdd);
124+
}
125+
expect(function () {
126+
db.prepare('INSERT INTO entries VALUES (@a, @b, @c, @d)').run(new Foo);
127+
}).to.throw(Error);
128+
});
129+
});

0 commit comments

Comments
 (0)