Skip to content

Commit eb193bd

Browse files
Merge pull request #95 from RobertEMackay/verbose_exceptions_should_work_with_prepare_errors
Verbose exception messages should extend to errors thrown when Prepar…
2 parents 61565c4 + e11de8f commit eb193bd

File tree

3 files changed

+133
-43
lines changed

3 files changed

+133
-43
lines changed

sqlest/src/main/scala/sqlest/executor/Database.scala

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -118,29 +118,35 @@ class Session(database: Database) extends Logging {
118118
withConnection { connection =>
119119
val (preprocessedSelect, sql, argumentLists) = database.statementBuilder(select)
120120
val startTime = new DateTime
121-
val preparedStatement = prepareStatement(connection, preprocessedSelect, sql, argumentLists)
122121
try {
123-
val resultSet = preparedStatement.executeQuery
122+
val preparedStatement = prepareStatement(connection, preprocessedSelect, sql, argumentLists)
124123
try {
125-
val result = extractor(resultSet)
126-
val endTime = new DateTime
127-
logger.info(s"Ran sql in ${endTime.getMillis - startTime.getMillis}ms: ${logDetails(connection, sql, argumentLists)}")
128-
result
124+
val resultSet = preparedStatement.executeQuery
125+
try {
126+
val result = extractor(resultSet)
127+
val endTime = new DateTime
128+
logger.info(s"Ran sql in ${endTime.getMillis - startTime.getMillis}ms: ${logDetails(connection, sql, argumentLists)}")
129+
result
130+
} finally {
131+
try {
132+
if (resultSet != null) resultSet.close
133+
} catch {
134+
case e: SQLException =>
135+
}
136+
}
129137
} finally {
130138
try {
131-
if (resultSet != null) resultSet.close
132-
} catch { case e: SQLException => }
139+
if (preparedStatement != null) preparedStatement.close
140+
} catch {
141+
case e: SQLException =>
142+
}
133143
}
134144
} catch {
135145
case NonFatal(e) =>
136146
if (!database.verboseExceptions)
137147
throw e
138148
else
139149
throw new SqlestException(s"Exception running sql: ${logDetails(connection, sql, argumentLists)}", e)
140-
} finally {
141-
try {
142-
if (preparedStatement != null) preparedStatement.close
143-
} catch { case e: SQLException => }
144150
}
145151
}
146152

