Unverified Commit 18908c39 authored by Sergei Morozov's avatar Sergei Morozov Committed by GitHub

Merge pull request #3948 from morozov/master

Manually merge 3.0.x into master
parents 1eba78d6 d2288393
......@@ -269,6 +269,14 @@ The Doctrine\DBAL\Version class is no longer available: please refrain from chec
# Upgrade to 3.0
## BC BREAK: Dropped support for `FetchMode::CUSTOM_OBJECT` and `::STANDARD_OBJECT`
Instead of fetching an object, fetch an array and map it to an object of the desired class.
## BC BREAK: Dropped support for the `$columnIndex` argument in `ResultStatement::fetchColumn()`, other `ResultStatement::fetch*()` methods invoked with `FetchMode::COLUMN` and `Connection::fetchColumn()`.
In order to fetch a column with an index other than `0`, use `FetchMode::NUMERIC` and the array element with the corresponding index.
## BC BREAK: Removed `EchoSQLLogger`
`EchoSQLLogger` is no longer available as part of the package.
......
......@@ -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": "d33d9fbc27c8a727a565ef5524bbbcda",
"content-hash": "c4f3212f2eb936c849f99146f9ad2d9c",
"packages": [
{
"name": "doctrine/cache",
......@@ -1299,16 +1299,16 @@
},
{
"name": "phpunit/phpunit",
"version": "9.0.1",
"version": "9.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "68d7e5b17a6b9461e17c00446caa409863154f76"
"reference": "848f6521c906500e66229668768576d35de0227e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/68d7e5b17a6b9461e17c00446caa409863154f76",
"reference": "68d7e5b17a6b9461e17c00446caa409863154f76",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/848f6521c906500e66229668768576d35de0227e",
"reference": "848f6521c906500e66229668768576d35de0227e",
"shasum": ""
},
"require": {
......@@ -1324,14 +1324,15 @@
"phar-io/version": "^2.0.1",
"php": "^7.3",
"phpspec/prophecy": "^1.8.1",
"phpunit/php-code-coverage": "^8.0",
"phpunit/php-code-coverage": "^8.0.1",
"phpunit/php-file-iterator": "^3.0",
"phpunit/php-invoker": "^3.0",
"phpunit/php-text-template": "^2.0",
"phpunit/php-timer": "^3.0",
"sebastian/code-unit": "^1.0",
"sebastian/comparator": "^4.0",
"sebastian/diff": "^4.0",
"sebastian/environment": "^5.0",
"sebastian/environment": "^5.0.1",
"sebastian/exporter": "^4.0",
"sebastian/global-state": "^4.0",
"sebastian/object-enumerator": "^4.0",
......@@ -1352,7 +1353,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "9.0-dev"
"dev-master": "9.1-dev"
}
},
"autoload": {
......@@ -1381,7 +1382,7 @@
"testing",
"xunit"
],
"time": "2020-02-13T07:30:12+00:00"
"time": "2020-04-03T14:40:04+00:00"
},
{
"name": "psr/log",
......@@ -1430,6 +1431,52 @@
],
"time": "2020-03-23T09:12:05+00:00"
},
{
"name": "sebastian/code-unit",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git",
"reference": "8d8f09bd47c75159921e6e84fdef146343962866"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/8d8f09bd47c75159921e6e84fdef146343962866",
"reference": "8d8f09bd47c75159921e6e84fdef146343962866",
"shasum": ""
},
"require": {
"php": "^7.3"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"description": "Collection of value objects that represent the PHP code units",
"homepage": "https://github.com/sebastianbergmann/code-unit",
"time": "2020-03-30T11:59:20+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
"version": "2.0.0",
......@@ -1597,16 +1644,16 @@
},
{
"name": "sebastian/environment",
"version": "5.0.1",
"version": "5.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "9bffdefa7810031a165ddd6275da6a2c1f6f2dfb"
"reference": "c39c1db0a5cffc98173f3de5a17d489d1043fd7b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/9bffdefa7810031a165ddd6275da6a2c1f6f2dfb",
"reference": "9bffdefa7810031a165ddd6275da6a2c1f6f2dfb",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/c39c1db0a5cffc98173f3de5a17d489d1043fd7b",
"reference": "c39c1db0a5cffc98173f3de5a17d489d1043fd7b",
"shasum": ""
},
"require": {
......@@ -1646,7 +1693,7 @@
"environment",
"hhvm"
],
"time": "2020-02-19T13:40:20+00:00"
"time": "2020-03-31T12:14:15+00:00"
},
{
"name": "sebastian/exporter",
......@@ -2338,16 +2385,16 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.14.0",
"version": "v1.15.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "fbdeaec0df06cf3d51c93de80c7eb76e271f5a38"
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/fbdeaec0df06cf3d51c93de80c7eb76e271f5a38",
"reference": "fbdeaec0df06cf3d51c93de80c7eb76e271f5a38",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14",
"shasum": ""
},
"require": {
......@@ -2359,7 +2406,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.14-dev"
"dev-master": "1.15-dev"
}
},
"autoload": {
......@@ -2392,7 +2439,21 @@
"polyfill",
"portable"
],
"time": "2020-01-13T11:15:53+00:00"
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-02-27T09:26:54+00:00"
},
{
"name": "symfony/polyfill-mbstring",
......
......@@ -70,12 +70,6 @@ parameters:
- %currentWorkingDirectory%/src/Platforms/*Platform.php
- %currentWorkingDirectory%/src/Schema/*SchemaManager.php
# FetchMode::CUSTOM_OBJECT requires variable property access
-
message: '~^Variable property access on object\.~'
paths:
- %currentWorkingDirectory%/src/Driver/*/*Statement.php
# Some APIs use variable method calls internally
-
message: '~^Variable method call on .*~'
......
......@@ -6,11 +6,9 @@ namespace Doctrine\DBAL\Cache;
use ArrayIterator;
use Doctrine\DBAL\Driver\ResultStatement;
use Doctrine\DBAL\Exception\InvalidColumnIndex;
use Doctrine\DBAL\FetchMode;
use InvalidArgumentException;
use IteratorAggregate;
use function array_key_exists;
use function array_merge;
use function array_values;
use function count;
......@@ -59,15 +57,8 @@ final class ArrayStatement implements IteratorAggregate, ResultStatement
return count($this->data);
}
/**
* {@inheritdoc}
*/
public function setFetchMode(int $fetchMode, ...$args) : void
public function setFetchMode(int $fetchMode) : void
{
if (count($args) > 0) {
throw new InvalidArgumentException('Caching layer does not support 2nd/3rd argument to setFetchMode().');
}
$this->defaultFetchMode = $fetchMode;
}
......@@ -84,7 +75,7 @@ final class ArrayStatement implements IteratorAggregate, ResultStatement
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null, ...$args)
public function fetch(?int $fetchMode = null)
{
if (! isset($this->data[$this->num])) {
return false;
......@@ -117,10 +108,10 @@ final class ArrayStatement implements IteratorAggregate, ResultStatement
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null, ...$args) : array
public function fetchAll(?int $fetchMode = null) : array
{
$rows = [];
while ($row = $this->fetch($fetchMode, ...$args)) {
while ($row = $this->fetch($fetchMode)) {
$rows[] = $row;
}
......@@ -130,7 +121,7 @@ final class ArrayStatement implements IteratorAggregate, ResultStatement
/**
* {@inheritdoc}
*/
public function fetchColumn(int $columnIndex = 0)
public function fetchColumn()
{
$row = $this->fetch(FetchMode::NUMERIC);
......@@ -138,10 +129,6 @@ final class ArrayStatement implements IteratorAggregate, ResultStatement
return false;
}
if (! array_key_exists($columnIndex, $row)) {
throw InvalidColumnIndex::new($columnIndex, count($row));
}
return $row[$columnIndex];
return $row[0];
}
}
......@@ -7,14 +7,11 @@ namespace Doctrine\DBAL\Cache;
use ArrayIterator;
use Doctrine\Common\Cache\Cache;
use Doctrine\DBAL\Driver\ResultStatement;
use Doctrine\DBAL\Exception\InvalidColumnIndex;
use Doctrine\DBAL\FetchMode;
use InvalidArgumentException;
use IteratorAggregate;
use function array_key_exists;
use function array_merge;
use function array_values;
use function count;
use function reset;
/**
......@@ -93,10 +90,7 @@ final class ResultCacheStatement implements IteratorAggregate, ResultStatement
return $this->statement->columnCount();
}
/**
* {@inheritdoc}
*/
public function setFetchMode(int $fetchMode, ...$args) : void
public function setFetchMode(int $fetchMode) : void
{
$this->defaultFetchMode = $fetchMode;
}
......@@ -114,7 +108,7 @@ final class ResultCacheStatement implements IteratorAggregate, ResultStatement
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null, ...$args)
public function fetch(?int $fetchMode = null)
{
if ($this->data === null) {
$this->data = [];
......@@ -154,9 +148,9 @@ final class ResultCacheStatement implements IteratorAggregate, ResultStatement
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null, ...$args) : array
public function fetchAll(?int $fetchMode = null) : array
{
$data = $this->statement->fetchAll($fetchMode, ...$args);
$data = $this->statement->fetchAll($fetchMode);
if ($fetchMode === FetchMode::COLUMN) {
foreach ($data as $key => $value) {
......@@ -173,7 +167,7 @@ final class ResultCacheStatement implements IteratorAggregate, ResultStatement
/**
* {@inheritdoc}
*/
public function fetchColumn(int $columnIndex = 0)
public function fetchColumn()
{
$row = $this->fetch(FetchMode::NUMERIC);
......@@ -181,11 +175,7 @@ final class ResultCacheStatement implements IteratorAggregate, ResultStatement
return false;
}
if (! array_key_exists($columnIndex, $row)) {
throw InvalidColumnIndex::new($columnIndex, count($row));
}
return $row[$columnIndex];
return $row[0];
}
/**
......
......@@ -494,16 +494,15 @@ class Connection implements DriverConnection
*
* @param string $query The SQL query to be executed.
* @param array<int, mixed>|array<string, mixed> $params The prepared statement params.
* @param int $column The 0-indexed column number to retrieve.
* @param array<int, int|string>|array<string, int|string> $types The query parameter types.
*
* @return mixed|false False is returned if no rows are found.
*
* @throws DBALException
*/
public function fetchColumn(string $query, array $params = [], int $column = 0, array $types = [])
public function fetchColumn(string $query, array $params = [], array $types = [])
{
return $this->executeQuery($query, $params, $types)->fetchColumn($column);
return $this->executeQuery($query, $params, $types)->fetchColumn();
}
/**
......
......@@ -6,42 +6,27 @@ namespace Doctrine\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\Exception\InvalidColumnIndex;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use ReflectionClass;
use ReflectionObject;
use ReflectionProperty;
use stdClass;
use function array_change_key_case;
use function array_key_exists;
use function assert;
use function count;
use function db2_bind_param;
use function db2_execute;
use function db2_fetch_array;
use function db2_fetch_assoc;
use function db2_fetch_both;
use function db2_fetch_object;
use function db2_free_result;
use function db2_num_fields;
use function db2_num_rows;
use function error_get_last;
use function fclose;
use function fwrite;
use function gettype;
use function is_int;
use function is_object;
use function is_resource;
use function is_string;
use function ksort;
use function sprintf;
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;
......@@ -64,12 +49,6 @@ final class DB2Statement implements IteratorAggregate, Statement
*/
private $lobs = [];
/** @var string Name of the default class to instantiate when fetching class instances. */
private $defaultFetchClass = '\stdClass';
/** @var mixed[] Constructor arguments for the default class to instantiate when fetching class instances. */
private $defaultFetchClassCtorArgs = [];
/** @var int */
private $defaultFetchMode = FetchMode::MIXED;
......@@ -192,22 +171,9 @@ final class DB2Statement implements IteratorAggregate, Statement
$this->result = true;
}
/**
* {@inheritdoc}
*/
public function setFetchMode(int $fetchMode, ...$args) : void
public function setFetchMode(int $fetchMode) : void
{
$this->defaultFetchMode = $fetchMode;
if (isset($args[0])) {
$this->defaultFetchClass = $args[0];
}
if (! isset($args[1])) {
return;
}
$this->defaultFetchClassCtorArgs = (array) $args[2];
}
/**
......@@ -221,7 +187,7 @@ final class DB2Statement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null, ...$args)
public function fetch(?int $fetchMode = null)
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
......@@ -240,29 +206,9 @@ final class DB2Statement implements IteratorAggregate, Statement
case FetchMode::ASSOCIATIVE:
return db2_fetch_assoc($this->stmt);
case FetchMode::CUSTOM_OBJECT:
$className = $this->defaultFetchClass;
$ctorArgs = $this->defaultFetchClassCtorArgs;
if (count($args) > 0) {
$className = $args[0];
$ctorArgs = $args[1] ?? [];
}
$result = db2_fetch_object($this->stmt);
if ($result instanceof stdClass) {
$result = $this->castObject($result, $className, $ctorArgs);
}
return $result;
case FetchMode::NUMERIC:
return db2_fetch_array($this->stmt);
case FetchMode::STANDARD_OBJECT:
return db2_fetch_object($this->stmt);
default:
throw new DB2Exception('Given Fetch-Style ' . $fetchMode . ' is not supported.');
}
......@@ -271,18 +217,11 @@ final class DB2Statement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null, ...$args) : array
public function fetchAll(?int $fetchMode = null) : array
{
$rows = [];
switch ($fetchMode) {
case FetchMode::CUSTOM_OBJECT:
while (($row = $this->fetch($fetchMode, ...$args)) !== false) {
$rows[] = $row;
}
break;
case FetchMode::COLUMN:
while (($row = $this->fetchColumn()) !== false) {
$rows[] = $row;
......@@ -302,7 +241,7 @@ final class DB2Statement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetchColumn(int $columnIndex = 0)
public function fetchColumn()
{
$row = $this->fetch(FetchMode::NUMERIC);
......@@ -310,11 +249,7 @@ final class DB2Statement implements IteratorAggregate, Statement
return false;
}
if (! array_key_exists($columnIndex, $row)) {
throw InvalidColumnIndex::new($columnIndex, count($row));
}
return $row[$columnIndex];
return $row[0];
}
public function rowCount() : int
......@@ -337,69 +272,6 @@ final class DB2Statement implements IteratorAggregate, Statement
}
}
/**
* Casts a stdClass object to the given class name mapping its' properties.
*
* @param stdClass $sourceObject Object to cast from.
* @param string|object $destinationClass Name of the class or class instance to cast to.
* @param mixed[] $ctorArgs Arguments to use for constructing the destination class instance.
*
* @throws DB2Exception
*/
private function castObject(stdClass $sourceObject, $destinationClass, array $ctorArgs = []) : object
{
if (! is_string($destinationClass)) {
if (! is_object($destinationClass)) {
throw new DB2Exception(sprintf(
'Destination class has to be of type string or object, %s given.',
gettype($destinationClass)
));
}
} else {
$destinationClass = new ReflectionClass($destinationClass);
$destinationClass = $destinationClass->newInstanceArgs($ctorArgs);
}
$sourceReflection = new ReflectionObject($sourceObject);
$destinationClassReflection = new ReflectionObject($destinationClass);
/** @var ReflectionProperty[] $destinationProperties */
$destinationProperties = array_change_key_case($destinationClassReflection->getProperties(), CASE_LOWER);
foreach ($sourceReflection->getProperties() as $sourceProperty) {
$sourceProperty->setAccessible(true);
$name = $sourceProperty->getName();
$value = $sourceProperty->getValue($sourceObject);
// Try to find a case-matching property.
if ($destinationClassReflection->hasProperty($name)) {
$destinationProperty = $destinationClassReflection->getProperty($name);
$destinationProperty->setAccessible(true);
$destinationProperty->setValue($destinationClass, $value);
continue;
}
$name = strtolower($name);
// Try to find a property without matching case.
// Fallback for the driver returning either all uppercase or all lowercase column names.
if (isset($destinationProperties[$name])) {
$destinationProperty = $destinationProperties[$name];
$destinationProperty->setAccessible(true);
$destinationProperty->setValue($destinationClass, $value);
continue;
}
$destinationClass->$name = $value;
}
return $destinationClass;
}
/**
* @return resource
*
......
......@@ -13,7 +13,6 @@ use Doctrine\DBAL\Driver\Mysqli\Exception\UnknownType;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use Doctrine\DBAL\Exception\InvalidColumnIndex;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
......@@ -22,7 +21,6 @@ use mysqli_stmt;
use stdClass;
use function array_combine;
use function array_fill;
use function array_key_exists;
use function array_map;
use function assert;
use function count;
......@@ -328,7 +326,7 @@ final class MysqliStatement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null, ...$args)
public function fetch(?int $fetchMode = null)
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
......@@ -366,9 +364,6 @@ final class MysqliStatement implements IteratorAggregate, Statement
case FetchMode::MIXED:
return $assoc + $values;
case FetchMode::STANDARD_OBJECT:
return (object) $assoc;
default:
throw UnknownFetchMode::new($fetchMode);
}
......@@ -377,7 +372,7 @@ final class MysqliStatement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null, ...$args) : array
public function fetchAll(?int $fetchMode = null) : array
{
$fetchMode = $fetchMode ?? $this->defaultFetchMode;
......@@ -399,7 +394,7 @@ final class MysqliStatement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetchColumn(int $columnIndex = 0)
public function fetchColumn()
{
$row = $this->fetch(FetchMode::NUMERIC);
......@@ -407,11 +402,7 @@ final class MysqliStatement implements IteratorAggregate, Statement
return false;
}
if (! array_key_exists($columnIndex, $row)) {
throw InvalidColumnIndex::new($columnIndex, count($row));
}
return $row[$columnIndex];
return $row[0];
}
public function closeCursor() : void
......@@ -434,10 +425,7 @@ final class MysqliStatement implements IteratorAggregate, Statement
return $this->stmt->field_count;
}
/**
* {@inheritdoc}
*/
public function setFetchMode(int $fetchMode, ...$args) : void
public function setFetchMode(int $fetchMode) : void
{
$this->defaultFetchMode = $fetchMode;
}
......
......@@ -6,14 +6,11 @@ namespace Doctrine\DBAL\Driver\OCI8;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\Exception\InvalidColumnIndex;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use InvalidArgumentException;
use IteratorAggregate;
use function array_key_exists;
use function assert;
use function count;
use function is_int;
use function is_resource;
use function oci_bind_by_name;
......@@ -22,7 +19,6 @@ use function oci_error;
use function oci_execute;
use function oci_fetch_all;
use function oci_fetch_array;
use function oci_fetch_object;
use function oci_new_descriptor;
use function oci_num_fields;
use function oci_num_rows;
......@@ -224,10 +220,7 @@ final class OCI8Statement implements IteratorAggregate, Statement
$this->result = true;
}
/**
* {@inheritdoc}
*/
public function setFetchMode(int $fetchMode, ...$args) : void
public function setFetchMode(int $fetchMode) : void
{
$this->_defaultFetchMode = $fetchMode;
}
......@@ -243,7 +236,7 @@ final class OCI8Statement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null, ...$args)
public function fetch(?int $fetchMode = null)
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
......@@ -257,10 +250,6 @@ final class OCI8Statement implements IteratorAggregate, Statement
return $this->fetchColumn();
}
if ($fetchMode === FetchMode::STANDARD_OBJECT) {
return oci_fetch_object($this->_sth);
}
if (! isset(self::$fetchModeMap[$fetchMode])) {
throw new InvalidArgumentException(sprintf('Invalid fetch mode %d.', $fetchMode));
}
......@@ -274,20 +263,12 @@ final class OCI8Statement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null, ...$args) : array
public function fetchAll(?int $fetchMode = null) : array
{
$fetchMode = $fetchMode ?? $this->_defaultFetchMode;
$result = [];
if ($fetchMode === FetchMode::STANDARD_OBJECT) {
while ($row = $this->fetch($fetchMode)) {
$result[] = $row;
}
return $result;
}
if (! isset(self::$fetchModeMap[$fetchMode])) {
throw new InvalidArgumentException(sprintf('Invalid fetch mode %d.', $fetchMode));
}
......@@ -328,7 +309,7 @@ final class OCI8Statement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetchColumn(int $columnIndex = 0)
public function fetchColumn()
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
......@@ -342,11 +323,7 @@ final class OCI8Statement implements IteratorAggregate, Statement
return false;
}
if (! array_key_exists($columnIndex, $row)) {
throw InvalidColumnIndex::new($columnIndex, count($row));
}
return $row[$columnIndex];
return $row[0];
}
public function rowCount() : int
......
......@@ -6,7 +6,6 @@ namespace Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Exception\UnknownFetchMode;
use Doctrine\DBAL\Driver\Exception\UnknownParamType;
use Doctrine\DBAL\Exception\InvalidColumnIndex;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
......@@ -36,9 +35,7 @@ class PDOStatement implements IteratorAggregate, Statement
FetchMode::ASSOCIATIVE => PDO::FETCH_ASSOC,
FetchMode::NUMERIC => PDO::FETCH_NUM,
FetchMode::MIXED => PDO::FETCH_BOTH,
FetchMode::STANDARD_OBJECT => PDO::FETCH_OBJ,
FetchMode::COLUMN => PDO::FETCH_COLUMN,
FetchMode::CUSTOM_OBJECT => PDO::FETCH_CLASS,
];
/** @var \PDOStatement */
......@@ -49,15 +46,12 @@ class PDOStatement implements IteratorAggregate, Statement
$this->stmt = $stmt;
}
/**
* {@inheritdoc}
*/
public function setFetchMode(int $fetchMode, ...$args) : void
public function setFetchMode(int $fetchMode) : void
{
$fetchMode = $this->convertFetchMode($fetchMode);
try {
$this->stmt->setFetchMode($fetchMode, ...$args);
$this->stmt->setFetchMode($fetchMode);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
......@@ -128,16 +122,16 @@ class PDOStatement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null, ...$args)
public function fetch(?int $fetchMode = null)
{
try {
if ($fetchMode === null) {
return $this->stmt->fetch();
}
$fetchMode = $this->convertFetchMode($fetchMode);
return $this->stmt->fetch($fetchMode, ...$args);
return $this->stmt->fetch(
$this->convertFetchMode($fetchMode)
);
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
......@@ -146,15 +140,14 @@ class PDOStatement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null, ...$args) : array
public function fetchAll(?int $fetchMode = null) : array
{
try {
if ($fetchMode === null) {
$data = $this->stmt->fetchAll();
} else {
$data = $this->stmt->fetchAll(
$this->convertFetchMode($fetchMode),
...$args
$this->convertFetchMode($fetchMode)
);
}
} catch (\PDOException $exception) {
......@@ -169,20 +162,10 @@ class PDOStatement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetchColumn(int $columnIndex = 0)
public function fetchColumn()
{
try {
$value = $this->stmt->fetchColumn($columnIndex);
if ($value === null) {
$columnCount = $this->columnCount();
if ($columnIndex < 0 || $columnIndex >= $columnCount) {
throw InvalidColumnIndex::new($columnIndex, $columnCount);
}
}
return $value;
return $this->stmt->fetchColumn();
} catch (\PDOException $exception) {
throw new PDOException($exception);
}
......
......@@ -41,9 +41,8 @@ interface ResultStatement extends Traversable
*
* @param int $fetchMode Controls how the next row will be returned to the caller.
* The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants.
* @param mixed ...$args Optional mode-specific arguments (see {@link self::fetchAll()}).
*/
public function setFetchMode(int $fetchMode, ...$args) : void;
public function setFetchMode(int $fetchMode) : void;
/**
* Returns the next row of a result set.
......@@ -51,12 +50,11 @@ interface ResultStatement extends Traversable
* @param int|null $fetchMode Controls how the next row will be returned to the caller.
* The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants,
* defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}.
* @param mixed ...$args Optional mode-specific arguments (see {@link self::fetchAll()}).
*
* @return mixed The return value of this method on success depends on the fetch mode. In all cases, FALSE is
* returned on failure.
*/
public function fetch(?int $fetchMode = null, ...$args);
public function fetch(?int $fetchMode = null);
/**
* Returns an array containing all of the result set rows.
......@@ -64,24 +62,15 @@ interface ResultStatement extends Traversable
* @param int|null $fetchMode Controls how the next row will be returned to the caller.
* The value must be one of the {@link \Doctrine\DBAL\FetchMode} constants,
* defaulting to {@link \Doctrine\DBAL\FetchMode::MIXED}.
* @param mixed ...$args Optional mode-specific arguments. Supported modes:
* * {@link \Doctrine\DBAL\FetchMode::COLUMN}
* 1. The 0-indexed column to be returned.
* * {@link \Doctrine\DBAL\FetchMode::CUSTOM_OBJECT}
* 1. The classname of the object to be created,
* 2. Array of constructor arguments
*
* @return mixed[]
*/
public function fetchAll(?int $fetchMode = null, ...$args) : array;
public function fetchAll(?int $fetchMode = null) : array;
/**
* Returns a single column from the next row of a result set or FALSE if there are no more rows.
*
* @param int $columnIndex 0-indexed number of the column you wish to retrieve from the row.
* If no value is supplied, fetches the first column.
*
* @return mixed|false A single column in the next row of a result set, or FALSE if there are no more rows.
*/
public function fetchColumn(int $columnIndex = 0);
public function fetchColumn();
}
......@@ -7,23 +7,15 @@ namespace Doctrine\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\Exception\GetVariableType;
use Doctrine\DBAL\Exception\InvalidColumnIndex;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use ReflectionClass;
use ReflectionObject;
use stdClass;
use function array_key_exists;
use function assert;
use function count;
use function is_int;
use function is_object;
use function is_resource;
use function is_string;
use function sasql_fetch_array;
use function sasql_fetch_assoc;
use function sasql_fetch_object;
use function sasql_fetch_row;
use function sasql_prepare;
use function sasql_stmt_affected_rows;
......@@ -43,12 +35,6 @@ final class SQLAnywhereStatement implements IteratorAggregate, Statement
/** @var resource The connection resource. */
private $conn;
/** @var string Name of the default class to instantiate when fetching class instances. */
private $defaultFetchClass = '\stdClass';
/** @var mixed[] Constructor arguments for the default class to instantiate when fetching class instances. */
private $defaultFetchClassCtorArgs = [];
/** @var int Default fetch mode to use. */
private $defaultFetchMode = FetchMode::MIXED;
......@@ -171,7 +157,7 @@ final class SQLAnywhereStatement implements IteratorAggregate, Statement
*
* @throws SQLAnywhereException
*/
public function fetch(?int $fetchMode = null, ...$args)
public function fetch(?int $fetchMode = null)
{
if (! is_resource($this->result)) {
return false;
......@@ -189,29 +175,9 @@ final class SQLAnywhereStatement implements IteratorAggregate, Statement
case FetchMode::MIXED:
return sasql_fetch_array($this->result, SASQL_BOTH);
case FetchMode::CUSTOM_OBJECT:
$className = $this->defaultFetchClass;
$ctorArgs = $this->defaultFetchClassCtorArgs;
if (count($args) > 0) {
$className = $args[0];
$ctorArgs = $args[1] ?? [];
}
$result = sasql_fetch_object($this->result);
if ($result instanceof stdClass) {
$result = $this->castObject($result, $className, $ctorArgs);
}
return $result;
case FetchMode::NUMERIC:
return sasql_fetch_row($this->result);
case FetchMode::STANDARD_OBJECT:
return sasql_fetch_object($this->result);
default:
throw new SQLAnywhereException(sprintf('Fetch mode is not supported %d.', $fetchMode));
}
......@@ -220,18 +186,11 @@ final class SQLAnywhereStatement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null, ...$args) : array
public function fetchAll(?int $fetchMode = null) : array
{
$rows = [];
switch ($fetchMode) {
case FetchMode::CUSTOM_OBJECT:
while (($row = $this->fetch($fetchMode, ...$args)) !== false) {
$rows[] = $row;
}
break;
case FetchMode::COLUMN:
while (($row = $this->fetchColumn()) !== false) {
$rows[] = $row;
......@@ -251,7 +210,7 @@ final class SQLAnywhereStatement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetchColumn(int $columnIndex = 0)
public function fetchColumn()
{
$row = $this->fetch(FetchMode::NUMERIC);
......@@ -259,11 +218,7 @@ final class SQLAnywhereStatement implements IteratorAggregate, Statement
return false;
}
if (! array_key_exists($columnIndex, $row)) {
throw InvalidColumnIndex::new($columnIndex, count($row));
}
return $row[$columnIndex];
return $row[0];
}
/**
......@@ -279,66 +234,8 @@ final class SQLAnywhereStatement implements IteratorAggregate, Statement
return sasql_stmt_affected_rows($this->stmt);
}
/**
* {@inheritdoc}
*/
public function setFetchMode(int $fetchMode, ...$args) : void
public function setFetchMode(int $fetchMode) : void
{
$this->defaultFetchMode = $fetchMode;
if (isset($args[0])) {
$this->defaultFetchClass = $args[0];
}
if (! isset($args[1])) {
return;
}
$this->defaultFetchClassCtorArgs = (array) $args[1];
}
/**
* Casts a stdClass object to the given class name mapping its' properties.
*
* @param stdClass $sourceObject Object to cast from.
* @param string|object $destinationClass Name of the class or class instance to cast to.
* @param mixed[] $ctorArgs Arguments to use for constructing the destination class instance.
*
* @throws SQLAnywhereException
*/
private function castObject(stdClass $sourceObject, $destinationClass, array $ctorArgs = []) : object
{
if (! is_string($destinationClass)) {
if (! is_object($destinationClass)) {
throw new SQLAnywhereException(sprintf(
'Destination class has to be of type string or object, "%s" given.',
(new GetVariableType())->__invoke($destinationClass)
));
}
} else {
$destinationClass = new ReflectionClass($destinationClass);
$destinationClass = $destinationClass->newInstanceArgs($ctorArgs);
}
$sourceReflection = new ReflectionObject($sourceObject);
$destinationClassReflection = new ReflectionObject($destinationClass);
foreach ($sourceReflection->getProperties() as $sourceProperty) {
$sourceProperty->setAccessible(true);
$name = $sourceProperty->getName();
$value = $sourceProperty->getValue($sourceObject);
if ($destinationClassReflection->hasProperty($name)) {
$destinationProperty = $destinationClassReflection->getProperty($name);
$destinationProperty->setAccessible(true);
$destinationProperty->setValue($destinationClass, $value);
} else {
$destinationClass->$name = $value;
}
}
return $destinationClass;
}
}
......@@ -6,19 +6,14 @@ namespace Doctrine\DBAL\Driver\SQLSrv;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use Doctrine\DBAL\Exception\InvalidColumnIndex;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use IteratorAggregate;
use function array_key_exists;
use function assert;
use function count;
use function in_array;
use function is_int;
use function sqlsrv_execute;
use function sqlsrv_fetch;
use function sqlsrv_fetch_array;
use function sqlsrv_fetch_object;
use function sqlsrv_get_field;
use function sqlsrv_next_result;
use function sqlsrv_num_fields;
......@@ -85,20 +80,6 @@ final class SQLSrvStatement implements IteratorAggregate, Statement
FetchMode::NUMERIC => SQLSRV_FETCH_NUMERIC,
];
/**
* The name of the default class to instantiate when fetching class instances.
*
* @var string
*/
private $defaultFetchClass = '\stdClass';
/**
* The constructor arguments for the default class to instantiate when fetching class instances.
*
* @var mixed[]
*/
private $defaultFetchClassCtorArgs = [];
/**
* The fetch style.
*
......@@ -230,22 +211,9 @@ final class SQLSrvStatement implements IteratorAggregate, Statement
$this->result = true;
}
/**
* {@inheritdoc}
*/
public function setFetchMode(int $fetchMode, ...$args) : void
public function setFetchMode(int $fetchMode) : void
{
$this->defaultFetchMode = $fetchMode;
if (isset($args[0])) {
$this->defaultFetchClass = $args[0];
}
if (! isset($args[1])) {
return;
}
$this->defaultFetchClassCtorArgs = (array) $args[1];
}
/**
......@@ -261,7 +229,7 @@ final class SQLSrvStatement implements IteratorAggregate, Statement
*
* @throws SQLSrvException
*/
public function fetch(?int $fetchMode = null, ...$args)
public function fetch(?int $fetchMode = null)
{
// do not try fetching from the statement if it's not expected to contain result
// in order to prevent exceptional situation
......@@ -279,36 +247,17 @@ final class SQLSrvStatement implements IteratorAggregate, Statement
return sqlsrv_fetch_array($this->stmt, self::$fetchMap[$fetchMode]) ?? false;
}
if (in_array($fetchMode, [FetchMode::STANDARD_OBJECT, FetchMode::CUSTOM_OBJECT], true)) {
$className = $this->defaultFetchClass;
$ctorArgs = $this->defaultFetchClassCtorArgs;
if (count($args) > 0) {
$className = $args[0];
$ctorArgs = $args[1] ?? [];
}
return sqlsrv_fetch_object($this->stmt, $className, $ctorArgs) ?? false;
}
throw new SQLSrvException('Fetch mode is not supported.');
}
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null, ...$args) : array
public function fetchAll(?int $fetchMode = null) : array
{
$rows = [];
switch ($fetchMode) {
case FetchMode::CUSTOM_OBJECT:
while (($row = $this->fetch($fetchMode, ...$args)) !== false) {
$rows[] = $row;
}
break;
case FetchMode::COLUMN:
while (($row = $this->fetchColumn()) !== false) {
$rows[] = $row;
......@@ -328,7 +277,7 @@ final class SQLSrvStatement implements IteratorAggregate, Statement
/**
* {@inheritdoc}
*/
public function fetchColumn(int $columnIndex = 0)
public function fetchColumn()
{
$row = $this->fetch(FetchMode::NUMERIC);
......@@ -336,11 +285,7 @@ final class SQLSrvStatement implements IteratorAggregate, Statement
return false;
}
if (! array_key_exists($columnIndex, $row)) {
throw InvalidColumnIndex::new($columnIndex, count($row));
}
return $row[$columnIndex];
return $row[0];
}
public function rowCount() : int
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Exception;
use Doctrine\DBAL\DBALException;
use function sprintf;
final class InvalidColumnIndex extends DBALException
{
public static function new(int $index, int $count) : self
{
return new self(sprintf(
'Invalid column index %d. The statement result contains %d column%s.',
$index,
$count,
$count === 1 ? '' : 's'
));
}
}
......@@ -37,15 +37,6 @@ final class FetchMode
*/
public const MIXED = 4;
/**
* Specifies that the fetch method shall return each row as an object with
* property names that correspond to the column names returned in the result
* set.
*
* @see \PDO::FETCH_OBJ
*/
public const STANDARD_OBJECT = 5;
/**
* Specifies that the fetch method shall return only a single requested
* column from the next row in the result set.
......@@ -54,14 +45,6 @@ final class FetchMode
*/
public const COLUMN = 7;
/**
* Specifies that the fetch method shall return a new instance of the
* requested class, mapping the columns to named properties in the class.
*
* @see \PDO::FETCH_CLASS
*/
public const CUSTOM_OBJECT = 8;
/**
* This class cannot be instantiated.
*/
......
......@@ -84,14 +84,11 @@ final class Statement implements IteratorAggregate, DriverStatement
$this->stmt->execute($params);
}
/**
* {@inheritdoc}
*/
public function setFetchMode(int $fetchMode, ...$args) : void
public function setFetchMode(int $fetchMode) : void
{
$this->defaultFetchMode = $fetchMode;
$this->stmt->setFetchMode($fetchMode, ...$args);
$this->stmt->setFetchMode($fetchMode);
}
/**
......@@ -105,11 +102,11 @@ final class Statement implements IteratorAggregate, DriverStatement
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null, ...$args)
public function fetch(?int $fetchMode = null)
{
$fetchMode = $fetchMode ?? $this->defaultFetchMode;
$row = $this->stmt->fetch($fetchMode, ...$args);
$row = $this->stmt->fetch($fetchMode);
$iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0;
$fixCase = $this->case !== null
......@@ -124,11 +121,11 @@ final class Statement implements IteratorAggregate, DriverStatement
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null, ...$args) : array
public function fetchAll(?int $fetchMode = null) : array
{
$fetchMode = $fetchMode ?? $this->defaultFetchMode;
$rows = $this->stmt->fetchAll($fetchMode, ...$args);
$rows = $this->stmt->fetchAll($fetchMode);
$iterateRow = ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) !== 0;
$fixCase = $this->case !== null
......@@ -161,9 +158,9 @@ final class Statement implements IteratorAggregate, DriverStatement
/**
* {@inheritdoc}
*/
public function fetchColumn(int $columnIndex = 0)
public function fetchColumn()
{
$value = $this->stmt->fetchColumn($columnIndex);
$value = $this->stmt->fetchColumn();
if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) !== 0 && $value === '') {
$value = null;
......
......@@ -180,12 +180,9 @@ class Statement implements IteratorAggregate, DriverStatement
return $this->stmt->columnCount();
}
/**
* {@inheritdoc}
*/
public function setFetchMode(int $fetchMode, ...$args) : void
public function setFetchMode(int $fetchMode) : void
{
$this->stmt->setFetchMode($fetchMode, ...$args);
$this->stmt->setFetchMode($fetchMode);
}
/**
......@@ -201,25 +198,25 @@ class Statement implements IteratorAggregate, DriverStatement
/**
* {@inheritdoc}
*/
public function fetch(?int $fetchMode = null, ...$args)
public function fetch(?int $fetchMode = null)
{
return $this->stmt->fetch($fetchMode, ...$args);
return $this->stmt->fetch($fetchMode);
}
/**
* {@inheritdoc}
*/
public function fetchAll(?int $fetchMode = null, ...$args) : array
public function fetchAll(?int $fetchMode = null) : array
{
return $this->stmt->fetchAll($fetchMode, ...$args);
return $this->stmt->fetchAll($fetchMode);
}
/**
* {@inheritDoc}
*/
public function fetchColumn(int $columnIndex = 0)
public function fetchColumn()
{
return $this->stmt->fetchColumn($columnIndex);
return $this->stmt->fetchColumn();
}
/**
......
......@@ -59,16 +59,6 @@ class ArrayStatementTest extends TestCase
self::assertSame($this->users[0], $statement->fetch());
}
public function testSetFetchModeThrowsInvalidArgumentException() : void
{
$statement = $this->createTestArrayStatement();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Caching layer does not support 2nd/3rd argument to setFetchMode().');
$statement->setFetchMode(FetchMode::ASSOCIATIVE, 'arg1', 'arg2');
}
public function testGetIterator() : void
{
$statement = $this->createTestArrayStatement();
......@@ -131,13 +121,8 @@ class ArrayStatementTest extends TestCase
{
$statement = $this->createTestArrayStatement();
self::assertSame('jwage', $statement->fetchColumn(0));
self::assertSame('romanb', $statement->fetchColumn(0));
$statement = $this->createTestArrayStatement();
self::assertTrue($statement->fetchColumn(1));
self::assertFalse($statement->fetchColumn(1));
self::assertSame('jwage', $statement->fetchColumn());
self::assertSame('romanb', $statement->fetchColumn());
}
private function createTestArrayStatement() : ArrayStatement
......
......@@ -573,7 +573,6 @@ class ConnectionTest extends TestCase
$statement = 'SELECT * FROM foo WHERE bar = ?';
$params = [666];
$types = [ParameterType::INTEGER];
$column = 0;
$result = [];
$driverMock = $this->createMock(Driver::class);
......@@ -588,7 +587,6 @@ class ConnectionTest extends TestCase
$driverStatementMock->expects(self::once())
->method('fetchColumn')
->with($column)
->will(self::returnValue($result));
/** @var Connection|MockObject $conn */
......@@ -602,7 +600,7 @@ class ConnectionTest extends TestCase
->with($statement, $params, $types)
->will(self::returnValue($driverStatementMock));
self::assertSame($result, $conn->fetchColumn($statement, $params, $column, $types));
self::assertSame($result, $conn->fetchColumn($statement, $params, $types));
}
public function testFetchAll() : void
......
<?php
declare(strict_types=1);
namespace Doctrine\DBAL\Tests\Exception;
use Doctrine\DBAL\Exception\InvalidColumnIndex;
use PHPUnit\Framework\TestCase;
class InvalidColumnIndexTest extends TestCase
{
public function testNew() : void
{
$exception = InvalidColumnIndex::new(5, 1);
self::assertSame('Invalid column index 5. The statement result contains 1 column.', $exception->getMessage());
}
public function testNewPlural() : void
{
$exception = InvalidColumnIndex::new(5, 2);
self::assertSame('Invalid column index 5. The statement result contains 2 columns.', $exception->getMessage());
}
}
......@@ -8,9 +8,6 @@ use DateTime;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\Mysqli\Driver as MySQLiDriver;
use Doctrine\DBAL\Driver\OCI8\Driver as Oci8Driver;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDOOracle\Driver as PDOOracleDriver;
use Doctrine\DBAL\Driver\SQLSrv\Driver as SQLSrvDriver;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
......@@ -19,11 +16,9 @@ use Doctrine\DBAL\Platforms\SqlitePlatform;
use Doctrine\DBAL\Platforms\TrimMode;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Statement;
use Doctrine\DBAL\Tests\Functional\DataAccess\FetchClass;
use Doctrine\DBAL\Tests\FunctionalTestCase;
use Doctrine\DBAL\Types\Types;
use InvalidArgumentException;
use PDO;
use function array_change_key_case;
use function array_filter;
use function array_keys;
......@@ -33,7 +28,6 @@ use function date;
use function is_array;
use function is_numeric;
use function json_encode;
use function property_exists;
use function sprintf;
use function strtotime;
use const CASE_LOWER;
......@@ -384,13 +378,13 @@ class DataAccessTest extends FunctionalTestCase
public function testFetchColumn() : void
{
$sql = 'SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?';
$testInt = $this->connection->fetchColumn($sql, [1, 'foo'], 0);
$sql = 'SELECT test_int FROM fetch_table WHERE test_int = ? AND test_string = ?';
$testInt = $this->connection->fetchColumn($sql, [1, 'foo']);
self::assertEquals(1, $testInt);
$sql = 'SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?';
$testString = $this->connection->fetchColumn($sql, [1, 'foo'], 1);
$sql = 'SELECT test_string FROM fetch_table WHERE test_int = ? AND test_string = ?';
$testString = $this->connection->fetchColumn($sql, [1, 'foo']);
self::assertEquals('foo', $testString);
}
......@@ -400,15 +394,14 @@ class DataAccessTest extends FunctionalTestCase
$datetimeString = '2010-01-01 10:10:10';
$datetime = new DateTime($datetimeString);
$sql = 'SELECT test_int, test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?';
$sql = 'SELECT test_datetime FROM fetch_table WHERE test_int = ? AND test_datetime = ?';
$column = $this->connection->fetchColumn(
$sql,
[1, $datetime],
1,
[ParameterType::STRING, Types::DATETIME_MUTABLE]
);
self::assertNotFalse($column);
self::assertIsString($column);
self::assertStringStartsWith($datetimeString, $column);
}
......@@ -426,7 +419,7 @@ class DataAccessTest extends FunctionalTestCase
$this->expectException(DBALException::class);
$this->connection->fetchColumn($sql, [1, $datetime], 1);
$this->connection->fetchColumn($sql, [1, $datetime]);
}
/**
......@@ -913,7 +906,7 @@ class DataAccessTest extends FunctionalTestCase
$sql = 'SELECT COUNT(*) FROM fetch_table_date_math WHERE ';
$sql .= $platform->getDateSubDaysExpression('test_date', 'test_days') . " < '2010-05-12'";
$rowCount = $this->connection->fetchColumn($sql, [], 0);
$rowCount = $this->connection->fetchColumn($sql);
self::assertEquals(1, $rowCount);
}
......@@ -1059,62 +1052,6 @@ class DataAccessTest extends FunctionalTestCase
}), 'should be no non-numerical elements in the result.');
}
/**
* @group DBAL-1091
*/
public function testFetchAllStyleObject() : void
{
$this->setupFixture();
$sql = 'SELECT test_int, test_string, test_datetime FROM fetch_table';
$stmt = $this->connection->prepare($sql);
$stmt->execute();
$results = $stmt->fetchAll(FetchMode::STANDARD_OBJECT);
self::assertCount(1, $results);
self::assertInstanceOf('stdClass', $results[0]);
self::assertEquals(
1,
property_exists($results[0], 'test_int') ? $results[0]->test_int : $results[0]->TEST_INT
);
self::assertEquals(
'foo',
property_exists($results[0], 'test_string') ? $results[0]->test_string : $results[0]->TEST_STRING
);
self::assertStringStartsWith(
'2010-01-01 10:10:10',
property_exists($results[0], 'test_datetime') ? $results[0]->test_datetime : $results[0]->TEST_DATETIME
);
}
/**
* @group DBAL-196
*/
public function testFetchAllSupportFetchClass() : void
{
$this->beforeFetchClassTest();
$this->setupFixture();
$sql = 'SELECT test_int, test_string, test_datetime FROM fetch_table';
$stmt = $this->connection->prepare($sql);
$stmt->execute();
$results = $stmt->fetchAll(
FetchMode::CUSTOM_OBJECT,
FetchClass::class
);
self::assertCount(1, $results);
self::assertInstanceOf(FetchClass::class, $results[0]);
self::assertEquals(1, $results[0]->test_int);
self::assertEquals('foo', $results[0]->test_string);
self::assertStringStartsWith('2010-01-01 10:10:10', $results[0]->test_datetime);
}
/**
* @group DBAL-241
*/
......@@ -1132,53 +1069,6 @@ class DataAccessTest extends FunctionalTestCase
self::assertEquals([1, 10], $rows);
}
/**
* @group DBAL-214
*/
public function testSetFetchModeClassFetchAll() : void
{
$this->beforeFetchClassTest();
$this->setupFixture();
$sql = 'SELECT * FROM fetch_table';
$stmt = $this->connection->query($sql);
$stmt->setFetchMode(FetchMode::CUSTOM_OBJECT, FetchClass::class);
$results = $stmt->fetchAll();
self::assertCount(1, $results);
self::assertInstanceOf(FetchClass::class, $results[0]);
self::assertEquals(1, $results[0]->test_int);
self::assertEquals('foo', $results[0]->test_string);
self::assertStringStartsWith('2010-01-01 10:10:10', $results[0]->test_datetime);
}
/**
* @group DBAL-214
*/
public function testSetFetchModeClassFetch() : void
{
$this->beforeFetchClassTest();
$this->setupFixture();
$sql = 'SELECT * FROM fetch_table';
$stmt = $this->connection->query($sql);
$stmt->setFetchMode(FetchMode::CUSTOM_OBJECT, FetchClass::class);
$results = [];
while ($row = $stmt->fetch()) {
$results[] = $row;
}
self::assertCount(1, $results);
self::assertInstanceOf(FetchClass::class, $results[0]);
self::assertEquals(1, $results[0]->test_int);
self::assertEquals('foo', $results[0]->test_string);
self::assertStringStartsWith('2010-01-01 10:10:10', $results[0]->test_datetime);
}
/**
* @group DBAL-257
*/
......@@ -1219,21 +1109,6 @@ class DataAccessTest extends FunctionalTestCase
self::assertEquals([], $rows);
}
/**
* @group DBAL-1028
*/
public function testFetchColumnNullValue() : void
{
$this->connection->executeUpdate(
'INSERT INTO fetch_table (test_int, test_string) VALUES (?, ?)',
[2, 'foo']
);
self::assertNull(
$this->connection->fetchColumn('SELECT test_datetime FROM fetch_table WHERE test_int = ?', [2])
);
}
/**
* @group DBAL-1028
*/
......@@ -1243,36 +1118,4 @@ class DataAccessTest extends FunctionalTestCase
$this->connection->fetchColumn('SELECT test_int FROM fetch_table WHERE test_int = ?', [-1])
);
}
private function setupFixture() : void
{
$this->connection->exec('DELETE FROM fetch_table');
$this->connection->insert('fetch_table', [
'test_int' => 1,
'test_string' => 'foo',
'test_datetime' => '2010-01-01 10:10:10',
]);
}
private function beforeFetchClassTest() : void
{
$driver = $this->connection->getDriver();
if ($driver instanceof Oci8Driver) {
self::markTestSkipped('Not supported by OCI8');
}
if ($driver instanceof MySQLiDriver) {
self::markTestSkipped('Mysqli driver dont support this feature.');
}
if (! $driver instanceof PDOOracleDriver) {
return;
}
/** @var PDOConnection $connection */
$connection = $this->connection
->getWrappedConnection();
$connection->getWrappedConnection()->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
}
}
......@@ -25,7 +25,10 @@ class SQLAnywhereSchemaManagerTest extends SchemaManagerFunctionalTestCase
self::assertCount(1, $views, 'Database has to have one view.');
self::assertEquals($name, $views[$name]->getName());
self::assertRegExp('/^SELECT \* from "?DBA"?\."?view_test_table"?$/', $views[$name]->getSql());
self::assertMatchesRegularExpression(
'/^SELECT \* from "?DBA"?\."?view_test_table"?$/',
$views[$name]->getSql()
);
}
public function testDropAndCreateAdvancedIndex() : void
......
......@@ -37,7 +37,7 @@ class SqliteSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->schemaManager->createDatabase($path);
self::assertFileExists($path);
$this->schemaManager->dropDatabase($path);
self::assertFileNotExists($path);
self::assertFileDoesNotExist($path);
}
/**
......@@ -59,7 +59,7 @@ class SqliteSchemaManagerTest extends SchemaManagerFunctionalTestCase
$this->schemaManager->dropDatabase('test_drop_database');
self::assertFileNotExists('test_drop_database');
self::assertFileDoesNotExist('test_drop_database');
unset($connection);
}
......
......@@ -6,7 +6,6 @@ namespace Doctrine\DBAL\Tests\Functional;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\IBMDB2\DB2Driver;
use Doctrine\DBAL\Driver\PDOConnection;
use Doctrine\DBAL\Driver\PDOMySql\Driver as PDOMySQLDriver;
use Doctrine\DBAL\Driver\PDOOracle\Driver as PDOOracleDriver;
use Doctrine\DBAL\Driver\PDOSqlsrv\Driver as PDOSQLSRVDriver;
......@@ -377,34 +376,4 @@ EOF
$this->expectException(DBALException::class);
$stmt->execute([null]);
}
/**
* @throws DBALException
*
* @dataProvider nonExistingIndexProvider
*/
public function testFetchColumnNonExistingIndex(int $index) : void
{
if ($this->connection->getWrappedConnection() instanceof PDOConnection) {
self::markTestSkipped('PDO supports this behavior natively but throws a different exception');
}
$platform = $this->connection->getDatabasePlatform();
$query = $platform->getDummySelectSQL();
$stmt = $this->connection->query($query);
$this->expectException(DBALException::class);
$stmt->fetchColumn($index);
}
/**
* @return mixed[][]
*/
public static function nonExistingIndexProvider() : iterable
{
return [
[1],
[-1],
];
}
}
......@@ -77,7 +77,6 @@ class BinaryTest extends FunctionalTestCase
$value = $this->connection->fetchColumn(
'SELECT val FROM binary_table WHERE id = ?',
[$id],
0,
[ParameterType::BINARY]
);
......
......@@ -5,13 +5,11 @@ declare(strict_types=1);
namespace Doctrine\DBAL\Tests\Portability;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Portability\Connection;
use Doctrine\DBAL\Portability\Statement;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use ReflectionProperty;
use function iterator_to_array;
class StatementTest extends TestCase
......@@ -95,25 +93,6 @@ class StatementTest extends TestCase
$this->stmt->execute($params);
}
public function testSetFetchMode() : void
{
$fetchMode = FetchMode::CUSTOM_OBJECT;
$arg1 = 'MyClass';
$arg2 = [1, 2];
$this->wrappedStmt->expects(self::once())
->method('setFetchMode')
->with($fetchMode, $arg1, $arg2)
->will(self::returnValue(true));
$re = new ReflectionProperty($this->stmt, 'defaultFetchMode');
$re->setAccessible(true);
self::assertSame(FetchMode::MIXED, $re->getValue($this->stmt));
$this->stmt->setFetchMode($fetchMode, $arg1, $arg2);
self::assertSame($fetchMode, $re->getValue($this->stmt));
}
public function testGetIterator() : void
{
$this->wrappedStmt->expects(self::exactly(3))
......
......@@ -10,7 +10,6 @@ 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;
......@@ -151,15 +150,4 @@ class StatementTest extends TestCase
$statement->execute();
}
public function testPDOCustomClassConstructorArgs() : void
{
$statement = new Statement('', $this->conn);
$this->driverStatement->expects(self::once())
->method('fetchAll')
->with(self::equalTo(FetchMode::CUSTOM_OBJECT), self::equalTo('Example'), self::equalTo(['arg1']));
$statement->fetchAll(FetchMode::CUSTOM_OBJECT, 'Example', ['arg1']);
}
}
......@@ -75,8 +75,8 @@ class RunSqlCommandTest extends TestCase
]);
self::assertSame(0, $exitCode);
self::assertRegExp('@int.*1.*@', $this->commandTester->getDisplay());
self::assertRegExp('@array.*1.*@', $this->commandTester->getDisplay());
self::assertMatchesRegularExpression('@int.*1.*@', $this->commandTester->getDisplay());
self::assertMatchesRegularExpression('@array.*1.*@', $this->commandTester->getDisplay());
}
public function testUpdateStatementsPrintsAffectedLines() : void
......@@ -88,8 +88,8 @@ class RunSqlCommandTest extends TestCase
'sql' => 'UPDATE foo SET bar = 42',
]);
self::assertRegExp('@int.*42.*@', $this->commandTester->getDisplay());
self::assertNotRegExp('@array.*1.*@', $this->commandTester->getDisplay());
self::assertMatchesRegularExpression('@int.*42.*@', $this->commandTester->getDisplay());
self::assertDoesNotMatchRegularExpression('@array.*1.*@', $this->commandTester->getDisplay());
}
private function expectConnectionExecuteUpdate() : void
......@@ -122,7 +122,7 @@ class RunSqlCommandTest extends TestCase
'--force-fetch' => true,
]);
self::assertRegExp('@int.*1.*@', $this->commandTester->getDisplay());
self::assertRegExp('@array.*1.*@', $this->commandTester->getDisplay());
self::assertMatchesRegularExpression('@int.*1.*@', $this->commandTester->getDisplay());
self::assertMatchesRegularExpression('@array.*1.*@', $this->commandTester->getDisplay());
}
}
......@@ -14,7 +14,7 @@ class TypeAlreadyRegisteredTest extends TestCase
{
$exception = TypeAlreadyRegistered::new(Type::getType('string'));
self::assertRegExp(
self::assertMatchesRegularExpression(
'/Type of the class Doctrine\\\DBAL\\\Types\\\StringType@([0-9a-zA-Z]+) is already registered./',
$exception->getMessage()
);
......
......@@ -14,7 +14,7 @@ class TypeNotRegisteredTest extends TestCase
{
$exception = TypeNotRegistered::new(Type::getType('string'));
self::assertRegExp(
self::assertMatchesRegularExpression(
'/Type of the class Doctrine\\\DBAL\\\Types\\\StringType@([0-9a-zA-Z]+) is not registered./',
$exception->getMessage()
);
......
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