Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/node_sqlite.cc
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,22 @@ void DatabaseSync::New(const FunctionCallbackInfo<Value>& args) {
allow_load_extension = allow_extension_v.As<Boolean>()->Value();
}

Local<String> read_bigints_string =
FIXED_ONE_BYTE_STRING(env->isolate(), "readBigInts");
Local<Value> read_bigints_v;
if (options->Get(env->context(), read_bigints_string)
.ToLocal(&read_bigints_v)) {
if (!read_bigints_v->IsUndefined()) {
if (!read_bigints_v->IsBoolean()) {
THROW_ERR_INVALID_ARG_TYPE(
env->isolate(),
"The \"options.readBigInts\" argument must be a boolean.");
return;
}
open_config.set_use_big_ints(read_bigints_v.As<Boolean>()->Value());
}
}

Local<Value> timeout_v;
if (!options->Get(env->context(), env->timeout_string())
.ToLocal(&timeout_v)) {
Expand Down Expand Up @@ -1772,10 +1788,10 @@ StatementSync::StatementSync(Environment* env,
: BaseObject(env, object), db_(std::move(db)) {
MakeWeak();
statement_ = stmt;
use_big_ints_ = db_->use_big_ints();
// In the future, some of these options could be set at the database
// connection level and inherited by statements to reduce boilerplate.
return_arrays_ = false;
use_big_ints_ = false;
allow_bare_named_params_ = true;
allow_unknown_named_params_ = false;
bare_named_params_ = std::nullopt;
Expand Down
6 changes: 6 additions & 0 deletions src/node_sqlite.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,17 @@ class DatabaseOpenConfiguration {

inline int get_timeout() { return timeout_; }

inline void set_use_big_ints(bool flag) { use_big_ints_ = flag; }

inline bool get_use_big_ints() const { return use_big_ints_; }

private:
std::string location_;
bool read_only_ = false;
bool enable_foreign_keys_ = true;
bool enable_dqs_ = false;
int timeout_ = 0;
bool use_big_ints_ = false;
};

class StatementSync;
Expand Down Expand Up @@ -82,6 +87,7 @@ class DatabaseSync : public BaseObject {
void FinalizeBackups();
void UntrackStatement(StatementSync* statement);
bool IsOpen();
bool use_big_ints() const { return open_config_.get_use_big_ints(); }
sqlite3* Connection();

// In some situations, such as when using custom functions, it is possible
Expand Down
55 changes: 55 additions & 0 deletions test/parallel/test-sqlite-database-sync.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,61 @@ suite('DatabaseSync() constructor', () => {
t.after(() => { db.close(); });
db.exec('SELECT "foo";');
});

test('throws if options.readBigInts is provided but is not a boolean', (t) => {
t.assert.throws(() => {
new DatabaseSync('foo', { readBigInts: 42 });
}, {
code: 'ERR_INVALID_ARG_TYPE',
message: /The "options\.readBigInts" argument must be a boolean/,
});
});

test('allows reading big integers', (t) => {
const dbPath = nextDb();
const db = new DatabaseSync(dbPath, { readBigInts: true });
t.after(() => { db.close(); });

const setup = db.exec(`
CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER) STRICT;
INSERT INTO data (key, val) VALUES (1, 42);
`);
t.assert.strictEqual(setup, undefined);

const query = db.prepare('SELECT val FROM data');
t.assert.strictEqual(query.setReadBigInts(true), undefined);
t.assert.deepStrictEqual(query.get(), { __proto__: null, val: 42n });

const insert = db.prepare('INSERT INTO data (key) VALUES (?)');
t.assert.strictEqual(insert.setReadBigInts(true), undefined);
t.assert.deepStrictEqual(
insert.run(20),
{ changes: 1n, lastInsertRowid: 20n },
);
});

test('allows reading numbers', (t) => {
const dbPath = nextDb();
const db = new DatabaseSync(dbPath, { readBigInts: false });
t.after(() => { db.close(); });

const setup = db.exec(`
CREATE TABLE data(key INTEGER PRIMARY KEY, val INTEGER) STRICT;
INSERT INTO data (key, val) VALUES (1, 42);
`);
t.assert.strictEqual(setup, undefined);

const query = db.prepare('SELECT val FROM data');
t.assert.strictEqual(query.setReadBigInts(false), undefined);
t.assert.deepStrictEqual(query.get(), { __proto__: null, val: 42 });

const insert = db.prepare('INSERT INTO data (key) VALUES (?)');
t.assert.strictEqual(insert.setReadBigInts(false), undefined);
t.assert.deepStrictEqual(
insert.run(20),
{ changes: 1, lastInsertRowid: 20 },
);
});
});

suite('DatabaseSync.prototype.open()', () => {
Expand Down
Loading