@@ -300,53 +306,60 @@ case class Transaction(database: Database) extends Session(database) {
300306
withConnection { connection =>
301307
val (preprocessedCommand, sql, argumentLists) = database.statementBuilder(command)
302308
val startTime = new DateTime
303-
val preparedStatement = prepareStatement(connection, preprocessedCommand, sql, argumentLists)
309+
304310
try {
305-
val result = preparedStatement.executeBatch.sum
306-
val endTime = new DateTime
307-
logger.info(s"Ran sql in ${endTime.getMillis - startTime.getMillis}ms: ${logDetails(connection, sql, argumentLists)}")
308-
result
311+
val preparedStatement = prepareStatement(connection, preprocessedCommand, sql, argumentLists)
312+
try {
313+
val result = preparedStatement.executeBatch.sum
314+
val endTime = new DateTime
315+
logger.info(s"Ran sql in ${endTime.getMillis - startTime.getMillis}ms: ${logDetails(connection, sql, argumentLists)}")
316+
result
317+
} finally {
318+
try {
319+
if (preparedStatement != null) preparedStatement.close
320+
} catch { case e: SQLException => }
321+
}
309322
} catch {
310323
case NonFatal(e) =>
311324
if (!database.verboseExceptions)
312325
throw e
313326
else
314327
throw new SqlestException(s"Exception running sql: ${logDetails(connection, sql, argumentLists)}", e)
315-
} finally {
316-
try {
317-
if (preparedStatement != null) preparedStatement.close
318-
} catch { case e: SQLException => }
319328
}
320329
}
321330

322331
def executeInsertReturningKeys[T](command: Insert)(implicit columnType: ColumnType[T]): List[T] =
323332
withConnection { connection =>
324333
val (preprocessedCommand, sql, argumentLists) = database.statementBuilder(command)
325334
val startTime = new DateTime
326-
val preparedStatement = prepareStatement(
327-
connection,
328-
preprocessedCommand,
329-
sql,
330-
argumentLists,
331-
returnKeys = true
332-
)
333335
try {
334-
val result = preparedStatement.executeUpdate
335-
val rs = preparedStatement.getGeneratedKeys
336-
val keys = IndexedExtractor[T](1).extractAll(ResultSetIterable(rs))
337-
val endTime = new DateTime
338-
logger.info(s"Ran sql in ${endTime.getMillis - startTime.getMillis}ms: ${logDetails(connection, sql, argumentLists)}")
339-
keys
336+
val preparedStatement = prepareStatement(
337+
connection,
338+
preprocessedCommand,
339+
sql,
340+
argumentLists,
341+
returnKeys = true
342+
)
343+
try {
344+
val result = preparedStatement.executeUpdate
345+
val rs = preparedStatement.getGeneratedKeys
346+
val keys = IndexedExtractor[T](1).extractAll(ResultSetIterable(rs))
347+
val endTime = new DateTime
348+
logger.info(s"Ran sql in ${endTime.getMillis - startTime.getMillis}ms: ${logDetails(connection, sql, argumentLists)}")
349+
keys
350+
} finally {
351+
try {
352+
if (preparedStatement != null) preparedStatement.close
353+
} catch {
354+
case e: SQLException =>
355+
}
356+
}
340357
} catch {
341358
case NonFatal(e) =>
342359
if (!database.verboseExceptions)
343360
throw e
344361
else
345362
throw new SqlestException(s"Exception running sql: ${logDetails(connection, sql, argumentLists)}", e)
346-
} finally {
347-
try {
348-
if (preparedStatement != null) preparedStatement.close
349-
} catch { case e: SQLException => }
350363
}
351364
}
352365

sqlest/src/test/scala/sqlest/executor/ExecutorSpec.scala

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,4 +441,80 @@ class ExecutorSpec extends FlatSpec with Matchers {
441441

442442
updateException shouldBe database.anException
443443
}
444+
445+
it should "return verbose exception messages on prepare when configured to do so" in {
446+
val database = TestDatabase(testResultSet, Some(keyResultSet), shouldThrow = true, verboseExceptionMessages = true, throwExceptionOnPrepare = true)
447+
448+
val selectException = intercept[SqlestException] {
449+
database.withSession { implicit session =>
450+
selectStatement.fetchAll
451+
}
452+
}
453+
454+
assert(selectException.message.startsWith("Exception running sql"))
455+
selectException.cause shouldBe database.anException
456+
457+
val insertException = intercept[SqlestException] {
458+
database.withTransaction { implicit transaction =>
459+
insertStatement.execute
460+
}
461+
}
462+
463+
assert(insertException.message.startsWith("Exception running sql"))
464+
insertException.cause shouldBe database.anException
465+
466+
val insertReturningKeysException = intercept[SqlestException] {
467+
database.withTransaction { implicit transaction =>
468+
insertStatement.executeReturningKeys[String]
469+
}
470+
}
471+
472+
assert(insertReturningKeysException.message.startsWith("Exception running sql"))
473+
insertReturningKeysException.cause shouldBe database.anException
474+
475+
val updateException = intercept[SqlestException] {
476+
database.withTransaction { implicit transaction =>
477+
updateStatement.execute
478+
}
479+
}
480+
481+
assert(updateException.message.startsWith("Exception running sql"))
482+
updateException.cause shouldBe database.anException
483+
}
484+
485+
it should "return the underlying exception on prepare otherwise " in {
486+
val database = TestDatabase(testResultSet, Some(keyResultSet), shouldThrow = true, verboseExceptionMessages = false, throwExceptionOnPrepare = true)
487+
488+
val selectException = intercept[Exception] {
489+
database.withSession { implicit session =>
490+
selectStatement.fetchAll
491+
}
492+
}
493+
494+
selectException shouldBe database.anException
495+
496+
val insertException = intercept[Exception] {
497+
database.withTransaction { implicit transaction =>
498+
insertStatement.execute
499+
}
500+
}
501+
502+
insertException shouldBe database.anException
503+
504+
val insertReturningKeysException = intercept[Exception] {
505+
database.withTransaction { implicit transaction =>
506+
insertStatement.executeReturningKeys[String]
507+
}
508+
}
509+
510+
insertReturningKeysException shouldBe database.anException
511+
512+
val updateException = intercept[Exception] {
513+
database.withTransaction { implicit transaction =>
514+
updateStatement.execute
515+
}
516+
}
517+
518+
updateException shouldBe database.anException
519+
}
444520
}

