Skip to content

Commit

Permalink
Merge branch '3.2.x' into 4.0.x
Browse files Browse the repository at this point in the history
  • Loading branch information
morozov committed Jun 25, 2021
2 parents 08efef7 + c570c15 commit ea319d6
Show file tree
Hide file tree
Showing 26 changed files with 160 additions and 108 deletions.
11 changes: 11 additions & 0 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
- "7.3"
- "7.4"
- "8.0"
- "8.1"
dependencies:
- "highest"
include:
Expand Down Expand Up @@ -68,6 +69,7 @@ jobs:
php-version:
- "7.4"
- "8.0"
- "8.1"

services:
oracle:
Expand Down Expand Up @@ -111,6 +113,7 @@ jobs:
php-version:
- "7.4"
- "8.0"
- "8.1"

services:
oracle:
Expand Down Expand Up @@ -159,6 +162,8 @@ jobs:
include:
- php-version: "8.0"
postgres-version: "13"
- php-version: "8.1"
postgres-version: "13"

services:
postgres:
Expand Down Expand Up @@ -220,6 +225,12 @@ jobs:
- php-version: "8.0"
mariadb-version: "10.5"
extension: "pdo_mysql"
- php-version: "8.1"
mariadb-version: "10.5"
extension: "mysqli"
- php-version: "8.1"
mariadb-version: "10.5"
extension: "pdo_mysql"

services:
mariadb:
Expand Down
6 changes: 6 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,12 @@ The following methods have been removed.

# Upgrade to 3.2

## Deprecated `Connection::lastInsertId($name)`

The usage of `Connection::lastInsertId()` with a sequence name is deprecated as unsafe in scenarios with multiple
concurrent connections. If a newly inserted row needs to be referenced, it is recommended to generate its identifier
explicitly prior to insertion.

## Introduction of PSR-6 for result caching

Instead of relying on the deprecated `doctrine/cache` library, a PSR-6 cache
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"phpstan/phpstan": "0.12.81",
"phpstan/phpstan-phpunit": "0.12.18",
"phpstan/phpstan-strict-rules": "0.12.2",
"phpunit/phpunit": "9.5.0",
"phpunit/phpunit": "9.5.5",
"psalm/plugin-phpunit": "0.13.0",
"squizlabs/php_codesniffer": "3.6.0",
"symfony/cache": "^5.2|^6.0",
Expand Down
43 changes: 27 additions & 16 deletions docs/en/reference/data-retrieval-and-manipulation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ are then replaced by their actual values in a second step (execute).
$sql = "SELECT * FROM articles WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bindValue(1, $id);
$stmt->execute();
$resultSet = $stmt->executeQuery();
Placeholders in prepared statements are either simple positional question marks (``?``) or named labels starting with
a colon (e.g. ``:name1``). You cannot mix the positional and the named approach. You have to bind a parameter
Expand All @@ -108,7 +108,7 @@ position of the variable to bind into the ``bindValue()`` method:
$stmt = $conn->prepare($sql);
$stmt->bindValue(1, $id);
$stmt->bindValue(2, $status);
$stmt->execute();
$resultSet = $stmt->executeQuery();
Named parameters have the advantage that their labels can be re-used and only need to be bound once:

Expand All @@ -120,7 +120,7 @@ Named parameters have the advantage that their labels can be re-used and only ne
$sql = "SELECT * FROM users WHERE name = :name OR username = :name";
$stmt = $conn->prepare($sql);
$stmt->bindValue("name", $name);
$stmt->execute();
$resultSet = $stmt->executeQuery();
The following section describes the API of Doctrine DBAL with regard to prepared statements.

Expand Down Expand Up @@ -159,17 +159,28 @@ and methods to retrieve data from a statement.
- ``bindParam($pos, &$param, $type)`` - Bind a given reference to the positional or
named parameter in the prepared statement.

If you are finished with binding parameters you have to call ``execute()`` on the statement, which
will trigger a query to the database. After the query is finished you can access the results
of this query using the fetch API of a statement:
If you are finished with binding parameters you have to call ``executeQuery()`` on the statement,
which will trigger a query to the database. After the query is finished, a ``Doctrine\DBAL\Result``
instance is returned and you can access the results of this query using the fetch API of the result:

- ``fetch($fetchStyle)`` - Retrieves the next row from the statement or false if there are none.
- ``fetchNumeric()`` - Retrieves the next row from the statement or false if there are none.
The row is fetched as an array with numeric keys where the columns appear in the same order as
they were specified in the executed ``SELECT`` query.
Moves the pointer forward one row, so that consecutive calls will always return the next row.
- ``fetchColumn($column)`` - Retrieves only one column of the next row specified by column index.
- ``fetchAssociative()`` - Retrieves the next row from the statement or false if there are none.
The row is fetched as an associative array where the keys represent the column names as
specified in the executed ``SELECT`` query.
Moves the pointer forward one row, so that consecutive calls will always return the next row.
- ``fetchAll($fetchStyle)`` - Retrieves all rows from the statement.
- ``fetchOne()`` - Retrieves the value of the first column of the next row from the statement
or false if there are none.
Moves the pointer forward one row, so that consecutive calls will always return the next row.
- ``fetchAllNumeric()`` - Retrieves all rows from the statement as arrays with numeric keys.
- ``fetchAllAssociative()`` - Retrieves all rows from the statement as associative arrays.
- ``fetchFirstColumn()`` - Retrieves the value of the first column of all rows.

