Skip to content

Commit

Permalink
Merge pull request #101 from tursodatabase/tx-modes
Browse files Browse the repository at this point in the history
Add support for transaction modes
  • Loading branch information
penberg authored Apr 16, 2024
2 parents e43fedb + 489dc21 commit 7e0106c
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 22 deletions.
36 changes: 25 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,18 +121,32 @@ class Database {
if (typeof fn !== "function")
throw new TypeError("Expected first argument to be a function");

return (...bindParameters) => {
// TODO: Use libsql transaction API.
this.exec("BEGIN");
try {
const result = fn(...bindParameters);
this.exec("COMMIT");
return result;
} catch (err) {
this.exec("ROLLBACK");
throw err;
}
const db = this;
const wrapTxn = (mode) => {
return (...bindParameters) => {
db.exec("BEGIN " + mode);
try {
const result = fn(...bindParameters);
db.exec("COMMIT");
return result;
} catch (err) {
db.exec("ROLLBACK");
throw err;
}
};
};
const properties = {
default: { value: wrapTxn("") },
deferred: { value: wrapTxn("DEFERRED") },
immediate: { value: wrapTxn("IMMEDIATE") },
exclusive: { value: wrapTxn("EXCLUSIVE") },
database: { value: this, enumerable: true },
};
Object.defineProperties(properties.default.value, properties);
Object.defineProperties(properties.deferred.value, properties);
Object.defineProperties(properties.immediate.value, properties);
Object.defineProperties(properties.exclusive.value, properties);
return properties.default.value;
}

pragma(source, options) {
Expand Down
18 changes: 18 additions & 0 deletions integration-tests/tests/async.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,24 @@ test.serial("Database.transaction()", async (t) => {
t.is(stmt.get(5).name, "Junior");
});

test.serial("Database.transaction().immediate()", async (t) => {
const db = t.context.db;
const insert = await db.prepare(
"INSERT INTO users(name, email) VALUES (:name, :email)"
);
const insertMany = db.transaction((users) => {
t.is(db.inTransaction, true);
for (const user of users) insert.run(user);
});
t.is(db.inTransaction, false);
await insertMany.immediate([
{ name: "Joey", email: "[email protected]" },
{ name: "Sally", email: "[email protected]" },
{ name: "Junior", email: "[email protected]" },
]);
t.is(db.inTransaction, false);
});

test.serial("Database.pragma()", async (t) => {
const db = t.context.db;
await db.pragma("cache_size = 2000");
Expand Down
18 changes: 18 additions & 0 deletions integration-tests/tests/sync.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,24 @@ test.serial("Database.transaction()", async (t) => {
t.is(stmt.get(5).name, "Junior");
});

test.serial("Database.transaction().immediate()", async (t) => {
const db = t.context.db;
const insert = db.prepare(
"INSERT INTO users(name, email) VALUES (:name, :email)"
);
const insertMany = db.transaction((users) => {
t.is(db.inTransaction, true);
for (const user of users) insert.run(user);
});
t.is(db.inTransaction, false);
insertMany.immediate([
{ name: "Joey", email: "[email protected]" },
{ name: "Sally", email: "[email protected]" },
{ name: "Junior", email: "[email protected]" },
]);
t.is(db.inTransaction, false);
});

test.serial("values", async (t) => {
const db = t.context.db;

Expand Down
36 changes: 25 additions & 11 deletions promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,18 +124,32 @@ class Database {
if (typeof fn !== "function")
throw new TypeError("Expected first argument to be a function");

return async (...bindParameters) => {
// TODO: Use libsql transaction API.
await this.exec("BEGIN");
try {
const result = fn(...bindParameters);
await this.exec("COMMIT");
return result;
} catch (err) {
await this.exec("ROLLBACK");
throw err;
}
const db = this;
const wrapTxn = (mode) => {
return async (...bindParameters) => {
await db.exec("BEGIN " + mode);
try {
const result = fn(...bindParameters);
await db.exec("COMMIT");
return result;
} catch (err) {
await db.exec("ROLLBACK");
throw err;
}
};
};
const properties = {
default: { value: wrapTxn("") },
deferred: { value: wrapTxn("DEFERRED") },
immediate: { value: wrapTxn("IMMEDIATE") },
exclusive: { value: wrapTxn("EXCLUSIVE") },
database: { value: this, enumerable: true },
};
Object.defineProperties(properties.default.value, properties);
Object.defineProperties(properties.deferred.value, properties);
Object.defineProperties(properties.immediate.value, properties);
Object.defineProperties(properties.exclusive.value, properties);
return properties.default.value;
}

pragma(source, options) {
Expand Down

0 comments on commit 7e0106c

Please sign in to comment.