Unverified Commit 0a2e2f1e authored by Grégoire Paris's avatar Grégoire Paris

Merge remote-tracking branch 'origin/2.10.x' into 2.11.x

parents b3131f82 4c03ed81
......@@ -23,11 +23,11 @@ jobs:
uses: "actions/cache@v1.0.3"
with:
path: "~/.composer/cache"
key: "composer-${{ hashFiles('composer.json') }}"
key: "composer-${{ hashFiles('composer.lock') }}"
restore-keys: "composer-"
- name: "Install dependencies with composer"
run: "composer update --no-interaction --no-progress --no-suggest"
run: "composer install --no-interaction --no-progress --no-suggest"
- name: Psalm
run: "vendor/bin/psalm"
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "b7f970513c9756e5eaaba3974429c23c",
"content-hash": "6bf4905b268231ccd58bdbe30d4ecf81",
"packages": [
{
"name": "doctrine/cache",
......@@ -478,28 +478,28 @@
},
{
"name": "doctrine/coding-standard",
"version": "6.0.0",
"version": "7.0.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/coding-standard.git",
"reference": "d33f69eb98b25aa51ffe3a909f0ec77000af4701"
"reference": "d8a60ec4da68025c42795b714f66e277dd3e11de"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/coding-standard/zipball/d33f69eb98b25aa51ffe3a909f0ec77000af4701",
"reference": "d33f69eb98b25aa51ffe3a909f0ec77000af4701",
"url": "https://api.github.com/repos/doctrine/coding-standard/zipball/d8a60ec4da68025c42795b714f66e277dd3e11de",
"reference": "d8a60ec4da68025c42795b714f66e277dd3e11de",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.5.0",
"php": "^7.1",
"slevomat/coding-standard": "^5.0",
"squizlabs/php_codesniffer": "^3.4.0"
"php": "^7.2",
"slevomat/coding-standard": "^6.0",
"squizlabs/php_codesniffer": "^3.5.3"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "6.0.x-dev"
"dev-master": "7.0.x-dev"
}
},
"autoload": {
......@@ -535,7 +535,7 @@
"standard",
"style"
],
"time": "2019-03-15T12:45:47+00:00"
"time": "2019-12-11T07:59:21+00:00"
},
{
"name": "doctrine/instantiator",
......@@ -1282,16 +1282,16 @@
},
{
"name": "phpstan/phpdoc-parser",
"version": "0.3.5",
"version": "0.4.4",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "8c4ef2aefd9788238897b678a985e1d5c8df6db4"
"reference": "d8d9d4645379e677466d407034436bb155b11c65"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/8c4ef2aefd9788238897b678a985e1d5c8df6db4",
"reference": "8c4ef2aefd9788238897b678a985e1d5c8df6db4",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/d8d9d4645379e677466d407034436bb155b11c65",
"reference": "d8d9d4645379e677466d407034436bb155b11c65",
"shasum": ""
},
"require": {
......@@ -1299,18 +1299,20 @@
},
"require-dev": {
"consistence/coding-standard": "^3.5",
"ergebnis/composer-normalize": "^2.0.2",
"jakub-onderka/php-parallel-lint": "^0.9.2",
"phing/phing": "^2.16.0",
"phpstan/phpstan": "^0.10",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12.19",
"phpstan/phpstan-strict-rules": "^0.12",
"phpunit/phpunit": "^6.3",
"slevomat/coding-standard": "^4.7.2",
"squizlabs/php_codesniffer": "^3.3.2",
"symfony/process": "^3.4 || ^4.0"
"symfony/process": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.3-dev"
"dev-master": "0.4-dev"
}
},
"autoload": {
......@@ -1325,7 +1327,7 @@
"MIT"
],
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"time": "2019-06-07T19:13:52+00:00"
"time": "2020-04-13T16:28:46+00:00"
},
{
"name": "phpstan/phpstan",
......@@ -2414,32 +2416,39 @@
},
{
"name": "slevomat/coding-standard",
"version": "5.0.2",
"version": "6.3.3",
"source": {
"type": "git",
"url": "https://github.com/slevomat/coding-standard.git",
"reference": "223f02b6193fe47b7b483bfa5bf75693535482dd"
"reference": "b905a82255749de847fd4de607c7a4c8163f058d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/223f02b6193fe47b7b483bfa5bf75693535482dd",
"reference": "223f02b6193fe47b7b483bfa5bf75693535482dd",
"url": "https://api.github.com/repos/slevomat/coding-standard/zipball/b905a82255749de847fd4de607c7a4c8163f058d",
"reference": "b905a82255749de847fd4de607c7a4c8163f058d",
"shasum": ""
},
"require": {
"php": "^7.1",
"phpstan/phpdoc-parser": "^0.3.1",
"squizlabs/php_codesniffer": "^3.4.0"
"phpstan/phpdoc-parser": "0.4.0 - 0.4.4",
"squizlabs/php_codesniffer": "^3.5.5"
},
"require-dev": {
"jakub-onderka/php-parallel-lint": "1.0.0",
"phing/phing": "2.16.1",
"phpstan/phpstan": "0.11.1",
"phpstan/phpstan-phpunit": "0.11",
"phpstan/phpstan-strict-rules": "0.11",
"phpunit/phpunit": "8.0.0"
"dealerdirect/phpcodesniffer-composer-installer": "0.6.2",
"phing/phing": "2.16.3",
"php-parallel-lint/php-parallel-lint": "1.2.0",
"phpstan/phpstan": "0.12.19",
"phpstan/phpstan-deprecation-rules": "0.12.2",
"phpstan/phpstan-phpunit": "0.12.8",
"phpstan/phpstan-strict-rules": "0.12.2",
"phpunit/phpunit": "7.5.20|8.5.2|9.1.2"
},
"type": "phpcodesniffer-standard",
"extra": {
"branch-alias": {
"dev-master": "6.x-dev"
}
},
"autoload": {
"psr-4": {
"SlevomatCodingStandard\\": "SlevomatCodingStandard"
......@@ -2450,20 +2459,30 @@
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
"time": "2019-03-12T20:26:36+00:00"
"funding": [
{
"url": "https://github.com/kukulich",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard",
"type": "tidelift"
}
],
"time": "2020-04-28T07:15:08+00:00"
},
{
"name": "squizlabs/php_codesniffer",
"version": "3.4.0",
"version": "3.5.5",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "379deb987e26c7cd103a7b387aea178baec96e48"
"reference": "73e2e7f57d958e7228fce50dc0c61f58f017f9f6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/379deb987e26c7cd103a7b387aea178baec96e48",
"reference": "379deb987e26c7cd103a7b387aea178baec96e48",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/73e2e7f57d958e7228fce50dc0c61f58f017f9f6",
"reference": "73e2e7f57d958e7228fce50dc0c61f58f017f9f6",
"shasum": ""
},
"require": {
......@@ -2496,12 +2515,12 @@
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "http://www.squizlabs.com/php-codesniffer",
"homepage": "https://github.com/squizlabs/PHP_CodeSniffer",
"keywords": [
"phpcs",
"standards"
],
"time": "2018-12-19T23:57:18+00:00"
"time": "2020-04-17T01:09:41+00:00"
},
{
"name": "symfony/console",
......
......@@ -10,7 +10,7 @@ use Doctrine\DBAL\DBALException;
class CacheException extends DBALException
{
/**
* @return \Doctrine\DBAL\Cache\CacheException
* @return CacheException
*/
public static function noCacheKey()
{
......@@ -18,7 +18,7 @@ class CacheException extends DBALException
}
/**
* @return \Doctrine\DBAL\Cache\CacheException
* @return CacheException
*/
public static function noResultDriverConfigured()
{
......
......@@ -92,7 +92,7 @@ class QueryCacheProfile
}
/**
* @return \Doctrine\DBAL\Cache\QueryCacheProfile
* @return QueryCacheProfile
*/
public function setResultCacheDriver(Cache $cache)
{
......@@ -102,7 +102,7 @@ class QueryCacheProfile
/**
* @param string|null $cacheKey
*
* @return \Doctrine\DBAL\Cache\QueryCacheProfile
* @return QueryCacheProfile
*/
public function setCacheKey($cacheKey)
{
......@@ -112,7 +112,7 @@ class QueryCacheProfile
/**
* @param int $lifetime
*
* @return \Doctrine\DBAL\Cache\QueryCacheProfile
* @return QueryCacheProfile
*/
public function setLifetime($lifetime)
{
......
......@@ -86,6 +86,7 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement
if (! $data) {
$data = [];
}
$data[$this->realKey] = $this->data;
$this->resultCache->save($this->cacheKey, $data, $this->lifetime);
......
......@@ -1063,6 +1063,7 @@ class Connection implements DriverConnection
} else {
$stmt->execute($params);
}
$result = $stmt->rowCount();
} else {
$result = $connection->exec($query);
......@@ -1179,9 +1180,11 @@ class Connection implements DriverConnection
return $res;
} catch (Exception $e) {
$this->rollBack();
throw $e;
} catch (Throwable $e) {
$this->rollBack();
throw $e;
}
}
......@@ -1254,6 +1257,7 @@ class Connection implements DriverConnection
if ($logger) {
$logger->startQuery('"SAVEPOINT"');
}
$this->createSavepoint($this->_getNestedTransactionSavePointName());
if ($logger) {
$logger->stopQuery();
......@@ -1274,6 +1278,7 @@ class Connection implements DriverConnection
if ($this->transactionNestingLevel === 0) {
throw ConnectionException::noActiveTransaction();
}
if ($this->isRollbackOnly) {
throw ConnectionException::commitFailedRollbackOnly();
}
......@@ -1298,6 +1303,7 @@ class Connection implements DriverConnection
if ($logger) {
$logger->startQuery('"RELEASE SAVEPOINT"');
}
$this->releaseSavepoint($this->_getNestedTransactionSavePointName());
if ($logger) {
$logger->stopQuery();
......@@ -1354,6 +1360,7 @@ class Connection implements DriverConnection
if ($logger) {
$logger->startQuery('"ROLLBACK"');
}
$this->transactionNestingLevel = 0;
$connection->rollBack();
$this->isRollbackOnly = false;
......@@ -1368,6 +1375,7 @@ class Connection implements DriverConnection
if ($logger) {
$logger->startQuery('"ROLLBACK TO SAVEPOINT"');
}
$this->rollbackSavepoint($this->_getNestedTransactionSavePointName());
--$this->transactionNestingLevel;
if ($logger) {
......@@ -1479,6 +1487,7 @@ class Connection implements DriverConnection
if ($this->transactionNestingLevel === 0) {
throw ConnectionException::noActiveTransaction();
}
$this->isRollbackOnly = true;
}
......@@ -1555,6 +1564,7 @@ class Connection implements DriverConnection
} else {
$stmt->bindValue($bindIndex, $value);
}
++$bindIndex;
}
} else {
......@@ -1584,6 +1594,7 @@ class Connection implements DriverConnection
if (is_string($type)) {
$type = Type::getType($type);
}
if ($type instanceof Type) {
$value = $type->convertToDatabaseValue($value, $this->getDatabasePlatform());
$bindingType = $type->getBindingType();
......@@ -1623,6 +1634,7 @@ class Connection implements DriverConnection
} else {
$resolvedParams[$bindIndex] = $value;
}
++$bindIndex;
}
} else {
......
......@@ -8,7 +8,7 @@ namespace Doctrine\DBAL;
class ConnectionException extends DBALException
{
/**
* @return \Doctrine\DBAL\ConnectionException
* @return ConnectionException
*/
public static function commitFailedRollbackOnly()
{
......@@ -16,7 +16,7 @@ class ConnectionException extends DBALException
}
/**
* @return \Doctrine\DBAL\ConnectionException
* @return ConnectionException
*/
public static function noActiveTransaction()
{
......@@ -24,7 +24,7 @@ class ConnectionException extends DBALException
}
/**
* @return \Doctrine\DBAL\ConnectionException
* @return ConnectionException
*/
public static function savepointsNotSupported()
{
......@@ -32,7 +32,7 @@ class ConnectionException extends DBALException
}
/**
* @return \Doctrine\DBAL\ConnectionException
* @return ConnectionException
*/
public static function mayNotAlterNestedTransactionWithSavepointsInTransaction()
{
......
......@@ -95,6 +95,7 @@ class MasterSlaveConnection extends Connection
if (! isset($params['slaves'], $params['master'])) {
throw new InvalidArgumentException('master or slaves configuration missing');
}
if (count($params['slaves']) === 0) {
throw new InvalidArgumentException('You have to configure at least one slaves.');
}
......
......@@ -30,7 +30,7 @@ class DBALException extends Exception
/**
* @param string $method
*
* @return \Doctrine\DBAL\DBALException
* @return DBALException
*/
public static function notSupported($method)
{
......@@ -89,7 +89,7 @@ class DBALException extends Exception
}
/**
* @return \Doctrine\DBAL\DBALException
* @return DBALException
*/
public static function invalidPdoInstance()
{
......@@ -102,7 +102,7 @@ class DBALException extends Exception
/**
* @param string|null $url The URL that was provided in the connection parameters (if any).
*
* @return \Doctrine\DBAL\DBALException
* @return DBALException
*/
public static function driverRequired($url = null)
{
......@@ -124,7 +124,7 @@ class DBALException extends Exception
* @param string $unknownDriverName
* @param string[] $knownDrivers
*
* @return \Doctrine\DBAL\DBALException
* @return DBALException
*/
public static function unknownDriver($unknownDriverName, array $knownDrivers)
{
......@@ -144,6 +144,7 @@ class DBALException extends Exception
if ($params) {
$msg .= ' with params ' . self::formatParameters($params);
}
$msg .= ":\n\n" . $driverEx->getMessage();
return static::wrapException($driver, $driverEx, $msg);
......@@ -165,6 +166,7 @@ class DBALException extends Exception
if ($driverEx instanceof DriverException) {
return $driverEx;
}
if ($driver instanceof ExceptionConverterDriver && $driverEx instanceof DriverExceptionInterface) {
return $driver->convertException($msg, $driverEx);
}
......@@ -201,7 +203,7 @@ class DBALException extends Exception
/**
* @param string $wrapperClass
*
* @return \Doctrine\DBAL\DBALException
* @return DBALException
*/
public static function invalidWrapperClass($wrapperClass)
{
......@@ -212,7 +214,7 @@ class DBALException extends Exception
/**
* @param string $driverClass
*
* @return \Doctrine\DBAL\DBALException
* @return DBALException
*/
public static function invalidDriverClass($driverClass)
{
......@@ -222,7 +224,7 @@ class DBALException extends Exception
/**
* @param string $tableName
*
* @return \Doctrine\DBAL\DBALException
* @return DBALException
*/
public static function invalidTableName($tableName)
{
......@@ -232,7 +234,7 @@ class DBALException extends Exception
/**
* @param string $tableName
*
* @return \Doctrine\DBAL\DBALException
* @return DBALException
*/
public static function noColumnsSpecifiedForTable($tableName)
{
......@@ -240,7 +242,7 @@ class DBALException extends Exception
}
/**
* @return \Doctrine\DBAL\DBALException
* @return DBALException
*/
public static function limitOffsetInvalid()
{
......@@ -250,7 +252,7 @@ class DBALException extends Exception
/**
* @param string $name
*
* @return \Doctrine\DBAL\DBALException
* @return DBALException
*/
public static function typeExists($name)
{
......@@ -260,7 +262,7 @@ class DBALException extends Exception
/**
* @param string $name
*
* @return \Doctrine\DBAL\DBALException
* @return DBALException
*/
public static function unknownColumnType($name)
{
......@@ -276,7 +278,7 @@ class DBALException extends Exception
/**
* @param string $name
*
* @return \Doctrine\DBAL\DBALException
* @return DBALException
*/
public static function typeNotFound($name)
{
......
......@@ -32,8 +32,10 @@ abstract class AbstractMySQLDriver implements Driver, ExceptionConverterDriver,
switch ($exception->getErrorCode()) {
case '1213':
return new Exception\DeadlockException($message, $exception);
case '1205':
return new Exception\LockWaitTimeoutException($message, $exception);
case '1050':
return new Exception\TableExistsException($message, $exception);
......@@ -123,6 +125,7 @@ abstract class AbstractMySQLDriver implements Driver, ExceptionConverterDriver,
if (version_compare($oracleMysqlVersion, '8', '>=')) {
return new MySQL80Platform();
}
if (version_compare($oracleMysqlVersion, '5.7.9', '>=')) {
return new MySQL57Platform();
}
......@@ -151,6 +154,7 @@ abstract class AbstractMySQLDriver implements Driver, ExceptionConverterDriver,
'<major_version>.<minor_version>.<patch_version>'
);
}
$majorVersion = $versionParts['major'];
$minorVersion = $versionParts['minor'] ?? 0;
$patchVersion = $versionParts['patch'] ?? null;
......
......@@ -33,6 +33,7 @@ abstract class AbstractPostgreSQLDriver implements Driver, ExceptionConverterDri
case '40001':
case '40P01':
return new Exception\DeadlockException($message, $exception);
case '0A000':
// Foreign key constraint violations during a TRUNCATE operation
// are considered "feature not supported" in PostgreSQL.
......@@ -41,6 +42,7 @@ abstract class AbstractPostgreSQLDriver implements Driver, ExceptionConverterDri
}
break;
case '23502':
return new Exception\NotNullConstraintViolationException($message, $exception);
......
......@@ -32,31 +32,41 @@ abstract class AbstractSQLAnywhereDriver implements Driver, ExceptionConverterDr
case '-307':
case '-684':
return new Exception\DeadlockException($message, $exception);
case '-210':
case '-1175':
case '-1281':
return new Exception\LockWaitTimeoutException($message, $exception);
case '-100':
case '-103':
case '-832':
return new Exception\ConnectionException($message, $exception);
case '-143':
return new Exception\InvalidFieldNameException($message, $exception);
case '-193':
case '-196':
return new Exception\UniqueConstraintViolationException($message, $exception);
case '-194':
case '-198':
return new Exception\ForeignKeyConstraintViolationException($message, $exception);
case '-144':
return new Exception\NonUniqueFieldNameException($message, $exception);
case '-184':
case '-195':
return new Exception\NotNullConstraintViolationException($message, $exception);
case '-131':
return new Exception\SyntaxErrorException($message, $exception);
case '-110':
return new Exception\TableExistsException($message, $exception);
case '-141':
case '-1041':
return new Exception\TableNotFoundException($message, $exception);
......@@ -90,10 +100,13 @@ abstract class AbstractSQLAnywhereDriver implements Driver, ExceptionConverterDr
switch (true) {
case version_compare($version, '16', '>='):
return new SQLAnywhere16Platform();
case version_compare($version, '12', '>='):
return new SQLAnywhere12Platform();
case version_compare($version, '11', '>='):
return new SQLAnywhere11Platform();
default:
return new SQLAnywherePlatform();
}
......
......@@ -67,6 +67,10 @@ abstract class AbstractSQLiteDriver implements Driver, ExceptionConverterDriver
return new Exception\ConnectionException($message, $exception);
}
if (strpos($exception->getMessage(), 'FOREIGN KEY constraint failed') !== false) {
return new Exception\ForeignKeyConstraintViolationException($message, $exception);
}
return new Exception\DriverException($message, $exception);
}
......
......@@ -6,8 +6,6 @@ use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\ParameterType;
use stdClass;
use const DB2_AUTOCOMMIT_OFF;
use const DB2_AUTOCOMMIT_ON;
use function assert;
use function db2_autocommit;
use function db2_commit;
......@@ -25,6 +23,8 @@ use function db2_server_info;
use function db2_stmt_errormsg;
use function func_get_args;
use function is_bool;
use const DB2_AUTOCOMMIT_OFF;
use const DB2_AUTOCOMMIT_ON;
class DB2Connection implements Connection, ServerInfoAwareConnection
{
......@@ -61,8 +61,8 @@ class DB2Connection implements Connection, ServerInfoAwareConnection
*/
public function getServerVersion()
{
/** @var stdClass $serverInfo */
$serverInfo = db2_server_info($this->conn);
assert($serverInfo instanceof stdClass);
return $serverInfo->DBMS_VER;
}
......
......@@ -12,12 +12,6 @@ use ReflectionClass;
use ReflectionObject;
use ReflectionProperty;
use stdClass;
use const CASE_LOWER;
use const DB2_BINARY;
use const DB2_CHAR;
use const DB2_LONG;
use const DB2_PARAM_FILE;
use const DB2_PARAM_IN;
use function array_change_key_case;
use function db2_bind_param;
use function db2_execute;
......@@ -45,6 +39,12 @@ use function stream_copy_to_stream;
use function stream_get_meta_data;
use function strtolower;
use function tmpfile;
use const CASE_LOWER;
use const DB2_BINARY;
use const DB2_CHAR;
use const DB2_LONG;
use const DB2_PARAM_FILE;
use const DB2_PARAM_IN;
class DB2Statement implements IteratorAggregate, Statement
{
......@@ -309,12 +309,16 @@ class DB2Statement implements IteratorAggregate, Statement
while (($row = $this->fetch(...func_get_args())) !== false) {
$rows[] = $row;
}
break;
case FetchMode::COLUMN:
while (($row = $this->fetchColumn()) !== false) {
$rows[] = $row;
}
break;
default:
while (($row = $this->fetch($fetchMode)) !== false) {
$rows[] = $row;
......
......@@ -7,12 +7,6 @@ use Doctrine\DBAL\Driver\PingableConnection;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\ParameterType;
use mysqli;
use const MYSQLI_INIT_COMMAND;
use const MYSQLI_OPT_CONNECT_TIMEOUT;
use const MYSQLI_OPT_LOCAL_INFILE;
use const MYSQLI_READ_DEFAULT_FILE;
use const MYSQLI_READ_DEFAULT_GROUP;
use const MYSQLI_SERVER_PUBLIC_KEY;
use function defined;
use function floor;
use function func_get_args;
......@@ -26,6 +20,12 @@ use function restore_error_handler;
use function set_error_handler;
use function sprintf;
use function stripos;
use const MYSQLI_INIT_COMMAND;
use const MYSQLI_OPT_CONNECT_TIMEOUT;
use const MYSQLI_OPT_LOCAL_INFILE;
use const MYSQLI_READ_DEFAULT_FILE;
use const MYSQLI_READ_DEFAULT_GROUP;
use const MYSQLI_SERVER_PUBLIC_KEY;
class MysqliConnection implements Connection, PingableConnection, ServerInfoAwareConnection
{
......
......@@ -224,6 +224,7 @@ class MysqliStatement implements IteratorAggregate, Statement
if (get_resource_type($value) !== 'stream') {
throw new InvalidArgumentException('Resources passed with the LARGE_OBJECT parameter type must be stream resources.');
}
$streams[$parameter] = $value;
$values[$parameter] = null;
continue;
......
......@@ -4,7 +4,7 @@ namespace Doctrine\DBAL\Driver\OCI8;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\AbstractOracleDriver;
use const OCI_DEFAULT;
use const OCI_NO_AUTO_COMMIT;
/**
* A Doctrine DBAL driver for the Oracle OCI8 PHP extensions.
......@@ -22,7 +22,7 @@ class Driver extends AbstractOracleDriver
(string) $password,
$this->_constructDsn($params),
$params['charset'] ?? '',
$params['sessionMode'] ?? OCI_DEFAULT,
$params['sessionMode'] ?? OCI_NO_AUTO_COMMIT,
$params['persistent'] ?? false
);
} catch (OCI8Exception $e) {
......
......@@ -6,9 +6,6 @@ use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\ParameterType;
use UnexpectedValueException;
use const OCI_COMMIT_ON_SUCCESS;
use const OCI_DEFAULT;
use const OCI_NO_AUTO_COMMIT;
use function addcslashes;
use function func_get_args;
use function is_float;
......@@ -22,6 +19,8 @@ use function oci_server_version;
use function preg_match;
use function sprintf;
use function str_replace;
use const OCI_COMMIT_ON_SUCCESS;
use const OCI_NO_AUTO_COMMIT;
/**
* OCI8 implementation of the Connection interface.
......@@ -51,7 +50,7 @@ class OCI8Connection implements Connection, ServerInfoAwareConnection
$password,
$db,
$charset = '',
$sessionMode = OCI_DEFAULT,
$sessionMode = OCI_NO_AUTO_COMMIT,
$persistent = false
) {
$dbh = $persistent
......@@ -130,6 +129,7 @@ class OCI8Connection implements Connection, ServerInfoAwareConnection
if (is_int($value) || is_float($value)) {
return $value;
}
$value = str_replace("'", "''", $value);
return "'" . addcslashes($value, "\000\n\r\\\032") . "'";
......@@ -194,6 +194,7 @@ class OCI8Connection implements Connection, ServerInfoAwareConnection
if (! oci_commit($this->dbh)) {
throw OCI8Exception::fromErrorInfo($this->errorInfo());
}
$this->executeMode = OCI_COMMIT_ON_SUCCESS;
return true;
......@@ -207,6 +208,7 @@ class OCI8Connection implements Connection, ServerInfoAwareConnection
if (! oci_rollback($this->dbh)) {
throw OCI8Exception::fromErrorInfo($this->errorInfo());
}
$this->executeMode = OCI_COMMIT_ON_SUCCESS;
return true;
......
......@@ -12,7 +12,7 @@ class OCI8Exception extends AbstractDriverException
/**
* @param mixed[]|false $error
*
* @return \Doctrine\DBAL\Driver\OCI8\OCI8Exception
* @return OCI8Exception
*/
public static function fromErrorInfo($error)
{
......
......@@ -9,19 +9,6 @@ use Doctrine\DBAL\ParameterType;
use InvalidArgumentException;
use IteratorAggregate;
use PDO;
use const OCI_ASSOC;
use const OCI_B_BIN;
use const OCI_B_BLOB;
use const OCI_BOTH;
use const OCI_D_LOB;
use const OCI_FETCHSTATEMENT_BY_COLUMN;
use const OCI_FETCHSTATEMENT_BY_ROW;
use const OCI_NUM;
use const OCI_RETURN_LOBS;
use const OCI_RETURN_NULLS;
use const OCI_TEMP_BLOB;
use const PREG_OFFSET_CAPTURE;
use const SQLT_CHR;
use function array_key_exists;
use function assert;
use function count;
......@@ -43,6 +30,19 @@ use function preg_match;
use function preg_quote;
use function sprintf;
use function substr;
use const OCI_ASSOC;
use const OCI_B_BIN;
use const OCI_B_BLOB;
use const OCI_BOTH;
use const OCI_D_LOB;
use const OCI_FETCHSTATEMENT_BY_COLUMN;
use const OCI_FETCHSTATEMENT_BY_ROW;
use const OCI_NUM;
use const OCI_RETURN_LOBS;
use const OCI_RETURN_NULLS;
use const OCI_TEMP_BLOB;
use const PREG_OFFSET_CAPTURE;
use const SQLT_CHR;
/**
* The OCI8 implementation of the Statement interface.
......
......@@ -38,9 +38,11 @@ class Driver extends AbstractDB2Driver
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'] . ';';
......
......@@ -44,15 +44,19 @@ class Driver extends AbstractMySQLDriver
if (isset($params['host']) && $params['host'] !== '') {
$dsn .= 'host=' . $params['host'] . ';';
}
if (isset($params['port'])) {
$dsn .= 'port=' . $params['port'] . ';';
}
if (isset($params['dbname'])) {
$dsn .= 'dbname=' . $params['dbname'] . ';';
}
if (isset($params['unix_socket'])) {
$dsn .= 'unix_socket=' . $params['unix_socket'] . ';';
}
if (isset($params['charset'])) {
$dsn .= 'charset=' . $params['charset'] . ';';
}
......
......@@ -5,13 +5,13 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use PDO;
use const E_USER_DEPRECATED;
use function array_slice;
use function assert;
use function func_get_args;
use function is_array;
use function sprintf;
use function trigger_error;
use const E_USER_DEPRECATED;
/**
* The PDO implementation of the Statement interface.
......
......@@ -11,7 +11,6 @@ use PDO;
use ReflectionClass;
use ReflectionObject;
use stdClass;
use const SASQL_BOTH;
use function array_key_exists;
use function func_get_args;
use function func_num_args;
......@@ -35,6 +34,7 @@ use function sasql_stmt_field_count;
use function sasql_stmt_reset;
use function sasql_stmt_result_metadata;
use function sprintf;
use const SASQL_BOTH;
/**
* SAP SQL Anywhere implementation of the Statement interface.
......@@ -258,12 +258,14 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement
while (($row = $this->fetch(...func_get_args())) !== false) {
$rows[] = $row;
}
break;
case FetchMode::COLUMN:
while (($row = $this->fetchColumn()) !== false) {
$rows[] = $row;
}
break;
default:
......
......@@ -5,7 +5,6 @@ namespace Doctrine\DBAL\Driver\SQLSrv;
use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\ParameterType;
use const SQLSRV_ERR_ERRORS;
use function func_get_args;
use function is_float;
use function is_int;
......@@ -20,6 +19,7 @@ use function sqlsrv_rollback;
use function sqlsrv_rows_affected;
use function sqlsrv_server_info;
use function str_replace;
use const SQLSRV_ERR_ERRORS;
/**
* SQL Server implementation for the Connection interface.
......
......@@ -3,9 +3,9 @@
namespace Doctrine\DBAL\Driver\SQLSrv;
use Doctrine\DBAL\Driver\AbstractDriverException;
use const SQLSRV_ERR_ERRORS;
use function rtrim;
use function sqlsrv_errors;
use const SQLSRV_ERR_ERRORS;
/**
* @psalm-immutable
......@@ -15,7 +15,7 @@ class SQLSrvException extends AbstractDriverException
/**
* Helper method to turn sql server errors into exception.
*
* @return \Doctrine\DBAL\Driver\SQLSrv\SQLSrvException
* @return SQLSrvException
*/
public static function fromSqlSrvErrors()
{
......
......@@ -8,12 +8,6 @@ use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use PDO;
use const SQLSRV_ENC_BINARY;
use const SQLSRV_ERR_ERRORS;
use const SQLSRV_FETCH_ASSOC;
use const SQLSRV_FETCH_BOTH;
use const SQLSRV_FETCH_NUMERIC;
use const SQLSRV_PARAM_IN;
use function array_key_exists;
use function count;
use function func_get_args;
......@@ -34,6 +28,12 @@ use function sqlsrv_prepare;
use function sqlsrv_rows_affected;
use function SQLSRV_SQLTYPE_VARBINARY;
use function stripos;
use const SQLSRV_ENC_BINARY;
use const SQLSRV_ERR_ERRORS;
use const SQLSRV_FETCH_ASSOC;
use const SQLSRV_FETCH_BOTH;
use const SQLSRV_FETCH_NUMERIC;
use const SQLSRV_PARAM_IN;
/**
* SQL Server Statement.
......@@ -387,12 +387,14 @@ class SQLSrvStatement implements IteratorAggregate, Statement
while (($row = $this->fetch(...func_get_args())) !== false) {
$rows[] = $row;
}
break;
case FetchMode::COLUMN:
while (($row = $this->fetchColumn()) !== false) {
$rows[] = $row;
}
break;
default:
......
......@@ -130,6 +130,7 @@ final class DriverManager
if (! $config) {
$config = new Configuration();
}
if (! $eventManager) {
$eventManager = new EventManager();
}
......@@ -273,12 +274,15 @@ final class DriverManager
if (isset($url['host'])) {
$params['host'] = $url['host'];
}
if (isset($url['port'])) {
$params['port'] = $url['port'];
}
if (isset($url['user'])) {
$params['user'] = $url['user'];
}
if (isset($url['pass'])) {
$params['password'] = $url['pass'];
}
......
......@@ -5,11 +5,11 @@ namespace Doctrine\DBAL\Event\Listeners;
use Doctrine\Common\EventSubscriber;
use Doctrine\DBAL\Event\ConnectionEventArgs;
use Doctrine\DBAL\Events;
use const CASE_UPPER;
use function array_change_key_case;
use function array_merge;
use function count;
use function implode;
use const CASE_UPPER;
/**
* Should be used when Oracle Server default environment does not match the Doctrine requirements.
......@@ -57,6 +57,7 @@ class OracleSessionInit implements EventSubscriber
$vars[] = $option . " = '" . $value . "'";
}
}
$sql = 'ALTER SESSION SET ' . implode(' ', $vars);
$args->getConnection()->executeUpdate($sql);
}
......
......@@ -62,7 +62,7 @@ class SchemaAlterTableAddColumnEventArgs extends SchemaEventArgs
*
* @param string|string[] $sql
*
* @return \Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs
* @return SchemaAlterTableAddColumnEventArgs
*/
public function addSql($sql)
{
......
......@@ -62,7 +62,7 @@ class SchemaAlterTableChangeColumnEventArgs extends SchemaEventArgs
*
* @param string|string[] $sql
*
* @return \Doctrine\DBAL\Event\SchemaAlterTableChangeColumnEventArgs
* @return SchemaAlterTableChangeColumnEventArgs
*/
public function addSql($sql)
{
......
......@@ -49,7 +49,7 @@ class SchemaAlterTableEventArgs extends SchemaEventArgs
*
* @param string|string[] $sql
*
* @return \Doctrine\DBAL\Event\SchemaAlterTableEventArgs
* @return SchemaAlterTableEventArgs
*/
public function addSql($sql)
{
......
......@@ -62,7 +62,7 @@ class SchemaAlterTableRemoveColumnEventArgs extends SchemaEventArgs
*
* @param string|string[] $sql
*
* @return \Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs
* @return SchemaAlterTableRemoveColumnEventArgs
*/
public function addSql($sql)
{
......
......@@ -77,7 +77,7 @@ class SchemaAlterTableRenameColumnEventArgs extends SchemaEventArgs
*
* @param string|string[] $sql
*
* @return \Doctrine\DBAL\Event\SchemaAlterTableRenameColumnEventArgs
* @return SchemaAlterTableRenameColumnEventArgs
*/
public function addSql($sql)
{
......
......@@ -47,7 +47,7 @@ class SchemaColumnDefinitionEventArgs extends SchemaEventArgs
* Allows to clear the column which means the column will be excluded from
* tables column list.
*
* @return \Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs
* @return SchemaColumnDefinitionEventArgs
*/
public function setColumn(?Column $column = null)
{
......
......@@ -62,7 +62,7 @@ class SchemaCreateTableColumnEventArgs extends SchemaEventArgs
*
* @param string|string[] $sql
*
* @return \Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs
* @return SchemaCreateTableColumnEventArgs
*/
public function addSql($sql)
{
......
......@@ -77,7 +77,7 @@ class SchemaCreateTableEventArgs extends SchemaEventArgs
*
* @param string|string[] $sql
*
* @return \Doctrine\DBAL\Event\SchemaCreateTableEventArgs
* @return SchemaCreateTableEventArgs
*/
public function addSql($sql)
{
......
......@@ -50,7 +50,7 @@ class SchemaDropTableEventArgs extends SchemaEventArgs
/**
* @param string $sql
*
* @return \Doctrine\DBAL\Event\SchemaDropTableEventArgs
* @return SchemaDropTableEventArgs
*/
public function setSql($sql)
{
......
......@@ -13,7 +13,7 @@ class SchemaEventArgs extends EventArgs
private $preventDefault = false;
/**
* @return \Doctrine\DBAL\Event\SchemaEventArgs
* @return SchemaEventArgs
*/
public function preventDefault()
{
......
......@@ -8,10 +8,10 @@ use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\LockMode;
use Throwable;
use const CASE_LOWER;
use function array_change_key_case;
use function assert;
use function is_int;
use const CASE_LOWER;
/**
* Table ID Generator for those poor languages that are missing sequences.
......@@ -72,6 +72,7 @@ class TableGenerator
if ($params['driver'] === 'pdo_sqlite') {
throw new DBALException('Cannot use TableGenerator with SQLite.');
}
$this->conn = DriverManager::getConnection($params, $conn->getConfiguration(), $conn->getEventManager());
$this->generatorTableName = $generatorTableName;
}
......@@ -141,6 +142,7 @@ class TableGenerator
$this->conn->commit();
} catch (Throwable $e) {
$this->conn->rollBack();
throw new DBALException('Error occurred while generating ID with TableGenerator, aborted generation: ' . $e->getMessage(), 0, $e);
}
......
<?php
namespace Doctrine\DBAL\Internal;
use function array_reverse;
/**
* DependencyOrderCalculator implements topological sorting, which is an ordering
* algorithm for directed graphs (DG) and/or directed acyclic graphs (DAG) by
* using a depth-first searching (DFS) to traverse the graph built in memory.
* This algorithm have a linear running time based on nodes (V) and dependency
* between the nodes (E), resulting in a computational complexity of O(V + E).
*/
final class DependencyOrderCalculator
{
public const NOT_VISITED = 0;
public const IN_PROGRESS = 1;
public const VISITED = 2;
/**
* Matrix of nodes (aka. vertex).
* Keys are provided hashes and values are the node definition objects.
*
* @var array<string,DependencyOrderNode>
*/
private $nodeList = [];
/**
* Volatile variable holding calculated nodes during sorting process.
*
* @var array<object>
*/
private $sortedNodeList = [];
/**
* Checks for node (vertex) existence in graph.
*/
public function hasNode(string $hash) : bool
{
return isset($this->nodeList[$hash]);
}
/**
* Adds a new node (vertex) to the graph, assigning its hash and value.
*
* @param object $node
*/
public function addNode(string $hash, $node) : void
{
$vertex = new DependencyOrderNode();
$vertex->hash = $hash;
$vertex->state = self::NOT_VISITED;
$vertex->value = $node;
$this->nodeList[$hash] = $vertex;
}
/**
* Adds a new dependency (edge) to the graph using their hashes.
*/
public function addDependency(string $fromHash, string $toHash) : void
{
$vertex = $this->nodeList[$fromHash];
$edge = new DependencyOrderEdge();
$edge->from = $fromHash;
$edge->to = $toHash;
$vertex->dependencyList[$toHash] = $edge;
}
/**
* Return a valid order list of all current nodes.
* The desired topological sorting is the reverse post order of these searches.
*
* {@internal Highly performance-sensitive method.}
*
* @return array<object>
*/
public function sort() : array
{
foreach ($this->nodeList as $vertex) {
if ($vertex->state !== self::NOT_VISITED) {
continue;
}
$this->visit($vertex);
}
$sortedList = $this->sortedNodeList;
$this->nodeList = [];
$this->sortedNodeList = [];
return array_reverse($sortedList);
}
/**
* Visit a given node definition for reordering.
*
* {@internal Highly performance-sensitive method.}
*/
private function visit(DependencyOrderNode $vertex) : void
{
$vertex->state = self::IN_PROGRESS;
foreach ($vertex->dependencyList as $edge) {
$adjacentVertex = $this->nodeList[$edge->to];
switch ($adjacentVertex->state) {
case self::VISITED:
case self::IN_PROGRESS:
// Do nothing, since node was already visited or is
// currently visited
break;
case self::NOT_VISITED:
$this->visit($adjacentVertex);
}
}
if ($vertex->state === self::VISITED) {
return;
}
$vertex->state = self::VISITED;
$this->sortedNodeList[] = $vertex->value;
}
}
<?php
namespace Doctrine\DBAL\Internal;
class DependencyOrderEdge
{
/** @var string */
public $from;
/** @var string */
public $to;
}
<?php
namespace Doctrine\DBAL\Internal;
class DependencyOrderNode
{
/** @var string */
public $hash;
/** @var int */
public $state;
/** @var object */
public $value;
/** @var DependencyOrderEdge[] */
public $dependencyList = [];
}
......@@ -2,8 +2,8 @@
namespace Doctrine\DBAL\Logging;
use const PHP_EOL;
use function var_dump;
use const PHP_EOL;
/**
* A SQL logger that logs to the standard output using echo/var_dump.
......
......@@ -28,7 +28,6 @@ use Doctrine\DBAL\Types;
use Doctrine\DBAL\Types\Type;
use InvalidArgumentException;
use UnexpectedValueException;
use const E_USER_DEPRECATED;
use function addcslashes;
use function array_map;
use function array_merge;
......@@ -55,6 +54,7 @@ use function strpos;
use function strtolower;
use function strtoupper;
use function trigger_error;
use const E_USER_DEPRECATED;
/**
* Base class for all DatabasePlatforms. The DatabasePlatforms are the central
......@@ -1552,7 +1552,6 @@ abstract class AbstractPlatform
if (($createFlags&self::CREATE_INDEXES) > 0) {
foreach ($table->getIndexes() as $index) {
/** @var $index Index */
if ($index->isPrimary()) {
$options['primary'] = $index->getQuotedColumns($this);
$options['primary_index'] = $index;
......@@ -1614,6 +1613,7 @@ abstract class AbstractPlatform
if ($table->hasOption('comment')) {
$sql[] = $this->getCommentOnTableSQL($tableName, $table->getOption('comment'));
}
foreach ($table->getColumns() as $column) {
$comment = $this->getColumnComment($column);
......@@ -1712,6 +1712,7 @@ abstract class AbstractPlatform
if (! empty($check)) {
$query .= ', ' . $check;
}
$query .= ')';
$sql[] = $query;
......@@ -1793,6 +1794,7 @@ abstract class AbstractPlatform
$referencesClause = ' REFERENCES ' . $constraint->getQuotedForeignTableName($this) .
' (' . implode(', ', $constraint->getQuotedForeignColumns($this)) . ')';
}
$query .= ' ' . $columnList . $referencesClause;
return $query;
......@@ -1812,6 +1814,7 @@ abstract class AbstractPlatform
if ($table instanceof Table) {
$table = $table->getQuotedName($this);
}
$name = $index->getQuotedName($this);
$columns = $index->getColumns();
......@@ -2080,6 +2083,7 @@ abstract class AbstractPlatform
foreach ($diff->removedForeignKeys as $foreignKey) {
$sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
}
foreach ($diff->changedForeignKeys as $foreignKey) {
$sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
}
......@@ -2088,6 +2092,7 @@ abstract class AbstractPlatform
foreach ($diff->removedIndexes as $index) {
$sql[] = $this->getDropIndexSQL($index, $tableName);
}
foreach ($diff->changedIndexes as $index) {
$sql[] = $this->getDropIndexSQL($index, $tableName);
}
......@@ -2515,6 +2520,7 @@ abstract class AbstractPlatform
if ($this->supportsForeignKeyOnUpdate() && $foreignKey->hasOption('onUpdate')) {
$query .= ' ON UPDATE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onUpdate'));
}
if ($foreignKey->hasOption('onDelete')) {
$query .= ' ON DELETE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete'));
}
......@@ -2541,6 +2547,7 @@ abstract class AbstractPlatform
case 'RESTRICT':
case 'SET DEFAULT':
return $upper;
default:
throw new InvalidArgumentException('Invalid foreign key action: ' . $upper);
}
......@@ -2560,14 +2567,17 @@ abstract class AbstractPlatform
if (strlen($foreignKey->getName())) {
$sql .= 'CONSTRAINT ' . $foreignKey->getQuotedName($this) . ' ';
}
$sql .= 'FOREIGN KEY (';
if (count($foreignKey->getLocalColumns()) === 0) {
throw new InvalidArgumentException("Incomplete definition. 'local' required.");
}
if (count($foreignKey->getForeignColumns()) === 0) {
throw new InvalidArgumentException("Incomplete definition. 'foreign' required.");
}
if (strlen($foreignKey->getForeignTableName()) === 0) {
throw new InvalidArgumentException("Incomplete definition. 'foreignTable' required.");
}
......@@ -2744,12 +2754,16 @@ abstract class AbstractPlatform
switch ($level) {
case TransactionIsolationLevel::READ_UNCOMMITTED:
return 'READ UNCOMMITTED';
case TransactionIsolationLevel::READ_COMMITTED:
return 'READ COMMITTED';
case TransactionIsolationLevel::REPEATABLE_READ:
return 'REPEATABLE READ';
case TransactionIsolationLevel::SERIALIZABLE:
return 'SERIALIZABLE';
default:
throw new InvalidArgumentException('Invalid isolation level:' . $level);
}
......@@ -3184,6 +3198,16 @@ abstract class AbstractPlatform
return true;
}
/**
* Whether foreign key constraints can be dropped.
*
* If false, then getDropForeignKeySQL() throws exception.
*/
public function supportsCreateDropForeignKeyConstraints() : bool
{
return true;
}
/**
* Whether this platform supports onUpdate in foreign key constraints.
*
......
......@@ -22,9 +22,6 @@ use function strtoupper;
class DB2Platform extends AbstractPlatform
{
/**
* {@inheritdoc}
*/
public function getCharMaxLength() : int
{
return 254;
......@@ -495,6 +492,7 @@ class DB2Platform extends AbstractPlatform
if (isset($options['indexes'])) {
$indexes = $options['indexes'];
}
$options['indexes'] = [];
$sqls = parent::_getCreateTableSQL($tableName, $columns, $options);
......@@ -708,21 +706,23 @@ class DB2Platform extends AbstractPlatform
foreach ($diff->removedIndexes as $remKey => $remIndex) {
foreach ($diff->addedIndexes as $addKey => $addIndex) {
if ($remIndex->getColumns() === $addIndex->getColumns()) {
if ($remIndex->isPrimary()) {
$sql[] = 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY';
} elseif ($remIndex->isUnique()) {
$sql[] = 'ALTER TABLE ' . $table . ' DROP UNIQUE ' . $remIndex->getQuotedName($this);
} else {
$sql[] = $this->getDropIndexSQL($remIndex, $table);
}
if ($remIndex->getColumns() !== $addIndex->getColumns()) {
continue;
}
$sql[] = $this->getCreateIndexSQL($addIndex, $table);
if ($remIndex->isPrimary()) {
$sql[] = 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY';
} elseif ($remIndex->isUnique()) {
$sql[] = 'ALTER TABLE ' . $table . ' DROP UNIQUE ' . $remIndex->getQuotedName($this);
} else {
$sql[] = $this->getDropIndexSQL($remIndex, $table);
}
unset($diff->removedIndexes[$remKey], $diff->addedIndexes[$addKey]);
$sql[] = $this->getCreateIndexSQL($addIndex, $table);
break;
}
unset($diff->removedIndexes[$remKey], $diff->addedIndexes[$addKey]);
break;
}
}
......
......@@ -552,6 +552,7 @@ class DrizzlePlatform extends AbstractPlatform
if (count($queryParts) > 0) {
$sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(', ', $queryParts);
}
$sql = array_merge(
$this->getPreAlterTableIndexForeignKeySQL($diff),
$sql,
......
......@@ -9,9 +9,6 @@ namespace Doctrine\DBAL\Platforms\Keywords;
*/
final class MariaDb102Keywords extends MySQLKeywords
{
/**
* {@inheritdoc}
*/
public function getName() : string
{
return 'MariaDb102';
......
......@@ -9,9 +9,6 @@ namespace Doctrine\DBAL\Platforms\Keywords;
*/
class PostgreSQL100Keywords extends PostgreSQL94Keywords
{
/**
* {@inheritdoc}
*/
public function getName() : string
{
return 'PostgreSQL100';
......
......@@ -21,17 +21,11 @@ final class MariaDb1027Platform extends MySqlPlatform
return 'LONGTEXT';
}
/**
* {@inheritdoc}
*/
protected function getReservedKeywordsClass() : string
{
return Keywords\MariaDb102Keywords::class;
}
/**
* {@inheritdoc}
*/
protected function initializeDoctrineTypeMappings() : void
{
parent::initializeDoctrineTypeMappings();
......
......@@ -635,6 +635,7 @@ SQL
if (count($queryParts) > 0) {
$sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(', ', $queryParts);
}
$sql = array_merge(
$this->getPreAlterTableIndexForeignKeySQL($diff),
$sql,
......@@ -661,25 +662,27 @@ SQL
$sql = array_merge($sql, $this->getPreAlterTableAlterPrimaryKeySQL($diff, $remIndex));
foreach ($diff->addedIndexes as $addKey => $addIndex) {
if ($remIndex->getColumns() === $addIndex->getColumns()) {
$indexClause = 'INDEX ' . $addIndex->getName();
if ($remIndex->getColumns() !== $addIndex->getColumns()) {
continue;
}
if ($addIndex->isPrimary()) {
$indexClause = 'PRIMARY KEY';
} elseif ($addIndex->isUnique()) {
$indexClause = 'UNIQUE INDEX ' . $addIndex->getName();
}
$indexClause = 'INDEX ' . $addIndex->getName();
$query = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $remIndex->getName() . ', ';
$query .= 'ADD ' . $indexClause;
$query .= ' (' . $this->getIndexFieldDeclarationListSQL($addIndex) . ')';
if ($addIndex->isPrimary()) {
$indexClause = 'PRIMARY KEY';
} elseif ($addIndex->isUnique()) {
$indexClause = 'UNIQUE INDEX ' . $addIndex->getName();
}
$sql[] = $query;
$query = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $remIndex->getName() . ', ';
$query .= 'ADD ' . $indexClause;
$query .= ' (' . $this->getIndexFieldDeclarationListSQL($addIndex) . ')';
unset($diff->removedIndexes[$remKey], $diff->addedIndexes[$addKey]);
$sql[] = $query;
break;
}
unset($diff->removedIndexes[$remKey], $diff->addedIndexes[$addKey]);
break;
}
}
......@@ -985,6 +988,7 @@ SQL
if ($foreignKey->hasOption('match')) {
$query .= ' MATCH ' . $foreignKey->getOption('match');
}
$query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey);
return $query;
......@@ -1180,9 +1184,6 @@ SQL
return TransactionIsolationLevel::REPEATABLE_READ;
}
/**
* {@inheritdoc}
*/
public function supportsColumnLengthIndexes() : bool
{
return true;
......
......@@ -242,11 +242,14 @@ class OraclePlatform extends AbstractPlatform
switch ($level) {
case TransactionIsolationLevel::READ_UNCOMMITTED:
return 'READ UNCOMMITTED';
case TransactionIsolationLevel::READ_COMMITTED:
return 'READ COMMITTED';
case TransactionIsolationLevel::REPEATABLE_READ:
case TransactionIsolationLevel::SERIALIZABLE:
return 'SERIALIZABLE';
default:
return parent::_getTransactionIsolationLevelSQL($level);
}
......
......@@ -11,14 +11,14 @@ use Doctrine\DBAL\Platforms\Keywords\PostgreSQL100Keywords;
*/
class PostgreSQL100Platform extends PostgreSQL94Platform
{
/**
* {@inheritdoc}
*/
protected function getReservedKeywordsClass() : string
{
return PostgreSQL100Keywords::class;
}
/**
* {@inheritDoc}
*/
public function getListSequencesSQL($database) : string
{
return 'SELECT sequence_name AS relname,
......
......@@ -533,7 +533,6 @@ SQL
}
foreach ($diff->changedColumns as $columnDiff) {
/** @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */
if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) {
continue;
}
......
......@@ -17,6 +17,7 @@ use InvalidArgumentException;
use function array_merge;
use function array_unique;
use function array_values;
use function assert;
use function count;
use function explode;
use function func_get_args;
......@@ -638,6 +639,7 @@ class SQLAnywherePlatform extends AbstractPlatform
case self::FOREIGN_KEY_MATCH_FULL_UNIQUE:
return 'UNIQUE FULL';
default:
throw new InvalidArgumentException('Invalid foreign key match type: ' . $type);
}
......@@ -1129,8 +1131,10 @@ SQL
switch ($pos) {
case TrimMode::LEADING:
return $this->getLtrimExpression($str);
case TrimMode::TRAILING:
return $this->getRtrimExpression($str);
default:
return 'TRIM(' . $str . ')';
}
......@@ -1141,8 +1145,10 @@ SQL
switch ($pos) {
case TrimMode::LEADING:
return 'SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))';
case TrimMode::TRAILING:
return 'REVERSE(SUBSTR(REVERSE(' . $str . '), PATINDEX(' . $pattern . ', REVERSE(' . $str . '))))';
default:
return 'REVERSE(SUBSTR(REVERSE(SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))), ' .
'PATINDEX(' . $pattern . ', REVERSE(SUBSTR(' . $str . ', PATINDEX(' . $pattern . ', ' . $str . '))))))';
......@@ -1254,8 +1260,8 @@ SQL
}
if (! empty($options['indexes'])) {
/** @var Index $index */
foreach ((array) $options['indexes'] as $index) {
assert($index instanceof Index);
$indexSql[] = $this->getCreateIndexSQL($index, $tableName);
}
}
......@@ -1296,12 +1302,16 @@ SQL
switch ($level) {
case TransactionIsolationLevel::READ_UNCOMMITTED:
return '0';
case TransactionIsolationLevel::READ_COMMITTED:
return '1';
case TransactionIsolationLevel::REPEATABLE_READ:
return '2';
case TransactionIsolationLevel::SERIALIZABLE:
return '3';
default:
throw new InvalidArgumentException('Invalid isolation level:' . $level);
}
......
......@@ -3,10 +3,10 @@
namespace Doctrine\DBAL\Platforms;
use Doctrine\DBAL\Schema\Sequence;
use const PREG_OFFSET_CAPTURE;
use function preg_match;
use function preg_match_all;
use function substr_count;
use const PREG_OFFSET_CAPTURE;
/**
* Platform to ensure compatibility of Doctrine with Microsoft SQL Server 2012 version.
......@@ -105,7 +105,7 @@ class SQLServer2012Platform extends SQLServer2008Platform
$matchesCount = preg_match_all('/[\\s]+order\\s+by\\s/im', $query, $matches, PREG_OFFSET_CAPTURE);
$orderByPos = false;
if ($matchesCount > 0) {
$orderByPos = $matches[0][($matchesCount - 1)][1];
$orderByPos = $matches[0][$matchesCount - 1][1];
}
if ($orderByPos === false
......
......@@ -287,6 +287,7 @@ SQL
if (isset($options['primary_index']) && $options['primary_index']->hasFlag('nonclustered')) {
$flags = ' NONCLUSTERED';
}
$columnListSql .= ', PRIMARY KEY' . $flags . ' (' . implode(', ', array_unique(array_values($options['primary']))) . ')';
}
......@@ -296,6 +297,7 @@ SQL
if (! empty($check)) {
$query .= ', ' . $check;
}
$query .= ')';
$sql = [$query];
......@@ -1671,8 +1673,8 @@ SQL
{
return sprintf(
<<<'SQL'
EXEC sys.sp_addextendedproperty @name=N'MS_Description',
@value=N%s, @level0type=N'SCHEMA', @level0name=N'dbo',
EXEC sys.sp_addextendedproperty @name=N'MS_Description',
@value=N%s, @level0type=N'SCHEMA', @level0name=N'dbo',
@level1type=N'TABLE', @level1name=N%s
SQL
,
......
......@@ -64,8 +64,10 @@ class SqlitePlatform extends AbstractPlatform
switch ($type) {
case 'time':
return 'time(\'now\')';
case 'date':
return 'date(\'now\')';
case 'timestamp':
default:
return 'datetime(\'now\')';
......@@ -77,7 +79,7 @@ class SqlitePlatform extends AbstractPlatform
*/
public function getTrimExpression($str, $pos = TrimMode::UNSPECIFIED, $char = false)
{
$trimChar = $char !== false ? (', ' . $char) : '';
$trimChar = $char !== false ? ', ' . $char : '';
switch ($pos) {
case TrimMode::LEADING:
......@@ -131,26 +133,25 @@ class SqlitePlatform extends AbstractPlatform
case DateIntervalUnit::MINUTE:
case DateIntervalUnit::HOUR:
return 'DATETIME(' . $date . ",'" . $operator . $interval . ' ' . $unit . "')";
}
default:
switch ($unit) {
case DateIntervalUnit::WEEK:
$interval *= 7;
$unit = DateIntervalUnit::DAY;
break;
case DateIntervalUnit::QUARTER:
$interval *= 3;
$unit = DateIntervalUnit::MONTH;
break;
}
switch ($unit) {
case DateIntervalUnit::WEEK:
$interval *= 7;
$unit = DateIntervalUnit::DAY;
break;
if (! is_numeric($interval)) {
$interval = "' || " . $interval . " || '";
}
case DateIntervalUnit::QUARTER:
$interval *= 3;
$unit = DateIntervalUnit::MONTH;
break;
}
return 'DATE(' . $date . ",'" . $operator . $interval . ' ' . $unit . "')";
if (! is_numeric($interval)) {
$interval = "' || " . $interval . " || '";
}
return 'DATE(' . $date . ",'" . $operator . $interval . ' ' . $unit . "')";
}
/**
......@@ -169,10 +170,12 @@ class SqlitePlatform extends AbstractPlatform
switch ($level) {
case TransactionIsolationLevel::READ_UNCOMMITTED:
return '0';
case TransactionIsolationLevel::READ_COMMITTED:
case TransactionIsolationLevel::REPEATABLE_READ:
case TransactionIsolationLevel::SERIALIZABLE:
return '1';
default:
return parent::_getTransactionIsolationLevelSQL($level);
}
......@@ -769,6 +772,11 @@ class SqlitePlatform extends AbstractPlatform
* {@inheritDoc}
*/
public function supportsForeignKeyConstraints()
{
return true;
}
public function supportsCreateDropForeignKeyConstraints() : bool
{
return false;
}
......@@ -786,7 +794,7 @@ class SqlitePlatform extends AbstractPlatform
*/
public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table)
{
throw new DBALException('Sqlite platform does not support alter foreign key.');
throw new DBALException('Sqlite platform does not support alter foreign key, the table must be fully recreated using getAlterTableSQL.');
}
/**
......@@ -794,7 +802,7 @@ class SqlitePlatform extends AbstractPlatform
*/
public function getDropForeignKeySQL($foreignKey, $table)
{
throw new DBALException('Sqlite platform does not support alter foreign key.');
throw new DBALException('Sqlite platform does not support alter foreign key, the table must be fully recreated using getAlterTableSQL.');
}
/**
......
......@@ -6,9 +6,9 @@ use Doctrine\DBAL\Cache\QueryCacheProfile;
use Doctrine\DBAL\ColumnCase;
use Doctrine\DBAL\Driver\PDOConnection;
use PDO;
use function func_get_args;
use const CASE_LOWER;
use const CASE_UPPER;
use function func_get_args;
/**
* Portability wrapper for a Connection.
......@@ -62,6 +62,7 @@ class Connection extends \Doctrine\DBAL\Connection
} else {
$params['portability'] &= self::PORTABILITY_OTHERVENDORS;
}
$this->portability = $params['portability'];
}
......
......@@ -74,7 +74,7 @@ class CompositeExpression implements Countable
*
* @param self[]|string[] $parts
*
* @return \Doctrine\DBAL\Query\Expression\CompositeExpression
* @return CompositeExpression
*/
public function addMultiple(array $parts = [])
{
......@@ -92,7 +92,7 @@ class CompositeExpression implements Countable
*
* @param mixed $part
*
* @return \Doctrine\DBAL\Query\Expression\CompositeExpression
* @return CompositeExpression
*/
public function add($part)
{
......
......@@ -231,6 +231,7 @@ class QueryBuilder
case self::INSERT:
$sql = $this->getSQLForInsert();
break;
case self::DELETE:
$sql = $this->getSQLForDelete();
break;
......@@ -1286,6 +1287,7 @@ class QueryBuilder
$this->boundCounter++;
$placeHolder = ':dcValue' . $this->boundCounter;
}
$this->setParameter(substr($placeHolder, 1), $value, $type);
return $placeHolder;
......@@ -1338,11 +1340,13 @@ class QueryBuilder
if (array_key_exists($join['joinAlias'], $knownAliases)) {
throw QueryException::nonUniqueAlias($join['joinAlias'], array_keys($knownAliases));
}
$sql .= ' ' . strtoupper($join['joinType'])
. ' JOIN ' . $join['joinTable'] . ' ' . $join['joinAlias'];
if ($join['joinCondition'] !== null) {
$sql .= ' ON ' . $join['joinCondition'];
}
$knownAliases[$join['joinAlias']] = true;
}
......
......@@ -14,7 +14,7 @@ class QueryException extends DBALException
* @param string $alias
* @param string[] $registeredAliases
*
* @return \Doctrine\DBAL\Query\QueryException
* @return QueryException
*/
public static function unknownAlias($alias, $registeredAliases)
{
......@@ -27,7 +27,7 @@ class QueryException extends DBALException
* @param string $alias
* @param string[] $registeredAliases
*
* @return \Doctrine\DBAL\Query\QueryException
* @return QueryException
*/
public static function nonUniqueAlias($alias, $registeredAliases)
{
......
......@@ -2,7 +2,6 @@
namespace Doctrine\DBAL;
use const PREG_OFFSET_CAPTURE;
use function array_fill;
use function array_fill_keys;
use function array_key_exists;
......@@ -20,6 +19,7 @@ use function sprintf;
use function strlen;
use function strpos;
use function substr;
use const PREG_OFFSET_CAPTURE;
/**
* Utility class that parses sql statements with regard to types and parameters.
......@@ -195,8 +195,8 @@ class SQLParserUtils
$expandStr = $count ? implode(', ', array_fill(0, $count, '?')) : 'NULL';
$query = substr($query, 0, $needlePos) . $expandStr . substr($query, $needlePos + 1);
$paramOffset += ($count - 1); // Grows larger by number of parameters minus the replaced needle.
$queryOffset += (strlen($expandStr) - 1);
$paramOffset += $count - 1; // Grows larger by number of parameters minus the replaced needle.
$queryOffset += strlen($expandStr) - 1;
}
return [$query, $params, $types];
......@@ -214,10 +214,10 @@ class SQLParserUtils
if (! isset($arrayPositions[$paramName]) && ! isset($arrayPositions[':' . $paramName])) {
$pos += $queryOffset;
$queryOffset -= ($paramLen - 1);
$queryOffset -= $paramLen - 1;
$paramsOrd[] = $value;
$typesOrd[] = static::extractParam($paramName, $types, false, ParameterType::STRING);
$query = substr($query, 0, $pos) . '?' . substr($query, ($pos + $paramLen));
$query = substr($query, 0, $pos) . '?' . substr($query, $pos + $paramLen);
continue;
}
......@@ -231,8 +231,8 @@ class SQLParserUtils
}
$pos += $queryOffset;
$queryOffset += (strlen($expandStr) - $paramLen);
$query = substr($query, 0, $pos) . $expandStr . substr($query, ($pos + $paramLen));
$queryOffset += strlen($expandStr) - $paramLen;
$query = substr($query, 0, $pos) . $expandStr . substr($query, $pos + $paramLen);
}
return [$query, $paramsOrd, $typesOrd];
......
......@@ -14,7 +14,7 @@ class SQLParserUtilsException extends DBALException
/**
* @param string $paramName
*
* @return \Doctrine\DBAL\SQLParserUtilsException
* @return SQLParserUtilsException
*/
public static function missingParam($paramName)
{
......@@ -24,7 +24,7 @@ class SQLParserUtilsException extends DBALException
/**
* @param string $typeName
*
* @return \Doctrine\DBAL\SQLParserUtilsException
* @return SQLParserUtilsException
*/
public static function missingType($typeName)
{
......
......@@ -48,11 +48,13 @@ abstract class AbstractAsset
$this->_quoted = true;
$name = $this->trimQuotes($name);
}
if (strpos($name, '.') !== false) {
$parts = explode('.', $name);
$this->_namespace = $parts[0];
$name = $parts[1];
}
$this->_name = $name;
}
......
......@@ -132,6 +132,7 @@ abstract class AbstractSchemaManager
if ($database === null) {
$database = $this->_conn->getDatabase();
}
$sql = $this->_platform->getListSequencesSQL($database);
$sequences = $this->_conn->fetchAll($sql);
......@@ -273,6 +274,7 @@ abstract class AbstractSchemaManager
if ($this->_platform->supportsForeignKeyConstraints()) {
$foreignKeys = $this->listTableForeignKeys($tableName);
}
$indexes = $this->listTableIndexes($tableName);
return new Table($tableName, $columns, $indexes, $foreignKeys);
......@@ -305,6 +307,7 @@ abstract class AbstractSchemaManager
if ($database === null) {
$database = $this->_conn->getDatabase();
}
$sql = $this->_platform->getListTableForeignKeysSQL($table, $database);
$tableForeignKeys = $this->_conn->fetchAll($sql);
......@@ -846,6 +849,7 @@ abstract class AbstractSchemaManager
if ($tableIndex['primary']) {
$keyName = 'primary';
}
$keyName = strtolower($keyName);
if (! isset($result[$keyName])) {
......@@ -1075,9 +1079,11 @@ abstract class AbstractSchemaManager
if (! isset($params['defaultTableOptions'])) {
$params['defaultTableOptions'] = [];
}
if (! isset($params['defaultTableOptions']['charset']) && isset($params['charset'])) {
$params['defaultTableOptions']['charset'] = $params['charset'];
}
$schemaConfig->setDefaultTableOptions($params['defaultTableOptions']);
return $schemaConfig;
......
......@@ -3,12 +3,12 @@
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Types\Type;
use const E_USER_DEPRECATED;
use function array_merge;
use function is_numeric;
use function method_exists;
use function sprintf;
use function trigger_error;
use const E_USER_DEPRECATED;
/**
* Object representation of a database column.
......@@ -86,6 +86,7 @@ class Column extends AbstractAsset
continue;
}
$this->$method($value);
}
......
......@@ -89,6 +89,7 @@ class Comparator
if (! isset($foreignKeysToTable[$foreignTable])) {
$foreignKeysToTable[$foreignTable] = [];
}
$foreignKeysToTable[$foreignTable][] = $foreignKey;
}
}
......@@ -116,6 +117,7 @@ class Comparator
if ($tableName !== strtolower($removedForeignKey->getForeignTableName())) {
continue;
}
unset($diff->changedTables[$localTableName]->removedForeignKeys[$key]);
}
}
......@@ -205,6 +207,7 @@ class Comparator
$tableDifferences->addedColumns[$columnName] = $column;
$changes++;
}
/* See if there are any removed fields in table 2 */
foreach ($table1Columns as $columnName => $column) {
// See if column is removed in table 2.
......@@ -241,6 +244,7 @@ class Comparator
$tableDifferences->addedIndexes[$indexName] = $index;
$changes++;
}
/* See if there are any removed indexes in table 2 */
foreach ($table1Indexes as $indexName => $index) {
// See if index is removed in table 2.
......@@ -465,6 +469,7 @@ class Comparator
if (($properties1['precision'] ?: 10) !== ($properties2['precision'] ?: 10)) {
$changedProperties[] = 'precision';
}
if ($properties1['scale'] !== $properties2['scale']) {
$changedProperties[] = 'scale';
}
......
......@@ -4,14 +4,15 @@ namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Platforms\DB2Platform;
use Doctrine\DBAL\Types\Type;
use const CASE_LOWER;
use function array_change_key_case;
use function assert;
use function is_resource;
use function preg_match;
use function str_replace;
use function strpos;
use function strtolower;
use function substr;
use const CASE_LOWER;
/**
* IBM Db2 Schema Manager.
......@@ -68,13 +69,16 @@ class DB2SchemaManager extends AbstractSchemaManager
$length = $tableColumn['length'];
$fixed = false;
break;
case 'character':
$length = $tableColumn['length'];
$fixed = true;
break;
case 'clob':
$length = $tableColumn['length'];
break;
case 'decimal':
case 'double':
case 'real':
......@@ -213,13 +217,16 @@ class DB2SchemaManager extends AbstractSchemaManager
return new View($view['name'], $sql);
}
/**
* {@inheritdoc}
*/
public function listTableDetails($tableName) : Table
{
$table = parent::listTableDetails($tableName);
/** @var DB2Platform $platform */
$platform = $this->_platform;
$sql = $platform->getListTableCommentsSQL($tableName);
assert($platform instanceof DB2Platform);
$sql = $platform->getListTableCommentsSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql);
......
......@@ -65,6 +65,7 @@ class Index extends AbstractAsset implements Constraint
foreach ($columns as $column) {
$this->_addColumn($column);
}
foreach ($flags as $flag) {
$this->addFlag($flag);
}
......
......@@ -5,7 +5,6 @@ namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Platforms\MariaDb1027Platform;
use Doctrine\DBAL\Platforms\MySqlPlatform;
use Doctrine\DBAL\Types\Type;
use const CASE_LOWER;
use function array_change_key_case;
use function array_shift;
use function array_values;
......@@ -17,6 +16,7 @@ use function strpos;
use function strtok;
use function strtolower;
use function strtr;
use const CASE_LOWER;
/**
* Schema manager for the MySql RDBMS.
......@@ -82,11 +82,13 @@ class MySqlSchemaManager extends AbstractSchemaManager
} else {
$v['primary'] = false;
}
if (strpos($v['index_type'], 'FULLTEXT') !== false) {
$v['flags'] = ['FULLTEXT'];
} elseif (strpos($v['index_type'], 'SPATIAL') !== false) {
$v['flags'] = ['SPATIAL'];
}
$v['length'] = isset($v['sub_part']) ? (int) $v['sub_part'] : null;
$tableIndexes[$k] = $v;
......@@ -138,6 +140,7 @@ class MySqlSchemaManager extends AbstractSchemaManager
case 'binary':
$fixed = true;
break;
case 'float':
case 'double':
case 'real':
......@@ -148,25 +151,33 @@ class MySqlSchemaManager extends AbstractSchemaManager
$scale = $match[2];
$length = null;
}
break;
case 'tinytext':
$length = MySqlPlatform::LENGTH_LIMIT_TINYTEXT;
break;
case 'text':
$length = MySqlPlatform::LENGTH_LIMIT_TEXT;
break;
case 'mediumtext':
$length = MySqlPlatform::LENGTH_LIMIT_MEDIUMTEXT;
break;
case 'tinyblob':
$length = MySqlPlatform::LENGTH_LIMIT_TINYBLOB;
break;
case 'blob':
$length = MySqlPlatform::LENGTH_LIMIT_BLOB;
break;
case 'mediumblob':
$length = MySqlPlatform::LENGTH_LIMIT_MEDIUMBLOB;
break;
case 'tinyint':
case 'smallint':
case 'mediumint':
......@@ -208,6 +219,7 @@ class MySqlSchemaManager extends AbstractSchemaManager
if (isset($tableColumn['characterset'])) {
$column->setPlatformOption('charset', $tableColumn['characterset']);
}
if (isset($tableColumn['collation'])) {
$column->setPlatformOption('collation', $tableColumn['collation']);
}
......@@ -244,8 +256,10 @@ class MySqlSchemaManager extends AbstractSchemaManager
switch ($columnDefault) {
case 'current_timestamp()':
return $platform->getCurrentTimestampSQL();
case 'curdate()':
return $platform->getCurrentDateSQL();
case 'curtime()':
return $platform->getCurrentTimeSQL();
}
......@@ -265,6 +279,7 @@ class MySqlSchemaManager extends AbstractSchemaManager
if (! isset($value['delete_rule']) || $value['delete_rule'] === 'RESTRICT') {
$value['delete_rule'] = null;
}
if (! isset($value['update_rule']) || $value['update_rule'] === 'RESTRICT') {
$value['update_rule'] = null;
}
......@@ -278,6 +293,7 @@ class MySqlSchemaManager extends AbstractSchemaManager
'onUpdate' => $value['update_rule'],
];
}
$list[$value['constraint_name']]['local'][] = $value['column_name'];
$list[$value['constraint_name']]['foreign'][] = $value['referenced_column_name'];
}
......@@ -299,13 +315,16 @@ class MySqlSchemaManager extends AbstractSchemaManager
return $result;
}
/**
* {@inheritdoc}
*/
public function listTableDetails($tableName)
{
$table = parent::listTableDetails($tableName);
/** @var MySqlPlatform $platform */
$platform = $this->_platform;
$sql = $platform->getListTableMetadataSQL($tableName);
assert($platform instanceof MySqlPlatform);
$sql = $platform->getListTableMetadataSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql);
......
......@@ -7,7 +7,6 @@ use Doctrine\DBAL\Driver\DriverException;
use Doctrine\DBAL\Platforms\OraclePlatform;
use Doctrine\DBAL\Types\Type;
use Throwable;
use const CASE_LOWER;
use function array_change_key_case;
use function array_values;
use function assert;
......@@ -18,6 +17,7 @@ use function strpos;
use function strtolower;
use function strtoupper;
use function trim;
use const CASE_LOWER;
/**
* Oracle Schema Manager.
......@@ -107,6 +107,7 @@ class OracleSchemaManager extends AbstractSchemaManager
$buffer['primary'] = false;
$buffer['non_unique'] = ! $tableIndex['is_unique'];
}
$buffer['key_name'] = $keyName;
$buffer['column_name'] = $this->getQuotedIdentifierName($tableIndex['column_name']);
$indexBuffer[] = $buffer;
......@@ -176,12 +177,14 @@ class OracleSchemaManager extends AbstractSchemaManager
}
break;
case 'varchar':
case 'varchar2':
case 'nvarchar2':
$length = $tableColumn['char_length'];
$fixed = false;
break;
case 'char':
case 'nchar':
$length = $tableColumn['char_length'];
......@@ -392,13 +395,16 @@ SQL;
}
}
/**
* {@inheritdoc}
*/
public function listTableDetails($tableName) : Table
{
$table = parent::listTableDetails($tableName);
/** @var OraclePlatform $platform */
$platform = $this->_platform;
$sql = $platform->getListTableCommentsSQL($tableName);
assert($platform instanceof OraclePlatform);
$sql = $platform->getListTableCommentsSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql);
......
......@@ -7,7 +7,6 @@ use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Types\Types;
use const CASE_LOWER;
use function array_change_key_case;
use function array_filter;
use function array_keys;
......@@ -25,6 +24,7 @@ use function strlen;
use function strpos;
use function strtolower;
use function trim;
use const CASE_LOWER;
/**
* PostgreSQL Schema Manager.
......@@ -141,6 +141,7 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
if (preg_match('(ON UPDATE ([a-zA-Z0-9]+( (NULL|ACTION|DEFAULT))?))', $tableForeignKey['condef'], $match)) {
$onUpdate = $match[1];
}
if (preg_match('(ON DELETE ([a-zA-Z0-9]+( (NULL|ACTION|DEFAULT))?))', $tableForeignKey['condef'], $match)) {
$onDelete = $match[1];
}
......@@ -339,9 +340,11 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
if ($length === '-1' && isset($tableColumn['atttypmod'])) {
$length = $tableColumn['atttypmod'] - 4;
}
if ((int) $length <= 0) {
$length = null;
}
$fixed = null;
if (! isset($tableColumn['name'])) {
......@@ -368,17 +371,20 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
$tableColumn['default'] = $this->fixVersion94NegativeNumericDefaultValue($tableColumn['default']);
$length = null;
break;
case 'int':
case 'int4':
case 'integer':
$tableColumn['default'] = $this->fixVersion94NegativeNumericDefaultValue($tableColumn['default']);
$length = null;
break;
case 'bigint':
case 'int8':
$tableColumn['default'] = $this->fixVersion94NegativeNumericDefaultValue($tableColumn['default']);
$length = null;
break;
case 'bool':
case 'boolean':
if ($tableColumn['default'] === 'true') {
......@@ -391,6 +397,7 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
$length = null;
break;
case 'text':
case '_varchar':
case 'varchar':
......@@ -400,10 +407,12 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
case 'interval':
$fixed = false;
break;
case 'char':
case 'bpchar':
$fixed = true;
break;
case 'float':
case 'float4':
case 'float8':
......@@ -420,7 +429,9 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
$scale = $match[2];
$length = null;
}
break;
case 'year':
$length = null;
break;
......@@ -490,13 +501,16 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
return str_replace("''", "'", $default);
}
/**
* {@inheritdoc}
*/
public function listTableDetails($tableName) : Table
{
$table = parent::listTableDetails($tableName);
/** @var PostgreSqlPlatform $platform */
$platform = $this->_platform;
$sql = $platform->getListTableMetadataSQL($tableName);
assert($platform instanceof PostgreSqlPlatform);
$sql = $platform->getListTableMetadataSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql);
......
......@@ -112,6 +112,7 @@ class SQLAnywhereSchemaManager extends AbstractSchemaManager
case 'char':
case 'nchar':
$fixed = true;
break;
}
switch ($type) {
......@@ -119,6 +120,7 @@ class SQLAnywhereSchemaManager extends AbstractSchemaManager
case 'float':
$precision = $tableColumn['length'];
$scale = $tableColumn['scale'];
break;
}
return new Column(
......
......@@ -87,11 +87,13 @@ class SQLServerSchemaManager extends AbstractSchemaManager
// Unicode data requires 2 bytes per character
$length /= 2;
break;
case 'varchar':
// TEXT type is returned as VARCHAR(MAX) with a length of -1
if ($length === -1) {
$dbType = 'text';
}
break;
}
......@@ -334,9 +336,9 @@ class SQLServerSchemaManager extends AbstractSchemaManager
{
$table = parent::listTableDetails($tableName);
/** @var SQLServerPlatform $platform */
$platform = $this->_platform;
$sql = $platform->getListTableMetadataSQL($tableName);
assert($platform instanceof SQLServerPlatform);
$sql = $platform->getListTableMetadataSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql);
......
......@@ -67,6 +67,7 @@ class Schema extends AbstractAsset
if ($schemaConfig === null) {
$schemaConfig = new SchemaConfig();
}
$this->_schemaConfig = $schemaConfig;
$this->_setName($schemaConfig->getName() ?: 'public');
......@@ -287,7 +288,7 @@ class Schema extends AbstractAsset
*
* @param string $namespaceName The name of the namespace to create.
*
* @return \Doctrine\DBAL\Schema\Schema This schema instance.
* @return Schema This schema instance.
*
* @throws SchemaException
*/
......@@ -329,7 +330,7 @@ class Schema extends AbstractAsset
* @param string $oldTableName
* @param string $newTableName
*
* @return \Doctrine\DBAL\Schema\Schema
* @return Schema
*/
public function renameTable($oldTableName, $newTableName)
{
......@@ -347,7 +348,7 @@ class Schema extends AbstractAsset
*
* @param string $tableName
*
* @return \Doctrine\DBAL\Schema\Schema
* @return Schema
*/
public function dropTable($tableName)
{
......@@ -378,7 +379,7 @@ class Schema extends AbstractAsset
/**
* @param string $sequenceName
*
* @return \Doctrine\DBAL\Schema\Schema
* @return Schema
*/
public function dropSequence($sequenceName)
{
......@@ -468,6 +469,7 @@ class Schema extends AbstractAsset
foreach ($this->_tables as $k => $table) {
$this->_tables[$k] = clone $table;
}
foreach ($this->_sequences as $k => $sequence) {
$this->_sequences[$k] = clone $sequence;
}
......
......@@ -2,6 +2,7 @@
namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\Internal\DependencyOrderCalculator;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use function array_merge;
......@@ -137,13 +138,16 @@ class SchemaDiff
}
$foreignKeySql = [];
foreach ($this->newTables as $table) {
$sql = array_merge(
$sql,
$platform->getCreateTableSQL($table, AbstractPlatform::CREATE_INDEXES)
);
$createFlags = AbstractPlatform::CREATE_INDEXES;
if (! $platform->supportsCreateDropForeignKeyConstraints()) {
$createFlags |= AbstractPlatform::CREATE_FOREIGNKEYS;
}
if (! $platform->supportsForeignKeyConstraints()) {
foreach ($this->getNewTablesSortedByDependencies() as $table) {
$sql = array_merge($sql, $platform->getCreateTableSQL($table, $createFlags));
if (! $platform->supportsCreateDropForeignKeyConstraints()) {
continue;
}
......@@ -151,6 +155,7 @@ class SchemaDiff
$foreignKeySql[] = $platform->getCreateForeignKeySQL($foreignKey, $table);
}
}
$sql = array_merge($sql, $foreignKeySql);
if ($saveMode === false) {
......@@ -165,4 +170,37 @@ class SchemaDiff
return $sql;
}
/**
* Sorts tables by dependencies so that they are created in the right order.
*
* This is necessary when one table depends on another while creating foreign key
* constraints directly during CREATE TABLE.
*
* @return array<Table>
*/
private function getNewTablesSortedByDependencies()
{
$calculator = new DependencyOrderCalculator();
$newTables = [];
foreach ($this->newTables as $table) {
$newTables[$table->getName()] = true;
$calculator->addNode($table->getName(), $table);
}
foreach ($this->newTables as $table) {
foreach ($table->getForeignKeys() as $foreignKey) {
$foreignTableName = $foreignKey->getForeignTableName();
if (! isset($newTables[$foreignTableName])) {
continue;
}
$calculator->addDependency($foreignTableName, $table->getName());
}
}
return $calculator->sort();
}
}
......@@ -26,7 +26,7 @@ class SchemaException extends DBALException
/**
* @param string $tableName
*
* @return \Doctrine\DBAL\Schema\SchemaException
* @return SchemaException
*/
public static function tableDoesNotExist($tableName)
{
......@@ -36,7 +36,7 @@ class SchemaException extends DBALException
/**
* @param string $indexName
*
* @return \Doctrine\DBAL\Schema\SchemaException
* @return SchemaException
*/
public static function indexNameInvalid($indexName)
{
......@@ -50,7 +50,7 @@ class SchemaException extends DBALException
* @param string $indexName
* @param string $table
*
* @return \Doctrine\DBAL\Schema\SchemaException
* @return SchemaException
*/
public static function indexDoesNotExist($indexName, $table)
{
......@@ -64,7 +64,7 @@ class SchemaException extends DBALException
* @param string $indexName
* @param string $table
*
* @return \Doctrine\DBAL\Schema\SchemaException
* @return SchemaException
*/
public static function indexAlreadyExists($indexName, $table)
{
......@@ -78,7 +78,7 @@ class SchemaException extends DBALException
* @param string $columnName
* @param string $table
*
* @return \Doctrine\DBAL\Schema\SchemaException
* @return SchemaException
*/
public static function columnDoesNotExist($columnName, $table)
{
......@@ -91,7 +91,7 @@ class SchemaException extends DBALException
/**
* @param string $namespaceName
*
* @return \Doctrine\DBAL\Schema\SchemaException
* @return SchemaException
*/
public static function namespaceAlreadyExists($namespaceName)
{
......@@ -104,7 +104,7 @@ class SchemaException extends DBALException
/**
* @param string $tableName
*
* @return \Doctrine\DBAL\Schema\SchemaException
* @return SchemaException
*/
public static function tableAlreadyExists($tableName)
{
......@@ -115,7 +115,7 @@ class SchemaException extends DBALException
* @param string $tableName
* @param string $columnName
*
* @return \Doctrine\DBAL\Schema\SchemaException
* @return SchemaException
*/
public static function columnAlreadyExists($tableName, $columnName)
{
......@@ -128,7 +128,7 @@ class SchemaException extends DBALException
/**
* @param string $sequenceName
*
* @return \Doctrine\DBAL\Schema\SchemaException
* @return SchemaException
*/
public static function sequenceAlreadyExists($sequenceName)
{
......@@ -138,7 +138,7 @@ class SchemaException extends DBALException
/**
* @param string $sequenceName
*
* @return \Doctrine\DBAL\Schema\SchemaException
* @return SchemaException
*/
public static function sequenceDoesNotExist($sequenceName)
{
......@@ -149,7 +149,7 @@ class SchemaException extends DBALException
* @param string $fkName
* @param string $table
*
* @return \Doctrine\DBAL\Schema\SchemaException
* @return SchemaException
*/
public static function foreignKeyDoesNotExist($fkName, $table)
{
......@@ -160,7 +160,7 @@ class SchemaException extends DBALException
}
/**
* @return \Doctrine\DBAL\Schema\SchemaException
* @return SchemaException
*/
public static function namedForeignKeyRequired(Table $localTable, ForeignKeyConstraint $foreignKey)
{
......@@ -175,7 +175,7 @@ class SchemaException extends DBALException
/**
* @param string $changeName
*
* @return \Doctrine\DBAL\Schema\SchemaException
* @return SchemaException
*/
public static function alterTableChangeNotSupported($changeName)
{
......
......@@ -61,7 +61,7 @@ class Sequence extends AbstractAsset
/**
* @param int $allocationSize
*
* @return \Doctrine\DBAL\Schema\Sequence
* @return Sequence
*/
public function setAllocationSize($allocationSize)
{
......@@ -73,7 +73,7 @@ class Sequence extends AbstractAsset
/**
* @param int $initialValue
*
* @return \Doctrine\DBAL\Schema\Sequence
* @return Sequence
*/
public function setInitialValue($initialValue)
{
......@@ -85,7 +85,7 @@ class Sequence extends AbstractAsset
/**
* @param int $cache
*
* @return \Doctrine\DBAL\Schema\Sequence
* @return Sequence
*/
public function setCache($cache)
{
......
......@@ -8,7 +8,6 @@ use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\Types\StringType;
use Doctrine\DBAL\Types\TextType;
use Doctrine\DBAL\Types\Type;
use const CASE_LOWER;
use function array_change_key_case;
use function array_map;
use function array_reverse;
......@@ -27,6 +26,7 @@ use function strtolower;
use function trim;
use function unlink;
use function usort;
use const CASE_LOWER;
/**
* Sqlite SchemaManager.
......@@ -113,6 +113,7 @@ class SqliteSchemaManager extends AbstractSchemaManager
if ($database === null) {
$database = $this->_conn->getDatabase();
}
$sql = $this->_platform->getListTableForeignKeysSQL($table, $database);
$tableForeignKeys = $this->_conn->fetchAll($sql);
......@@ -358,8 +359,10 @@ class SqliteSchemaManager extends AbstractSchemaManager
if (strpos($tableColumn['length'], ',') === false) {
$tableColumn['length'] .= ',0';
}
[$precision, $scale] = array_map('trim', explode(',', $tableColumn['length']));
}
$length = null;
break;
}
......@@ -399,6 +402,7 @@ class SqliteSchemaManager extends AbstractSchemaManager
if (! isset($value['on_delete']) || $value['on_delete'] === 'RESTRICT') {
$value['on_delete'] = null;
}
if (! isset($value['on_update']) || $value['on_update'] === 'RESTRICT') {
$value['on_update'] = null;
}
......@@ -414,6 +418,7 @@ class SqliteSchemaManager extends AbstractSchemaManager
'deferred'=> $value['deferred'],
];
}
$list[$name]['local'][] = $value['from'];
$list[$name]['foreign'][] = $value['to'];
}
......
......@@ -5,13 +5,13 @@ namespace Doctrine\DBAL\Schema;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Schema\Visitor\Visitor;
use Doctrine\DBAL\Types\Type;
use const ARRAY_FILTER_USE_KEY;
use function array_filter;
use function array_merge;
use function in_array;
use function preg_match;
use function strlen;
use function strtolower;
use const ARRAY_FILTER_USE_KEY;
/**
* Object Representation of a table.
......@@ -161,6 +161,7 @@ class Table extends AbstractAsset
if (! $this->hasIndex($indexName)) {
throw SchemaException::indexDoesNotExist($indexName, $this->_name);
}
unset($this->_indexes[$indexName]);
}
......@@ -240,7 +241,6 @@ class Table extends AbstractAsset
public function columnsAreIndexed(array $columnNames)
{
foreach ($this->getIndexes() as $index) {
/** @var $index Index */
if ($index->spansColumns($columnNames)) {
return true;
}
......@@ -510,6 +510,7 @@ class Table extends AbstractAsset
$this->_getMaxIdentifierLength()
);
}
$name = $this->normalizeIdentifier($name);
$this->_fkConstraints[$name] = $constraint;
......@@ -816,9 +817,11 @@ class Table extends AbstractAsset
foreach ($this->_columns as $k => $column) {
$this->_columns[$k] = clone $column;
}
foreach ($this->_indexes as $k => $index) {
$this->_indexes[$k] = clone $index;
}
foreach ($this->_fkConstraints as $k => $fk) {
$this->_fkConstraints[$k] = clone $fk;
$this->_fkConstraints[$k]->setLocalTable($this);
......
......@@ -8,6 +8,7 @@ use Doctrine\DBAL\Schema\SchemaException;
use Doctrine\DBAL\Schema\Sequence;
use Doctrine\DBAL\Schema\Table;
use SplObjectStorage;
use function assert;
use function strlen;
/**
......@@ -46,6 +47,10 @@ class DropSchemaSqlCollector extends AbstractVisitor
*/
public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint)
{
if (! $this->platform->supportsCreateDropForeignKeyConstraints()) {
return;
}
if (strlen($fkConstraint->getName()) === 0) {
throw SchemaException::namedForeignKeyRequired($localTable, $fkConstraint);
}
......@@ -78,19 +83,19 @@ class DropSchemaSqlCollector extends AbstractVisitor
{
$sql = [];
/** @var ForeignKeyConstraint $fkConstraint */
foreach ($this->constraints as $fkConstraint) {
assert($fkConstraint instanceof ForeignKeyConstraint);
$localTable = $this->constraints[$fkConstraint];
$sql[] = $this->platform->getDropForeignKeySQL($fkConstraint, $localTable);
}
/** @var Sequence $sequence */
foreach ($this->sequences as $sequence) {
assert($sequence instanceof Sequence);
$sql[] = $this->platform->getDropSequenceSQL($sequence);
}
/** @var Table $table */
foreach ($this->tables as $table) {
assert($table instanceof Table);
$sql[] = $this->platform->getDropTableSQL($table);
}
......
......@@ -87,6 +87,7 @@ class Graphviz extends AbstractVisitor
if ($primaryKey !== null && in_array($column->getName(), $primaryKey->getColumns())) {
$label .= "\xe2\x9c\xb7";
}
$label .= '</TD></TR>';
}
......@@ -108,6 +109,7 @@ class Graphviz extends AbstractVisitor
foreach ($options as $key => $value) {
$node .= $key . '=' . $value . ' ';
}
$node .= "]\n";
return $node;
......@@ -126,6 +128,7 @@ class Graphviz extends AbstractVisitor
foreach ($options as $key => $value) {
$relation .= $key . '=' . $value . ' ';
}
$relation .= "]\n";
return $relation;
......
......@@ -110,6 +110,7 @@ class MultiTenantVisitor implements Visitor
return $index;
}
}
throw new RuntimeException('No clustered index found on table ' . $table->getName());
}
......
......@@ -14,7 +14,7 @@ use Doctrine\DBAL\DBALException;
class ShardingException extends DBALException
{
/**
* @return \Doctrine\DBAL\Sharding\ShardingException
* @return ShardingException
*/
public static function notImplemented()
{
......@@ -22,7 +22,7 @@ class ShardingException extends DBALException
}
/**
* @return \Doctrine\DBAL\Sharding\ShardingException
* @return ShardingException
*/
public static function missingDefaultFederationName()
{
......@@ -30,7 +30,7 @@ class ShardingException extends DBALException
}
/**
* @return \Doctrine\DBAL\Sharding\ShardingException
* @return ShardingException
*/
public static function missingDefaultDistributionKey()
{
......@@ -38,7 +38,7 @@ class ShardingException extends DBALException
}
/**
* @return \Doctrine\DBAL\Sharding\ShardingException
* @return ShardingException
*/
public static function activeTransaction()
{
......@@ -46,7 +46,7 @@ class ShardingException extends DBALException
}
/**
* @return \Doctrine\DBAL\Sharding\ShardingException
* @return ShardingException
*/
public static function noShardDistributionValue()
{
......@@ -54,7 +54,7 @@ class ShardingException extends DBALException
}
/**
* @return \Doctrine\DBAL\Sharding\ShardingException
* @return ShardingException
*/
public static function missingDistributionType()
{
......
......@@ -95,6 +95,7 @@ class Statement implements IteratorAggregate, DriverStatement
if (is_string($type)) {
$type = Type::getType($type);
}
if ($type instanceof Type) {
$value = $type->convertToDatabaseValue($value, $this->platform);
$bindingType = $type->getBindingType();
......@@ -155,6 +156,7 @@ class Statement implements IteratorAggregate, DriverStatement
if ($logger) {
$logger->stopQuery();
}
throw DBALException::driverExceptionDuringQuery(
$this->conn->getDriver(),
$ex,
......@@ -166,6 +168,7 @@ class Statement implements IteratorAggregate, DriverStatement
if ($logger) {
$logger->stopQuery();
}
$this->params = [];
$this->types = [];
......
......@@ -11,7 +11,6 @@ use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use const PHP_EOL;
use function assert;
use function error_get_last;
use function file_exists;
......@@ -19,6 +18,7 @@ use function file_get_contents;
use function is_readable;
use function realpath;
use function sprintf;
use const PHP_EOL;
/**
* Task for executing arbitrary SQL that can come from a file or directly from
......
......@@ -27,6 +27,7 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use function array_keys;
use function assert;
use function count;
use function implode;
......@@ -120,8 +121,8 @@ EOT
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
/** @var Connection $conn */
$conn = $this->getHelper('db')->getConnection();
assert($conn instanceof Connection);
$keywordLists = (array) $input->getOption('list');
if (! $keywordLists) {
......@@ -152,6 +153,7 @@ EOT
'Known lists: ' . implode(', ', array_keys($this->keywordListClasses))
);
}
$class = $this->keywordListClasses[$keywordList];
$keywords[] = new $class();
}
......
......@@ -150,6 +150,7 @@ final class Dumper
if ($aux[0] === '') {
$name .= ':' . ($aux[1] === '*' ? 'protected' : $aux[1] . ':private');
}
$return->$name = self::export($clone[$key], $maxDepth - 1);
}
......
......@@ -26,7 +26,7 @@ class ConversionException extends DBALException
* @param string $value
* @param string $toType
*
* @return \Doctrine\DBAL\Types\ConversionException
* @return ConversionException
*/
public static function conversionFailed($value, $toType, ?Throwable $previous = null)
{
......@@ -43,7 +43,7 @@ class ConversionException extends DBALException
* @param string $toType
* @param string $expectedFormat
*
* @return \Doctrine\DBAL\Types\ConversionException
* @return ConversionException
*/
public static function conversionFailedFormat($value, $toType, $expectedFormat, ?Throwable $previous = null)
{
......@@ -64,7 +64,7 @@ class ConversionException extends DBALException
* @param string $toType
* @param string[] $possibleTypes
*
* @return \Doctrine\DBAL\Types\ConversionException
* @return ConversionException
*/
public static function conversionFailedInvalidType(
$value,
......
......@@ -3,13 +3,13 @@
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use const JSON_ERROR_NONE;
use function is_resource;
use function json_decode;
use function json_encode;
use function json_last_error;
use function json_last_error_msg;
use function stream_get_contents;
use const JSON_ERROR_NONE;
/**
* Type generating json objects values
......
......@@ -222,7 +222,7 @@ abstract class Type
*
* @param string $name The name of the type (as returned by getName()).
*
* @return \Doctrine\DBAL\Types\Type
* @return Type
*
* @throws DBALException
*/
......
<?xml version="1.0"?>
<ruleset>
<ruleset
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd"
>
<arg name="basepath" value="."/>
<arg name="extensions" value="php"/>
<arg name="parallel" value="80"/>
......@@ -17,15 +20,32 @@
<exclude name="SlevomatCodingStandard.TypeHints.DeclareStrictTypes"/>
<exclude name="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming"/>
<exclude name="SlevomatCodingStandard.Classes.SuperfluousExceptionNaming"/>
<exclude name="SlevomatCodingStandard.ControlStructures.ControlStructureSpacing.IncorrectLinesCountAfterLastControlStructure"/>
<exclude name="SlevomatCodingStandard.Classes.DisallowLateStaticBindingForConstants.DisallowedLateStaticBindingForConstant"/>
<exclude name="SlevomatCodingStandard.ControlStructures.ControlStructureSpacing.IncorrectLinesCountAfterLastControlStructure"/>
<!-- https://github.com/slevomat/coding-standard/issues/867 -->
<exclude name="SlevomatCodingStandard.ControlStructures.JumpStatementsSpacing.IncorrectLinesCountAfterLastControlStructure"/>
<!-- See https://github.com/squizlabs/PHP_CodeSniffer/issues/2937 -->
<exclude name="Squiz.Arrays.ArrayDeclaration.ValueNoNewline"/>
<exclude name="Squiz.NamingConventions.ValidVariableName.PublicHasUnderscore"/>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint">
<!-- Disable the rules that will require PHP 7.4 -->
<rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint">
<properties>
<property name="enableNativeTypeHint" value="false"/>
</properties>
</rule>
<rule ref="Squiz.NamingConventions.ValidVariableName.PublicHasUnderscore">
<exclude-pattern>*/lib/*</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingReturnTypeHint">
<rule ref="SlevomatCodingStandard.TypeHints.ParameterTypeHint.MissingNativeTypeHint">
<exclude-pattern>*/lib/*</exclude-pattern>
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingNativeTypeHint">
<exclude-pattern>*/lib/*</exclude-pattern>
</rule>
......@@ -45,6 +65,11 @@
<exclude-pattern>tests/Doctrine/Tests/DBAL/Tools/TestAsset/*</exclude-pattern>
</rule>
<!-- https://github.com/slevomat/coding-standard/issues/868 -->
<rule ref="SlevomatCodingStandard.PHP.UselessParentheses.UselessParentheses">
<exclude-pattern>tests/continuousphp/bootstrap.php</exclude-pattern>
</rule>
<!-- see https://github.com/squizlabs/PHP_CodeSniffer/issues/2099 -->
<rule ref="Squiz.Commenting.FunctionComment.InvalidNoReturn">
<exclude-pattern>lib/Doctrine/DBAL/Platforms/AbstractPlatform.php</exclude-pattern>
......@@ -52,6 +77,31 @@
<exclude-pattern>tests/Doctrine/Tests/DBAL/Platforms/AbstractPlatformTestCase.php</exclude-pattern>
</rule>
<!-- see https://github.com/squizlabs/PHP_CodeSniffer/issues/2838 -->
<rule ref="Squiz.Commenting.FunctionComment.SpacingAfter">
<exclude-pattern>lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php</exclude-pattern>
</rule>
<rule ref="Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps">
<!-- This test contains a fixture class that should use snake case -->
<exclude-pattern>tests/Doctrine/Tests/DBAL/Functional/DataAccessTest.php</exclude-pattern>
</rule>
<!-- https://github.com/squizlabs/PHP_CodeSniffer/issues/2837 -->
<rule ref="Squiz.NamingConventions.ValidVariableName.NotCamelCaps">
<!--
This file uses the return value db2_server_info(), which does not follow conventions
phpcs wrongly complains about it, and that has been reported here:
https://github.com/squizlabs/PHP_CodeSniffer/issues/2950
-->
<exclude-pattern>lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php</exclude-pattern>
<!-- See https://github.com/squizlabs/PHP_CodeSniffer/issues/2837 -->
<exclude-pattern>lib/Doctrine/DBAL/SQLParserUtils.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/DBAL/Tools/Dumper.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/DBAL/Driver/StatementIteratorTest.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/DBAL/Tools/DumperTest.php</exclude-pattern>
</rule>
<!-- some statement classes close cursor using an empty while-loop -->
<rule ref="Generic.CodeAnalysis.EmptyStatement.DetectedWhile">
<exclude-pattern>lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php</exclude-pattern>
......@@ -62,21 +112,20 @@
<exclude-pattern>lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php</exclude-pattern>
</rule>
<!-- see https://github.com/squizlabs/PHP_CodeSniffer/issues/2165 -->
<rule ref="Squiz.Arrays.ArrayDeclaration.SpaceBeforeComma">
<exclude-pattern>tests/Doctrine/Tests/DBAL/Platforms/OraclePlatformTest.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/DBAL/SQLParserUtilsTest.php</exclude-pattern>
</rule>
<!-- see https://github.com/doctrine/dbal/issues/3377 -->
<rule ref="SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedNotEqualOperator">
<exclude-pattern>lib/Doctrine/DBAL/Schema/Comparator.php</exclude-pattern>
</rule>
<!-- see https://github.com/slevomat/coding-standard/issues/737 -->
<rule ref="SlevomatCodingStandard.TypeHints.TypeHintDeclaration.IncorrectReturnTypeHint">
<exclude-pattern>lib/Doctrine/DBAL/Types/ArrayType.php</exclude-pattern>
<exclude-pattern>lib/Doctrine/DBAL/Types/ObjectType.php</exclude-pattern>
<exclude-pattern>tests/Doctrine/Tests/DBAL/Driver/Mysqli/MysqliConnectionTest.php</exclude-pattern>
<!-- DB2_AUTOCOMMIT_ON/DB2_AUTOCOMMIT_OFF are of int type but db2_autocommit() incorrectly expects bool,
see https://bugs.php.net/bug.php?id=77591 -->
<rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing">
<exclude-pattern>lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php</exclude-pattern>
</rule>
<!-- The SQLSRV_* functions are defined in the upper case by the sqlsrv extension and violate the standard
see https://docs.microsoft.com/en-us/sql/connect/php/constants-microsoft-drivers-for-php-for-sql-server -->
<rule ref="Squiz.PHP.LowercasePHPFunctions.UseStatementUppercase">
<exclude-pattern>lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php</exclude-pattern>
</rule>
</ruleset>
......@@ -72,3 +72,14 @@ parameters:
-
message: '~^Cannot cast array<string>\|bool\|string\|null to int\.$~'
path: %currentWorkingDirectory%/lib/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php
# Requires a release of https://github.com/JetBrains/phpstorm-stubs/pull/732
-
message: '~^Access to undefined constant PDO::PGSQL_ATTR_DISABLE_PREPARES\.$~'
path: %currentWorkingDirectory%/lib/Doctrine/DBAL/Driver/PDOPgSql/Driver.php
# False Positive
- '~Strict comparison using === between 1 and 2 will always evaluate to false~'
# Needs Generics
- '~Method Doctrine\\DBAL\\Schema\\SchemaDiff::getNewTablesSortedByDependencies\(\) should return array<Doctrine\\DBAL\\Schema\\Table> but returns array<object>.~'
......@@ -17,9 +17,6 @@ class ConfigurationTest extends DbalTestCase
*/
protected $config;
/**
* {@inheritdoc}
*/
protected function setUp() : void
{
$this->config = new Configuration();
......
......@@ -165,13 +165,11 @@ class ConnectionTest extends DbalTestCase
{
$eventManager = new EventManager();
/** @var AbstractPlatform|MockObject $driver */
$platform = $this->createMock(AbstractPlatform::class);
$platform->expects($this->once())
->method('setEventManager')
->with($eventManager);
/** @var Driver|MockObject $driver */
$driver = $this->createMock(Driver::class);
$driver->expects($this->any())
->method('getDatabasePlatform')
......@@ -564,7 +562,6 @@ class ConnectionTest extends DbalTestCase
->with(FetchMode::ASSOCIATIVE)
->will($this->returnValue($result));
/** @var Connection|MockObject $conn */
$conn = $this->getMockBuilder(Connection::class)
->onlyMethods(['executeQuery'])
->setConstructorArgs([[], $driverMock])
......@@ -600,7 +597,6 @@ class ConnectionTest extends DbalTestCase
->with(FetchMode::NUMERIC)
->will($this->returnValue($result));
/** @var Connection|MockObject $conn */
$conn = $this->getMockBuilder(Connection::class)
->onlyMethods(['executeQuery'])
->setConstructorArgs([[], $driverMock])
......@@ -637,7 +633,6 @@ class ConnectionTest extends DbalTestCase
->with($column)
->will($this->returnValue($result));
/** @var Connection|MockObject $conn */
$conn = $this->getMockBuilder(Connection::class)
->onlyMethods(['executeQuery'])
->setConstructorArgs([[], $driverMock])
......@@ -672,7 +667,6 @@ class ConnectionTest extends DbalTestCase
->method('fetchAll')
->will($this->returnValue($result));
/** @var Connection|MockObject $conn */
$conn = $this->getMockBuilder(Connection::class)
->onlyMethods(['executeQuery'])
->setConstructorArgs([[], $driverMock])
......@@ -710,7 +704,6 @@ class ConnectionTest extends DbalTestCase
public function testCallingDeleteWithNoDeletionCriteriaResultsInInvalidArgumentException() : void
{
/** @var Driver $driver */
$driver = $this->createMock(Driver::class);
$pdoMock = $this->createMock(\Doctrine\DBAL\Driver\Connection::class);
......@@ -769,13 +762,10 @@ class ConnectionTest extends DbalTestCase
*/
public function testPlatformDetectionIsTriggerOnlyOnceOnRetrievingPlatform() : void
{
/** @var Driver|VersionAwarePlatformDriver|MockObject $driverMock */
$driverMock = $this->createMock([Driver::class, VersionAwarePlatformDriver::class]);
/** @var ServerInfoAwareConnection|MockObject $driverConnectionMock */
$driverConnectionMock = $this->createMock(ServerInfoAwareConnection::class);
/** @var AbstractPlatform|MockObject $platformMock */
$platformMock = $this->getMockForAbstractClass(AbstractPlatform::class);
$connection = new Connection([], $driverMock);
......@@ -814,7 +804,6 @@ class ConnectionTest extends DbalTestCase
$params = [666];
$types = [ParameterType::INTEGER];
/** @var QueryCacheProfile|MockObject $queryCacheProfileMock */
$queryCacheProfileMock = $this->createMock(QueryCacheProfile::class);
$queryCacheProfileMock
......@@ -829,7 +818,6 @@ class ConnectionTest extends DbalTestCase
->with($query, $params, $types, $this->params)
->will($this->returnValue(['cacheKey', 'realKey']));
/** @var Driver $driver */
$driver = $this->createMock(Driver::class);
self::assertInstanceOf(
......@@ -851,7 +839,6 @@ class ConnectionTest extends DbalTestCase
->with('cacheKey')
->will($this->returnValue(['realKey' => []]));
/** @var QueryCacheProfile|MockObject $queryCacheProfileMock */
$queryCacheProfileMock = $this->createMock(QueryCacheProfile::class);
$queryCacheProfileMock
......@@ -871,7 +858,6 @@ class ConnectionTest extends DbalTestCase
$connectionParams['platform'] = $this->createMock(AbstractPlatform::class);
/** @var Driver $driver */
$driver = $this->createMock(Driver::class);
(new Connection($connectionParams, $driver))->executeCacheQuery($query, [], [], $queryCacheProfileMock);
......@@ -885,7 +871,6 @@ class ConnectionTest extends DbalTestCase
$connectionParams = $this->params;
$connectionParams['platform'] = new stdClass();
/** @var Driver $driver */
$driver = $this->createMock(Driver::class);
$this->expectException(DBALException::class);
......@@ -898,7 +883,6 @@ class ConnectionTest extends DbalTestCase
*/
public function testRethrowsOriginalExceptionOnDeterminingPlatformWhenConnectingToNonExistentDatabase() : void
{
/** @var Driver|VersionAwarePlatformDriver|MockObject $driverMock */
$driverMock = $this->createMock([Driver::class, VersionAwarePlatformDriver::class]);
$connection = new Connection(['dbname' => 'foo'], $driverMock);
......@@ -923,16 +907,12 @@ class ConnectionTest extends DbalTestCase
*/
public function testExecuteCacheQueryStripsPlatformFromConnectionParamsBeforeGeneratingCacheKeys() : void
{
/** @var Driver|MockObject $driver */
$driver = $this->createMock(Driver::class);
/** @var AbstractPlatform|MockObject $platform */
$platform = $this->createMock(AbstractPlatform::class);
/** @var QueryCacheProfile|MockObject $queryCacheProfile */
$queryCacheProfile = $this->createMock(QueryCacheProfile::class);
/** @var Cache|MockObject $resultCacheDriver */
$resultCacheDriver = $this->createMock(Cache::class);
$queryCacheProfile
......
......@@ -17,7 +17,6 @@ class DBALExceptionTest extends DbalTestCase
{
public function testDriverExceptionDuringQueryAcceptsBinaryData() : void
{
/** @var Driver $driver */
$driver = $this->createMock(Driver::class);
$e = DBALException::driverExceptionDuringQuery($driver, new Exception(), '', ['ABC', chr(128)]);
self::assertStringContainsString('with params ["ABC", "\x80"]', $e->getMessage());
......@@ -25,7 +24,6 @@ class DBALExceptionTest extends DbalTestCase
public function testDriverExceptionDuringQueryAcceptsResource() : void
{
/** @var Driver $driver */
$driver = $this->createMock(Driver::class);
$e = DBALException::driverExceptionDuringQuery($driver, new Exception(), 'INSERT INTO file (`content`) VALUES (?)', [1 => fopen(__FILE__, 'r')]);
self::assertStringContainsString('Resource', $e->getMessage());
......@@ -33,10 +31,8 @@ class DBALExceptionTest extends DbalTestCase
public function testAvoidOverWrappingOnDriverException() : void
{
/** @var Driver $driver */
$driver = $this->createMock(Driver::class);
/** @var InnerDriverException $inner */
$inner = $this->createMock(InnerDriverException::class);
$ex = new DriverException('', $inner);
......
......@@ -28,7 +28,6 @@ use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\VersionAwarePlatformDriver;
use Doctrine\Tests\DbalTestCase;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionProperty;
use function array_merge;
use function get_class;
......@@ -79,7 +78,6 @@ abstract class AbstractDriverTest extends DbalTestCase
$this->markTestSkipped('This test is only intended for exception converter drivers.');
}
/** @var DriverExceptionInterface|MockObject $driverException */
$driverException = $this->getMockBuilder(DriverExceptionInterface::class)
->setConstructorArgs([$message])
->getMock();
......
This diff is collapsed.
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