Unverified Commit 8be6d163 authored by Sergei Morozov's avatar Sergei Morozov

Merge branch '2.11.x' into 3.0.x

parents 61629103 239d3fb0
/.appveyor.yml export-ignore
/composer.lock export-ignore
/docs export-ignore
/.doctrine-project.json export-ignore
/.gitattributes export-ignore
/.github export-ignore
/.gitignore export-ignore
/.scrutinizer.yml export-ignore
/.travis.yml export-ignore
/build.properties export-ignore
/build.xml export-ignore
/composer.lock export-ignore
/docs export-ignore
/phpcs.xml.dist export-ignore
/phpstan.neon.dist export-ignore
/phpunit.xml.dist export-ignore
/run-all.sh export-ignore
/.scrutinizer.yml export-ignore
/SECURITY.md export-ignore
/tests export-ignore
/.travis.yml export-ignore
/UPGRADE.md export-ignore
This diff is collapsed.
......@@ -5,6 +5,8 @@ parameters:
autoload_files:
- %currentWorkingDirectory%/tests/phpstan-polyfill.php
reportUnmatchedIgnoredErrors: false
checkMissingIterableValueType: false
checkGenericClassInNonGenericObjectType: false
ignoreErrors:
# extension not available
- '~^(Used )?(Function|Constant) sasql_\S+ not found\.\z~i'
......@@ -23,7 +25,6 @@ parameters:
- '~^Property Doctrine\\DBAL\\Schema\\Schema::\$_schemaConfig \(Doctrine\\DBAL\\Schema\\SchemaConfig\) does not accept default value of type false\.\z~'
- '~^Method Doctrine\\DBAL\\Schema\\ForeignKeyConstraint::onEvent\(\) should return string\|null but returns false\.\z~'
- '~^Method Doctrine\\DBAL\\Schema\\(Oracle|PostgreSql|SQLServer)SchemaManager::_getPortableTableDefinition\(\) should return array but returns string\.\z~'
- '~^Method Doctrine\\DBAL\\Platforms\\(|SQLAnywhere16|Sqlite)Platform::_getTransactionIsolationLevelSQL\(\) should return string but returns int\.\z~'
- '~^Method Doctrine\\DBAL\\Driver\\OCI8\\OCI8Connection::lastInsertId\(\) should return string but returns (int|false)\.\z~'
- '~^Method Doctrine\\DBAL\\Driver\\SQLSrv\\SQLSrvConnection::errorCode\(\) should return string\|null but returns false\.\z~'
......@@ -31,11 +32,11 @@ parameters:
- '~^Call to an undefined method PDO::sqliteCreateFunction\(\)\.\z~'
# https://github.com/phpstan/phpstan/issues/1847
- '~^Parameter #2 \$registeredAliases of static method Doctrine\\DBAL\\Query\\QueryException::unknownAlias\(\) expects array<string>, array<int, int|string> given\.\z~'
- '~^Parameter #2 \$registeredAliases of static method Doctrine\\DBAL\\Query\\QueryException::nonUniqueAlias\(\) expects array<string>, array<int, int|string> given\.\z~'
- '~^Parameter #2 \$registeredAliases of static method Doctrine\\DBAL\\Query\\QueryException::unknownAlias\(\) expects array<string>, array<int, int\|string> given\.\z~'
- '~^Parameter #2 \$registeredAliases of static method Doctrine\\DBAL\\Query\\QueryException::nonUniqueAlias\(\) expects array<string>, array<int, int\|string> given\.\z~'
# PHPStan is too strict about preg_replace(): https://phpstan.org/r/993dc99f-0d43-4b51-868b-d01f982c1463
- '~^Method Doctrine\\DBAL\\Platforms\\AbstractPlatform::escapeStringForLike\(\) should return string but returns string|null\.\z~'
- '~^Method Doctrine\\DBAL\\Platforms\\AbstractPlatform::escapeStringForLike\(\) should return string but returns string\|null\.\z~'
# legacy variadic-like signature
- '~^Method Doctrine\\DBAL(\\.*)?Connection::query\(\) invoked with \d+ parameters?, 0 required\.\z~'
......@@ -55,3 +56,19 @@ parameters:
# weird class name, represented in stubs as OCI_(Lob|Collection)
- '~unknown class OCI-(Lob|Collection)~'
# https://github.com/JetBrains/phpstorm-stubs/pull/766
- '~^Method Doctrine\\DBAL\\Driver\\Mysqli\\MysqliStatement::_fetch\(\) never returns null so it can be removed from the return typehint\.$~'
# The ReflectionException in the case when the class does not exist is acceptable and does not need to be handled
- '~^Parameter #1 \$argument of class ReflectionClass constructor expects class-string<T of object>\|T of object, string given\.$~'
# https://github.com/phpstan/phpstan/issues/3132
-
message: '~^Call to function in_array\(\) with arguments Doctrine\\DBAL\\Schema\\Column, array<string> and true will always evaluate to false\.$~'
path: %currentWorkingDirectory%/src/Schema/Table.php
# https://github.com/phpstan/phpstan/issues/3133
-
message: '~^Cannot cast array<string>\|bool\|string\|null to int\.$~'
path: %currentWorkingDirectory%/src/Tools/Console/Command/RunSqlCommand.php
......@@ -44,11 +44,7 @@
<testsuites>
<testsuite name="Doctrine DBAL Test Suite">
<directory>./tests</directory>
<exclude>./tests/Performance</exclude>
</testsuite>
<testsuite name="Doctrine DBAL Performance Test Suite">
<directory>./tests/Performance</directory>
<directory>tests</directory>
</testsuite>
</testsuites>
......@@ -57,14 +53,4 @@
<directory suffix=".php">src</directory>
</whitelist>
</filter>
<listeners>
<listener class="Doctrine\DBAL\Tests\PerformanceTestListener"/>
</listeners>
<groups>
<exclude>
<group>performance</group>
</exclude>
</groups>
</phpunit>
......@@ -45,6 +45,8 @@ class ArrayStatement implements IteratorAggregate, ResultStatement
public function closeCursor()
{
unset($this->data);
return true;
}
/**
......
......@@ -140,6 +140,8 @@ class Configuration
* @see getAutoCommit
*
* @param bool $autoCommit True to enable auto-commit mode; false to disable it.
*
* @return void
*/
public function setAutoCommit($autoCommit)
{
......
......@@ -376,7 +376,7 @@ class Connection implements DriverConnection
*
* @throws DBALException If an invalid platform was specified for this connection.
*/
private function detectDatabasePlatform()
private function detectDatabasePlatform() : void
{
$version = $this->getDatabasePlatformVersion();
......@@ -497,6 +497,8 @@ class Connection implements DriverConnection
* @see isAutoCommit
*
* @param bool $autoCommit True to enable auto-commit mode; false to disable it.
*
* @return void
*/
public function setAutoCommit($autoCommit)
{
......@@ -1291,7 +1293,7 @@ class Connection implements DriverConnection
/**
* Commits all current nesting transactions.
*/
private function commitAll()
private function commitAll() : void
{
while ($this->transactionNestingLevel !== 0) {
if ($this->autoCommit === false && $this->transactionNestingLevel === 1) {
......@@ -1309,6 +1311,8 @@ class Connection implements DriverConnection
/**
* Cancels any database changes done during the current transaction.
*
* @return bool
*
* @throws ConnectionException If the rollback operation failed.
*/
public function rollBack()
......@@ -1348,6 +1352,8 @@ class Connection implements DriverConnection
$this->isRollbackOnly = true;
--$this->transactionNestingLevel;
}
return true;
}
/**
......
......@@ -121,7 +121,9 @@ class MasterSlaveConnection extends Connection
}
/**
* {@inheritDoc}
* @param string|null $connectionName
*
* @return bool
*/
public function connect($connectionName = null)
{
......
......@@ -157,7 +157,7 @@ class DBALException extends Exception
/**
* @return self
*/
private static function wrapException(Driver $driver, Throwable $driverEx, $msg)
private static function wrapException(Driver $driver, Throwable $driverEx, string $msg)
{
if ($driverEx instanceof DriverException) {
return $driverEx;
......
......@@ -9,6 +9,7 @@ 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;
use function db2_conn_error;
......@@ -23,6 +24,7 @@ use function db2_prepare;
use function db2_rollback;
use function db2_server_info;
use function db2_stmt_errormsg;
use function is_bool;
class DB2Connection implements ServerInfoAwareConnection
{
......@@ -138,7 +140,10 @@ class DB2Connection implements ServerInfoAwareConnection
*/
public function beginTransaction()
{
db2_autocommit($this->conn, DB2_AUTOCOMMIT_OFF);
$result = db2_autocommit($this->conn, DB2_AUTOCOMMIT_OFF);
assert(is_bool($result));
return $result;
}
/**
......@@ -149,7 +154,11 @@ class DB2Connection implements ServerInfoAwareConnection
if (! db2_commit($this->conn)) {
throw new DB2Exception(db2_conn_errormsg($this->conn));
}
db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON);
$result = db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON);
assert(is_bool($result));
return $result;
}
/**
......@@ -160,7 +169,11 @@ class DB2Connection implements ServerInfoAwareConnection
if (! db2_rollback($this->conn)) {
throw new DB2Exception(db2_conn_errormsg($this->conn));
}
db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON);
$result = db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON);
assert(is_bool($result));
return $result;
}
/**
......
......@@ -225,7 +225,7 @@ class MysqliConnection implements PingableConnection, ServerInfoAwareConnection
* @throws MysqliException When one of of the options is not supported.
* @throws MysqliException When applying doesn't work - e.g. due to incorrect value.
*/
private function setDriverOptions(array $driverOptions = [])
private function setDriverOptions(array $driverOptions = []) : void
{
$supportedDriverOptions = [
MYSQLI_OPT_CONNECT_TIMEOUT,
......@@ -284,7 +284,7 @@ class MysqliConnection implements PingableConnection, ServerInfoAwareConnection
*
* @throws MysqliException
*/
private function setSecureConnection(array $params)
private function setSecureConnection(array $params) : void
{
if (! isset($params['ssl_key']) &&
! isset($params['ssl_cert']) &&
......
......@@ -206,12 +206,14 @@ class MysqliStatement implements IteratorAggregate, Statement
/**
* Binds parameters with known types previously bound to the statement
*/
private function bindTypedParameters()
private function bindTypedParameters() : void
{
$streams = $values = [];
$types = $this->types;
foreach ($this->_bindedValues as $parameter => $value) {
assert(is_int($parameter));
if (! isset($types[$parameter - 1])) {
$types[$parameter - 1] = static::$_paramTypeMap[ParameterType::STRING];
}
......@@ -242,9 +244,11 @@ class MysqliStatement implements IteratorAggregate, Statement
/**
* Handle $this->_longData after regular query parameters have been bound
*
* @param array<int, resource> $streams
*
* @throws MysqliException
*/
private function sendLongData($streams)
private function sendLongData(array $streams) : void
{
foreach ($streams as $paramNr => $stream) {
while (! feof($stream)) {
......
......@@ -73,7 +73,13 @@ class PDOStatement implements IteratorAggregate, Statement
}
/**
* {@inheritdoc}
* @param mixed $column
* @param mixed $variable
* @param int $type
* @param int|null $length
* @param mixed $driverOptions
*
* @return bool
*/
public function bindParam($column, &$variable, $type = ParameterType::STRING, $length = null, $driverOptions = null)
{
......
......@@ -12,6 +12,8 @@ class LastInsertId
/**
* @param int $id
*
* @return void
*/
public function setId($id)
{
......
......@@ -150,6 +150,8 @@ class SQLSrvConnection implements ServerInfoAwareConnection
if (! sqlsrv_begin_transaction($this->conn)) {
throw SQLSrvException::fromSqlSrvErrors();
}
return true;
}
/**
......@@ -160,6 +162,8 @@ class SQLSrvConnection implements ServerInfoAwareConnection
if (! sqlsrv_commit($this->conn)) {
throw SQLSrvException::fromSqlSrvErrors();
}
return true;
}
/**
......@@ -170,6 +174,8 @@ class SQLSrvConnection implements ServerInfoAwareConnection
if (! sqlsrv_rollback($this->conn)) {
throw SQLSrvException::fromSqlSrvErrors();
}
return true;
}
/**
......
......@@ -156,6 +156,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement
$this->variables[$param] = $value;
$this->types[$param] = $type;
return true;
}
/**
......@@ -172,6 +174,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement
// unset the statement resource if it exists as the new one will need to be bound to the new variable
$this->stmt = null;
return true;
}
/**
......@@ -261,6 +265,8 @@ class SQLSrvStatement implements IteratorAggregate, Statement
}
$this->result = true;
return true;
}
/**
......
......@@ -49,9 +49,8 @@ class OracleSessionInit implements EventSubscriber
return;
}
array_change_key_case($this->_defaultSessionVars, CASE_UPPER);
$vars = [];
foreach ($this->_defaultSessionVars as $option => $value) {
foreach (array_change_key_case($this->_defaultSessionVars, CASE_UPPER) as $option => $value) {
if ($option === 'CURRENT_SCHEMA') {
$vars[] = $option . ' = ' . $value;
} else {
......
......@@ -10,6 +10,8 @@ use Doctrine\DBAL\LockMode;
use Throwable;
use const CASE_LOWER;
use function array_change_key_case;
use function assert;
use function is_int;
/**
* Table ID Generator for those poor languages that are missing sequences.
......@@ -111,6 +113,8 @@ class TableGenerator
$value = $row['sequence_value'];
$value++;
assert(is_int($value));
if ($row['sequence_increment_by'] > 1) {
$this->sequences[$sequenceName] = [
'value' => $value,
......
......@@ -156,6 +156,8 @@ abstract class AbstractPlatform
/**
* Sets the EventManager used by the Platform.
*
* @return void
*/
public function setEventManager(EventManager $eventManager)
{
......@@ -391,6 +393,8 @@ abstract class AbstractPlatform
* @param string $dbType
* @param string $doctrineType
*
* @return void
*
* @throws DBALException If the type is not found.
*/
public function registerDoctrineTypeMapping($dbType, $doctrineType)
......@@ -3291,6 +3295,8 @@ abstract class AbstractPlatform
/**
* @deprecated
*
* @return string
*
* @todo Remove in 3.0
*/
public function getIdentityColumnNullInsertSQL()
......
......@@ -628,7 +628,7 @@ class DB2Platform extends AbstractPlatform
* @param string[] $sql The sequence of table alteration statements to fill.
* @param mixed[] $queryParts The sequence of column alteration clauses to fill.
*/
private function gatherAlterColumnSQL(Identifier $table, ColumnDiff $columnDiff, array &$sql, array &$queryParts)
private function gatherAlterColumnSQL(Identifier $table, ColumnDiff $columnDiff, array &$sql, array &$queryParts) : void
{
$alterColumnClauses = $this->getAlterColumnClausesSQL($columnDiff);
......
......@@ -175,7 +175,10 @@ class MySqlPlatform extends AbstractPlatform
}
/**
* {@inheritDoc}
* @param string $table
* @param string|null $database
*
* @return string
*/
public function getListTableForeignKeysSQL($table, $database = null)
{
......
......@@ -37,6 +37,8 @@ class OraclePlatform extends AbstractPlatform
*
* @param string $identifier
*
* @return void
*
* @throws DBALException
*/
public static function assertValidIdentifier($identifier)
......@@ -59,7 +61,9 @@ class OraclePlatform extends AbstractPlatform
}
/**
* {@inheritDoc}
* @param string $type
*
* @return string
*/
public function getNowExpression($type = 'timestamp')
{
......
......@@ -67,6 +67,8 @@ class PostgreSQL94Platform extends AbstractPlatform
* Enables use of 'true'/'false' or otherwise 1 and 0 instead.
*
* @param bool $flag
*
* @return void
*/
public function setUseBooleanTrueFalseStrings($flag)
{
......@@ -275,7 +277,10 @@ class PostgreSQL94Platform extends AbstractPlatform
}
/**
* {@inheritDoc}
* @param string $table
* @param string|null $database
*
* @return string
*/
public function getListTableForeignKeysSQL($table, $database = null)
{
......
......@@ -629,15 +629,12 @@ class SQLAnywhere16Platform extends AbstractPlatform
case self::FOREIGN_KEY_MATCH_SIMPLE:
return 'SIMPLE';
break;
case self::FOREIGN_KEY_MATCH_FULL:
return 'FULL';
break;
case self::FOREIGN_KEY_MATCH_SIMPLE_UNIQUE:
return 'UNIQUE SIMPLE';
break;
case self::FOREIGN_KEY_MATCH_FULL_UNIQUE:
return 'UNIQUE FULL';
default:
......@@ -1369,13 +1366,13 @@ SQL
{
switch ($level) {
case TransactionIsolationLevel::READ_UNCOMMITTED:
return 0;
return '0';
case TransactionIsolationLevel::READ_COMMITTED:
return 1;
return '1';
case TransactionIsolationLevel::REPEATABLE_READ:
return 2;
return '2';
case TransactionIsolationLevel::SERIALIZABLE:
return 3;
return '3';
default:
throw new InvalidArgumentException('Invalid isolation level:' . $level);
}
......
......@@ -994,7 +994,10 @@ SQL
}
/**
* {@inheritDoc}
* @param string $table
* @param string|null $database
*
* @return string
*/
public function getListTableForeignKeysSQL($table, $database = null)
{
......
......@@ -55,7 +55,9 @@ class SqlitePlatform extends AbstractPlatform
}
/**
* {@inheritDoc}
* @param string $type
*
* @return string
*/
public function getNowExpression($type = 'timestamp')
{
......@@ -166,11 +168,11 @@ class SqlitePlatform extends AbstractPlatform
{
switch ($level) {
case TransactionIsolationLevel::READ_UNCOMMITTED:
return 0;
return '0';
case TransactionIsolationLevel::READ_COMMITTED:
case TransactionIsolationLevel::REPEATABLE_READ:
case TransactionIsolationLevel::SERIALIZABLE:
return 1;
return '1';
default:
return parent::_getTransactionIsolationLevelSQL($level);
}
......@@ -222,7 +224,9 @@ class SqlitePlatform extends AbstractPlatform
}
/**
* {@inheritDoc}
* @param array<string, mixed> $field
*
* @return string
*/
public function getTinyIntTypeDeclarationSql(array $field)
{
......@@ -248,7 +252,9 @@ class SqlitePlatform extends AbstractPlatform
}
/**
* {@inheritDoc}
* @param array<string, mixed> $field
*
* @return string
*/
public function getMediumIntTypeDeclarationSql(array $field)
{
......@@ -600,7 +606,7 @@ class SqlitePlatform extends AbstractPlatform
/**
* {@inheritDoc}
*/
public function getForUpdateSql()
public function getForUpdateSQL()
{
return '';
}
......@@ -810,7 +816,10 @@ class SqlitePlatform extends AbstractPlatform
}
/**
* {@inheritDoc}
* @param string $table
* @param string|null $database
*
* @return string
*/
public function getListTableForeignKeysSQL($table, $database = null)
{
......
......@@ -1186,7 +1186,7 @@ class QueryBuilder
*
* @throws QueryException
*/
private function verifyAllAliasesAreKnown(array $knownAliases)
private function verifyAllAliasesAreKnown(array $knownAliases) : void
{
foreach ($this->sqlParts['join'] as $fromAlias => $joins) {
if (! isset($knownAliases[$fromAlias])) {
......
......@@ -178,7 +178,9 @@ class DB2SchemaManager extends AbstractSchemaManager
}
/**
* {@inheritdoc}
* @param string $def
*
* @return string|null
*/
protected function _getPortableForeignKeyRuleDef($def)
{
......@@ -220,7 +222,10 @@ class DB2SchemaManager extends AbstractSchemaManager
$sql = $platform->getListTableCommentsSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql);
$table->addOption('comment', $tableOptions['REMARKS']);
if ($tableOptions !== false) {
$table->addOption('comment', $tableOptions['REMARKS']);
}
return $table;
}
......
......@@ -365,7 +365,7 @@ class ForeignKeyConstraint extends AbstractAsset implements Constraint
}
}
return false;
return null;
}
/**
......
......@@ -399,7 +399,10 @@ SQL;
$sql = $platform->getListTableCommentsSQL($tableName);
$tableOptions = $this->_conn->fetchAssoc($sql);
$table->addOption('comment', $tableOptions['COMMENTS']);
if ($tableOptions !== false) {
$table->addOption('comment', $tableOptions['COMMENTS']);
}
return $table;
}
......
......@@ -500,7 +500,9 @@ class PostgreSqlSchemaManager extends AbstractSchemaManager
$tableOptions = $this->_conn->fetchAssoc($sql);
$table->addOption('comment', $tableOptions['table_comment']);
if ($tableOptions !== false) {
$table->addOption('comment', $tableOptions['table_comment']);
}
return $table;
}
......
......@@ -47,6 +47,8 @@ class SQLAnywhereSchemaManager extends AbstractSchemaManager
* Starts a database.
*
* @param string $database The name of the database to start.
*
* @return void
*/
public function startDatabase($database)
{
......@@ -58,6 +60,8 @@ class SQLAnywhereSchemaManager extends AbstractSchemaManager
* Stops a database.
*
* @param string $database The name of the database to stop.
*
* @return void
*/
public function stopDatabase($database)
{
......
......@@ -223,9 +223,11 @@ class SqliteSchemaManager extends AbstractSchemaManager
}
/**
* {@inheritdoc}
*
* @deprecated
*
* @param array<string, mixed> $tableIndex
*
* @return array<string, bool|string>
*/
protected function _getPortableTableIndexDefinition($tableIndex)
{
......
......@@ -20,6 +20,8 @@ abstract class AbstractSchemaSynchronizer implements SchemaSynchronizer
/**
* @param string[] $sql
*
* @return void
*/
protected function processSqlSafely(array $sql)
{
......@@ -33,6 +35,8 @@ abstract class AbstractSchemaSynchronizer implements SchemaSynchronizer
/**
* @param string[] $sql
*
* @return void
*/
protected function processSql(array $sql)
{
......
......@@ -300,6 +300,8 @@ class Table extends AbstractAsset
* @param string $oldColumnName
* @param string $newColumnName
*
* @return void
*
* @throws DBALException
*/
public function renameColumn($oldColumnName, $newColumnName)
......
......@@ -11,6 +11,8 @@ interface NamespaceVisitor
* Accepts a schema namespace name.
*
* @param string $namespaceName The schema namespace name to accept.
*
* @return void
*/
public function acceptNamespace($namespaceName);
}
......@@ -14,26 +14,37 @@ interface SchemaDiffVisitor
{
/**
* Visit an orphaned foreign key whose table was deleted.
*
* @return void
*/
public function visitOrphanedForeignKey(ForeignKeyConstraint $foreignKey);
/**
* Visit a sequence that has changed.
*
* @return void
*/
public function visitChangedSequence(Sequence $sequence);
/**
* Visit a sequence that has been removed.
*
* @return void
*/
public function visitRemovedSequence(Sequence $sequence);
/** @return void */
public function visitNewSequence(Sequence $sequence);
/** @return void */
public function visitNewTable(Table $table);
/** @return void */
public function visitNewTableForeignKey(Table $table, ForeignKeyConstraint $foreignKey);
/** @return void */
public function visitRemovedTable(Table $table);
/** @return void */
public function visitChangedTable(TableDiff $tableDiff);
}
......@@ -54,9 +54,7 @@ class ReservedWordsCommand extends Command
$this->keywordListClasses[$name] = $class;
}
/**
* {@inheritdoc}
*/
/** @return void */
protected function configure()
{
$this
......
......@@ -21,9 +21,7 @@ use function stripos;
*/
class RunSqlCommand extends Command
{
/**
* {@inheritdoc}
*/
/** @return void */
protected function configure()
{
$this
......
......@@ -61,6 +61,8 @@ class ConsoleRunner
/**
* Prints the instructions to create a configuration file
*
* @return void
*/
public static function printCliConfigTemplate()
{
......
......@@ -17,7 +17,6 @@ use function explode;
use function extension_loaded;
use function get_class;
use function html_entity_decode;
use function ini_get;
use function ini_set;
use function is_array;
use function is_object;
......@@ -55,14 +54,11 @@ final class Dumper
*/
public static function dump($var, int $maxDepth = 2) : string
{
$html = ini_get('html_errors');
if ($html !== true) {
ini_set('html_errors', true);
}
$html = ini_set('html_errors', '1');
assert(is_string($html));
if (extension_loaded('xdebug')) {
ini_set('xdebug.var_display_max_depth', $maxDepth);
ini_set('xdebug.var_display_max_depth', (string) $maxDepth);
}
$var = self::export($var, $maxDepth);
......
......@@ -90,6 +90,13 @@ class ConversionException extends DBALException
), 0, $previous);
}
/**
* @param mixed $value
* @param string $format
* @param string $error
*
* @return ConversionException
*/
public static function conversionFailedSerialization($value, $format, $error)
{
$actualType = is_object($value) ? get_class($value) : gettype($value);
......
<?php
namespace Doctrine\DBAL\Tests\Performance;
use DateTime;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Tests\PerformanceTestCase;
use Doctrine\DBAL\Types\Type;
/**
* @group performance
*/
class TypeConversionPerformanceTest extends PerformanceTestCase
{
/**
* @throws DBALException
*
* @dataProvider itemCountProvider
*/
public function testDateTimeTypeConversionPerformance(int $count) : void
{
$value = new DateTime();
$type = Type::getType('datetime');
$platform = $this->connection->getDatabasePlatform();
$this->startTiming();
for ($i = 0; $i < $count; $i++) {
$type->convertToDatabaseValue($value, $platform);
}
$this->stopTiming();
}
/**
* @return mixed[][]
*/
public static function itemCountProvider() : iterable
{
return [
'100 items' => [100],
'1000 items' => [1000],
'10000 items' => [10000],
'100000 items' => [100000],
];
}
}
<?php
namespace Doctrine\DBAL\Tests;
use function microtime;
/**
* Base class for all DBAL performance tests.
*
* Tests implemented in this class must call startTiming at the beginning
* and stopTiming at the end of all tests. Tests that do not start or stop
* timing will fail.
*/
abstract class PerformanceTestCase extends FunctionalTestCase
{
/**
* time the test started
*
* @var float
*/
private $startTime;
/**
* elapsed run time of the last test
*
* @var float
*/
private $runTime;
/**
* {@inheritdoc}
*/
protected function assertPostConditions() : void
{
// If a perf test doesn't start or stop, it fails.
self::assertNotNull($this->startTime, 'Test timing was started');
self::assertNotNull($this->runTime, 'Test timing was stopped');
}
/**
* begin timing
*/
protected function startTiming() : void
{
$this->startTime = microtime(true);
}
/**
* end timing
*/
protected function stopTiming() : void
{
$this->runTime = microtime(true) - $this->startTime;
}
/**
* @return float elapsed test execution time
*/
public function getTime() : float
{
return $this->runTime;
}
}
<?php
namespace Doctrine\DBAL\Tests;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestListener;
use PHPUnit\Framework\TestListenerDefaultImplementation;
use function get_class;
use function printf;
use function str_replace;
/**
* Listener for collecting and reporting results of performance tests
*/
class PerformanceTestListener implements TestListener
{
use TestListenerDefaultImplementation;
/** @var string[][] */
private $timings = [];
/**
* {@inheritdoc}
*/
public function endTest(Test $test, float $time) : void
{
// This listener only applies to performance tests.
if (! ($test instanceof PerformanceTestCase)) {
return;
}
// we identify perf tests by class, method, and dataset
$class = str_replace('\\Doctrine\\Tests\\DBAL\\Performance\\', '', get_class($test));
if (! isset($this->timings[$class])) {
$this->timings[$class] = [];
}
// Store timing data for each test in the order they were run.
$this->timings[$class][$test->getName(true)] = $test->getTime();
}
/**
* Report performance test timings.
*
* Note: __destruct is used here because PHPUnit doesn't have a
* 'All tests over' hook.
*/
public function __destruct()
{
if (empty($this->timings)) {
return;
}
// Report timings.
print "\nPerformance test results:\n\n";
foreach ($this->timings as $class => $tests) {
printf("%s:\n", $class);
foreach ($tests as $test => $time) {
printf("\t%s: %.3f seconds\n", $test, $time);
}
}
}
}
......@@ -8,6 +8,7 @@ use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Connection as DriverConnection;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\Logging\SQLLogger;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Statement;
......@@ -148,4 +149,15 @@ class StatementTest extends TestCase
$statement->execute();
}
public function testPDOCustomClassConstructorArgs() : void
{
$statement = new Statement('', $this->conn);
$this->driverStatement->expects($this->once())
->method('fetchAll')
->with(self::equalTo(FetchMode::CUSTOM_OBJECT), self::equalTo('Example'), self::equalTo(['arg1']));
$statement->fetchAll(FetchMode::CUSTOM_OBJECT, 'Example', ['arg1']);
}
}
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