sqlest/src/test/scala/sqlest/executor/TestDatabase.scala

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ package sqlest.executor
1919
import java.sql.ResultSet
2020
import sqlest._
2121

22-
case class TestDatabase(resultSet: ResultSet, keyResultSet: Option[ResultSet] = None, shouldThrow: Boolean = false, verboseExceptionMessages: Boolean = false) extends Database {
22+
case class TestDatabase(resultSet: ResultSet, keyResultSet: Option[ResultSet] = None, shouldThrow: Boolean = false, verboseExceptionMessages: Boolean = false, throwExceptionOnPrepare: Boolean = false) extends Database {
2323
var preparedStatement: Option[AbstractPreparedStatement] = None
2424
var lastConnection: Option[AbstractConnection] = None
2525
override val verboseExceptions = verboseExceptionMessages
@@ -46,7 +46,8 @@ case class TestDatabase(resultSet: ResultSet, keyResultSet: Option[ResultSet] =
4646
override def execute(sql: String) = if (shouldThrow) throw anException else true
4747
}
4848
override def prepareStatement(inSql: String, columnIndices: Array[Int]) = {
49-
val statement = new AbstractPreparedStatement {
49+
50+
val statement = if (throwExceptionOnPrepare) throw anException else new AbstractPreparedStatement {
5051
val sql = inSql
5152
override def executeQuery() = if (shouldThrow) throw anException else resultSet
5253
override def executeUpdate() = if (shouldThrow) throw anException else 1
@@ -59,7 +60,7 @@ case class TestDatabase(resultSet: ResultSet, keyResultSet: Option[ResultSet] =
5960
statement
6061
}
6162
override def prepareStatement(inSql: String, columnNames: Array[String]) = {
62-
val statement = new AbstractPreparedStatement {
63+
val statement = if (throwExceptionOnPrepare) throw anException else new AbstractPreparedStatement {
6364
val sql = inSql
6465
override def executeQuery() = if (shouldThrow) throw anException else resultSet
6566
override def executeUpdate() = if (shouldThrow) throw anException else 1
@@ -72,7 +73,7 @@ case class TestDatabase(resultSet: ResultSet, keyResultSet: Option[ResultSet] =
7273
statement
7374
}
7475
override def prepareStatement(inSql: String, returnGeneratedKeys: Int) = {
75-
val statement = new AbstractPreparedStatement {
76+
val statement = if (throwExceptionOnPrepare) throw anException else new AbstractPreparedStatement {
7677
val sql = inSql
7778
override def executeQuery() = if (shouldThrow) throw anException else resultSet
7879
override def executeUpdate() = if (shouldThrow) throw anException else 1
@@ -87,7 +88,7 @@ case class TestDatabase(resultSet: ResultSet, keyResultSet: Option[ResultSet] =
8788
statement
8889
}
8990
override def prepareStatement(inSql: String) = {
90-
val statement = new AbstractPreparedStatement {
91+
val statement = if (throwExceptionOnPrepare) throw anException else new AbstractPreparedStatement {
9192
val sql = inSql
9293
override def executeQuery() = if (shouldThrow) throw anException else resultSet
9394
override def executeUpdate() = if (shouldThrow) throw anException else 1

0 commit comments

Comments
 (0)