Permalink
Browse files

Remove transaction handling from JdbcBackend#Session:

It was only needed for `insertOrUpdate` and could cause the wrong
Exceptions to be swallowed. `InsertOrUpdateAction` now implements the
correct transaction logic based directly on `startInTransaction` and
`endInTransaction`.

Fixes #1279.
  • Loading branch information...
szeiger committed Sep 22, 2015
1 parent 079c110 commit 0cfff09c4e5181d45ba705ce57dbcff8b2e341b4
@@ -538,7 +538,19 @@ trait JdbcActionComponent extends SqlActionComponent { driver: JdbcDriver =>
def run(ctx: Backend#Context, sql: Vector[String]) = {
def f: SingleInsertOrUpdateResult =
if(useServerSideUpsert) nativeUpsert(value, sql.head)(ctx.session) else emulate(value, sql(0), sql(1), sql(2))(ctx.session)
if(useTransactionForUpsert) ctx.session.withTransaction(f) else f
if(useTransactionForUpsert) {
ctx.session.startInTransaction
var done = false
try {
val res = f
done = true
ctx.session.endInTransaction(ctx.session.conn.commit())
res
} finally {
if(!done)
try ctx.session.endInTransaction(ctx.session.conn.rollback()) catch ignoreFollowOnError
}
} else f
}
protected def nativeUpsert(value: U, sql: String)(implicit session: Backend#Session): SingleInsertOrUpdateResult =
@@ -371,21 +371,8 @@ trait JdbcBackend extends RelationalBackend {
def close(): Unit
/**
* Call this method within a <em>withTransaction</em> call to roll back the current
* transaction after <em>withTransaction</em> returns.
*/
def rollback(): Unit
def force() { conn }
/**
* Run the supplied function within a transaction. If the function throws an Exception
* or the session's rollback() method is called, the transaction is rolled back,
* otherwise it is commited when the function returns.
*/
def withTransaction[T](f: => T): T
private[slick] final def internalForParameters(rsType: ResultSetType, rsConcurrency: ResultSetConcurrency,
rsHoldability: ResultSetHoldability, statementInit: Statement => Unit, _fetchSize: Int): Session = new Session {
override def resultSetType = rsType
@@ -401,8 +388,6 @@ trait JdbcBackend extends RelationalBackend {
def metaData = self.metaData
def capabilities = self.capabilities
def close() = self.close()
def rollback() = self.rollback()
def withTransaction[T](f: => T) = self.withTransaction(f)
private[slick] def startInTransaction: Unit = self.startInTransaction
private[slick] def endInTransaction(f: => Unit): Unit = self.endInTransaction(f)
}
@@ -421,7 +406,6 @@ trait JdbcBackend extends RelationalBackend {
class BaseSession(val database: Database) extends SessionDef {
protected var open = false
protected var doRollback = false
protected var inTransactionally = 0
def isOpen = open
@@ -449,26 +433,6 @@ trait JdbcBackend extends RelationalBackend {
if(open) conn.close()
}
def rollback() {
if(conn.getAutoCommit) throw new SlickException("Cannot roll back session in auto-commit mode")
doRollback = true
}
def withTransaction[T](f: => T): T = if(isInTransaction) f else {
startInTransaction
try {
var done = false
try {
doRollback = false
val res = f
if(doRollback) conn.rollback()
else conn.commit()
done = true
res
} finally if(!done) conn.rollback()
} finally endInTransaction()
}
private[slick] def startInTransaction: Unit = {
if(!isInTransaction) conn.setAutoCommit(false)
inTransactionally += 1

0 comments on commit 0cfff09

Please sign in to comment.