Unverified Commit ac0e13a1 authored by Sergei Morozov's avatar Sergei Morozov

Merge branch '3.0.x'

parents d3a3e01d 8be6d163
/.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.
......@@ -6,6 +6,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'
......@@ -27,6 +29,36 @@ parameters:
-
message: '~Parameter #3 \$type of method Doctrine\\DBAL\\Driver\\Statement::bindValue\(\) expects int, string given\.~'
path: %currentWorkingDirectory%/tests/Functional/DataAccessTest.php
# 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
# Temporaily suppressed during up-merging an upgrade PHPStan 0.12
- '~^Unable to resolve the template type ExpectedType in call to method static method PHPUnit\\Framework\\Assert::assertInstanceOf\(\)$~'
- '~^Unable to resolve the template type RealInstanceType in call to method PHPUnit\\Framework\\TestCase::getMockClass\(\)$~'
# Temporaily suppressed during up-merging an upgrade PHPStan 0.12
-
message: '~^Parameter #1 \$expected of static method PHPUnit\\Framework\\Assert::assertInstanceOf\(\) expects class-string<object>, string given\.$~'
path: %currentWorkingDirectory%/tests/Driver/AbstractDriverTest.php
# Temporaily suppressed during up-merging an upgrade PHPStan 0.12
-
message: '~^Call to an undefined method Doctrine\\DBAL\\Driver::createDatabasePlatformForVersion\(\)\.$~'
path: %currentWorkingDirectory%/tests/Driver/AbstractDriverTest.php
includes:
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
......@@ -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>
......@@ -236,6 +236,7 @@ final class MysqliStatement implements IteratorAggregate, Statement
$types = $this->types;
foreach ($this->boundValues as $parameter => $value) {
assert(is_int($parameter));
if (! isset($types[$parameter - 1])) {
$types[$parameter - 1] = self::$paramTypeMap[ParameterType::STRING];
}
......@@ -267,7 +268,7 @@ final class MysqliStatement implements IteratorAggregate, Statement
/**
* Handle $this->_longData after regular query parameters have been bound
*
* @param resource[] $streams
* @param array<int, resource> $streams
*
* @throws MysqliException
*/
......
......@@ -78,7 +78,9 @@ class PDOStatement implements IteratorAggregate, Statement
}
/**
* {@inheritdoc}
* @param mixed $param
* @param mixed $variable
* @param mixed $driverOptions
*/
public function bindParam($param, &$variable, int $type = ParameterType::STRING, ?int $length = null, $driverOptions = null) : void
{
......
......@@ -48,9 +48,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 {
......
......@@ -11,6 +11,8 @@ use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\LockMode;
use Throwable;
use function array_change_key_case;
use function assert;
use function is_int;
use function sprintf;
use const CASE_LOWER;
......@@ -109,6 +111,8 @@ class TableGenerator
$value = $row['sequence_value'];
$value++;
assert(is_int($value));
if ($row['sequence_increment_by'] > 1) {
$this->sequences[$sequenceName] = [
'value' => $value,
......
......@@ -201,7 +201,7 @@ class SqlitePlatform extends AbstractPlatform
}
/**
* {@inheritDoc}
* @param array<string, mixed> $field
*/
public function getTinyIntTypeDeclarationSql(array $field) : string
{
......@@ -227,7 +227,7 @@ class SqlitePlatform extends AbstractPlatform
}
/**
* {@inheritDoc}
* @param array<string, mixed> $field
*/
public function getMediumIntTypeDeclarationSql(array $field) : string
{
......@@ -510,7 +510,7 @@ class SqlitePlatform extends AbstractPlatform
return 0;
}
public function getForUpdateSql() : string
public function getForUpdateSQL() : string
{
return '';
}
......
......@@ -199,7 +199,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;
}
......
......@@ -367,7 +367,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;
}
......
......@@ -499,7 +499,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;
}
......
......@@ -19,7 +19,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;
......@@ -57,11 +56,8 @@ final class Dumper
*/
public static function dump($var, int $maxDepth = 2) : string
{
$html = ini_get('html_errors');
if ($html !== '1') {
ini_set('html_errors', '1');
}
$html = ini_set('html_errors', '1');
assert(is_string($html));
if (extension_loaded('xdebug')) {
ini_set('xdebug.var_display_max_depth', (string) $maxDepth);
......
<?php
declare(strict_types=1);
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
declare(strict_types=1);
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;
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
declare(strict_types=1);
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 = [];
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);
}
}
}
}
......@@ -10,6 +10,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;
......@@ -150,4 +151,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