Skip to content

Commit

Permalink
The IBM DB2 driver Exception class must implement the DriverException…
Browse files Browse the repository at this point in the history
… interface
  • Loading branch information
morozov committed Jun 18, 2020
1 parent 2cfd54a commit bb9f853
Show file tree
Hide file tree
Showing 11 changed files with 217 additions and 73 deletions.
18 changes: 11 additions & 7 deletions lib/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
namespace Doctrine\DBAL\Driver\IBMDB2;

use Doctrine\DBAL\Driver\Connection;
use Doctrine\DBAL\Driver\IBMDB2\Exception\ConnectionError;
use Doctrine\DBAL\Driver\IBMDB2\Exception\ConnectionFailed;
use Doctrine\DBAL\Driver\IBMDB2\Exception\PrepareFailed;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\ParameterType;
use stdClass;
Expand All @@ -21,7 +24,7 @@
use function db2_prepare;
use function db2_rollback;
use function db2_server_info;
use function db2_stmt_errormsg;
use function error_get_last;
use function func_get_args;
use function is_bool;

Expand Down Expand Up @@ -52,7 +55,7 @@ public function __construct(array $params, $username, $password, $driverOptions
}

if ($conn === false) {
throw new DB2Exception(db2_conn_errormsg());
throw ConnectionFailed::new();
}

