diff --git a/lib/Doctrine/DBAL/Driver/IbmDb2/Db2Connection.php b/lib/Doctrine/DBAL/Driver/IbmDb2/Db2Connection.php new file mode 100644 index 000000000..f6909a437 --- /dev/null +++ b/lib/Doctrine/DBAL/Driver/IbmDb2/Db2Connection.php @@ -0,0 +1,119 @@ +. +*/ + +namespace Doctrine\DBAL\Driver\IbmDb2; + +class Db2Connection implements \Doctrine\DBAL\Driver\Connection +{ + private $_conn = null; + + public function __construct($dbname, $username, $password, $driverOptions = array(), $isPersistant = false) + { + if ($isPersistant) { + $this->_conn = db2_pconnect($dbname, $username, $password, $driverOptions); + } else { + $this->_conn = db2_connect($dbname, $username, $password, $driverOptions); + } + if (!$this->_conn) { + throw new Db2Exception(db2_conn_errormsg()); + } + } + + function prepare($sql) + { + $stmt = @db2_prepare($this->_conn, $sql); + if (!$stmt) { + throw new Db2Exception(db2_stmt_errormsg()); + } + return new Db2Statement($stmt); + } + + function query() + { + $args = func_get_args(); + $sql = $args[0]; + $stmt = $this->prepare($sql); + $stmt->execute(); + return $stmt; + } + + function quote($input, $type=\PDO::PARAM_STR) + { + $input = db2_escape_string($input); + if ($type == \PDO::PARAM_INT ) { + return $input; + } else { + return "'".$input."'"; + } + } + + function exec($statement) + { + $stmt = $this->prepare($statement); + $stmt->execute(); + return $stmt; + } + + function lastInsertId($name = null) + { + $sql = 'SELECT IDENTITY_VAL_LOCAL() AS VAL FROM SYSIBM.SYSDUMMY1'; + if ($stmt = $this->query($sql)) { + if ($col = $stmt->fetchColumn()) { + return $col; + } + } + return false; + } + + function beginTransaction() + { + db2_autocommit($this->_conn, DB2_AUTOCOMMIT_OFF); + } + + function commit() + { + if (!db2_commit($this->_conn)) { + throw new Db2Exception(db2_conn_errormsg($this->_conn)); + } + db2_autocommit($this->_conn, DB2_AUTOCOMMIT_ON); + } + + function rollBack() + { + if (!db2_rollback($this->_conn)) { + throw new Db2Exception(db2_conn_errormsg($this->_conn)); + } + db2_autocommit($this->_conn, DB2_AUTOCOMMIT_ON); + } + + function errorCode() + { + return db2_conn_error($this->_conn); + } + + function errorInfo() + { + return array( + 0 => db2_conn_errormsg($this->_conn), + 1 => $this->errorCode(), + ); + } +} \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Driver/IbmDb2/Db2Driver.php b/lib/Doctrine/DBAL/Driver/IbmDb2/Db2Driver.php new file mode 100644 index 000000000..5a88b488c --- /dev/null +++ b/lib/Doctrine/DBAL/Driver/IbmDb2/Db2Driver.php @@ -0,0 +1,113 @@ +. +*/ + +namespace Doctrine\DBAL\Driver\IbmDb2; + +use Doctrine\DBAL\Driver, + Doctrine\DBAL\Connection; + +/** + * IBM Db2 Driver + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 1.0 + * @version $Revision$ + * @author Benjamin Eberlei + */ +class Db2Driver implements Driver +{ + /** + * Attempts to create a connection with the database. + * + * @param array $params All connection parameters passed by the user. + * @param string $username The username to use when connecting. + * @param string $password The password to use when connecting. + * @param array $driverOptions The driver options to use when connecting. + * @return Doctrine\DBAL\Driver\Connection The database connection. + */ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) + { + if ($params['host'] !== 'localhost' && $params['host'] != '127.0.0.1') { + // if the host isn't localhost, use extended connection params + $dbname = 'DRIVER={IBM DB2 ODBC DRIVER}' . + ';DATABASE=' . $params['dbname'] . + ';HOSTNAME=' . $params['host'] . + ';PORT=' . $params['port'] . + ';PROTOCOL=' . $params['protocol'] . + ';UID=' . $username . + ';PWD=' . $password .';'; + $username = null; + $password = null; + } else { + $dbname = $params['dbname']; + } + + $isPersistant = (isset($params['persistent']) && $params['persistent'] == true); + + return new Db2Connection($dbname, $username, $password, $driverOptions, $isPersistant); + } + + /** + * Gets the DatabasePlatform instance that provides all the metadata about + * the platform this driver connects to. + * + * @return Doctrine\DBAL\Platforms\AbstractPlatform The database platform. + */ + public function getDatabasePlatform() + { + return new \Doctrine\DBAL\Platforms\IbmDb2Platform; + } + + /** + * Gets the SchemaManager that can be used to inspect and change the underlying + * database schema of the platform this driver connects to. + * + * @param Doctrine\DBAL\Connection $conn + * @return Doctrine\DBAL\SchemaManager + */ + public function getSchemaManager(Connection $conn) + { + return new \Doctrine\DBAL\Schema\IbmDb2SchemaManager($conn); + } + + /** + * Gets the name of the driver. + * + * @return string The name of the driver. + */ + public function getName() + { + return 'ibm_db2'; + } + + /** + * Get the name of the database connected to for this driver. + * + * @param Doctrine\DBAL\Connection $conn + * @return string $database + */ + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + return $params['dbname']; + } +} diff --git a/lib/Doctrine/DBAL/Driver/IbmDb2/Db2Exception.php b/lib/Doctrine/DBAL/Driver/IbmDb2/Db2Exception.php new file mode 100644 index 000000000..76d992b50 --- /dev/null +++ b/lib/Doctrine/DBAL/Driver/IbmDb2/Db2Exception.php @@ -0,0 +1,27 @@ +. +*/ + +namespace Doctrine\DBAL\Driver\IbmDb2; + +class Db2Exception extends \Exception +{ + +} \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Driver/IbmDb2/Db2Statement.php b/lib/Doctrine/DBAL/Driver/IbmDb2/Db2Statement.php new file mode 100644 index 000000000..c4594ff04 --- /dev/null +++ b/lib/Doctrine/DBAL/Driver/IbmDb2/Db2Statement.php @@ -0,0 +1,285 @@ +. +*/ + +namespace Doctrine\DBAL\Driver\IbmDb2; + +class Db2Statement implements \Doctrine\DBAL\Driver\Statement +{ + private $_stmt = null; + + /** + * DB2_BINARY, DB2_CHAR, DB2_DOUBLE, or DB2_LONG + * @var + */ + static private $_typeMap = array( + \PDO::PARAM_INT => DB2_LONG, + \PDO::PARAM_STR => DB2_CHAR, + ); + + public function __construct($stmt) + { + $this->_stmt = $stmt; + } + + /** + * Binds a value to a corresponding named or positional + * placeholder in the SQL statement that was used to prepare the statement. + * + * @param mixed $param Parameter identifier. For a prepared statement using named placeholders, + * this will be a parameter name of the form :name. For a prepared statement + * using question mark placeholders, this will be the 1-indexed position of the parameter + * + * @param mixed $value The value to bind to the parameter. + * @param integer $type Explicit data type for the parameter using the PDO::PARAM_* constants. + * + * @return boolean Returns TRUE on success or FALSE on failure. + */ + function bindValue($param, $value, $type = null) + { + return $this->bindParam($param, $variable, $type); + } + + /** + * Binds a PHP variable to a corresponding named or question mark placeholder in the + * SQL statement that was use to prepare the statement. Unlike PDOStatement->bindValue(), + * the variable is bound as a reference and will only be evaluated at the time + * that PDOStatement->execute() is called. + * + * Most parameters are input parameters, that is, parameters that are + * used in a read-only fashion to build up the query. Some drivers support the invocation + * of stored procedures that return data as output parameters, and some also as input/output + * parameters that both send in data and are updated to receive it. + * + * @param mixed $param Parameter identifier. For a prepared statement using named placeholders, + * this will be a parameter name of the form :name. For a prepared statement + * using question mark placeholders, this will be the 1-indexed position of the parameter + * + * @param mixed $variable Name of the PHP variable to bind to the SQL statement parameter. + * + * @param integer $type Explicit data type for the parameter using the PDO::PARAM_* constants. To return + * an INOUT parameter from a stored procedure, use the bitwise OR operator to set the + * PDO::PARAM_INPUT_OUTPUT bits for the data_type parameter. + * @return boolean Returns TRUE on success or FALSE on failure. + */ + function bindParam($column, &$variable, $type = null) + { + if (!$type && isset(self::$_typeMap[$type])) { + $type = self::$_typeMap[$type]; + } else { + $type = DB2_CHAR; + } + + if (!db2_bind_param($this->_stmt, $column, "variable", DB2_PARAM_IN, $type)) { + throw new Db2Exception(db2_stmt_errormsg()); + } + } + + /** + * Closes the cursor, enabling the statement to be executed again. + * + * @return boolean Returns TRUE on success or FALSE on failure. + */ + function closeCursor() + { + if (!$this->_stmt) { + return false; + } + + $ret = db2_free_stmt($this->_stmt); + $this->_stmt = false; + return $ret; + } + + /** + * columnCount + * Returns the number of columns in the result set + * + * @return integer Returns the number of columns in the result set represented + * by the PDOStatement object. If there is no result set, + * this method should return 0. + */ + function columnCount() + { + if (!$this->_stmt) { + return false; + } + return db2_num_fields($this->_stmt); + } + + /** + * errorCode + * Fetch the SQLSTATE associated with the last operation on the statement handle + * + * @see Doctrine_Adapter_Interface::errorCode() + * @return string error code string + */ + function errorCode() + { + return db2_stmt_error(); + } + + /** + * errorInfo + * Fetch extended error information associated with the last operation on the statement handle + * + * @see Doctrine_Adapter_Interface::errorInfo() + * @return array error info array + */ + function errorInfo() + { + return array( + 0 => db2_stmt_errormsg(), + 1 => db2_stmt_error(), + ); + } + + /** + * Executes a prepared statement + * + * If the prepared statement included parameter markers, you must either: + * call PDOStatement->bindParam() to bind PHP variables to the parameter markers: + * bound variables pass their value as input and receive the output value, + * if any, of their associated parameter markers or pass an array of input-only + * parameter values + * + * + * @param array $params An array of values with as many elements as there are + * bound parameters in the SQL statement being executed. + * @return boolean Returns TRUE on success or FALSE on failure. + */ + function execute($params = null) + { + if (!$this->_stmt) { + return false; + } + + $retval = true; + if ($params !== null) { + $retval = @db2_execute($this->_stmt, $params); + } else { + $retval = @db2_execute($this->_stmt); + } + + if ($retval === false) { + throw new Db2Exception(db2_stmt_errormsg()); + } + return $retval; + } + + /** + * fetch + * + * @see Query::HYDRATE_* constants + * @param integer $fetchStyle Controls how the next row will be returned to the caller. + * This value must be one of the Query::HYDRATE_* constants, + * defaulting to Query::HYDRATE_BOTH + * + * @param integer $cursorOrientation For a PDOStatement object representing a scrollable cursor, + * this value determines which row will be returned to the caller. + * This value must be one of the Query::HYDRATE_ORI_* constants, defaulting to + * Query::HYDRATE_ORI_NEXT. To request a scrollable cursor for your + * PDOStatement object, + * you must set the PDO::ATTR_CURSOR attribute to Doctrine::CURSOR_SCROLL when you + * prepare the SQL statement with Doctrine_Adapter_Interface->prepare(). + * + * @param integer $cursorOffset For a PDOStatement object representing a scrollable cursor for which the + * $cursorOrientation parameter is set to Query::HYDRATE_ORI_ABS, this value specifies + * the absolute number of the row in the result set that shall be fetched. + * + * For a PDOStatement object representing a scrollable cursor for + * which the $cursorOrientation parameter is set to Query::HYDRATE_ORI_REL, this value + * specifies the row to fetch relative to the cursor position before + * PDOStatement->fetch() was called. + * + * @return mixed + */ + function fetch($fetchStyle = \PDO::FETCH_BOTH) + { + switch ($fetchStyle) { + case \PDO::FETCH_BOTH: + return db2_fetch_both($this->_stmt); + case \PDO::FETCH_ASSOC: + return db2_fetch_assoc($this->_stmt); + case \PDO::FETCH_NUM: + return db2_fetch_array($this->_stmt); + default: + throw new Db2Exception("Given Fetch-Style " . $fetchStyle . " is not supported."); + } + } + + /** + * Returns an array containing all of the result set rows + * + * @param integer $fetchStyle Controls how the next row will be returned to the caller. + * This value must be one of the Query::HYDRATE_* constants, + * defaulting to Query::HYDRATE_BOTH + * + * @param integer $columnIndex Returns the indicated 0-indexed column when the value of $fetchStyle is + * Query::HYDRATE_COLUMN. Defaults to 0. + * + * @return array + */ + function fetchAll($fetchStyle = \PDO::FETCH_BOTH) + { + $rows = array(); + while ($row = $this->fetch($fetchStyle)) { + $rows[] = $row; + } + return $rows; + } + + /** + * fetchColumn + * Returns a single column from the next row of a + * result set or FALSE if there are no more rows. + * + * @param integer $columnIndex 0-indexed number of the column you wish to retrieve from the row. If no + * value is supplied, PDOStatement->fetchColumn() + * fetches the first column. + * + * @return string returns a single column in the next row of a result set. + */ + function fetchColumn($columnIndex = 0) + { + $row = $this->fetch(\PDO::FETCH_NUM); + if (!$row && isset($row[$columnIndex])) { + return $row[$columnIndex]; + } + return false; + } + + /** + * rowCount + * rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement + * executed by the corresponding object. + * + * If the last SQL statement executed by the associated Statement object was a SELECT statement, + * some databases may return the number of rows returned by that statement. However, + * this behaviour is not guaranteed for all databases and should not be + * relied on for portable applications. + * + * @return integer Returns the number of rows. + */ + function rowCount() + { + return (@db2_num_rows($this->_stmt))?:0; + } +} diff --git a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php index 961ca0b7d..e2d416dda 100644 --- a/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/AbstractPlatform.php @@ -1690,6 +1690,16 @@ abstract class AbstractPlatform return false; } + /** + * Some databases don't allow to create and drop databases at all or only with certain tools. + * + * @return bool + */ + public function supportsCreateDropDatabase() + { + return true; + } + /** * @return bool */ diff --git a/lib/Doctrine/DBAL/Platforms/IbmDb2Platform.php b/lib/Doctrine/DBAL/Platforms/IbmDb2Platform.php new file mode 100644 index 000000000..09de9c746 --- /dev/null +++ b/lib/Doctrine/DBAL/Platforms/IbmDb2Platform.php @@ -0,0 +1,222 @@ +. +*/ + +namespace Doctrine\DBAL\Platforms; + +class IbmDb2Platform extends AbstractPlatform +{ + /** + * Gets the SQL snippet used to declare a VARCHAR column type. + * + * @param array $field + */ + public function getVarcharTypeDeclarationSQL(array $field) + { + if ( ! isset($field['length'])) { + if (array_key_exists('default', $field)) { + $field['length'] = $this->getVarcharMaxLength(); + } else { + $field['length'] = false; + } + } + + $length = ($field['length'] <= $this->getVarcharMaxLength()) ? $field['length'] : false; + $fixed = (isset($field['fixed'])) ? $field['fixed'] : false; + + return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') + : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); + } + + /** + * Gets the SQL snippet used to declare a CLOB column type. + * + * @param array $field + */ + public function getClobTypeDeclarationSQL(array $field) + { + // todo clob(n) with $field['length']; + return 'CLOB(1M)'; + } + + /** + * Gets the name of the platform. + * + * @return string + */ + public function getName() + { + return 'db2'; + } + + + /** + * Gets the SQL snippet that declares a boolean column. + * + * @param array $columnDef + * @return string + */ + public function getBooleanTypeDeclarationSQL(array $columnDef) + { + return 'SMALLINT'; + } + + /** + * Gets the SQL snippet that declares a 4 byte integer column. + * + * @param array $columnDef + * @return string + */ + public function getIntegerTypeDeclarationSQL(array $columnDef) + { + return 'INTEGER'; + } + + /** + * Gets the SQL snippet that declares an 8 byte integer column. + * + * @param array $columnDef + * @return string + */ + public function getBigIntTypeDeclarationSQL(array $columnDef) + { + return 'BIGINT'; + } + + /** + * Gets the SQL snippet that declares a 2 byte integer column. + * + * @param array $columnDef + * @return string + */ + public function getSmallIntTypeDeclarationSQL(array $columnDef) + { + return 'SMALLINT'; + } + + /** + * Gets the SQL snippet that declares common properties of an integer column. + * + * @param array $columnDef + * @return string + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + + } + + public function getListDatabasesSQL() + { + throw DBALException::notSupported(__METHOD__); + } + + public function getListSequencesSQL($database) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getListTableConstraintsSQL($table) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getListTableColumnsSQL($table) + { + return "SELECT DISTINCT c.tabschema, c.tabname, c.colname, c.colno, + c.typename, c.default, c.nulls, c.length, c.scale, + c.identity, tc.type AS tabconsttype, k.colseq + FROM syscat.columns c + LEFT JOIN (syscat.keycoluse k JOIN syscat.tabconst tc + ON (k.tabschema = tc.tabschema + AND k.tabname = tc.tabname + AND tc.type = 'P')) + ON (c.tabschema = k.tabschema + AND c.tabname = k.tabname + AND c.colname = k.colname) + WHERE UPPER(c.tabname) = UPPER('" . $table . "') ORDER BY c.colno"; + } + + public function getListTablesSQL() + { + return "SELECT 'NAME' FROM SYSIBM.TABLES"; + } + + public function getListUsersSQL() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Get the SQL to list all views of a database or user. + * + * @param string $database + * @return string + */ + public function getListViewsSQL($database) + { + return "SELECT NAME, TEXT FROM SYSIBM.SYSVIEWS"; + } + + public function getListTableIndexesSQL($table) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getListTableForeignKeysSQL($table) + { + return "SELECT TBNAME, RELNAME, REFTBNAME, 'DELETE_RULE', 'UPDATE_RULE', FKCOLNAMES, PKCOLNAMES ". + "FROM SYSIBM.SYSRELS WHERE TBNAME = '".$table."'"; + } + + public function getCreateViewSQL($name, $sql) + { + return "CREATE VIEW ".$name." AS ".$sql; + } + + public function getDropViewSQL($name) + { + return "DROP VIEW ".$name; + } + + public function getDropSequenceSQL($sequence) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getSequenceNextValSQL($sequenceName) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getCreateDatabaseSQL($database) + { + return "CREATE DATABASE ".$database; + } + + public function getDropDatabaseSQL($database) + { + return "DROP DATABASE ".$database.";"; + } + + public function supportsCreateDropDatabase() + { + return false; + } +} \ No newline at end of file diff --git a/lib/Doctrine/DBAL/Schema/IbmDb2SchemaManager.php b/lib/Doctrine/DBAL/Schema/IbmDb2SchemaManager.php new file mode 100644 index 000000000..78c07cf33 --- /dev/null +++ b/lib/Doctrine/DBAL/Schema/IbmDb2SchemaManager.php @@ -0,0 +1,83 @@ +. +*/ + +namespace Doctrine\DBAL\Schema; + +/** + * IBM Db2 Schema Manager + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 1.0 + * @version $Revision$ + * @author Benjamin Eberlei + */ +class IbmDb2SchemaManager extends AbstractSchemaManager +{ + /** + * Get Table Column Definition + * + * @param array $tableColumn + * @return Column + */ + protected function _getPortableTableColumnDefinition($tableColumn) + { + + } + + protected function _getPortableTableForeignKeyDefinition($tableForeignKey) + { + $tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER); + + $tableForeignKey['delete_rule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['delete_rule']); + $tableForeignKey['update_rule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['update_rule']); + + return new ForeignKeyConstraint( + (array)$tableForeignKey['pkcolnames'], + $tableForeignKey['referenced_table_name'], + (array)$tableForeignKey['fkcolnames'], + $tableForeignKey['relname'], + array( + 'onUpdate' => $tableForeignKey['update_rule'], + 'onDelete' => $tableForeignKey['delete_rule'], + ) + ); + } + + protected function _getPortableForeignKeyRuleDef($def) + { + if ($def == "C") { + return "CASCADE"; + } else if ($def == "N") { + return "SET NULL"; + } + return null; + } + + protected function _getPortableViewDefinition($view) + { + $view = array_change_key_case($view, \CASE_LOWER); + $pos = strpos($view['text'], ' AS '); + $sql = substr($view['text'], $pos+4); + + return new View($view['name'], $sql); + } +} \ No newline at end of file diff --git a/tests/Doctrine/Tests/DBAL/Functional/DataAccessTest.php b/tests/Doctrine/Tests/DBAL/Functional/DataAccessTest.php new file mode 100644 index 000000000..4190025cd --- /dev/null +++ b/tests/Doctrine/Tests/DBAL/Functional/DataAccessTest.php @@ -0,0 +1,61 @@ +addColumn('test_int', 'integer'); + $table->addColumn('test_string', 'string'); + + $sm = $this->_conn->getSchemaManager(); + $sm->createTable($table); + + $this->_conn->insert('fetch_table', array('test_int' => 1, 'test_string' => 'foo')); + } catch(\Exception $e) { + + } + } + + public function testFetchAll() + { + $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?"; + $data = $this->_conn->fetchAll($sql, array(1, 'foo')); + + $this->assertEquals(1, count($data)); + + $row = $data[0]; + $this->assertEquals(2, count($row)); + + $row = array_change_key_case($row, \CASE_LOWER); + $this->assertEquals(1, $row['test_int']); + $this->assertEquals('foo', $row['test_string']); + } + + public function testFetchRow() + { + $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?"; + $row = $this->_conn->fetchRow($sql, array(1, 'foo')); + + $row = array_change_key_case($row, \CASE_LOWER); + + $this->assertEquals(1, $row['test_int']); + $this->assertEquals('foo', $row['test_string']); + } + + public function testFetchArray() + { + $sql = "SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?"; + $row = $this->_conn->fetchArray($sql, array(1, 'foo')); + + $this->assertEquals(1, $row[0]); + $this->assertEquals('foo', $row[1]); + } + +} \ No newline at end of file diff --git a/tests/Doctrine/Tests/DBAL/Functional/Schema/Db2SchemaManagerTest.php b/tests/Doctrine/Tests/DBAL/Functional/Schema/Db2SchemaManagerTest.php new file mode 100644 index 000000000..a567900c9 --- /dev/null +++ b/tests/Doctrine/Tests/DBAL/Functional/Schema/Db2SchemaManagerTest.php @@ -0,0 +1,12 @@ +real database connection using the following parameters * of the $GLOBALS array: - * + * * 'db_type' : The name of the Doctrine DBAL database driver to use. * 'db_username' : The username to use for connecting. * 'db_password' : The password to use for connecting. * 'db_host' : The hostname of the database to connect to. * 'db_name' : The name of the database to connect to. * 'db_port' : The port of the database to connect to. - * + * * Usually these variables of the $GLOBALS array are filled by PHPUnit based * on an XML configuration file. If no such parameters exist, an SQLite * in-memory database is used. - * + * * IMPORTANT: * 1) Each invocation of this method returns a NEW database connection. * 2) The database is dropped and recreated to ensure it's clean. - * + * * @return Doctrine\DBAL\Connection The database connection instance. */ public static function getConnection() @@ -52,18 +52,24 @@ class TestUtil 'dbname' => $GLOBALS['tmpdb_name'], 'port' => $GLOBALS['tmpdb_port'] ); - - // Connect to tmpdb in order to drop and create the real test db. - $tmpConn = \Doctrine\DBAL\DriverManager::getConnection($tmpDbParams); + $realConn = \Doctrine\DBAL\DriverManager::getConnection($realDbParams); - $dbname = $realConn->getDatabase(); - $realConn->close(); - - $tmpConn->getSchemaManager()->dropDatabase($dbname); - $tmpConn->getSchemaManager()->createDatabase($dbname); - - $tmpConn->close(); + $platform = $realConn->getDatabasePlatform(); + + if ($platform->supportsCreateDropDatabase()) { + $dbname = $realConn->getDatabase(); + // Connect to tmpdb in order to drop and create the real test db. + $tmpConn = \Doctrine\DBAL\DriverManager::getConnection($tmpDbParams); + $realConn->close(); + + $tmpConn->getSchemaManager()->dropDatabase($dbname); + $tmpConn->getSchemaManager()->createDatabase($dbname); + + $tmpConn->close(); + } else { + // wipe everything? + } $eventManager = null; if (isset($GLOBALS['db_event_subscribers'])) { @@ -73,9 +79,9 @@ class TestUtil $eventManager->addEventSubscriber($subscriberInstance); } } - + $conn = \Doctrine\DBAL\DriverManager::getConnection($realDbParams, null, $eventManager); - + } else { $params = array( 'driver' => 'pdo_sqlite',