Skip to content

Commit

Permalink
fix: disable transactionSupport option for CordovaDriver (#9391)
Browse files Browse the repository at this point in the history
* fix: disable transaction support for cordova driver

the cordova-sqlite-storage plugin does not support transactions. fc4133c
introduced an exception when starting a transactions but did not disable
the transactionSupport in general leading to errors when using the
`save` and `remove` method of the `EntityPersistExecutor`. With this PR
the `EntityPersistExecutor` will respect the drivers `transactionSupport`
option.

* docs: add note on transaction limitations for cordova driver
  • Loading branch information
michaelwolz committed Dec 3, 2022
1 parent f215e2d commit 53fad8f
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 5 deletions.
2 changes: 1 addition & 1 deletion docs/supported-platforms.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ In your main html page, you need to include reflect-metadata:
TypeORM is able to run on Cordova, PhoneGap, Ionic apps using the
[cordova-sqlite-storage](https://github.com/litehelpers/Cordova-sqlite-storage) plugin
You have the option to choose between module loaders just like in browser package.
For an example how to use TypeORM in Cordova see [typeorm/cordova-example](https://github.com/typeorm/cordova-example) and for Ionic see [typeorm/ionic-example](https://github.com/typeorm/ionic-example). **Important**: For use with Ionic, a custom webpack config file is needed! Please checkout the example to see the needed changes.
For an example how to use TypeORM in Cordova see [typeorm/cordova-example](https://github.com/typeorm/cordova-example) and for Ionic see [typeorm/ionic-example](https://github.com/typeorm/ionic-example). **Important**: For use with Ionic, a custom webpack config file is needed! Please checkout the example to see the needed changes. Note that there is currently no support for transactions when using the [cordova-sqlite-storage](https://github.com/litehelpers/Cordova-sqlite-storage) plugin. See https://github.com/storesafe/cordova-sqlite-storage#other-limitations for more information.

## React Native

Expand Down
2 changes: 2 additions & 0 deletions src/driver/cordova/CordovaDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ declare let window: Window
export class CordovaDriver extends AbstractSqliteDriver {
options: CordovaConnectionOptions

transactionSupport = "none" as const

// -------------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------------
Expand Down
5 changes: 4 additions & 1 deletion src/persistence/EntityPersistExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,10 @@ export class EntityPersistExecutor {
try {
// open transaction if its not opened yet
if (!queryRunner.isTransactionActive) {
if (!this.options || this.options.transaction !== false) {
if (
this.connection.driver.transactionSupport !== "none" &&
(!this.options || this.options.transaction !== false)
) {
// start transaction until it was not explicitly disabled
isTransactionStartedByUs = true
await queryRunner.startTransaction()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
} from "../../../../utils/test-utils"
import { Post } from "./entity/Post"
import { DataSource } from "../../../../../src/data-source/DataSource"
// import {expect} from "chai";
import sinon from "sinon"
import { expect } from "chai"

describe("persistence > persistence options > transaction", () => {
// -------------------------------------------------------------------------
Expand All @@ -31,8 +32,68 @@ describe("persistence > persistence options > transaction", () => {
const post = new Post()
post.title = "Bakhrom"
post.description = "Hello"
await connection.manager.save(post, { transaction: false })
// todo: check if actual transaction query is not executed

const queryRunner = connection.createQueryRunner()

const startTransactionFn = sinon.spy(
queryRunner,
"startTransaction",
)
const commitTransactionFn = sinon.spy(
queryRunner,
"commitTransaction",
)

await connection
.createEntityManager(queryRunner)
.getRepository(Post)
.save(post, { transaction: false })

expect(startTransactionFn.called).to.be.false
expect(commitTransactionFn.called).to.be.false

// Cleanup
await queryRunner.release()
sinon.restore()
}),
))

it("should disable transaction when the drivers transactionSupport setting equals `none`", () =>
Promise.all(
connections.map(async (connection) => {
const post = new Post()
post.title = "Bakhrom"
post.description = "Hello"

// Storing initial driver setting of the `transactionSupport` property
// in order to be able to restore it later
const transactionSupportInitial =
connection.driver.transactionSupport
connection.driver.transactionSupport = "none"

const queryRunner = connection.createQueryRunner()

const startTransactionFn = sinon.spy(
queryRunner,
"startTransaction",
)
const commitTransactionFn = sinon.spy(
queryRunner,
"commitTransaction",
)

await connection
.createEntityManager(queryRunner)
.getRepository(Post)
.save(post)

expect(startTransactionFn.called).to.be.false
expect(commitTransactionFn.called).to.be.false

// Cleanup
await queryRunner.release()
sinon.restore()
connection.driver.transactionSupport = transactionSupportInitial
}),
))
})

0 comments on commit 53fad8f

Please sign in to comment.