$this->conn = $conn;
Expand Down Expand Up @@ -83,8 +86,9 @@ public function requiresQueryForServerVersion()
public function prepare($sql)
{
$stmt = @db2_prepare($this->conn, $sql);
if (! $stmt) {
throw new DB2Exception(db2_stmt_errormsg());

if ($stmt === false) {
throw PrepareFailed::new(error_get_last()['message']);
}

return new DB2Statement($stmt);
Expand Down Expand Up @@ -125,7 +129,7 @@ public function exec($statement)
$stmt = @db2_exec($this->conn, $statement);

if ($stmt === false) {
throw new DB2Exception(db2_stmt_errormsg());
throw ConnectionError::new($this->conn);
}

return db2_num_rows($stmt);
Expand Down Expand Up @@ -156,7 +160,7 @@ public function beginTransaction()
public function commit()
{
if (! db2_commit($this->conn)) {
throw new DB2Exception(db2_conn_errormsg($this->conn));
throw ConnectionError::new($this->conn);
}

$result = db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON);
Expand All @@ -171,7 +175,7 @@ public function commit()
public function rollBack()
{
if (! db2_rollback($this->conn)) {
throw new DB2Exception(db2_conn_errormsg($this->conn));
throw ConnectionError::new($this->conn);
}

$result = db2_autocommit($this->conn, DB2_AUTOCOMMIT_ON);
Expand Down
4 changes: 2 additions & 2 deletions lib/Doctrine/DBAL/Driver/IBMDB2/DB2Exception.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

namespace Doctrine\DBAL\Driver\IBMDB2;

use Exception;
use Doctrine\DBAL\Driver\AbstractDriverException;

/**
* @psalm-immutable
*/
class DB2Exception extends Exception
class DB2Exception extends AbstractDriverException
{
}
7 changes: 4 additions & 3 deletions lib/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Doctrine\DBAL\Driver\IBMDB2;

use Doctrine\DBAL\Driver\FetchUtils;
use Doctrine\DBAL\Driver\IBMDB2\Exception\StatementError;
use Doctrine\DBAL\Driver\Result;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
Expand Down Expand Up @@ -141,7 +142,7 @@ private function bind($position, &$variable, int $parameterType, int $dataType):
$this->bindParam[$position] =& $variable;

if (! db2_bind_param($this->stmt, $position, 'variable', $parameterType, $dataType)) {
throw new DB2Exception(db2_stmt_errormsg());
throw StatementError::new($this->stmt);
}
}

Expand Down Expand Up @@ -219,7 +220,7 @@ public function execute($params = null)
$this->writeStringToStream($source, $target);
}

$retval = db2_execute($this->stmt, $params);
$retval = @db2_execute($this->stmt, $params);

foreach ($this->lobs as [, $handle]) {
fclose($handle);
Expand All @@ -228,7 +229,7 @@ public function execute($params = null)
$this->lobs = [];

if ($retval === false) {
throw new DB2Exception(db2_stmt_errormsg());
throw StatementError::new($this->stmt);
}

$this->result = true;
Expand Down
24 changes: 24 additions & 0 deletions lib/Doctrine/DBAL/Driver/IBMDB2/Exception/ConnectionError.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Doctrine\DBAL\Driver\IBMDB2\Exception;

use Doctrine\DBAL\Driver\IBMDB2\DB2Exception;

use function db2_conn_error;
use function db2_conn_errormsg;

/**
* @psalm-immutable
*/
final class ConnectionError extends DB2Exception
{
/**
* @param resource $connection
*/
public static function new($connection): self
{
return new self(db2_conn_errormsg($connection), db2_conn_error($connection));
}
}
21 changes: 21 additions & 0 deletions lib/Doctrine/DBAL/Driver/IBMDB2/Exception/ConnectionFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Doctrine\DBAL\Driver\IBMDB2\Exception;

use Doctrine\DBAL\Driver\IBMDB2\DB2Exception;

use function db2_conn_error;
use function db2_conn_errormsg;

/**
* @psalm-immutable
*/
final class ConnectionFailed extends DB2Exception
{
public static function new(): self
{
return new self(db2_conn_errormsg(), db2_conn_error());
}
}
18 changes: 18 additions & 0 deletions lib/Doctrine/DBAL/Driver/IBMDB2/Exception/PrepareFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Doctrine\DBAL\Driver\IBMDB2\Exception;

use Doctrine\DBAL\Driver\IBMDB2\DB2Exception;

/**
* @psalm-immutable
*/
final class PrepareFailed extends DB2Exception
{
public static function new(string $message): self
{
return new self($message);
}
}
24 changes: 24 additions & 0 deletions lib/Doctrine/DBAL/Driver/IBMDB2/Exception/StatementError.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Doctrine\DBAL\Driver\IBMDB2\Exception;

use Doctrine\DBAL\Driver\IBMDB2\DB2Exception;

use function db2_stmt_error;
use function db2_stmt_errormsg;

/**
* @psalm-immutable
*/
final class StatementError extends DB2Exception
{
/**
* @param resource $statement
*/
public static function new($statement): self
{
return new self(db2_stmt_errormsg($statement), db2_stmt_error($statement));
}
}
5 changes: 5 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@
<exclude-pattern>lib/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php</exclude-pattern>
</rule>

<!-- See https://github.com/slevomat/coding-standard/issues/1038 -->
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses">
<exclude-pattern>tests/Doctrine/Tests/DBAL/Functional/Driver/IBMDB2/DB2StatementTest.php</exclude-pattern>
</rule>

<!-- see https://github.com/doctrine/dbal/issues/3377 -->
<rule ref="SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedNotEqualOperator">
<exclude-pattern>lib/Doctrine/DBAL/Schema/Comparator.php</exclude-pattern>
Expand Down
98 changes: 42 additions & 56 deletions tests/Doctrine/Tests/DBAL/Functional/DataAccessTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use DateTime;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Driver\IBMDB2\DB2Driver;
use Doctrine\DBAL\Driver\Mysqli\Driver as MySQLiDriver;
use Doctrine\DBAL\Driver\OCI8\Driver as Oci8Driver;
use Doctrine\DBAL\Driver\PDOConnection;
Expand Down Expand Up @@ -245,8 +246,9 @@ public function testFetchAllWithTypes(): void

/**
* @group DBAL-209
* @dataProvider fetchProvider
*/
public function testFetchAllWithMissingTypes(): void
public function testFetchAllWithMissingTypes(callable $fetch): void
{
if (
$this->connection->getDriver() instanceof MySQLiDriver ||
Expand All @@ -255,13 +257,51 @@ public function testFetchAllWithMissingTypes(): void
$this->markTestSkipped('mysqli and sqlsrv actually supports this');
}

if (
$this->connection->getDriver() instanceof DB2Driver
) {
$this->markTestSkipped(
'ibm_ibm2 may or may not report the error depending on the PHP version and the connection state'
);
}

$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 = ?';

$this->expectException(DBALException::class);

$this->connection->fetchAll($sql, [1, $datetime]);
$fetch($this->connection, $sql, [1, $datetime]);
}

/**
* @return iterable<string,array<int,mixed>>
*/
public static function fetchProvider(): iterable
{
yield 'fetch-all-associative' => [
static function (Connection $connection, string $query, array $params): void {
$connection->fetchAll($query, $params);
},
];

yield 'fetch-numeric' => [
static function (Connection $connection, string $query, array $params): void {
$connection->fetchArray($query, $params);
},
];

yield 'fetch-associative' => [
static function (Connection $connection, string $query, array $params): void {
$connection->fetchAssoc($query, $params);
},
];

yield 'fetch-one' => [
static function (Connection $connection, string $query, array $params): void {
$connection->fetchColumn($query, $params);
},
];
}

public function testFetchBoth(): void
Expand Down Expand Up @@ -319,24 +359,6 @@ public function testFetchAssocWithTypes(): void
self::assertStringStartsWith($datetimeString, $row['test_datetime']);
}

public function testFetchAssocWithMissingTypes(): void
{
if (
$this->connection->getDriver() instanceof MySQLiDriver ||
$this->connection->getDriver() instanceof SQLSrvDriver
) {
$this->markTestSkipped('mysqli and sqlsrv actually supports this');
}

$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 = ?';

$this->expectException(DBALException::class);

$this->connection->fetchAssoc($sql, [1, $datetime]);
}

public function testFetchArray(): void
{
$sql = 'SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?';
Expand Down Expand Up @@ -366,24 +388,6 @@ public function testFetchArrayWithTypes(): void
self::assertStringStartsWith($datetimeString, $row[1]);
}

public function testFetchArrayWithMissingTypes(): void
{
if (
$this->connection->getDriver() instanceof MySQLiDriver ||
$this->connection->getDriver() instanceof SQLSrvDriver
) {
$this->markTestSkipped('mysqli and sqlsrv actually supports this');
}

$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 = ?';

$this->expectException(DBALException::class);

$this->connection->fetchArray($sql, [1, $datetime]);
}

public function testFetchColumn(): void
{
$sql = 'SELECT test_int, test_string FROM fetch_table WHERE test_int = ? AND test_string = ?';
Expand Down Expand Up @@ -415,24 +419,6 @@ public function testFetchColumnWithTypes(): void
self::assertStringStartsWith($datetimeString, $column);
}

public function testFetchColumnWithMissingTypes(): void
{
if (
$this->connection->getDriver() instanceof MySQLiDriver ||
$this->connection->getDriver() instanceof SQLSrvDriver
) {
$this->markTestSkipped('mysqli and sqlsrv actually supports this');
}

$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 = ?';

$this->expectException(DBALException::class);

$this->connection->fetchColumn($sql, [1, $datetime], 1);
}

/**
* @group DDC-697
*/
Expand Down
Loading

0 comments on commit bb9f853

Please sign in to comment.