mirror of
https://github.com/nodejs/node.git
synced 2025-12-28 07:50:41 +00:00
sqlite: add getter to detect transactions
This commit adds an isTransaction getter to the DatabaseSync class for determining if the database is currently within a transaction. Fixes: https://github.com/nodejs/node/issues/57922 PR-URL: https://github.com/nodejs/node/pull/57925 Reviewed-By: Edy Silva <edigleyssonsilva@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Zeyu "Alex" Yang <himself65@outlook.com>
This commit is contained in:
parent
7102ea1559
commit
2e0ec72f54
@ -291,6 +291,15 @@ added: v23.11.0
|
||||
|
||||
* {boolean} Whether the database is currently open or not.
|
||||
|
||||
### `database.isTransaction`
|
||||
|
||||
<!-- YAML
|
||||
added: REPLACEME
|
||||
-->
|
||||
|
||||
* {boolean} Whether the database is currently within a transaction. This method
|
||||
is a wrapper around [`sqlite3_get_autocommit()`][].
|
||||
|
||||
### `database.open()`
|
||||
|
||||
<!-- YAML
|
||||
@ -839,6 +848,7 @@ resolution handler passed to [`database.applyChangeset()`][]. See also
|
||||
[`sqlite3_create_window_function()`]: https://www.sqlite.org/c3ref/create_function.html
|
||||
[`sqlite3_exec()`]: https://www.sqlite.org/c3ref/exec.html
|
||||
[`sqlite3_expanded_sql()`]: https://www.sqlite.org/c3ref/expanded_sql.html
|
||||
[`sqlite3_get_autocommit()`]: https://sqlite.org/c3ref/get_autocommit.html
|
||||
[`sqlite3_last_insert_rowid()`]: https://www.sqlite.org/c3ref/last_insert_rowid.html
|
||||
[`sqlite3_load_extension()`]: https://www.sqlite.org/c3ref/load_extension.html
|
||||
[`sqlite3_prepare_v2()`]: https://www.sqlite.org/c3ref/prepare.html
|
||||
|
||||
@ -979,6 +979,15 @@ void DatabaseSync::IsOpenGetter(const FunctionCallbackInfo<Value>& args) {
|
||||
args.GetReturnValue().Set(db->IsOpen());
|
||||
}
|
||||
|
||||
void DatabaseSync::IsTransactionGetter(
|
||||
const FunctionCallbackInfo<Value>& args) {
|
||||
DatabaseSync* db;
|
||||
ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
THROW_AND_RETURN_ON_BAD_STATE(env, !db->IsOpen(), "database is not open");
|
||||
args.GetReturnValue().Set(sqlite3_get_autocommit(db->connection_) == 0);
|
||||
}
|
||||
|
||||
void DatabaseSync::Close(const FunctionCallbackInfo<Value>& args) {
|
||||
DatabaseSync* db;
|
||||
ASSIGN_OR_RETURN_UNWRAP(&db, args.This());
|
||||
@ -2623,6 +2632,10 @@ static void Initialize(Local<Object> target,
|
||||
db_tmpl,
|
||||
FIXED_ONE_BYTE_STRING(isolate, "isOpen"),
|
||||
DatabaseSync::IsOpenGetter);
|
||||
SetSideEffectFreeGetter(isolate,
|
||||
db_tmpl,
|
||||
FIXED_ONE_BYTE_STRING(isolate, "isTransaction"),
|
||||
DatabaseSync::IsTransactionGetter);
|
||||
SetConstructorFunction(context, target, "DatabaseSync", db_tmpl);
|
||||
SetConstructorFunction(context,
|
||||
target,
|
||||
|
||||
@ -61,6 +61,8 @@ class DatabaseSync : public BaseObject {
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Open(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void IsOpenGetter(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void IsTransactionGetter(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Prepare(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Exec(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
@ -324,3 +324,40 @@ suite('DatabaseSync.prototype.exec()', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('DatabaseSync.prototype.isTransaction', () => {
|
||||
test('correctly detects a committed transaction', (t) => {
|
||||
const db = new DatabaseSync(':memory:');
|
||||
|
||||
t.assert.strictEqual(db.isTransaction, false);
|
||||
db.exec('BEGIN');
|
||||
t.assert.strictEqual(db.isTransaction, true);
|
||||
db.exec('CREATE TABLE foo (id INTEGER PRIMARY KEY)');
|
||||
t.assert.strictEqual(db.isTransaction, true);
|
||||
db.exec('COMMIT');
|
||||
t.assert.strictEqual(db.isTransaction, false);
|
||||
});
|
||||
|
||||
test('correctly detects a rolled back transaction', (t) => {
|
||||
const db = new DatabaseSync(':memory:');
|
||||
|
||||
t.assert.strictEqual(db.isTransaction, false);
|
||||
db.exec('BEGIN');
|
||||
t.assert.strictEqual(db.isTransaction, true);
|
||||
db.exec('CREATE TABLE foo (id INTEGER PRIMARY KEY)');
|
||||
t.assert.strictEqual(db.isTransaction, true);
|
||||
db.exec('ROLLBACK');
|
||||
t.assert.strictEqual(db.isTransaction, false);
|
||||
});
|
||||
|
||||
test('throws if database is not open', (t) => {
|
||||
const db = new DatabaseSync(nextDb(), { open: false });
|
||||
|
||||
t.assert.throws(() => {
|
||||
return db.isTransaction;
|
||||
}, {
|
||||
code: 'ERR_INVALID_STATE',
|
||||
message: /database is not open/,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user