Commit 3899888a authored by Roman S. Borschel's avatar Roman S. Borschel

Merge commit 'upstream/master'

parents 080f7373 9277dba3
......@@ -173,12 +173,19 @@
<xs:complexType name="id">
<xs:sequence>
<xs:element name="generator" type="orm:generator" minOccurs="0" />
<xs:element name="sequence-generator" type="orm:sequence-generator" minOccurs="0" maxOccurs="1" />
</xs:sequence>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="type" type="xs:NMTOKEN" use="required" />
<xs:attribute name="column" type="xs:NMTOKEN" />
</xs:complexType>
<xs:complexType name="sequence-generator">
<xs:attribute name="sequence-name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="allocation-size" type="xs:integer" use="optional" default="1" />
<xs:attribute name="initial-value" type="xs:integer" use="optional" default="1" />
</xs:complexType>
<xs:complexType name="inverse-join-columns">
<xs:sequence>
<xs:element name="join-column" type="orm:join-column" minOccurs="1" maxOccurs="unbounded" />
......
......@@ -789,7 +789,7 @@ class Connection implements DriverConnection
* Gets the SchemaManager that can be used to inspect or change the
* database schema through the connection.
*
* @return Doctrine\DBAL\Schema\SchemaManager
* @return Doctrine\DBAL\Schema\AbstractSchemaManager
*/
public function getSchemaManager()
{
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\IBMDB2;
class DB2Connection implements \Doctrine\DBAL\Driver\Connection
{
private $_conn = null;
public function __construct(array $params, $username, $password, $driverOptions = array())
{
$isPersistant = (isset($params['persistent']) && $params['persistent'] == true);
if ($isPersistant) {
$this->_conn = db2_pconnect($params['dbname'], $username, $password, $driverOptions);
} else {
$this->_conn = db2_connect($params['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->rowCount();
}
function lastInsertId($name = null)
{
return db2_last_insert_id($this->_conn);
}
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
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
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 <kontakt@beberlei.de>
*/
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 ( !isset($params['schema']) ) {
}
if ($params['host'] !== 'localhost' && $params['host'] != '127.0.0.1') {
// if the host isn't localhost, use extended connection params
$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;
}
return new DB2Connection($params, $username, $password, $driverOptions);
}
/**
* 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\DB2Platform;
}
/**
* 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\DB2SchemaManager($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'];
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\IBMDB2;
class DB2Exception extends \Exception
{
}
\ No newline at end of file
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\IBMDB2;
class DB2Statement implements \Doctrine\DBAL\Driver\Statement
{
private $_stmt = null;
private $_bindParam = array();
/**
* DB2_BINARY, DB2_CHAR, DB2_DOUBLE, or DB2_LONG
* @var <type>
*/
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, $value, $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)
{
$this->_bindParam[$column] =& $variable;
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());
}
return true;
}
/**
* 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;
}
$this->_bindParam = array();
db2_free_result($this->_stmt);
$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 ($params === null) {
ksort($this->_bindParam);
$params = array_values($this->_bindParam);
}
$retval = @db2_execute($this->_stmt, $params);
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;
}
}
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\PDOIbm;
use Doctrine\DBAL\Connection;
/**
* Driver for the PDO IBM extension
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class Driver implements \Doctrine\DBAL\Driver
{
/**
* Attempts to establish a connection with the underlying driver.
*
* @param array $params
* @param string $username
* @param string $password
* @param array $driverOptions
* @return Doctrine\DBAL\Driver\Connection
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
$conn = new \Doctrine\DBAL\Driver\PDOConnection(
$this->_constructPdoDsn($params),
$username,
$password,
$driverOptions
);
return $conn;
}
/**
* Constructs the MySql PDO DSN.
*
* @return string The DSN.
*/
private function _constructPdoDsn(array $params)
{
$dsn = 'ibm:';
if (isset($params['host'])) {
$dsn .= 'HOSTNAME=' . $params['host'] . ';';
}
if (isset($params['port'])) {
$dsn .= 'PORT=' . $params['port'] . ';';
}
$dsn .= 'PROTOCOL=TCPIP;';
if (isset($params['dbname'])) {
$dsn .= 'DATABASE=' . $params['dbname'] . ';';
}
return $dsn;
}
/**
* 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\DB2Platform;
}
/**
* 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\DB2SchemaManager($conn);
}
/**
* Gets the name of the driver.
*
* @return string The name of the driver.
*/
public function getName()
{
return 'pdo_ibm';
}
/**
* 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'];
}
}
\ No newline at end of file
......@@ -43,7 +43,9 @@ final class DriverManager
'pdo_pgsql' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver',
'pdo_oci' => 'Doctrine\DBAL\Driver\PDOOracle\Driver',
'pdo_mssql' => 'Doctrine\DBAL\Driver\PDOMsSql\Driver',
'oci8' => 'Doctrine\DBAL\Driver\OCI8\Driver'
'oci8' => 'Doctrine\DBAL\Driver\OCI8\Driver',
'ibm_db2' => 'Doctrine\DBAL\Driver\IBMDB2\DB2Driver',
'pdo_ibm' => 'Doctrine\DBAL\Driver\PDOIbm\Driver',
);
/** Private constructor. This class cannot be instantiated. */
......
......@@ -1095,7 +1095,7 @@ abstract class AbstractPlatform
throw \InvalidArgumentException("Incomplete definition. 'columns' required.");
}
return 'CONSTRAINT' . $name . ' UNIQUE ('
return 'CONSTRAINT ' . $name . ' UNIQUE ('
. $this->getIndexFieldDeclarationListSQL($index->getColumns())
. ')';
}
......@@ -1177,6 +1177,17 @@ abstract class AbstractPlatform
return 'TEMPORARY';
}
/**
* Some vendors require temporary table names to be qualified specially.
*
* @param string $tableName
* @return string
*/
public function getTemporaryTableName($tableName)
{
return $tableName;
}
/**
* Get sql query to show a list of database.
*
......@@ -1690,6 +1701,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
*/
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\TableDiff;
class DB2Platform 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' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef);
}
/**
* Gets the SQL snippet that declares an 8 byte integer column.
*
* @param array $columnDef
* @return string
*/
public function getBigIntTypeDeclarationSQL(array $columnDef)
{
return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef);
}
/**
* Gets the SQL snippet that declares a 2 byte integer column.
*
* @param array $columnDef
* @return string
*/
public function getSmallIntTypeDeclarationSQL(array $columnDef)
{
return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef);
}
/**
* Gets the SQL snippet that declares common properties of an integer column.
*
* @param array $columnDef
* @return string
*/
protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef)
{
$autoinc = '';
if ( ! empty($columnDef['autoincrement'])) {
$autoinc = ' GENERATED BY DEFAULT AS IDENTITY';
}
return $autoinc;
}
/**
* Obtain DBMS specific SQL to be used to create datetime fields in
* statements like CREATE TABLE
*
* @param array $fieldDeclaration
* @return string
*/
public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration)
{
if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) {
return "TIMESTAMP(0) WITH DEFAULT";
}
return 'TIMESTAMP(0)';
}
/**
* Obtain DBMS specific SQL to be used to create date fields in statements
* like CREATE TABLE.
*
* @param array $fieldDeclaration
* @return string
*/
public function getDateTypeDeclarationSQL(array $fieldDeclaration)
{
return 'DATE';
}
/**
* Obtain DBMS specific SQL to be used to create time fields in statements
* like CREATE TABLE.
*
* @param array $fieldDeclaration
* @return string
*/
public function getTimeTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIME';
}
public function getListDatabasesSQL()
{
throw DBALException::notSupported(__METHOD__);
}
public function getListSequencesSQL($database)
{
throw DBALException::notSupported(__METHOD__);
}
public function getListTableConstraintsSQL($table)
{
throw DBALException::notSupported(__METHOD__);
}
/**
* This code fragment is originally from the Zend_Db_Adapter_Db2 class.
*
* @license New BSD License
* @param string $table
* @return string
*/
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.SYSTABLES WHERE TYPE = 'T'";
}
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)
{
return "SELECT NAME, COLNAMES, UNIQUERULE FROM SYSIBM.SYSINDEXES WHERE TBNAME = UPPER('" . $table . "')";
}
public function getListTableForeignKeysSQL($table)
{
return "SELECT TBNAME, RELNAME, REFTBNAME, DELETERULE, UPDATERULE, FKCOLNAMES, PKCOLNAMES ".
"FROM SYSIBM.SYSRELS WHERE TBNAME = UPPER('".$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;
}
/**
* Gets the SQL specific for the platform to get the current date.
*
* @return string
*/
public function getCurrentDateSQL()
{
return 'VALUES CURRENT DATE';
}
/**
* Gets the SQL specific for the platform to get the current time.
*
* @return string
*/
public function getCurrentTimeSQL()
{
return 'VALUES CURRENT TIME';
}
/**
* Gets the SQL specific for the platform to get the current timestamp
*
* @return string
*/
public function getCurrentTimestampSQL()
{
return "VALUES CURRENT TIMESTAMP";
}
/**
* Obtain DBMS specific SQL code portion needed to set an index
* declaration to be used in statements like CREATE TABLE.
*
* @param string $name name of the index
* @param Index $index index definition
* @return string DBMS specific SQL code portion needed to set an index
*/
public function getIndexDeclarationSQL($name, Index $index)
{
return $this->getUniqueConstraintDeclarationSQL($name, $index);
}
/**
* @param string $tableName
* @param array $columns
* @param array $options
* @return array
*/
protected function _getCreateTableSQL($tableName, array $columns, array $options = array())
{
$indexes = array();
if (isset($options['indexes'])) {
$indexes = $options['indexes'];
}
$options['indexes'] = array();
$sqls = parent::_getCreateTableSQL($tableName, $columns, $options);
foreach ($indexes as $index => $definition) {
$sqls[] = $this->getCreateIndexSQL($definition, $tableName);
}
return $sqls;
}
/**
* Gets the SQL to alter an existing table.
*
* @param TableDiff $diff
* @return array
*/
public function getAlterTableSQL(TableDiff $diff)
{
$sql = array();
$queryParts = array();
foreach ($diff->addedColumns AS $fieldName => $column) {
$queryParts[] = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getName(), $column->toArray());
}
foreach ($diff->removedColumns AS $column) {
$queryParts[] = 'DROP COLUMN ' . $column->getName();
}
foreach ($diff->changedColumns AS $columnDiff) {
/* @var $columnDiff Doctrine\DBAL\Schema\ColumnDiff */
$column = $columnDiff->column;
$queryParts[] = 'ALTER ' . ($columnDiff->oldColumnName) . ' '
. $this->getColumnDeclarationSQL($column->getName(), $column->toArray());
}
foreach ($diff->renamedColumns AS $oldColumnName => $column) {
$queryParts[] = 'RENAME ' . $oldColumnName . ' TO ' . $column->getName();
}
if (count($queryParts) > 0) {
$sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(" ", $queryParts);
}
$sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff));
if ($diff->newName !== false) {
$sql[] = 'RENAME TABLE TO ' . $diff->newName;
}
return $sql;
}
public function getDefaultValueDeclarationSQL($field)
{
if (isset($field['notnull']) && $field['notnull'] && !isset($field['default'])) {
if (in_array((string)$field['type'], array("Integer", "BigInteger", "SmallInteger"))) {
$field['default'] = 0;
} else if((string)$field['type'] == "DateTime") {
$field['default'] = "00-00-00 00:00:00";
} else if ((string)$field['type'] == "Date") {
$field['default'] = "00-00-00";
} else if((string)$field['type'] == "Time") {
$field['default'] = "00:00:00";
} else {
$field['default'] = '';
}
}
unset($field['default']); // @todo this needs fixing
if (isset($field['version']) && $field['version']) {
if ((string)$field['type'] != "DateTime") {
$field['default'] = "1";
}
}
return parent::getDefaultValueDeclarationSQL($field);
}
/**
* Get the insert sql for an empty insert statement
*
* @param string $tableName
* @param string $identifierColumnName
* @return string $sql
*/
public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName)
{
return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (DEFAULT)';
}
public function getCreateTemporaryTableSnippetSQL()
{
return "DECLARE GLOBAL TEMPORARY TABLE";
}
/**
* DB2 automatically moves temporary tables into the SESSION. schema.
*
* @param string $tableName
* @return string
*/
public function getTemporaryTableName($tableName)
{
return "SESSION." . $tableName;
}
public function modifyLimitQuery($query, $limit, $offset = null)
{
if ($limit === null && $offset === null) {
return $query;
}
$limit = (int)$limit;
$offset = (int)(($offset)?:0);
// Todo OVER() needs ORDER BY data!
$sql = 'SELECT db22.* FROM (SELECT ROW_NUMBER() OVER() AS DC_ROWNUM, db21.* '.
'FROM (' . $query . ') db21) db22 WHERE db22.DC_ROWNUM BETWEEN ' . ($offset+1) .' AND ' . ($offset+$limit);
return $sql;
}
/**
* returns the position of the first occurrence of substring $substr in string $str
*
* @param string $substr literal string to find
* @param string $str literal string
* @param int $pos position to start at, beginning of string by default
* @return integer
*/
public function getLocateExpression($str, $substr, $startPos = false)
{
if ($startPos == false) {
return 'LOCATE(' . $substr . ', ' . $str . ')';
} else {
return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')';
}
}
/**
* return string to call a function to get a substring inside an SQL statement
*
* Note: Not SQL92, but common functionality.
*
* SQLite only supports the 2 parameter variant of this function
*
* @param string $value an sql string literal or column name/alias
* @param integer $from where to start the substring portion
* @param integer $len the substring portion length
* @return string
*/
public function getSubstringExpression($value, $from, $len = null)
{
if ($len === null)
return 'SUBSTR(' . $value . ', ' . $from . ')';
else {
return 'SUBSTR(' . $value . ', ' . $from . ', ' . $len . ')';
}
}
public function supportsIdentityColumns()
{
return true;
}
public function prefersIdentityColumns()
{
return true;
}
/**
* Gets the character casing of a column in an SQL result set of this platform.
*
* DB2 returns all column names in SQL result sets in uppercase.
*
* @param string $column The column name for which to get the correct character casing.
* @return string The column name in the character casing used in SQL result sets.
*/
public function getSQLResultCasing($column)
{
return strtoupper($column);
}
}
\ No newline at end of file
......@@ -412,91 +412,8 @@ class MySqlPlatform extends AbstractPlatform
/**
* Gets the SQL to alter an existing table.
*
* @param string $name The name of the table that is intended to be changed.
* @param array $changes Associative array that contains the details of each type
* of change that is intended to be performed. The types of
* changes that are currently supported are defined as follows:
*
* name
*
* New name for the table.
*
* add
*
* Associative array with the names of fields to be added as
* indexes of the array. The value of each entry of the array
* should be set to another associative array with the properties
* of the fields to be added. The properties of the fields should
* be the same as defined by the Metabase parser.
*
*
* remove
*
* Associative array with the names of fields to be removed as indexes
* of the array. Currently the values assigned to each entry are ignored.
* An empty array should be used for future compatibility.
*
* rename
*
* Associative array with the names of fields to be renamed as indexes
* of the array. The value of each entry of the array should be set to
* another associative array with the entry named name with the new
* field name and the entry named Declaration that is expected to contain
* the portion of the field declaration already in DBMS specific SQL code
* as it is used in the CREATE TABLE statement.
*
* change
*
* Associative array with the names of the fields to be changed as indexes
* of the array. Keep in mind that if it is intended to change either the
* name of a field and any other properties, the change array entries
* should have the new names of the fields as array indexes.
*
* The value of each entry of the array should be set to another associative
* array with the properties of the fields to that are meant to be changed as
* array entries. These entries should be assigned to the new values of the
* respective properties. The properties of the fields should be the same
* as defined by the Metabase parser.
*
* Example
* array(
* 'name' => 'userlist',
* 'add' => array(
* 'quota' => array(
* 'type' => 'integer',
* 'unsigned' => 1
* )
* ),
* 'remove' => array(
* 'file_limit' => array(),
* 'time_limit' => array()
* ),
* 'change' => array(
* 'name' => array(
* 'length' => '20',
* 'definition' => array(
* 'type' => 'text',
* 'length' => 20,
* ),
* )
* ),
* 'rename' => array(
* 'sex' => array(
* 'name' => 'gender',
* 'definition' => array(
* 'type' => 'text',
* 'length' => 1,
* 'default' => 'M',
* ),
* )
* )
* )
*
* @param boolean $check indicates whether the function should just check if the DBMS driver
* can perform the requested table alterations if the value is true or
* actually perform them otherwise.
* @return boolean
* @override
* @param TableDiff $diff
* @return array
*/
public function getAlterTableSQL(TableDiff $diff)
{
......
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
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 <kontakt@beberlei.de>
*/
class DB2SchemaManager extends AbstractSchemaManager
{
/**
* Return a list of all tables in the current database
*
* Apparently creator is the schema not the user who created it:
* {@link http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db29.doc.sqlref/db2z_sysibmsystablestable.htm}
*
* @return array
*/
public function listTableNames()
{
$sql = $this->_platform->getListTablesSQL();
$sql .= " AND CREATOR = UPPER('".$this->_conn->getUsername()."')";
$tables = $this->_conn->fetchAll($sql);
return $this->_getPortableTablesList($tables);
}
/**
* Get Table Column Definition
*
* @param array $tableColumn
* @return Column
*/
protected function _getPortableTableColumnDefinition($tableColumn)
{
$tableColumn = array_change_key_case($tableColumn, \CASE_LOWER);
$length = null;
$fixed = null;
$unsigned = false;
$scale = false;
$precision = false;
switch (strtolower($tableColumn['typename'])) {
case 'smallint':
case 'bigint':
case 'integer':
case 'time':
case 'date':
$type = strtolower($tableColumn['typename']);
break;
case 'varchar':
$type = 'string';
$length = $tableColumn['length'];
$fixed = false;
break;
case 'character':
$type = 'string';
$length = $tableColumn['length'];
$fixed = true;
break;
case 'clob':
$type = 'text';
$length = $tableColumn['length'];
break;
case 'decimal':
case 'double':
case 'real':
$type = 'decimal';
$scale = $tableColumn['scale'];
$precision = $tableColumn['length'];
break;
case 'timestamp':
$type = 'datetime';
break;
default:
throw new \Doctrine\DBAL\DBALException("Unknown Type: ".$tableColumn['typename']);
}
$options = array(
'length' => $length,
'unsigned' => (bool)$unsigned,
'fixed' => (bool)$fixed,
'default' => ($tableColumn['default'] == "NULL") ? null : $tableColumn['default'],
'notnull' => (bool) ($tableColumn['nulls'] == 'N'),
'scale' => null,
'precision' => null,
'platformOptions' => array(),
);
if ($scale !== null && $precision !== null) {
$options['scale'] = $scale;
$options['precision'] = $precision;
}
return new Column($tableColumn['colname'], \Doctrine\DBAL\Types\Type::getType($type), $options);
}
protected function _getPortableTablesList($tables)
{
$tableNames = array();
foreach ($tables AS $tableRow) {
$tableRow = array_change_key_case($tableRow, \CASE_LOWER);
$tableNames[] = $tableRow['name'];
}
return $tableNames;
}
protected function _getPortableTableIndexesList($tableIndexes, $tableName=null)
{
$tableIndexRows = array();
$indexes = array();
foreach($tableIndexes AS $indexKey => $data) {
$data = array_change_key_case($data, \CASE_LOWER);
$unique = ($data['uniquerule'] == "D") ? false : true;
$primary = ($data['uniquerule'] == "P");
$indexName = strtolower($data['name']);
if ($primary) {
$keyName = 'primary';
} else {
$keyName = $indexName;
}
$indexes[$keyName] = new Index($indexName, explode("+", ltrim($data['colnames'], '+')), $unique, $primary);
}
return $indexes;
}
protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
{
$tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER);
$tableForeignKey['deleterule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['deleterule']);
$tableForeignKey['updaterule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['updaterule']);
return new ForeignKeyConstraint(
array_map('trim', (array)$tableForeignKey['fkcolnames']),
$tableForeignKey['reftbname'],
array_map('trim', (array)$tableForeignKey['pkcolnames']),
$tableForeignKey['relname'],
array(
'onUpdate' => $tableForeignKey['updaterule'],
'onDelete' => $tableForeignKey['deleterule'],
)
);
}
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);
// sadly this still segfaults on PDO_IBM, see http://pecl.php.net/bugs/bug.php?id=17199
//$view['text'] = (is_resource($view['text']) ? stream_get_contents($view['text']) : $view['text']);
if (!is_resource($view['text'])) {
$pos = strpos($view['text'], ' AS ');
$sql = substr($view['text'], $pos+4);
} else {
$sql = '';
}
return new View($view['name'], $sql);
}
}
\ No newline at end of file
......@@ -510,7 +510,24 @@ class Table extends AbstractAsset
*/
public function getColumns()
{
return $this->_columns;
$columns = $this->_columns;
$pkCols = array();
$fkCols = array();
if ($this->hasIndex($this->_primaryKeyName)) {
$pkCols = $this->getPrimaryKey()->getColumns();
}
foreach ($this->getForeignKeys() AS $fk) {
/* @var $fk ForeignKeyConstraint */
$fkCols = array_merge($fkCols, $fk->getColumns());
}
$colNames = array_unique(array_merge($pkCols, $fkCols, array_keys($columns)));
uksort($columns, function($a, $b) use($colNames) {
return (array_search($a, $colNames) >= array_search($b, $colNames));
});
return $columns;
}
......
......@@ -40,6 +40,7 @@ class ArrayType extends Type
public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
$value = (is_resource($value)) ? stream_get_contents($value) : $value;
return unserialize($value);
}
......
......@@ -21,6 +21,7 @@ class ObjectType extends Type
public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
$value = (is_resource($value)) ? stream_get_contents($value) : $value;
return unserialize($value);
}
......
......@@ -36,6 +36,19 @@ class TextType extends Type
return $platform->getClobTypeDeclarationSQL($fieldDeclaration);
}
/**
* Converts a value from its database representation to its PHP representation
* of this type.
*
* @param mixed $value The value to convert.
* @param AbstractPlatform $platform The currently used database platform.
* @return mixed The PHP representation of the value.
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return (is_resource($value)) ? stream_get_contents($value) : $value;
}
public function getName()
{
return Type::TEXT;
......
......@@ -41,13 +41,6 @@ use ReflectionClass, ReflectionProperty;
*/
class ClassMetadata extends ClassMetadataInfo
{
/**
* The ReflectionClass instance of the mapped class.
*
* @var ReflectionClass
*/
public $reflClass;
/**
* The ReflectionProperty instances of the mapped class.
*
......@@ -76,16 +69,6 @@ class ClassMetadata extends ClassMetadataInfo
$this->table['name'] = $this->reflClass->getShortName();
}
/**
* Gets the ReflectionClass instance of the mapped class.
*
* @return ReflectionClass
*/
public function getReflectionClass()
{
return $this->reflClass;
}
/**
* Gets the ReflectionPropertys of the mapped class.
*
......
......@@ -19,6 +19,8 @@
namespace Doctrine\ORM\Mapping;
use ReflectionClass;
/**
* A <tt>ClassMetadata</tt> instance holds all the object-relational mapping metadata
* of an entity and it's associations.
......@@ -366,6 +368,13 @@ class ClassMetadataInfo
*/
public $versionField;
/**
* The ReflectionClass instance of the mapped class.
*
* @var ReflectionClass
*/
public $reflClass;
/**
* Initializes a new ClassMetadata instance that will hold the object-relational mapping
* metadata of the class with the given name.
......@@ -378,6 +387,19 @@ class ClassMetadataInfo
$this->rootEntityName = $entityName;
}
/**
* Gets the ReflectionClass instance of the mapped class.
*
* @return ReflectionClass
*/
public function getReflectionClass()
{
if ( ! $this->reflClass) {
$this->reflClass = new ReflectionClass($entityName);
}
return $this->reflClass;
}
/**
* Sets the change tracking policy used by this class.
*
......
......@@ -118,15 +118,17 @@ class XmlDriver extends AbstractFileDriver
// Evaluate <unique-constraints..>
if (isset($xmlRoot->{'unique-constraints'})) {
foreach ($xmlRoot->{'unique-constraints'}->{'unique-constraint'} as $unique) {
if (is_string($unique['columns'])) {
$columns = explode(',', $unique['columns']);
$columns = explode(',', (string)$unique['columns']);
if (isset($unique['name'])) {
$metadata->table['uniqueConstraints'][(string)$unique['name']] = array(
'columns' => $columns
);
} else {
$columns = $unique['columns'];
$metadata->table['uniqueConstraints'][] = array(
'columns' => $columns
);
}
$metadata->table['uniqueConstraints'][$unique['name']] = array(
'columns' => $columns
);
}
}
......@@ -205,7 +207,7 @@ class XmlDriver extends AbstractFileDriver
$metadata->setSequenceGeneratorDefinition(array(
'sequenceName' => (string)$seqGenerator['sequence-name'],
'allocationSize' => (string)$seqGenerator['allocation-size'],
'initialValue' => (string)$seqGeneratorAnnot['initial-value']
'initialValue' => (string)$seqGenerator['initial-value']
));
} else if (isset($idElement->{'table-generator'})) {
throw MappingException::tableIdGeneratorNotImplemented($className);
......
......@@ -135,6 +135,10 @@ class YamlDriver extends AbstractFileDriver
if (isset($element['id'])) {
// Evaluate identifier settings
foreach ($element['id'] as $name => $idElement) {
if (!isset($idElement['type'])) {
throw MappingException::propertyTypeIsRequired($className, $name);
}
$mapping = array(
'id' => true,
'fieldName' => $name,
......@@ -151,6 +155,12 @@ class YamlDriver extends AbstractFileDriver
$metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_'
. strtoupper($idElement['generator']['strategy'])));
}
// Check for SequenceGenerator/TableGenerator definition
if (isset($idElement['sequenceGenerator'])) {
$metadata->setSequenceGeneratorDefinition($idElement['sequenceGenerator']);
} else if (isset($idElement['tableGenerator'])) {
throw MappingException::tableIdGeneratorNotImplemented($className);
}
}
}
......@@ -177,12 +187,6 @@ class YamlDriver extends AbstractFileDriver
. strtoupper($fieldMapping['generator']['strategy'])));
}
}
// Check for SequenceGenerator/TableGenerator definition
if (isset($fieldMapping['sequenceGenerator'])) {
$metadata->setSequenceGeneratorDefinition($fieldMapping['sequenceGenerator']);
} else if (isset($fieldMapping['tableGenerator'])) {
throw MappingException::tableIdGeneratorNotImplemented($className);
}
if (isset($fieldMapping['column'])) {
$mapping['columnName'] = $fieldMapping['column'];
}
......
......@@ -58,7 +58,7 @@ class MultiTableDeleteExecutor extends AbstractSqlExecutor
$primaryDqlAlias = $AST->deleteClause->aliasIdentificationVariable;
$rootClass = $em->getClassMetadata($primaryClass->rootEntityName);
$tempTable = $rootClass->getTemporaryIdTableName();
$tempTable = $platform->getTemporaryTableName($rootClass->getTemporaryIdTableName());
$idColumnNames = $rootClass->getIdentifierColumnNames();
$idColumnList = implode(', ', $idColumnNames);
......@@ -95,8 +95,7 @@ class MultiTableDeleteExecutor extends AbstractSqlExecutor
);
}
$this->_createTempTableSql = $platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' ('
. $platform->getColumnDeclarationListSQL($columnDefinitions)
. ', PRIMARY KEY(' . $idColumnList . '))';
. $platform->getColumnDeclarationListSQL($columnDefinitions) . ')';
$this->_dropTempTableSql = 'DROP TABLE ' . $tempTable;
}
......
......@@ -59,7 +59,7 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
$updateItems = $updateClause->updateItems;
$tempTable = $rootClass->getTemporaryIdTableName();
$tempTable = $platform->getTemporaryTableName($rootClass->getTemporaryIdTableName());
$idColumnNames = $rootClass->getIdentifierColumnNames();
$idColumnList = implode(', ', $idColumnNames);
......@@ -126,8 +126,7 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
);
}
$this->_createTempTableSql = $platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' ('
. $platform->getColumnDeclarationListSQL($columnDefinitions)
. ', PRIMARY KEY(' . $idColumnList . '))';
. $platform->getColumnDeclarationListSQL($columnDefinitions) . ')';
$this->_dropTempTableSql = 'DROP TABLE ' . $tempTable;
}
......
......@@ -25,6 +25,7 @@ class AllTests
$suite->addTestSuite('Doctrine\Tests\DBAL\Functional\Schema\MySqlSchemaManagerTest');
$suite->addTestSuite('Doctrine\Tests\DBAL\Functional\Schema\PostgreSqlSchemaManagerTest');
$suite->addTestSuite('Doctrine\Tests\DBAL\Functional\Schema\OracleSchemaManagerTest');
$suite->addTestSuite('Doctrine\Tests\DBAL\Functional\Schema\Db2SchemaManagerTest');
$suite->addTestSuite('Doctrine\Tests\DBAL\Functional\ConnectionTest');
return $suite;
......
<?php
namespace Doctrine\Models\DBAL\Functional;
class DataAccessTest extends \Doctrine\Tests\DbalFunctionalTestCase
{
public function setUp()
{
parent::setUp();
try {
/* @var $sm \Doctrine\DBAL\Schema\AbstractSchemaManager */
$table = new \Doctrine\DBAL\Schema\Table("fetch_table");
$table->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
<?php
namespace Doctrine\Tests\DBAL\Functional\Schema;
use Doctrine\DBAL\Schema;
require_once __DIR__ . '/../../../TestInit.php';
class Db2SchemaManagerTest extends SchemaManagerFunctionalTestCase
{
}
\ No newline at end of file
......@@ -28,6 +28,8 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->markTestSkipped('The ' . $testClass .' requires the use of ' . $dbms);
}
#$this->_conn->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger);
$this->_sm = $this->_conn->getSchemaManager();
}
......@@ -59,6 +61,10 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
public function testListDatabases()
{
if (!$this->_sm->getDatabasePlatform()->supportsCreateDropDatabase()) {
$this->markTestSkipped('Cannot drop Database client side with this Driver.');
}
$this->_sm->dropAndCreateDatabase('test_create_database');
$databases = $this->_sm->listDatabases();
......@@ -73,12 +79,12 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$tables = $this->_sm->listTables();
$this->assertType('array', $tables);
$this->assertTrue(count($tables) > 0);
$this->assertTrue(count($tables) > 0, "List Tables has to find at least one table named 'list_tables_test'.");
$foundTable = false;
foreach ($tables AS $table) {
$this->assertType('Doctrine\DBAL\Schema\Table', $table);
if ($table->getName() == 'list_tables_test') {
if (strtolower($table->getName()) == 'list_tables_test') {
$foundTable = true;
$this->assertTrue($table->hasColumn('id'));
......@@ -86,6 +92,8 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->assertTrue($table->hasColumn('foreign_key_test'));
}
}
$this->assertTrue( $foundTable , "The 'list_tables_test' table has to be found.");
}
public function testListTableColumns()
......@@ -122,7 +130,6 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->assertEquals('foo', strtolower($columns['foo']->getname()));
$this->assertType('Doctrine\DBAL\Types\TextType', $columns['foo']->gettype());
$this->assertEquals(null, $columns['foo']->getlength());
$this->assertEquals(false, $columns['foo']->getunsigned());
$this->assertEquals(false, $columns['foo']->getfixed());
$this->assertEquals(true, $columns['foo']->getnotnull());
......@@ -171,6 +178,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->assertEquals(3, count($tableIndexes));
$this->assertArrayHasKey('primary', $tableIndexes, 'listTableIndexes() has to return a "primary" array key.');
$this->assertEquals(array('id'), array_map('strtolower', $tableIndexes['primary']->getColumns()));
$this->assertTrue($tableIndexes['primary']->isUnique());
$this->assertTrue($tableIndexes['primary']->isPrimary());
......@@ -218,7 +226,7 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->_sm->dropAndCreateTable($tableA);
$fkConstraints = $this->_sm->listTableForeignKeys('test_create_fk');
$this->assertEquals(1, count($fkConstraints));
$this->assertEquals(1, count($fkConstraints), "Table 'test_create_fk1' has to have one foreign key.");
$fkConstraint = current($fkConstraints);
$this->assertType('\Doctrine\DBAL\Schema\ForeignKeyConstraint', $fkConstraint);
......@@ -237,22 +245,20 @@ class SchemaManagerFunctionalTestCase extends \Doctrine\Tests\DbalFunctionalTest
$this->createTestTable('test_create_fk2');
$foreignKey = new \Doctrine\DBAL\Schema\ForeignKeyConstraint(
array('foreign_key_test'), 'test_create_fk2', array('id'), 'foreign_key_test_fk', array('onUpdate' => 'CASCADE', 'onDelete' => 'CASCADE')
array('foreign_key_test'), 'test_create_fk2', array('id'), 'foreign_key_test_fk', array('onDelete' => 'CASCADE')
);
$this->_sm->createForeignKey($foreignKey, 'test_create_fk1');
$fkeys = $this->_sm->listTableForeignKeys('test_create_fk1');
$this->assertEquals(1, count($fkeys));
$this->assertEquals(1, count($fkeys), "Table 'test_create_fk1' has to have one foreign key.");
$this->assertType('Doctrine\DBAL\Schema\ForeignKeyConstraint', $fkeys[0]);
$this->assertEquals(array('foreign_key_test'), array_map('strtolower', $fkeys[0]->getLocalColumns()));
$this->assertEquals(array('id'), array_map('strtolower', $fkeys[0]->getForeignColumns()));
$this->assertEquals('test_create_fk2', strtolower($fkeys[0]->getForeignTableName()));
if($fkeys[0]->hasOption('onUpdate')) {
$this->assertEquals('CASCADE', $fkeys[0]->getOption('onUpdate'));
}
if($fkeys[0]->hasOption('onDelete')) {
$this->assertEquals('CASCADE', $fkeys[0]->getOption('onDelete'));
}
......
......@@ -6,6 +6,10 @@ class DbalFunctionalTestCase extends DbalTestCase
{
/* Shared connection when a TestCase is run alone (outside of it's functional suite) */
private static $_sharedConn;
/**
* @var Doctrine\DBAL\Connection
*/
protected $_conn;
protected function setUp()
......
......@@ -122,7 +122,7 @@ class AdvancedDqlQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
public function testUpdateAs()
{
$dql = 'UPDATE Doctrine\Tests\Models\Company\CompanyEmployee AS p SET p.salary = 1';
$this->_em->createQuery($dql)->getResult();
$this->_em->createQuery($dql)->execute();
$this->assertTrue(count($this->_em->createQuery(
'SELECT count(p.id) FROM Doctrine\Tests\Models\Company\CompanyEmployee p WHERE p.salary = 1')->getResult()) > 0);
......
......@@ -28,7 +28,7 @@ class DefaultValuesTest extends \Doctrine\Tests\OrmFunctionalTestCase
$user->name = 'romanb';
$this->_em->persist($user);
$this->_em->flush();
$this->_em->clear();
$this->_em->clear();
$userId = $user->id; // e.g. from $_REQUEST
$user2 = $this->_em->getReference(get_class($user), $userId);
......
......@@ -47,7 +47,9 @@ class ManyToManyBasicAssociationTest extends \Doctrine\Tests\OrmFunctionalTestCa
// Get user
$user = $uRep->findOneById($user->getId());
$this->assertNotNull($user, "Has to return exactly one entry.");
$this->assertFalse($user->getGroups()->isInitialized());
// Check groups
......@@ -89,6 +91,8 @@ class ManyToManyBasicAssociationTest extends \Doctrine\Tests\OrmFunctionalTestCa
// Association should not exist
$user2 = $this->_em->find(get_class($user), $user->getId());
$this->assertNotNull($user2, "Has to return exactly one entry.");
$this->assertEquals(0, $user2->getGroups()->count());
}
......
......@@ -16,13 +16,12 @@ require_once __DIR__ . '/../../TestInit.php';
*/
class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
private $platform = null;
protected function setUp() {
$this->useModelSet('cms');
parent::setUp();
if ($this->_em->getConnection()->getDatabasePlatform()->getName() == 'oracle') {
$this->markTestSkipped('The ' . __CLASS__ .' does not work with Oracle due to character casing.');
}
$this->platform = $this->_em->getConnection()->getDatabasePlatform();
}
public function testBasicNativeQuery()
......@@ -38,8 +37,8 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$rsm = new ResultSetMapping;
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
$rsm->addFieldResult('u', 'id', 'id');
$rsm->addFieldResult('u', 'name', 'name');
$rsm->addFieldResult('u', $this->platform->getSQLResultCasing('id'), 'id');
$rsm->addFieldResult('u', $this->platform->getSQLResultCasing('name'), 'name');
$query = $this->_em->createNativeQuery('SELECT id, name FROM cms_users WHERE username = ?', $rsm);
$query->setParameter(1, 'romanb');
......@@ -70,11 +69,11 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$rsm = new ResultSetMapping;
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
$rsm->addFieldResult('u', 'id', 'id');
$rsm->addFieldResult('u', 'name', 'name');
$rsm->addFieldResult('u', 'status', 'status');
$rsm->addFieldResult('u', $this->platform->getSQLResultCasing('id'), 'id');
$rsm->addFieldResult('u', $this->platform->getSQLResultCasing('name'), 'name');
$rsm->addFieldResult('u', $this->platform->getSQLResultCasing('status'), 'status');
$rsm->addJoinedEntityResult('Doctrine\Tests\Models\CMS\CmsPhonenumber', 'p', 'u', 'phonenumbers');
$rsm->addFieldResult('p', 'phonenumber', 'phonenumber');
$rsm->addFieldResult('p', $this->platform->getSQLResultCasing('phonenumber'), 'phonenumber');
$query = $this->_em->createNativeQuery('SELECT id, name, status, phonenumber FROM cms_users INNER JOIN cms_phonenumbers ON id = user_id WHERE username = ?', $rsm);
$query->setParameter(1, 'romanb');
......@@ -115,14 +114,14 @@ class NativeQueryTest extends \Doctrine\Tests\OrmFunctionalTestCase
$rsm = new ResultSetMapping;
$rsm->addEntityResult('Doctrine\Tests\Models\CMS\CmsUser', 'u');
$rsm->addFieldResult('u', 'id', 'id');
$rsm->addFieldResult('u', 'name', 'name');
$rsm->addFieldResult('u', 'status', 'status');
$rsm->addFieldResult('u', $this->platform->getSQLResultCasing('id'), 'id');
$rsm->addFieldResult('u', $this->platform->getSQLResultCasing('name'), 'name');
$rsm->addFieldResult('u', $this->platform->getSQLResultCasing('status'), 'status');
$rsm->addJoinedEntityResult('Doctrine\Tests\Models\CMS\CmsAddress', 'a', 'u', 'address');
$rsm->addFieldResult('a', 'a_id', 'id');
$rsm->addFieldResult('a', 'country', 'country');
$rsm->addFieldResult('a', 'zip', 'zip');
$rsm->addFieldResult('a', 'city', 'city');
$rsm->addFieldResult('a', $this->platform->getSQLResultCasing('a_id'), 'id');
$rsm->addFieldResult('a', $this->platform->getSQLResultCasing('country'), 'country');
$rsm->addFieldResult('a', $this->platform->getSQLResultCasing('zip'), 'zip');
$rsm->addFieldResult('a', $this->platform->getSQLResultCasing('city'), 'city');
$query = $this->_em->createNativeQuery('SELECT u.id, u.name, u.status, a.id AS a_id, a.country, a.zip, a.city FROM cms_users u INNER JOIN cms_addresses a ON u.id = a.user_id WHERE u.username = ?', $rsm);
$query->setParameter(1, 'romanb');
......
......@@ -27,7 +27,7 @@ class MySqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
$tool = new SchemaTool($this->_em);
$sql = $tool->getCreateSchemaSql($classes);
$this->assertEquals(8, count($sql));
$this->assertEquals("CREATE TABLE cms_addresses (id INT AUTO_INCREMENT NOT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(id)) ENGINE = InnoDB", $sql[0]);
$this->assertEquals("CREATE TABLE cms_addresses (id INT AUTO_INCREMENT NOT NULL, user_id INT DEFAULT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB", $sql[0]);
$this->assertEquals("CREATE TABLE cms_users (id INT AUTO_INCREMENT NOT NULL, status VARCHAR(50) NOT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, UNIQUE INDEX cms_users_username_uniq (username), PRIMARY KEY(id)) ENGINE = InnoDB", $sql[1]);
$this->assertEquals("CREATE TABLE cms_users_groups (user_id INT NOT NULL, group_id INT NOT NULL, PRIMARY KEY(user_id, group_id)) ENGINE = InnoDB", $sql[2]);
$this->assertEquals("CREATE TABLE cms_phonenumbers (phonenumber VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(phonenumber)) ENGINE = InnoDB", $sql[3]);
......
......@@ -34,7 +34,7 @@ class PostgreSqlSchemaToolTest extends \Doctrine\Tests\OrmFunctionalTestCase
$sql = $tool->getCreateSchemaSql($classes);
$this->assertEquals(count($sql), 11);
$this->assertEquals("CREATE TABLE cms_addresses (id INT NOT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, user_id INT DEFAULT NULL, PRIMARY KEY(id))", $sql[0]);
$this->assertEquals("CREATE TABLE cms_addresses (id INT NOT NULL, user_id INT DEFAULT NULL, country VARCHAR(50) NOT NULL, zip VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, PRIMARY KEY(id))", $sql[0]);
$this->assertEquals("CREATE TABLE cms_users (id INT NOT NULL, status VARCHAR(50) NOT NULL, username VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))", $sql[1]);
$this->assertEquals("CREATE UNIQUE INDEX cms_users_username_uniq ON cms_users (username)", $sql[2]);
$this->assertEquals("CREATE TABLE cms_users_groups (user_id INT NOT NULL, group_id INT NOT NULL, PRIMARY KEY(user_id, group_id))", $sql[3]);
......
......@@ -36,6 +36,40 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
return $class;
}
/**
* @depends testEntityTableNameAndInheritance
* @param ClassMetadata $class
*/
public function testEntityUniqueConstraints($class)
{
$this->assertArrayHasKey('uniqueConstraints', $class->table,
'ClassMetadata should have uniqueConstraints key in table property when Unique Constraints are set.');
$this->assertEquals(array(
"search_idx" => array("columns" => array("name", "user_email"))
), $class->table['uniqueConstraints']);
return $class;
}
/**
* @depends testEntityTableNameAndInheritance
* @param ClassMetadata $class
*/
public function testEntitySequence($class)
{
$this->assertType('array', $class->sequenceGeneratorDefinition, 'No Sequence Definition set on this driver.');
$this->assertEquals(
array(
'sequenceName' => 'tablename_seq',
'allocationSize' => 100,
'initialValue' => 1,
),
$class->sequenceGeneratorDefinition
);
}
/**
* @depends testEntityTableNameAndInheritance
* @param ClassMetadata $class
......@@ -206,11 +240,16 @@ abstract class AbstractMappingDriverTest extends \Doctrine\Tests\OrmTestCase
/**
* @Entity
* @HasLifecycleCallbacks
* @Table(name="cms_users")
* @Table(name="cms_users", uniqueConstraints={@UniqueConstraint(name="search_idx", columns={"name", "user_email"})})
*/
class User
{
/** @Id @Column(type="integer") @generatedValue(strategy="AUTO") */
/**
* @Id
* @Column(type="integer")
* @generatedValue(strategy="AUTO")
* @SequenceGenerator(sequenceName="tablename_seq", initialValue=1, allocationSize=100)
**/
public $id;
/**
......@@ -369,5 +408,13 @@ class User
),
'orderBy' => NULL,
));
$metadata->table['uniqueConstraints'] = array(
'search_idx' => array('columns' => array('name', 'user_email')),
);
$metadata->setSequenceGeneratorDefinition(array(
'sequenceName' => 'tablename_seq',
'allocationSize' => 100,
'initialValue' => 1,
));
}
}
\ No newline at end of file
......@@ -102,4 +102,12 @@ $metadata->mapManyToMany(array(
),
),
'orderBy' => NULL,
));
\ No newline at end of file
));
$metadata->table['uniqueConstraints'] = array(
'search_idx' => array('columns' => array('name', 'user_email')),
);
$metadata->setSequenceGeneratorDefinition(array(
'sequenceName' => 'tablename_seq',
'allocationSize' => 100,
'initialValue' => 1,
));
\ No newline at end of file
......@@ -6,6 +6,10 @@
http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<entity name="Doctrine\Tests\ORM\Mapping\User" table="cms_users">
<unique-constraints>
<unique-constraint columns="name,user_email" name="search_idx" />
</unique-constraints>
<lifecycle-callbacks>
<lifecycle-callback type="prePersist" method="doStuffOnPrePersist"/>
......@@ -14,6 +18,7 @@
</lifecycle-callbacks>
<id name="id" type="integer" column="id">
<sequence-generator sequence-name="tablename_seq" allocation-size="100" initial-value="1" />
<generator strategy="AUTO"/>
</id>
......
......@@ -6,6 +6,10 @@ Doctrine\Tests\ORM\Mapping\User:
type: integer
generator:
strategy: AUTO
sequenceGenerator:
sequenceName: tablename_seq
allocationSize: 100
initialValue: 1
fields:
name:
type: string
......@@ -51,4 +55,7 @@ Doctrine\Tests\ORM\Mapping\User:
- all
lifecycleCallbacks:
prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ]
postPersist: [ doStuffOnPostPersist ]
\ No newline at end of file
postPersist: [ doStuffOnPostPersist ]
uniqueConstraints:
search_idx:
columns: name,user_email
\ No newline at end of file
......@@ -253,7 +253,7 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
$queries = "";
for($i = count($this->_sqlLoggerStack->queries)-1; $i > max(count($this->_sqlLoggerStack->queries)-25, 0); $i--) {
$query = $this->_sqlLoggerStack->queries[$i];
$params = array_map(function($p) { return "'".$p."'"; }, $query['params'] ?: array());
$params = array_map(function($p) { if (is_object($p)) return get_class($p); else return "'".$p."'"; }, $query['params'] ?: array());
$queries .= ($i+1).". SQL: '".$query['sql']."' Params: ".implode(", ", $params).PHP_EOL;
}
......
......@@ -13,9 +13,6 @@ require_once __DIR__ . '/../../../lib/Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine');
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Symfony', __DIR__ . "/../../../lib/vendor");
$classLoader->register();
if (!file_exists(__DIR__."/Proxies")) {
if (!mkdir(__DIR__."/Proxies")) {
throw new Exception("Could not create " . __DIR__."/Proxies Folder.");
......
......@@ -4,7 +4,7 @@ namespace Doctrine\Tests;
/**
* TestUtil is a class with static utility methods used during tests.
*
*
* @author robo
*/
class TestUtil
......@@ -12,22 +12,22 @@ class TestUtil
/**
* Gets a <b>real</b> 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,30 @@ 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 {
$sm = $realConn->getSchemaManager();
$tableNames = $sm->listTableNames();
foreach ($tableNames AS $tableName) {
$sm->dropTable($tableName);
}
}
$eventManager = null;
if (isset($GLOBALS['db_event_subscribers'])) {
......@@ -73,9 +85,9 @@ class TestUtil
$eventManager->addEventSubscriber($subscriberInstance);
}
}
$conn = \Doctrine\DBAL\DriverManager::getConnection($realDbParams, null, $eventManager);
} else {
$params = array(
'driver' => 'pdo_sqlite',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment