Commit 2c50eb9e authored by Benjamin Eberlei's avatar Benjamin Eberlei

Merge master

parents 46863217 1c77da6e
......@@ -4,9 +4,9 @@ Portability
There are often cases when you need to write an application or library that is portable
across multiple different database vendors. The Doctrine ORM is one example of such
a library. It is an abstraction layer over all the currently supported vendors (MySQL, Oracle,
PostgreSQL, SQLite and Microsoft SQL Server). If you want to use the DBAL to write a portable application
or library you have to follow lots of rules to make all the different vendors work the
same.
PostgreSQL, SQLite, SAP SQL Anywhere and Microsoft SQL Server). If you want to use the DBAL
to write a portable application or library you have to follow lots of rules to make
all the different vendors work the same.
There are many different layers that you need to take care of, here is a quick list:
......@@ -39,7 +39,7 @@ Connection Wrapper
This functionality is only implemented with Doctrine 2.1 upwards.
To handle all the points 1-3 you have to use a special wrapper around the database
connection. The handling and differences to tackle are all taken from the great
connection. The handling and differences to tackle are all taken from the great
`PEAR MDB2 library <http://pear.php.net/package/MDB2/redirected>`_.
Using the following code block in your initialization will:
......
......@@ -117,4 +117,36 @@ class Configuration
return null;
}
/**
* Sets the default auto-commit mode for connections.
*
* If a connection is in auto-commit mode, then all its SQL statements will be executed and committed as individual
* transactions. Otherwise, its SQL statements are grouped into transactions that are terminated by a call to either
* the method commit or the method rollback. By default, new connections are in auto-commit mode.
*
* @param boolean $autoCommit True to enable auto-commit mode; false to disable it.
*
* @see getAutoCommit
*/
public function setAutoCommit($autoCommit)
{
$this->_attributes['autoCommit'] = (boolean) $autoCommit;
}
/**
* Returns the default auto-commit mode for connections.
*
* @return boolean True if auto-commit mode is enabled by default for connections, false otherwise.
*
* @see setAutoCommit
*/
public function getAutoCommit()
{
if (isset($this->_attributes['autoCommit'])) {
return $this->_attributes['autoCommit'];
}
return true;
}
}
......@@ -117,6 +117,13 @@ class Connection implements DriverConnection
*/
private $_isConnected = false;
/**
* The current auto-commit mode of this connection.
*
* @var boolean
*/
private $autoCommit = true;
/**
* The transaction nesting level.
*
......@@ -225,6 +232,7 @@ class Connection implements DriverConnection
$this->_platform->setEventManager($eventManager);
$this->_transactionIsolationLevel = $this->_platform->getDefaultTransactionIsolationLevel();
$this->autoCommit = $config->getAutoCommit();
}
/**
......@@ -356,6 +364,10 @@ class Connection implements DriverConnection
$this->_conn = $this->_driver->connect($this->_params, $user, $password, $driverOptions);
$this->_isConnected = true;
if (false === $this->autoCommit) {
$this->beginTransaction();
}
if ($this->_eventManager->hasListeners(Events::postConnect)) {
$eventArgs = new Event\ConnectionEventArgs($this);
$this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs);
......@@ -364,6 +376,49 @@ class Connection implements DriverConnection
return true;
}
/**
* Returns the current auto-commit mode for this connection.
*
* @return boolean True if auto-commit mode is currently enabled for this connection, false otherwise.
*
* @see setAutoCommit
*/
public function isAutoCommit()
{
return true === $this->autoCommit;
}
/**
* Sets auto-commit mode for this connection.
*
* If a connection is in auto-commit mode, then all its SQL statements will be executed and committed as individual
* transactions. Otherwise, its SQL statements are grouped into transactions that are terminated by a call to either
* the method commit or the method rollback. By default, new connections are in auto-commit mode.
*
* NOTE: If this method is called during a transaction and the auto-commit mode is changed, the transaction is
* committed. If this method is called and the auto-commit mode is not changed, the call is a no-op.
*
* @param boolean $autoCommit True to enable auto-commit mode; false to disable it.
*
* @see isAutoCommit
*/
public function setAutoCommit($autoCommit)
{
$autoCommit = (boolean) $autoCommit;
// Mode not changed, no-op.
if ($autoCommit === $this->autoCommit) {
return;
}
$this->autoCommit = $autoCommit;
// Commit all currently active transactions if any when switching auto-commit mode.
if (true === $this->_isConnected && 0 !== $this->_transactionNestingLevel) {
$this->commitAll();
}
}
/**
* Sets the fetch mode.
*
......@@ -1095,6 +1150,28 @@ class Connection implements DriverConnection
}
--$this->_transactionNestingLevel;
if (false === $this->autoCommit && 0 === $this->_transactionNestingLevel) {
$this->beginTransaction();
}
}
/**
* Commits all current nesting transactions.
*/
private function commitAll()
{
while (0 !== $this->_transactionNestingLevel) {
if (false === $this->autoCommit && 1 === $this->_transactionNestingLevel) {
// When in no auto-commit mode, the last nesting commit immediately starts a new transaction.
// Therefore we need to do the final commit here and then leave to avoid an infinite loop.
$this->commit();
return;
}
$this->commit();
}
}
/**
......@@ -1125,6 +1202,10 @@ class Connection implements DriverConnection
if ($logger) {
$logger->stopQuery();
}
if (false === $this->autoCommit) {
$this->beginTransaction();
}
} else if ($this->_nestTransactionsWithSavepoints) {
if ($logger) {
$logger->startQuery('"ROLLBACK TO SAVEPOINT"');
......
......@@ -60,6 +60,8 @@ class MysqliConnection implements Connection
if (isset($params['charset'])) {
$this->_conn->set_charset($params['charset']);
}
$this->setDriverOptions($driverOptions);
}
/**
......@@ -159,4 +161,50 @@ class MysqliConnection implements Connection
{
return $this->_conn->error;
}
/**
* Apply the driver options to the connection.
*
* @param array $driverOptions
*
* @throws MysqliException When one of of the options is not supported.
* @throws MysqliException When applying doesn't work - e.g. due to incorrect value.
*/
private function setDriverOptions(array $driverOptions = array())
{
$supportedDriverOptions = array(
\MYSQLI_OPT_CONNECT_TIMEOUT,
\MYSQLI_OPT_LOCAL_INFILE,
\MYSQLI_INIT_COMMAND,
\MYSQLI_READ_DEFAULT_FILE,
\MYSQLI_READ_DEFAULT_GROUP,
);
if (version_compare(PHP_VERSION, '5.5.0') >= 0) {
$supportedDriverOptions[] = \MYSQLI_SERVER_PUBLIC_KEY;
}
$exceptionMsg = "%s option '%s' with value '%s'";
foreach ($driverOptions as $option => $value) {
if (!in_array($option, $supportedDriverOptions, true)) {
throw new MysqliException(
sprintf($exceptionMsg, 'Unsupported', $option, $value)
);
}
if (@mysqli_options($this->_conn, $option, $value)) {
continue;
}
$msg = sprintf($exceptionMsg, 'Failed to set', $option, $value);
$msg .= sprintf(', error: %s (%d)', mysqli_error($this->_conn), mysqli_errno($this->_conn));
throw new MysqliException(
$msg,
mysqli_errno($this->_conn)
);
}
}
}
<?php
/*
* 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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Platforms\SQLAnywhere12Platform;
use Doctrine\DBAL\Schema\SQLAnywhereSchemaManager;
/**
* A Doctrine DBAL driver for the SAP Sybase SQL Anywhere PHP extension.
*
* @author Steve Müller <st.mueller@dzh-online.de>
* @link www.doctrine-project.org
* @since 2.5
*/
class Driver implements \Doctrine\DBAL\Driver
{
/**
* Build the connection string for given connection parameters and driver options.
*
* @param string $host Host address to connect to.
* @param integer $port Port to use for the connection (default to SQL Anywhere standard port 2683).
* @param string $server Database server name on the host to connect to.
* SQL Anywhere allows multiple database server instances on the same host,
* therefore specifying the server instance name to use is mandatory.
* @param string $dbname Name of the database on the server instance to connect to.
* @param string $username User name to use for connection authentication.
* @param string $password Password to use for connection authentication.
* @param array $driverOptions Additional parameters to use for the connection.
*
* @return string
*/
public function buildDsn($host, $port, $server, $dbname, $username = null, $password = null, array $driverOptions = array())
{
$port = $port ?: 2683;
return
'LINKS=tcpip(HOST=' . $host . ';PORT=' . $port . ';DoBroadcast=Direct)' .
';ServerName=' . $server .
';DBN=' . $dbname .
';UID=' . $username .
';PWD=' . $password .
';' . implode(
';',
array_map(function ($key, $value) {
return $key . '=' . $value;
}, array_keys($driverOptions), $driverOptions)
);
}
/**
* {@inheritdoc}
*
* @throws SQLAnywhereException
*/
public function connect(array $params, $username = null, $password = null, array $driverOptions = array())
{
if ( ! isset($params['host'])) {
throw new SQLAnywhereException("Missing 'host' in configuration for sqlanywhere driver.");
}
if ( ! isset($params['server'])) {
throw new SQLAnywhereException("Missing 'server' in configuration for sqlanywhere driver.");
}
if ( ! isset($params['dbname'])) {
throw new SQLAnywhereException("Missing 'dbname' in configuration for sqlanywhere driver.");
}
return new SQLAnywhereConnection(
$this->buildDsn(
$params['host'],
isset($params['port']) ? $params['port'] : null,
$params['server'],
$params['dbname'],
$username,
$password,
$driverOptions
),
isset($params['persistent']) ? $params['persistent'] : false
);
}
/**
* {@inheritdoc}
*/
public function getDatabase(Connection $conn)
{
$params = $conn->getParams();
return $params['dbname'];
}
/**
* {@inheritdoc}
*/
public function getDatabasePlatform()
{
return new SQLAnywhere12Platform();
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'sqlanywhere';
}
/**
* {@inheritdoc}
*/
public function getSchemaManager(Connection $conn)
{
return new SQLAnywhereSchemaManager($conn);
}
}
<?php
/*
* 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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\Driver\Connection;
/**
* SAP Sybase SQL Anywhere implementation of the Connection interface.
*
* @author Steve Müller <st.mueller@dzh-online.de>
* @link www.doctrine-project.org
* @since 2.5
*/
class SQLAnywhereConnection implements Connection
{
/**
* @var resource The SQL Anywhere connection resource.
*/
private $connection;
/**
* Constructor.
*
* Connects to database with given connection string.
*
* @param string $dsn The connection string.
* @param boolean $persistent Whether or not to establish a persistent connection.
*
* @throws SQLAnywhereException
*/
public function __construct($dsn, $persistent = false)
{
$this->connection = $persistent ? @sasql_pconnect($dsn) : @sasql_connect($dsn);
if ( ! is_resource($this->connection) || get_resource_type($this->connection) !== 'SQLAnywhere connection') {
throw SQLAnywhereException::fromSQLAnywhereError();
}
// Disable PHP warnings on error.
if ( ! sasql_set_option($this->connection, 'verbose_errors', false)) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
// Enable auto committing by default.
if ( ! sasql_set_option($this->connection, 'auto_commit', 'on')) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
// Enable exact, non-approximated row count retrieval.
if ( ! sasql_set_option($this->connection, 'row_counts', true)) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
}
/**
* {@inheritdoc}
*
* @throws SQLAnywhereException
*/
public function beginTransaction()
{
if ( ! sasql_set_option($this->connection, 'auto_commit', 'off')) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
return true;
}
/**
* {@inheritdoc}
*
* @throws SQLAnywhereException
*/
public function commit()
{
if ( ! sasql_commit($this->connection)) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
$this->endTransaction();
return true;
}
/**
* {@inheritdoc}
*/
public function errorCode()
{
return sasql_errorcode($this->connection);
}
/**
* {@inheritdoc}
*/
public function errorInfo()
{
return sasql_error($this->connection);
}
/**
* {@inheritdoc}
*/
public function exec($statement)
{
$stmt = $this->prepare($statement);
$stmt->execute();
return $stmt->rowCount();
}
/**
* {@inheritdoc}
*/
public function lastInsertId($name = null)
{
if (null === $name) {
return sasql_insert_id($this->connection);
}
return $this->query('SELECT ' . $name . '.CURRVAL')->fetchColumn();
}
/**
* {@inheritdoc}
*/
public function prepare($prepareString)
{
return new SQLAnywhereStatement($this->connection, $prepareString);
}
/**
* {@inheritdoc}
*/
public function query()
{
$args = func_get_args();
$stmt = $this->prepare($args[0]);
$stmt->execute();
return $stmt;
}
/**
* {@inheritdoc}
*/
public function quote($input, $type = \PDO::PARAM_STR)
{
if (is_int($input) || is_float($input)) {
return $input;
}
return "'" . sasql_escape_string($this->connection, $input) . "'";
}
/**
* {@inheritdoc}
*
* @throws SQLAnywhereException
*/
public function rollBack()
{
if ( ! sasql_rollback($this->connection)) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
$this->endTransaction();
return true;
}
/**
* Ends transactional mode and enables auto commit again.
*
* @throws SQLAnywhereException
*
* @return boolean Whether or not ending transactional mode succeeded.
*/
private function endTransaction()
{
if ( ! sasql_set_option($this->connection, 'auto_commit', 'on')) {
throw SQLAnywhereException::fromSQLAnywhereError($this->connection);
}
return true;
}
}
<?php
/*
* 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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\DBALException;
/**
* SAP Sybase SQL Anywhere driver exception.
*
* @author Steve Müller <st.mueller@dzh-online.de>
* @link www.doctrine-project.org
* @since 2.5
*/
class SQLAnywhereException extends DBALException
{
/**
* Helper method to turn SQL Anywhere error into exception.
*
* @param resource|null $conn The SQL Anywhere connection resource to retrieve the last error from.
* @param resource|null $stmt The SQL Anywhere statement resource to retrieve the last error from.
*
* @return SQLAnywhereException
*
* @throws \InvalidArgumentException
*/
public static function fromSQLAnywhereError($conn = null, $stmt = null)
{
if (null !== $conn && ! (is_resource($conn) && get_resource_type($conn) === 'SQLAnywhere connection')) {
throw new \InvalidArgumentException('Invalid SQL Anywhere connection resource given: ' . $conn);
}
if (null !== $stmt && ! (is_resource($stmt) && get_resource_type($stmt) === 'SQLAnywhere statement')) {
throw new \InvalidArgumentException('Invalid SQL Anywhere statement resource given: ' . $stmt);
}
$state = $conn ? sasql_sqlstate($conn) : sasql_sqlstate();
$code = null;
$message = null;
/**
* Try retrieving the last error from statement resource if given
*/
if ($stmt) {
$code = sasql_stmt_errno($stmt);
$message = sasql_stmt_error($stmt);
}
/**
* Try retrieving the last error from the connection resource
* if either the statement resource is not given or the statement
* resource is given but the last error could not be retrieved from it (fallback).
* Depending on the type of error, it is sometimes necessary to retrieve
* it from the connection resource even though it occurred during
* a prepared statement.
*/
if ($conn && ! $code) {
$code = sasql_errorcode($conn);
$message = sasql_error($conn);
}
/**
* Fallback mode if either no connection resource is given
* or the last error could not be retrieved from the given
* connection / statement resource.
*/
if ( ! $conn || ! $code) {
$code = sasql_errorcode();
$message = sasql_error();
}
if ($message) {
return new self('SQLSTATE [' . $state . '] [' . $code . '] ' . $message, $code);
}
return new self('SQL Anywhere error occurred but no error message was retrieved from driver.', $code);
}
}
This diff is collapsed.
......@@ -38,18 +38,19 @@ final class DriverManager
* @var array
*/
private static $_driverMap = array(
'pdo_mysql' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'pdo_sqlite' => 'Doctrine\DBAL\Driver\PDOSqlite\Driver',
'pdo_pgsql' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver',
'pdo_oci' => 'Doctrine\DBAL\Driver\PDOOracle\Driver',
'oci8' => 'Doctrine\DBAL\Driver\OCI8\Driver',
'ibm_db2' => 'Doctrine\DBAL\Driver\IBMDB2\DB2Driver',
'pdo_ibm' => 'Doctrine\DBAL\Driver\PDOIbm\Driver',
'pdo_sqlsrv' => 'Doctrine\DBAL\Driver\PDOSqlsrv\Driver',
'mysqli' => 'Doctrine\DBAL\Driver\Mysqli\Driver',
'drizzle_pdo_mysql' => 'Doctrine\DBAL\Driver\DrizzlePDOMySql\Driver',
'sqlsrv' => 'Doctrine\DBAL\Driver\SQLSrv\Driver',
);
'pdo_mysql' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
'pdo_sqlite' => 'Doctrine\DBAL\Driver\PDOSqlite\Driver',
'pdo_pgsql' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver',
'pdo_oci' => 'Doctrine\DBAL\Driver\PDOOracle\Driver',
'oci8' => 'Doctrine\DBAL\Driver\OCI8\Driver',
'ibm_db2' => 'Doctrine\DBAL\Driver\IBMDB2\DB2Driver',
'pdo_ibm' => 'Doctrine\DBAL\Driver\PDOIbm\Driver',
'pdo_sqlsrv' => 'Doctrine\DBAL\Driver\PDOSqlsrv\Driver',
'mysqli' => 'Doctrine\DBAL\Driver\Mysqli\Driver',
'drizzle_pdo_mysql' => 'Doctrine\DBAL\Driver\DrizzlePDOMySql\Driver',
'sqlanywhere' => 'Doctrine\DBAL\Driver\SQLAnywhere\Driver',
'sqlsrv' => 'Doctrine\DBAL\Driver\SQLSrv\Driver',
);
/**
* Private constructor. This class cannot be instantiated.
......@@ -75,6 +76,7 @@ final class DriverManager
* pdo_ibm (unstable)
* pdo_sqlsrv
* mysqli
* sqlanywhere
* sqlsrv
* ibm_db2 (unstable)
* drizzle_pdo_mysql
......
<?php
/*
* 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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
/**
* SAP Sybase SQL Anywhere 11 reserved keywords list.
*
* @author Steve Müller <st.mueller@dzh-online.de>
*/
class SQLAnywhere11Keywords extends SQLAnywhereKeywords
{
/**
* {@inheritdoc}
*/
public function getName()
{
return 'SQLAnywhere11';
}
/**
* {@inheritdoc}
*
* @link http://dcx.sybase.com/1100/en/dbreference_en11/alhakeywords.html
*/
protected function getKeywords()
{
return array_merge(
array_diff(
parent::getKeywords(),
array('IQ')
),
array(
'MERGE',
'OPENSTRING'
)
);
}
}
<?php
/*
* 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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
/**
* SAP Sybase SQL Anywhere 12 reserved keywords list.
*
* @author Steve Müller <st.mueller@dzh-online.de>
*/
class SQLAnywhere12Keywords extends SQLAnywhere11Keywords
{
/**
* {@inheritdoc}
*/
public function getName()
{
return 'SQLAnywhere12';
}
/**
* {@inheritdoc}
*
* @link http://dcx.sybase.com/1200/en/dbreference/alhakeywords.html
*/
protected function getKeywords()
{
return array_merge(
array_diff(
parent::getKeywords(),
array(
'INDEX_LPAREN',
'SYNTAX_ERROR',
'WITH_CUBE',
'WITH_LPAREN',
'WITH_ROLLUP'
)
),
array(
'DATETIMEOFFSET',
'LIMIT',
'OPENXML',
'SPATIAL',
'TREAT'
)
);
}
}
<?php
/*
* 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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
/**
* SAP Sybase SQL Anywhere 16 reserved keywords list.
*
* @author Steve Müller <st.mueller@dzh-online.de>
*/
class SQLAnywhere16Keywords extends SQLAnywhere12Keywords
{
/**
* {@inheritdoc}
*/
public function getName()
{
return 'SQLAnywhere16';
}
/**
* {@inheritdoc}
*
* @link http://dcx.sybase.com/index.html#sa160/en/dbreference/alhakeywords.html
*/
protected function getKeywords()
{
return array_merge(
parent::getKeywords(),
array(
'ARRAY',
'JSON',
'ROW',
'ROWTYPE',
'UNNEST',
'VARRAY'
)
);
}
}
<?php
/*
* 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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms\Keywords;
/**
* SAP Sybase SQL Anywhere 10 reserved keywords list.
*
* @author Steve Müller <st.mueller@dzh-online.de>
*/
class SQLAnywhereKeywords extends KeywordList
{
/**
* {@inheritdoc}
*/
public function getName()
{
return 'SQLAnywhere';
}
/**
* {@inheritdoc}
*
* @link http://infocenter.sybase.com/help/topic/com.sybase.dbrfen10/pdf/dbrfen10.pdf?noframes=true
*/
protected function getKeywords()
{
return array(
'ADD',
'ALL',
'ALTER',
'AND',
'ANY',
'AS',
'ASC',
'ATTACH',
'BACKUP',
'BEGIN',
'BETWEEN',
'BIGINT',
'BINARY',
'BIT',
'BOTTOM',
'BREAK',
'BY',
'CALL',
'CAPABILITY',
'CASCADE',
'CASE',
'CAST',
'CHAR',
'CHAR_CONVERT',
'CHARACTER',
'CHECK',
'CHECKPOINT',
'CLOSE',
'COMMENT',
'COMMIT',
'COMPRESSED',
'CONFLICT',
'CONNECT',
'CONSTRAINT',
'CONTAINS',
'CONTINUE',
'CONVERT',
'CREATE',
'CROSS',
'CUBE',
'CURRENT',
'CURRENT_TIMESTAMP',
'CURRENT_USER',
'CURSOR',
'DATE',
'DBSPACE',
'DEALLOCATE',
'DEC',
'DECIMAL',
'DECLARE',
'DEFAULT',
'DELETE',
'DELETING',
'DESC',
'DETACH',
'DISTINCT',
'DO',
'DOUBLE',
'DROP',
'DYNAMIC',
'ELSE',
'ELSEIF',
'ENCRYPTED',
'END',
'ENDIF',
'ESCAPE',
'EXCEPT',
'EXCEPTION',
'EXEC',
'EXECUTE',
'EXISTING',
'EXISTS',
'EXTERNLOGIN',
'FETCH',
'FIRST',
'FLOAT',
'FOR',
'FORCE',
'FOREIGN',
'FORWARD',
'FROM',
'FULL',
'GOTO',
'GRANT',
'GROUP',
'HAVING',
'HOLDLOCK',
'IDENTIFIED',
'IF',
'IN',
'INDEX',
'INDEX_LPAREN',
'INNER',
'INOUT',
'INSENSITIVE',
'INSERT',
'INSERTING',
'INSTALL',
'INSTEAD',
'INT',
'INTEGER',
'INTEGRATED',
'INTERSECT',
'INTO',
'IQ',
'IS',
'ISOLATION',
'JOIN',
'KERBEROS',
'KEY',
'LATERAL',
'LEFT',
'LIKE',
'LOCK',
'LOGIN',
'LONG',
'MATCH',
'MEMBERSHIP',
'MESSAGE',
'MODE',
'MODIFY',
'NATURAL',
'NCHAR',
'NEW',
'NO',
'NOHOLDLOCK',
'NOT',
'NOTIFY',
'NULL',
'NUMERIC',
'NVARCHAR',
'OF',
'OFF',
'ON',
'OPEN',
'OPTION',
'OPTIONS',
'OR',
'ORDER',
'OTHERS',
'OUT',
'OUTER',
'OVER',
'PASSTHROUGH',
'PRECISION',
'PREPARE',
'PRIMARY',
'PRINT',
'PRIVILEGES',
'PROC',
'PROCEDURE',
'PUBLICATION',
'RAISERROR',
'READTEXT',
'REAL',
'REFERENCE',
'REFERENCES',
'REFRESH',
'RELEASE',
'REMOTE',
'REMOVE',
'RENAME',
'REORGANIZE',
'RESOURCE',
'RESTORE',
'RESTRICT',
'RETURN',
'REVOKE',
'RIGHT',
'ROLLBACK',
'ROLLUP',
'SAVE',
'SAVEPOINT',
'SCROLL',
'SELECT',
'SENSITIVE',
'SESSION',
'SET',
'SETUSER',
'SHARE',
'SMALLINT',
'SOME',
'SQLCODE',
'SQLSTATE',
'START',
'STOP',
'SUBTRANS',
'SUBTRANSACTION',
'SYNCHRONIZE',
'SYNTAX_ERROR',
'TABLE',
'TEMPORARY',
'THEN',
'TIME',
'TIMESTAMP',
'TINYINT',
'TO',
'TOP',
'TRAN',
'TRIGGER',
'TRUNCATE',
'TSEQUAL',
'UNBOUNDED',
'UNION',
'UNIQUE',
'UNIQUEIDENTIFIER',
'UNKNOWN',
'UNSIGNED',
'UPDATE',
'UPDATING',
'USER',
'USING',
'VALIDATE',
'VALUES',
'VARBINARY',
'VARBIT',
'VARCHAR',
'VARIABLE',
'VARYING',
'VIEW',
'WAIT',
'WAITFOR',
'WHEN',
'WHERE',
'WHILE',
'WINDOW',
'WITH',
'WITH_CUBE',
'WITH_LPAREN',
'WITH_ROLLUP',
'WITHIN',
'WORK',
'WRITETEXT',
'XML'
);
}
}
......@@ -379,7 +379,7 @@ class MySqlPlatform extends AbstractPlatform
if ($database) {
return "SELECT COLUMN_NAME AS Field, COLUMN_TYPE AS Type, IS_NULLABLE AS `Null`, ".
"COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS Extra, COLUMN_COMMENT AS Comment, " .
"CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS CollactionName ".
"CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS CollationName ".
"FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '" . $database . "' AND TABLE_NAME = '" . $table . "'";
}
......
......@@ -862,6 +862,8 @@ LEFT JOIN user_cons_columns r_cols
'timestamp' => 'datetime',
'timestamptz' => 'datetimetz',
'float' => 'float',
'binary_float' => 'float',
'binary_double' => 'float',
'long' => 'string',
'clob' => 'text',
'nclob' => 'text',
......
<?php
/*
* 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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
/**
* The SQLAnywhere11Platform provides the behavior, features and SQL dialect of the
* SAP Sybase SQL Anywhere 11 database platform.
*
* @author Steve Müller <st.mueller@dzh-online.de>
* @link www.doctrine-project.org
* @since 2.5
*/
class SQLAnywhere11Platform extends SQLAnywherePlatform
{
/**
* {@inheritdoc}
*/
public function getRegexpExpression()
{
return 'REGEXP';
}
/**
* {@inheritdoc}
*/
protected function getReservedKeywordsClass()
{
return 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere11Keywords';
}
}
<?php
/*
* 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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Sequence;
/**
* The SQLAnywhere12Platform provides the behavior, features and SQL dialect of the
* SAP Sybase SQL Anywhere 12 database platform.
*
* @author Steve Müller <st.mueller@dzh-online.de>
* @link www.doctrine-project.org
* @since 2.5
*/
class SQLAnywhere12Platform extends SQLAnywhere11Platform
{
/**
* {@inheritdoc}
*/
public function getCreateSequenceSQL(Sequence $sequence)
{
return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) .
' INCREMENT BY ' . $sequence->getAllocationSize() .
' START WITH ' . $sequence->getInitialValue() .
' MINVALUE ' . $sequence->getInitialValue();
}
/**
* {@inheritdoc}
*/
public function getAlterSequenceSQL(Sequence $sequence)
{
return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) .
' INCREMENT BY ' . $sequence->getAllocationSize();
}
/**
* {@inheritdoc}
*/
public function getDateTimeTzFormatString()
{
return 'Y-m-d H:i:s.uP';
}
/**
* {@inheritdoc}
*/
public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration)
{
return 'TIMESTAMP WITH TIME ZONE';
}
/**
* {@inheritdoc}
*/
public function getDropSequenceSQL($sequence)
{
if ($sequence instanceof Sequence) {
$sequence = $sequence->getQuotedName($this);
}
return 'DROP SEQUENCE ' . $sequence;
}
/**
* {@inheritdoc}
*/
public function getListSequencesSQL($database)
{
return 'SELECT sequence_name, increment_by, start_with, min_value FROM SYS.SYSSEQUENCE';
}
/**
* {@inheritdoc}
*/
public function getSequenceNextValSQL($sequenceName)
{
return 'SELECT ' . $sequenceName . '.NEXTVAL';
}
/**
* {@inheritdoc}
*/
public function supportsSequences()
{
return true;
}
/**
* {@inheritdoc}
*/
protected function getAdvancedIndexOptionsSQL(Index $index)
{
if ( ! $index->isPrimary() && $index->isUnique() && $index->hasFlag('with_nulls_not_distinct')) {
return ' WITH NULLS NOT DISTINCT' . parent::getAdvancedIndexOptionsSQL($index);
}
return parent::getAdvancedIndexOptionsSQL($index);
}
/**
* {@inheritdoc}
*/
protected function getReservedKeywordsClass()
{
return 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere12Keywords';
}
/**
* {@inheritDoc}
*/
protected function initializeDoctrineTypeMappings()
{
parent::initializeDoctrineTypeMappings();
$this->doctrineTypeMapping['timestamp with time zone'] = 'datetime';
}
}
<?php
/*
* 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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Platforms;
use Doctrine\Common\Proxy\Exception\UnexpectedValueException;
use Doctrine\DBAL\Schema\Index;
/**
* The SQLAnywhere16Platform provides the behavior, features and SQL dialect of the
* SAP Sybase SQL Anywhere 16 database platform.
*
* @author Steve Müller <st.mueller@dzh-online.de>
* @link www.doctrine-project.org
* @since 2.5
*/
class SQLAnywhere16Platform extends SQLAnywhere12Platform
{
/**
* {@inheritdoc}
*/
protected function getAdvancedIndexOptionsSQL(Index $index)
{
if ($index->hasFlag('with_nulls_distinct') && $index->hasFlag('with_nulls_not_distinct')) {
throw new UnexpectedValueException(
'An Index can either have a "with_nulls_distinct" or "with_nulls_not_distinct" flag but not both.'
);
}
if ( ! $index->isPrimary() && $index->isUnique() && $index->hasFlag('with_nulls_distinct')) {
return ' WITH NULLS DISTINCT' . parent::getAdvancedIndexOptionsSQL($index);
}
return parent::getAdvancedIndexOptionsSQL($index);
}
/**
* {@inheritdoc}
*/
protected function getReservedKeywordsClass()
{
return 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere16Keywords';
}
}
This diff is collapsed.
......@@ -42,6 +42,7 @@ class Connection extends \Doctrine\DBAL\Connection
const PORTABILITY_SQLITE = 13;
const PORTABILITY_OTHERVENDORS = 12;
const PORTABILITY_DRIZZLE = 13;
const PORTABILITY_SQLANYWHERE = 13;
const PORTABILITY_SQLSRV = 13;
/**
......@@ -71,6 +72,8 @@ class Connection extends \Doctrine\DBAL\Connection
$params['portability'] = $params['portability'] & self::PORTABILITY_SQLITE;
} else if ($this->_platform->getName() === "drizzle") {
$params['portability'] = self::PORTABILITY_DRIZZLE;
} else if ($this->_platform->getName() === 'sqlanywhere') {
$params['portability'] = self::PORTABILITY_SQLANYWHERE;
} else if ($this->_platform->getName() === 'sqlsrv') {
$params['portability'] = $params['portabililty'] & self::PORTABILITY_SQLSRV;
} else {
......
......@@ -165,6 +165,8 @@ class OracleSchemaManager extends AbstractSchemaManager
$length = null;
break;
case 'float':
case 'binary_float':
case 'binary_double':
$precision = $tableColumn['data_precision'];
$scale = $tableColumn['data_scale'];
$length = null;
......
<?php
/*
* 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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Types\Type;
/**
* SAP Sybase SQL Anywhere schema manager.
*
* @author Steve Müller <st.mueller@dzh-online.de>
* @link www.doctrine-project.org
* @since 2.5
*/
class SQLAnywhereSchemaManager extends AbstractSchemaManager
{
/**
* {@inheritdoc}
*
* Starts a database after creation
* as SQL Anywhere needs a database to be started
* before it can be used.
*
* @see startDatabase
*/
public function createDatabase($database)
{
parent::createDatabase($database);
$this->startDatabase($database);
}
/**
* {@inheritdoc}
*
* Tries stopping a database before dropping
* as SQL Anywhere needs a database to be stopped
* before it can be dropped.
*
* @see stopDatabase
*/
public function dropDatabase($database)
{
$this->tryMethod('stopDatabase', $database);
parent::dropDatabase($database);
}
/**
* Starts a database.
*
* @param string $database The name of the database to start.
*/
public function startDatabase($database)
{
$this->_execSql($this->_platform->getStartDatabaseSQL($database));
}
/**
* Stops a database.
*
* @param string $database The name of the database to stop.
*/
public function stopDatabase($database)
{
$this->_execSql($this->_platform->getStopDatabaseSQL($database));
}
/**
* {@inheritdoc}
*/
protected function _getPortableDatabaseDefinition($database)
{
return $database['name'];
}
/**
* {@inheritdoc}
*/
protected function _getPortableSequenceDefinition($sequence)
{
return new Sequence($sequence['sequence_name'], $sequence['increment_by'], $sequence['start_with']);
}
/**
* {@inheritdoc}
*/
protected function _getPortableTableColumnDefinition($tableColumn)
{
$type = $this->_platform->getDoctrineTypeMapping($tableColumn['type']);
$type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type);
$tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type);
$precision = null;
$scale = null;
$fixed = false;
$default = null;
if ($tableColumn['default']) {
// Strip quotes from default value.
$default = preg_replace(array("/^'(.*)'$/", "/''/"), array("$1", "'"), $tableColumn['default']);
}
switch ($tableColumn['type']) {
case 'binary':
case 'char':
case 'nchar':
$fixed = true;
}
switch ($type) {
case 'decimal':
case 'float':
$precision = $tableColumn['length'];
$scale = $tableColumn['scale'];
}
return new Column(
$tableColumn['column_name'],
Type::getType($type),
array(
'length' => $type == 'string' ? $tableColumn['length'] : null,
'precision' => $precision,
'scale' => $scale,
'unsigned' => (bool) $tableColumn['unsigned'],
'fixed' => $fixed,
'notnull' => (bool) $tableColumn['notnull'],
'default' => $default,
'autoincrement' => (bool) $tableColumn['autoincrement'],
'comment' => $tableColumn['comment']
));
}
/**
* {@inheritdoc}
*/
protected function _getPortableTableDefinition($table)
{
return $table['table_name'];
}
/**
* {@inheritdoc}
*/
protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
{
return new ForeignKeyConstraint(
$tableForeignKey['local_columns'],
$tableForeignKey['foreign_table'],
$tableForeignKey['foreign_columns'],
$tableForeignKey['name'],
$tableForeignKey['options']
);
}
/**
* {@inheritdoc}
*/
protected function _getPortableTableForeignKeysList($tableForeignKeys)
{
$foreignKeys = array();
foreach ($tableForeignKeys as $tableForeignKey) {
if (!isset($foreignKeys[$tableForeignKey['index_name']])) {
$foreignKeys[$tableForeignKey['index_name']] = array(
'local_columns' => array($tableForeignKey['local_column']),
'foreign_table' => $tableForeignKey['foreign_table'],
'foreign_columns' => array($tableForeignKey['foreign_column']),
'name' => $tableForeignKey['index_name'],
'options' => array(
'notnull' => $tableForeignKey['notnull'],
'match' => $tableForeignKey['match'],
'onUpdate' => $tableForeignKey['on_update'],
'onDelete' => $tableForeignKey['on_delete'],
'check_on_commit' => $tableForeignKey['check_on_commit'],
'clustered' => $tableForeignKey['clustered'],
'for_olap_workload' => $tableForeignKey['for_olap_workload']
)
);
} else {
$foreignKeys[$tableForeignKey['index_name']]['local_columns'][] = $tableForeignKey['local_column'];
$foreignKeys[$tableForeignKey['index_name']]['foreign_columns'][] = $tableForeignKey['foreign_column'];
}
}
return parent::_getPortableTableForeignKeysList($foreignKeys);
}
/**
* {@inheritdoc}
*/
protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null)
{
foreach ($tableIndexRows as &$tableIndex) {
$tableIndex['primary'] = (boolean) $tableIndex['primary'];
$tableIndex['flags'] = array();
if ($tableIndex['clustered']) {
$tableIndex['flags'][] = 'clustered';
}
if ($tableIndex['with_nulls_not_distinct']) {
$tableIndex['flags'][] = 'with_nulls_not_distinct';
}
if ($tableIndex['for_olap_workload']) {
$tableIndex['flags'][] = 'for_olap_workload';
}
}
return parent::_getPortableTableIndexesList($tableIndexRows, $tableName);
}
/**
* {@inheritdoc}
*/
protected function _getPortableViewDefinition($view)
{
return new View(
$view['table_name'],
preg_replace('/^.*\s+as\s+SELECT(.*)/i', "SELECT$1", $view['view_def'])
);
}
}
......@@ -41,6 +41,10 @@ class ReservedWordsCommand extends Command
'pgsql' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords',
'oracle' => 'Doctrine\DBAL\Platforms\Keywords\OracleKeywords',
'db2' => 'Doctrine\DBAL\Platforms\Keywords\DB2Keywords',
'sqlanywhere' => 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhereKeywords',
'sqlanywhere11' => 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere11Keywords',
'sqlanywhere12' => 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere12Keywords',
'sqlanywhere16' => 'Doctrine\DBAL\Platforms\Keywords\SQLAnywhere16Keywords',
);
/**
......@@ -73,8 +77,8 @@ class ReservedWordsCommand extends Command
Checks if the current database contains tables and columns
with names that are identifiers in this dialect or in other SQL dialects.
By default SQLite, MySQL, PostgreSQL, Microsoft SQL Server and Oracle
keywords are checked:
By default SQLite, MySQL, PostgreSQL, Microsoft SQL Server, Oracle
and SQL Anywhere keywords are checked:
<info>%command.full_name%</info>
......@@ -93,6 +97,10 @@ The following keyword lists are currently shipped with Doctrine:
* sqlserver2005
* sqlserver2008
* sqlserver2012
* sqlanywhere
* sqlanywhere11
* sqlanywhere12
* sqlanywhere16
* db2 (Not checked by default)
EOT
);
......@@ -116,7 +124,11 @@ EOT
'sqlserver',
'sqlserver2005',
'sqlserver2008',
'sqlserver2012'
'sqlserver2012',
'sqlanywhere',
'sqlanywhere11',
'sqlanywhere12',
'sqlanywhere16',
);
}
......
......@@ -4,18 +4,19 @@
# Just create the phpunit.xmls as described in the array below and configure the specific files <php /> section
# to connect to that database. Just omit a file if you dont have that database and the tests will be skipped.
configs[1]="mysql.phpunit.xml"
configs[2]='postgres.phpunit.xml'
configs[1]="mysql.phpunit.xml"
configs[2]='postgres.phpunit.xml'
configs[3]='sqlite.phpunit.xml'
configs[4]='oracle.phpunit.xml'
configs[5]='db2.phpunit.xml'
configs[6]='pdo-ibm.phpunit.xml'
configs[7]='sqlsrv.phpunit.xml'
configs[8]='sqlanywhere.phpunit.xml'
for i in "${configs[@]}"; do
if [ -f "$i" ];
then
echo "RUNNING TESTS WITH CONFIG $i"
phpunit -c "$i" "$@"
phpunit -c "$i" "$@"
fi;
done
<?php
/*
* 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 MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\Tests\DBAL;
use Doctrine\DBAL\Configuration;
use Doctrine\Tests\DbalTestCase;
require_once __DIR__ . '/../TestInit.php';
/**
* Unit tests for the configuration container.
*
* @author Steve Müller <st.mueller@dzh-online.de>
*/
class ConfigurationTest extends DbalTestCase
{
/**
* The configuration container instance under test.
*
* @var \Doctrine\DBAL\Configuration
*/
protected $config;
/**
* {@inheritdoc}
*/
public function setUp()
{
$this->config = new Configuration();
}
/**
* Tests that the default auto-commit mode for connections can be retrieved from the configuration container.
*
* @group DBAL-81
*/
public function testReturnsDefaultConnectionAutoCommitMode()
{
$this->assertTrue($this->config->getAutoCommit());
}
/**
* Tests that the default auto-commit mode for connections can be set in the configuration container.
*
* @group DBAL-81
*/
public function testSetsDefaultConnectionAutoCommitMode()
{
$this->config->setAutoCommit(false);
$this->assertFalse($this->config->getAutoCommit());
$this->config->setAutoCommit(0);
$this->assertFalse($this->config->getAutoCommit());
}
}
......@@ -8,6 +8,7 @@ use Doctrine\DBAL\Connection;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\Events;
use Doctrine\Tests\Mocks\DriverConnectionMock;
class ConnectionTest extends \Doctrine\Tests\DbalTestCase
{
......@@ -174,4 +175,104 @@ SQLSTATE[HY000]: General error: 1 near \"MUUHAAAAHAAAA\"");
$this->_conn->getConfiguration()->setSQLLogger($logger);
$this->assertSame($logger, $this->_conn->getConfiguration()->getSQLLogger());
}
/**
* @group DBAL-81
*/
public function testIsAutoCommit()
{
$this->assertTrue($this->_conn->isAutoCommit());
}
/**
* @group DBAL-81
*/
public function testSetAutoCommit()
{
$this->_conn->setAutoCommit(false);
$this->assertFalse($this->_conn->isAutoCommit());
$this->_conn->setAutoCommit(0);
$this->assertFalse($this->_conn->isAutoCommit());
}
/**
* @group DBAL-81
*/
public function testConnectStartsTransactionInNoAutoCommitMode()
{
$driverMock = $this->getMock('Doctrine\DBAL\Driver');
$driverMock->expects($this->any())
->method('connect')
->will($this->returnValue(new DriverConnectionMock()));
$conn = new Connection(array('platform' => new Mocks\MockPlatform()), $driverMock);
$conn->setAutoCommit(false);
$this->assertFalse($conn->isTransactionActive());
$conn->connect();
$this->assertTrue($conn->isTransactionActive());
}
/**
* @group DBAL-81
*/
public function testCommitStartsTransactionInNoAutoCommitMode()
{
$driverMock = $this->getMock('Doctrine\DBAL\Driver');
$driverMock->expects($this->any())
->method('connect')
->will($this->returnValue(new DriverConnectionMock()));
$conn = new Connection(array('platform' => new Mocks\MockPlatform()), $driverMock);
$conn->setAutoCommit(false);
$conn->connect();
$conn->commit();
$this->assertTrue($conn->isTransactionActive());
}
/**
* @group DBAL-81
*/
public function testRollBackStartsTransactionInNoAutoCommitMode()
{
$driverMock = $this->getMock('Doctrine\DBAL\Driver');
$driverMock->expects($this->any())
->method('connect')
->will($this->returnValue(new DriverConnectionMock()));
$conn = new Connection(array('platform' => new Mocks\MockPlatform()), $driverMock);
$conn->setAutoCommit(false);
$conn->connect();
$conn->rollBack();
$this->assertTrue($conn->isTransactionActive());
}
/**
* @group DBAL-81
*/
public function testSwitchingAutoCommitModeCommitsAllCurrentTransactions()
{
$driverMock = $this->getMock('Doctrine\DBAL\Driver');
$driverMock->expects($this->any())
->method('connect')
->will($this->returnValue(new DriverConnectionMock()));
$conn = new Connection(array('platform' => new Mocks\MockPlatform()), $driverMock);
$conn->connect();
$conn->beginTransaction();
$conn->beginTransaction();
$conn->setAutoCommit(false);
$this->assertSame(1, $conn->getTransactionNestingLevel());
$conn->beginTransaction();
$conn->beginTransaction();
$conn->setAutoCommit(true);
$this->assertFalse($conn->isTransactionActive());
}
}
\ No newline at end of file
......@@ -203,7 +203,7 @@ class DataAccessTest extends \Doctrine\Tests\DbalFunctionalTestCase
$row = array_change_key_case($row, \CASE_LOWER);
$this->assertEquals(1, $row['test_int']);
$this->assertEquals($datetimeString, $row['test_datetime']);
$this->assertStringStartsWith($datetimeString, $row['test_datetime']);
}
/**
......
<?php
namespace Doctrine\Tests\DBAL\Functional\Mysqli;
class ConnectionTest extends \Doctrine\Tests\DbalFunctionalTestCase
{
public function setUp()
{
if (!extension_loaded('mysqli')) {
$this->markTestSkipped('mysqli is not installed.');
}
$driver = getenv('DB');
if (false !== $driver && $driver !== 'mysqli') {
$this->markTestSkipped('this test case is for mysqli only');
}
$this->resetSharedConn();
parent::setUp();
}
public function tearDown()
{
parent::tearDown();
$this->resetSharedConn();
}
public function testDriverOptions()
{
$driverOptions = array(
\MYSQLI_OPT_CONNECT_TIMEOUT => 1,
);
$connection = $this->getConnection($driverOptions);
$this->assertInstanceOf("\Doctrine\DBAL\Driver\Mysqli\MysqliConnection", $connection);
}
/**
* @expectedException \Doctrine\DBAL\Driver\Mysqli\MysqliException
*/
public function testUnsupportedDriverOption()
{
$this->getConnection(array('hello' => 'world')); // use local infile
}
private function getConnection(array $driverOptions)
{
return new \Doctrine\DBAL\Driver\Mysqli\MysqliConnection(
array(
'host' => $GLOBALS['db_host'],
'dbname' => $GLOBALS['db_name'],
),
$GLOBALS['db_username'],
$GLOBALS['db_password'],
$driverOptions
);
}
}
\ No newline at end of file
<?php
namespace Doctrine\Tests\DBAL\Functional\Schema;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\View;
class SQLAnywhereSchemaManagerTest extends SchemaManagerFunctionalTestCase
{
public function testCreateAndListViews()
{
$this->createTestTable('view_test_table');
$name = "doctrine_test_view";
$sql = "SELECT * from DBA.view_test_table";
$view = new View($name, $sql);
$this->_sm->dropAndCreateView($view);
$views = $this->_sm->listViews();
$this->assertEquals(1, count($views), "Database has to have one view.");
$this->assertInstanceOf('Doctrine\DBAL\Schema\View', $views[$name]);
$this->assertEquals($name, $views[$name]->getName());
$this->assertEquals($sql, $views[$name]->getSql());
}
public function testDropAndCreateAdvancedIndex()
{
$table = $this->getTestTable('test_create_advanced_index');
$this->_sm->dropAndCreateTable($table);
$this->_sm->dropAndCreateIndex(
new Index('test', array('test'), true, false, array('clustered', 'with_nulls_not_distinct', 'for_olap_workload')),
$table->getName()
);
$tableIndexes = $this->_sm->listTableIndexes('test_create_advanced_index');
$this->assertInternalType('array', $tableIndexes);
$this->assertEquals('test', $tableIndexes['test']->getName());
$this->assertEquals(array('test'), $tableIndexes['test']->getColumns());
$this->assertTrue($tableIndexes['test']->isUnique());
$this->assertFalse($tableIndexes['test']->isPrimary());
$this->assertTrue($tableIndexes['test']->hasFlag('clustered'));
$this->assertTrue($tableIndexes['test']->hasFlag('with_nulls_not_distinct'));
$this->assertTrue($tableIndexes['test']->hasFlag('for_olap_workload'));
}
public function testListTableColumnsWithFixedStringTypeColumn()
{
$table = new Table('list_table_columns_char');
$table->addColumn('id', 'integer', array('notnull' => true));
$table->addColumn('test', 'string', array('fixed' => true));
$table->setPrimaryKey(array('id'));
$this->_sm->dropAndCreateTable($table);
$columns = $this->_sm->listTableColumns('list_table_columns_char');
$this->assertArrayHasKey('test', $columns);
$this->assertTrue($columns['test']->getFixed());
}
}
......@@ -175,8 +175,8 @@ class WriteTest extends \Doctrine\Tests\DbalFunctionalTestCase
public function testLastInsertIdNoSequenceGiven()
{
if ( ! $this->_conn->getDatabasePlatform()->supportsSequences()) {
$this->markTestSkipped('Test only works on platforms with sequences.');
if ( ! $this->_conn->getDatabasePlatform()->supportsSequences() || $this->_conn->getDatabasePlatform()->supportsIdentityColumns()) {
$this->markTestSkipped("Test only works consistently on platforms that support sequences and don't support identity columns.");
}
$this->assertFalse($this->_conn->lastInsertId( null ));
......
<?php
namespace Doctrine\Tests\DBAL\Platforms;
use Doctrine\DBAL\Platforms\SQLAnywhere11Platform;
class SQLAnywhere11PlatformTest extends SQLAnywherePlatformTest
{
/**
* @var \Doctrine\DBAL\Platforms\SQLAnywhere11Platform
*/
protected $_platform;
public function createPlatform()
{
return new SQLAnywhere11Platform;
}
public function testDoesNotSupportRegexp()
{
$this->markTestSkipped('This version of the platform now supports regular expressions.');
}
public function testGeneratesRegularExpressionSQLSnippet()
{
$this->assertEquals('REGEXP', $this->_platform->getRegexpExpression());
}
}
<?php
namespace Doctrine\Tests\DBAL\Platforms;
use Doctrine\DBAL\Platforms\SQLAnywhere12Platform;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Sequence;
class SQLAnywhere12PlatformTest extends SQLAnywhere11PlatformTest
{
/**
* @var \Doctrine\DBAL\Platforms\SQLAnywhere12Platform
*/
protected $_platform;
public function createPlatform()
{
return new SQLAnywhere12Platform;
}
public function testDoesNotSupportSequences()
{
$this->markTestSkipped('This version of the platform now supports sequences.');
}
public function testSupportsSequences()
{
$this->assertTrue($this->_platform->supportsSequences());
}
public function testGeneratesSequenceSqlCommands()
{
$sequence = new Sequence('myseq', 20, 1);
$this->assertEquals(
'CREATE SEQUENCE myseq INCREMENT BY 20 START WITH 1 MINVALUE 1',
$this->_platform->getCreateSequenceSQL($sequence)
);
$this->assertEquals(
'ALTER SEQUENCE myseq INCREMENT BY 20',
$this->_platform->getAlterSequenceSQL($sequence)
);
$this->assertEquals(
'DROP SEQUENCE myseq',
$this->_platform->getDropSequenceSQL('myseq')
);
$this->assertEquals(
'DROP SEQUENCE myseq',
$this->_platform->getDropSequenceSQL($sequence)
);
$this->assertEquals(
"SELECT myseq.NEXTVAL",
$this->_platform->getSequenceNextValSQL('myseq')
);
$this->assertEquals(
'SELECT sequence_name, increment_by, start_with, min_value FROM SYS.SYSSEQUENCE',
$this->_platform->getListSequencesSQL(null)
);
}
public function testGeneratesDateTimeTzColumnTypeDeclarationSQL()
{
$this->assertEquals(
'TIMESTAMP WITH TIME ZONE',
$this->_platform->getDateTimeTzTypeDeclarationSQL(array(
'length' => 10,
'fixed' => true,
'unsigned' => true,
'autoincrement' => true
))
);
}
public function testHasCorrectDateTimeTzFormatString()
{
$this->assertEquals('Y-m-d H:i:s.uP', $this->_platform->getDateTimeTzFormatString());
}
public function testInitializesDateTimeTzTypeMapping()
{
$this->assertTrue($this->_platform->hasDoctrineTypeMappingFor('timestamp with time zone'));
$this->assertEquals('datetime', $this->_platform->getDoctrineTypeMapping('timestamp with time zone'));
}
public function testGeneratesCreateIndexWithAdvancedPlatformOptionsSQL()
{
$this->assertEquals(
'CREATE VIRTUAL UNIQUE CLUSTERED INDEX fooindex ON footable (a, b) WITH NULLS NOT DISTINCT FOR OLAP WORKLOAD',
$this->_platform->getCreateIndexSQL(
new Index(
'fooindex',
array('a', 'b'),
true,
false,
array('virtual', 'clustered', 'with_nulls_not_distinct', 'for_olap_workload')
),
'footable'
)
);
$this->assertEquals(
'CREATE VIRTUAL CLUSTERED INDEX fooindex ON footable (a, b) FOR OLAP WORKLOAD',
$this->_platform->getCreateIndexSQL(
new Index(
'fooindex',
array('a', 'b'),
false,
false,
array('virtual', 'clustered', 'with_nulls_not_distinct', 'for_olap_workload')
),
'footable'
)
);
// WITH NULLS NOT DISTINCT clause not available on primary indexes.
$this->assertEquals(
'ALTER TABLE footable ADD PRIMARY KEY (a, b)',
$this->_platform->getCreateIndexSQL(
new Index(
'fooindex',
array('a', 'b'),
false,
true,
array('with_nulls_not_distinct')
),
'footable'
)
);
// WITH NULLS NOT DISTINCT clause not available on non-unique indexes.
$this->assertEquals(
'CREATE INDEX fooindex ON footable (a, b)',
$this->_platform->getCreateIndexSQL(
new Index(
'fooindex',
array('a', 'b'),
false,
false,
array('with_nulls_not_distinct')
),
'footable'
)
);
}
}
<?php
namespace Doctrine\Tests\DBAL\Platforms;
use Doctrine\DBAL\Platforms\SQLAnywhere16Platform;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\Sequence;
class SQLAnywhere16PlatformTest extends SQLAnywhere12PlatformTest
{
public function createPlatform()
{
return new SQLAnywhere16Platform;
}
public function testGeneratesCreateIndexWithAdvancedPlatformOptionsSQL()
{
$this->assertEquals(
'CREATE UNIQUE INDEX fooindex ON footable (a, b) WITH NULLS DISTINCT',
$this->_platform->getCreateIndexSQL(
new Index(
'fooindex',
array('a', 'b'),
true,
false,
array('with_nulls_distinct')
),
'footable'
)
);
// WITH NULLS DISTINCT clause not available on primary indexes.
$this->assertEquals(
'ALTER TABLE footable ADD PRIMARY KEY (a, b)',
$this->_platform->getCreateIndexSQL(
new Index(
'fooindex',
array('a', 'b'),
false,
true,
array('with_nulls_distinct')
),
'footable'
)
);
// WITH NULLS DISTINCT clause not available on non-unique indexes.
$this->assertEquals(
'CREATE INDEX fooindex ON footable (a, b)',
$this->_platform->getCreateIndexSQL(
new Index(
'fooindex',
array('a', 'b'),
false,
false,
array('with_nulls_distinct')
),
'footable'
)
);
parent::testGeneratesCreateIndexWithAdvancedPlatformOptionsSQL();
}
public function testThrowsExceptionOnInvalidWithNullsNotDistinctIndexOptions()
{
$this->setExpectedException('UnexpectedValueException');
$this->_platform->getCreateIndexSQL(
new Index(
'fooindex',
array('a', 'b'),
false,
false,
array('with_nulls_distinct', 'with_nulls_not_distinct')
),
'footable'
);
}
}
......@@ -17,6 +17,8 @@ class TestUtil
* '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_server' : The server name of the database to connect to
* (optional, some vendors allow multiple server instances with different names on the same host).
* 'db_name' : The name of the database to connect to.
* 'db_port' : The port of the database to connect to.
*
......@@ -53,10 +55,18 @@ class TestUtil
'port' => $GLOBALS['tmpdb_port']
);
if (isset($GLOBALS['db_server'])) {
$realDbParams['server'] = $GLOBALS['db_server'];
}
if (isset($GLOBALS['db_unix_socket'])) {
$realDbParams['unix_socket'] = $GLOBALS['db_unix_socket'];
}
if (isset($GLOBALS['tmpdb_server'])) {
$tmpDbParams['server'] = $GLOBALS['tmpdb_server'];
}
if (isset($GLOBALS['tmpdb_unix_socket'])) {
$tmpDbParams['unix_socket'] = $GLOBALS['tmpdb_unix_socket'];
}
......@@ -124,6 +134,10 @@ class TestUtil
'port' => $GLOBALS['tmpdb_port']
);
if (isset($GLOBALS['tmpdb_server'])) {
$tmpDbParams['server'] = $GLOBALS['tmpdb_server'];
}
// Connect to tmpdb in order to drop and create the real test db.
return \Doctrine\DBAL\DriverManager::getConnection($tmpDbParams);
}
......
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