/* __ *\ ** ________ ___ / / ___ Scala API ** ** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** \* */ // $Id:Database.scala 6853 2006-03-20 16:58:47 +0100 (Mon, 20 Mar 2006) dubochet $ package scala.dbc2; import java.sql._; /** A database on wich queries can be executed. The actual connection * strategy is defined by the vendor parameter. * @param vendor The bridging object to the DBMS vendor. * @author Gilles Dubochet **/ class Database (vendor: Vendor) { /** Executes on this database a statement that returns a relation. * @param relationStatement The statement to execute. * @return The relation returned by the database for this statement. */ def executeStatement( relationStatement: statement.Relation ): result.Relation = new dbc2.result.Relation { val statement = relationStatement private val connection = vendor.getConnection val jdbcStatement: java.sql.Statement = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY) val sqlResult = jdbcStatement.executeQuery(statement.sqlString) val closeConnection = () => vendor.closeConnection(connection) statement.typeCheck(this) } /** Executes of the database a statement that updates the state without * returning any data. * @param statusStatement The statement to execute. * @return The status of the database after executing the statement. */ def executeStatement( statusStatement: statement.Status ): result.Status = new dbc2.result.Status { val statement = statusStatement val connection = vendor.getConnection val jdbcStatement: java.sql.Statement = connection.createStatement() jdbcStatement.execute(statement.sqlString) val touchedCount = Some(jdbcStatement.getUpdateCount()) vendor.closeConnection(connection) } /** Executes a list of statements or other operations inside a transaction. * Be advised that only database statements are executed transactionaly, * other Scala code is not. * @param transactionStatement The transaction to execute as a closure. * @return The status of the database after executing the statement. */ def executeStatement[ResultType]( transactionStatement: statement.Transaction[ResultType] ): ResultType = { val connection = vendor.getConnection connection.setAutoCommit(false) val jdbcStatement: java.sql.Statement = connection.createStatement() jdbcStatement.execute(transactionStatement.sqlStartString) val result: ResultType = try { val buffer = transactionStatement.transactionBody(Database.this) jdbcStatement.execute(transactionStatement.sqlCommitString) buffer } catch { case e: Throwable => jdbcStatement.execute(transactionStatement.sqlAbortString) throw e } connection.setAutoCommit(true) /* If the result is a relation, it needs to remain open for the cursor to work. It'll close itself alone alright when time comes. */ if (!result.isInstanceOf[dbc2.result.Relation]) { vendor.closeConnection(connection) } result } /** Finaliser method that makes sure all connections to the DBMS are * indeed closed. */ protected override def finalize() = { vendor.close } }