The fetch API of a prepared statement obviously works only for ``SELECT`` queries.
The fetch API of a prepared statement obviously works only for ``SELECT`` queries. If you want to
execute a statement that does not yield a result set, like ``INSERT``, ``UPDATE`` or ``DELETE``
for instance, you might want to call ``executeStatement()`` instead of ``executeQuery()``.

If you find it tedious to write all the prepared statement code you can alternatively use
the ``Doctrine\DBAL\Connection#executeQuery()`` and ``Doctrine\DBAL\Connection#executeStatement()``
Expand Down Expand Up @@ -201,7 +212,7 @@ to the appropriate vendors database format:
$date = new \DateTime("2011-03-05 14:00:21");
$stmt = $conn->prepare("SELECT * FROM articles WHERE publish_date > ?");
$stmt->bindValue(1, $date, "datetime");
$stmt->execute();
$resultSet = $stmt->executeQuery();
If you take a look at ``Doctrine\DBAL\Types\DateTimeType`` you will see that
parts of the conversion are delegated to a method on the current database platform,
Expand Down Expand Up @@ -238,7 +249,7 @@ Since you are using an ``IN`` expression you would really like to use it in the
$stmt = $conn->prepare('SELECT * FROM articles WHERE id IN (?)');
// THIS WILL NOT WORK:
$stmt->bindValue(1, array(1, 2, 3, 4, 5, 6));
$stmt->execute();
$resultSet = $stmt->executeQuery();
Implementing a generic way to handle this kind of query is tedious work. This is why most
developers fallback to inserting the parameters directly into the query, which can open
Expand Down Expand Up @@ -309,7 +320,7 @@ Prepare a given SQL statement and return the
<?php
$statement = $conn->prepare('SELECT * FROM user');
$resultSet = $statement->execute();
$resultSet = $statement->executeQuery();
$users = $resultSet->fetchAllAssociative();
/*
Expand Down Expand Up @@ -342,13 +353,13 @@ executeQuery()
~~~~~~~~~~~~~~

Creates a prepared statement for the given SQL and passes the
parameters to the execute method, then returning the statement:
parameters to the executeQuery method, then returning the result set:

.. code-block:: php
<?php
$statement = $conn->executeQuery('SELECT * FROM user WHERE username = ?', array('jwage'));
$user = $statement->fetchAssociative();
$resultSet = $conn->executeQuery('SELECT * FROM user WHERE username = ?', array('jwage'));
$user = $resultSet->fetchAssociative();
/*
array(
Expand Down
6 changes: 3 additions & 3 deletions docs/en/reference/security.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,13 @@ Following are examples of using prepared statements with SQL and DQL:
$sql = "SELECT * FROM users WHERE username = ?";
$stmt = $connection->prepare($sql);
$stmt->bindValue(1, $_GET['username']);
$stmt->execute();
$resultSet = $stmt->executeQuery();
// SQL Prepared Statements: Named
$sql = "SELECT * FROM users WHERE username = :user";
$stmt = $connection->prepare($sql);
$stmt->bindValue("user", $_GET['username']);
$stmt->execute();
$resultSet = $stmt->executeQuery();
// DQL Prepared Statements: Positional
$dql = "SELECT u FROM User u WHERE u.username = ?1";
Expand All @@ -133,7 +133,7 @@ are using just the DBAL there are also helper methods which simplify the usage q
<?php
// bind parameters and execute query at once.
$sql = "SELECT * FROM users WHERE username = ?";
$stmt = $connection->executeQuery($sql, array($_GET['username']));
$resultSet = $connection->executeQuery($sql, array($_GET['username']));
There is also ``executeStatement`` which does not return a statement but the number of affected rows.

Expand Down
5 changes: 5 additions & 0 deletions psalm.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@
is no longer supported.
-->
<file name="src/Tools/Console/ConsoleRunner.php"/>
<!--
This suppression should be removed in 4.0.0.
-->
<referencedClass name="Doctrine\DBAL\Id\TableGenerator"/>
<referencedClass name="Doctrine\DBAL\Id\TableGeneratorSchemaVisitor"/>
</errorLevel>
</DeprecatedClass>
<DeprecatedMethod>
Expand Down
9 changes: 9 additions & 0 deletions src/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\SQL\Parser;
use Doctrine\DBAL\Types\Type;
use Doctrine\Deprecations\Deprecation;
use Throwable;
use Traversable;

Expand Down Expand Up @@ -1118,6 +1119,14 @@ public function getTransactionNestingLevel(): int
*/
public function lastInsertId(?string $name = null): string
{
if ($name !== null) {
Deprecation::trigger(
'doctrine/dbal',
'https://github.com/doctrine/dbal/issues/4687',
'The usage of Connection::lastInsertId() with a sequence name is deprecated.'
);
}

try {
return $this->getWrappedConnection()->lastInsertId($name);
} catch (Driver\Exception $e) {
Expand Down
9 changes: 9 additions & 0 deletions src/Driver/IBMDB2/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\Deprecations\Deprecation;
use stdClass;

use function assert;
Expand Down Expand Up @@ -104,6 +105,14 @@ public function exec(string $sql): int

public function lastInsertId(?string $name = null): string
{
if ($name !== null) {
Deprecation::triggerIfCalledFromOutside(
'doctrine/dbal',
'https://github.com/doctrine/dbal/issues/4687',
'The usage of Connection::lastInsertId() with a sequence name is deprecated.'
);
}

return db2_last_insert_id($this->conn);
}

Expand Down
14 changes: 14 additions & 0 deletions src/Driver/Mysqli/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\Deprecations\Deprecation;
use mysqli;

use function assert;
use function floor;
use function mysqli_init;
use function mysqli_report;
use function stripos;

use const MYSQLI_REPORT_OFF;

final class Connection implements ServerInfoAwareConnection
{
/**
Expand Down Expand Up @@ -46,6 +50,8 @@ public function __construct(
iterable $preInitializers = [],
iterable $postInitializers = []
) {
mysqli_report(MYSQLI_REPORT_OFF);

$connection = mysqli_init();
assert($connection !== false);

Expand Down Expand Up @@ -122,6 +128,14 @@ public function exec(string $sql): int

public function lastInsertId(?string $name = null): string
{
if ($name !== null) {
Deprecation::triggerIfCalledFromOutside(
'doctrine/dbal',
'https://github.com/doctrine/dbal/issues/4687',
'The usage of Connection::lastInsertId() with a sequence name is deprecated.'
);
}

return (string) $this->conn->insert_id;
}

Expand Down
7 changes: 7 additions & 0 deletions src/Driver/OCI8/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\Deprecations\Deprecation;

use function addcslashes;
use function assert;
Expand Down Expand Up @@ -102,6 +103,12 @@ public function lastInsertId(?string $name = null): string
throw IdentityColumnsNotSupported::new();
}

Deprecation::triggerIfCalledFromOutside(
'doctrine/dbal',
'https://github.com/doctrine/dbal/issues/4687',
'The usage of Connection::lastInsertId() with a sequence name is deprecated.'
);

$result = $this->query('SELECT ' . $name . '.CURRVAL FROM DUAL')->fetchOne();

if ($result === false) {
Expand Down
7 changes: 7 additions & 0 deletions src/Driver/PDO/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\Deprecations\Deprecation;
use PDO;
use PDOException;
use PDOStatement;
Expand Down Expand Up @@ -95,6 +96,12 @@ public function lastInsertId(?string $name = null): string
return $this->connection->lastInsertId();
}

Deprecation::triggerIfCalledFromOutside(
'doctrine/dbal',
'https://github.com/doctrine/dbal/issues/4687',
'The usage of Connection::lastInsertId() with a sequence name is deprecated.'
);

return $this->connection->lastInsertId($name);
} catch (PDOException $exception) {
throw Exception::new($exception);
Expand Down
7 changes: 7 additions & 0 deletions src/Driver/PDO/SQLSrv/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Doctrine\DBAL\Driver\Result;
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\Deprecations\Deprecation;
use PDO;

final class Connection implements ServerInfoAwareConnection
Expand Down Expand Up @@ -48,6 +49,12 @@ public function lastInsertId(?string $name = null): string
return $this->connection->lastInsertId($name);
}

Deprecation::triggerIfCalledFromOutside(
'doctrine/dbal',
'https://github.com/doctrine/dbal/issues/4687',
'The usage of Connection::lastInsertId() with a sequence name is deprecated.'
);

return $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?')
->execute([$name])
->fetchOne();
Expand Down
7 changes: 7 additions & 0 deletions src/Driver/SQLSrv/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Doctrine\DBAL\Driver\ServerInfoAwareConnection;
use Doctrine\DBAL\Driver\SQLSrv\Exception\Error;
use Doctrine\DBAL\Driver\Statement as DriverStatement;
use Doctrine\Deprecations\Deprecation;

use function sqlsrv_begin_transaction;
use function sqlsrv_commit;
Expand Down Expand Up @@ -89,6 +90,12 @@ public function exec(string $sql): int
public function lastInsertId(?string $name = null): string
{
if ($name !== null) {
Deprecation::triggerIfCalledFromOutside(
'doctrine/dbal',
'https://github.com/doctrine/dbal/issues/4687',
'The usage of Connection::lastInsertId() with a sequence name is deprecated.'
);

$result = $this->prepare('SELECT CONVERT(VARCHAR(MAX), current_value) FROM sys.sequences WHERE name = ?')
->execute([$name]);
} else {
Expand Down
Loading

0 comments on commit ea319d6

Please sign in to comment.