Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecated the concept of the fetch mode #4019

Merged
merged 2 commits into from
May 26, 2020

Conversation

morozov
Copy link
Member

@morozov morozov commented May 23, 2020

Q A
Type feature, deprecation
BC Break no

Proposed changes:

  1. The FetchMode class, the UnknownFetchMode exception and the setFetchMode() methods are deprecated as well as the entire concept of the fetch mode.
  2. The fetch() method is deprecated in favor of fetchNumeric(), fetchAssociative() and fetchOne() (like fetchOne() in ZF1).
  3. The fetchAll() method is deprecated in favor of fetchAllNumeric() and fetchAllAssociative(). There's no currently replacement for fetchAll(FETCH_MODE::COLUMN). In a future major version, fetchColumn() will be used as a replacement (like fetchCol() in ZF1).
  4. Connection::fetchAssoc() and ::fetchArray() are deprecated in favor of ::fetchAssociative() and ::fetchNumeric() respectively for consistency.
  5. In order to make the Driver and the DBAL APIs distinct, two forward-compatible result statement interfaces are introduced. The one at the DBAL level extends the one at the Driver level (therefore, it can gain new DBAL-level features w/o having to implement them at the driver level).
  6. Iteration over statements is deprecated. Only DBAL-level statements may be iterated via iterateNumeric(), iterateAssociative() or iterateColumn().
  7. The StatementIterator class is deprecated.
  8. Fetching in the “mixed”/“both” mode is deprecated.

See #4007.

TODO:

  • See if the deprecated methods can be partially reimplemented using the new ones (the new ones don't support mixed fetch mode). Too much work for throwaway code.
  • Add tests for the newly added APIs.
  • Add tests to ensure that forward-incompatible implementations still work.
  • Update slevomat/coding-standard in order to avoid false detection of the code like the following (cannot find the corresponding fixed issue):
    if ($condition) {
        yield from [];
    } else {
        yield from [];
    }

The existing tests are changed to the necessary minimum (only the expected method invocations) and do not represent intentional breaking changes.

@morozov morozov added this to the 2.11.0 milestone May 23, 2020
@morozov morozov force-pushed the deprecate-fetch-mode branch 5 times, most recently from a1535ef to 07d6bd8 Compare May 25, 2020 20:07
@morozov morozov removed the WIP label May 25, 2020
@morozov morozov changed the title Deprecated the concept of fetch mode Deprecated the concept of the fetch mode May 25, 2020
@morozov morozov requested a review from greg0ire May 25, 2020 20:30
*
* @return array<int,array<mixed>>
*/
private function store(array $data, bool $isArray) : array
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 what's the point of that second argument? It's always true, and the first argument is declared as array in the signature

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was needed before the introduction of FetchUtils to implement the "column" fetch modes. It's no longer needed, I’ll remove it.

@morozov
Copy link
Member Author

morozov commented May 25, 2020

Here's some food for thought:

private function iterate(int $mode, ...$arguments) : Traversable
{
parent::setFetchMode($mode, ...$arguments);

  1. We're getting rid of the fetch mode as such and the APIs that allow setting it as a shared state.
  2. We're introducing iterate*() methods at the driver statement level because some drivers natively implement it.
  3. In fact, PDO is the only such driver, and "natively" here is a stretch since PDO itself is a wrapper. Being able to leverage this driver capability requires relying on the shared state that we want to avoid.

With that said, I think we should not introduce iterate* methods at the driver level and leave them only at the DBAL level.

@morozov morozov merged commit 256cefa into doctrine:2.11.x May 26, 2020
@morozov morozov deleted the deprecate-fetch-mode branch May 26, 2020 13:45
@morozov morozov self-assigned this May 26, 2020
@derrabus
Copy link
Member

There's no currently replacement for fetchAll(FETCH_MODE::COLUMN).

If I had such a piece of code in my application and wanted to remove calls to deprecated functionality, what would be my upgrade path here?

nicolas-grekas added a commit to symfony/symfony that referenced this pull request May 28, 2020
This PR was merged into the 3.4 branch.

Discussion
----------

Handle fetch mode deprecation of DBAL 2.11.

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | no
| License       | MIT
| Doc PR        | N/A

See doctrine/dbal#4019

DBAL has deprecated PDO-style fetch modes in favor of more explicit methods.

Commits
-------

ed51855 Handle fetch mode deprecation of DBAL 2.11.
@morozov
Copy link
Member Author

morozov commented May 28, 2020

If I had such a piece of code in my application and wanted to remove calls to deprecated functionality, what would be my upgrade path here?

There's no immediate upgrade path. You'll have to keep using the deprecated API until the next major release where it will be implemented by fetchColumn().

@greg0ire
Copy link
Member

@morozov I didn't spot this issue, is that why you suggested to name the new method fetchCol()? It's not a perfect name because of the abbrevation, but it will make the upgrade experience better (and maybe we can then migrate to fetchColumn() in 4.x)

fabpot added a commit to symfony/symfony that referenced this pull request Jun 8, 2020
… 2.11+ (xabbuh)

This PR was merged into the 5.1 branch.

Discussion
----------

[Messenger] fix forward compatibility with Doctrine DBAL 2.11+

| Q             | A
| ------------- | ---
| Branch?       | 5.1
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Tickets       |
| License       | MIT
| Doc PR        |

The methods will be deprecated in 2.11 (see doctrine/dbal#4019), but the forward compatibility layer is only present in 3.0 (see doctrine/dbal#4007).

Commits
-------

bca4f99 fix forward compatibility with Doctrine DBAL 2.11+
nicolas-grekas pushed a commit to symfony/symfony that referenced this pull request Jun 9, 2020
… 2.11+ (xabbuh)

This PR was merged into the 5.1 branch.

Discussion
----------

[Messenger] fix forward compatibility with Doctrine DBAL 2.11+

| Q             | A
| ------------- | ---
| Branch?       | 5.1
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Tickets       |
| License       | MIT
| Doc PR        |

The methods will be deprecated in 2.11 (see doctrine/dbal#4019), but the forward compatibility layer is only present in 3.0 (see doctrine/dbal#4007).

Commits
-------

bca4f99 fix forward compatibility with Doctrine DBAL 2.11+
symfony-splitter pushed a commit to symfony/messenger that referenced this pull request Jun 9, 2020
… 2.11+ (xabbuh)

This PR was merged into the 5.1 branch.

Discussion
----------

[Messenger] fix forward compatibility with Doctrine DBAL 2.11+

| Q             | A
| ------------- | ---
| Branch?       | 5.1
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Tickets       |
| License       | MIT
| Doc PR        |

The methods will be deprecated in 2.11 (see doctrine/dbal#4019), but the forward compatibility layer is only present in 3.0 (see doctrine/dbal#4007).

Commits
-------

bca4f9970b fix forward compatibility with Doctrine DBAL 2.11+
@tswcode
Copy link

tswcode commented Sep 22, 2020

I just stumbled upon the deprecated methods.
Everything is cleary documentated, but i cannot find the special PDO fetch method for "FETCH_KEY_PAIR".
Let's assume a sql, summarizing entity ids and a special count. Then I need the workflow like the old one:

$counts = $sqlStatement->fetchAll(PDO::FETCH_KEY_PAIR, 0); $sqlStatement->free();

The result has been an array with the ids as keys and counts as values.
Will you include this in the future or do I have to do implement my own method for this?

@morozov
Copy link
Member Author

morozov commented Sep 22, 2020

@tswcode PDO::FETCH_KEY_PAIR was never supported by DBAL. It was and is supported by PDO but not by other drivers. I was going to start implementing it but then realized that it's just as simple as:

foreach ($statement->iterateNumeric() as [$key => $value]) {
    // your code goes here
}

At the same time, implementing it in the DBAL will require it to handle the error when the resulting record set contains fewer than two columns (not sure how PDO handles that). If it's implemented in the userland, it's clear that the user should do the error handling.

Is there a case when the above doesn't work for you and you need it implemented in DBAL?

@morozov
Copy link
Member Author

morozov commented Sep 22, 2020

$conn = new PDO('sqlite::memory:');
$stmt = $conn->query('SELECT 1');

$stmt->fetchAll(PDO::FETCH_KEY_PAIR);

// PDOStatement::fetchAll(): SQLSTATE[HY000]: General error: PDO::FETCH_KEY_PAIR fetch mode requires the result set to contain extactly 2 columns

Looks like PDO is strict enough about the number of columns. I think we can implement this in DBAL at the wrapper level which will automatically cover all supported drivers.

@tswcode
Copy link

tswcode commented Sep 22, 2020

@morozov Indeed it could be implemented in userland, yet I always try to avoid boilerplate code, when using this fetch mode. That would be great, if the DBAL would provide a method, so that i can replace the deprecated one.

@morozov
Copy link
Member Author

morozov commented Sep 23, 2020

@tswcode could you file a feature request please?

@tmotyl
Copy link

tmotyl commented Sep 30, 2020

Btw, do you consider providing rector rule to help project migrate to doctrine v3 where the deprecated methods will be dropped?

@morozov
Copy link
Member Author

morozov commented Sep 30, 2020

No, but it would be nice if somebody kicked that off. As far as I understand, Rector has some rules for other Doctrine projects, so the development would have to be done in its repo.

@jokaorgua
Copy link

Could anyone please advise how to change current deprecated code without losing functionality?

$query = $this->connection->createQueryBuilder()
    ->select()....

$result = $query->execute()->fetchAll(FetchMode::STANDARD_OBJECT);

how to fetch an array of objects after this merge?

@derrabus
Copy link
Member

derrabus commented Oct 2, 2020

$result = array_map(
    static fn (array $row) => (object) $row,
    $query->execute()->fetchAllAssociative()
);

@jokaorgua
Copy link

$result = array_map(
    static fn (array $row) => (object) $row,
    $query->execute()->fetchAllAssociative()
);

thanks. but this seems like a hack. are there any docs where it can be found why developers decided to remove the ability to fetch objects?

@morozov
Copy link
Member Author

morozov commented Oct 2, 2020

@jokaorgua please see #3070.

@derrabus
Copy link
Member

derrabus commented Oct 2, 2020

thanks. but this seems like a hack.

It is a hack to unblock codebases that rely on object fetching. In the long run, that code should be migrated to use associative arrays instead.

beberlei added a commit to beberlei/dbal that referenced this pull request Mar 6, 2021
beberlei added a commit to beberlei/dbal that referenced this pull request Mar 7, 2021
rgrellmann added a commit to Rossmann-IT/dbal that referenced this pull request Mar 7, 2021
Release [2.11.0](https://github.com/doctrine/dbal/milestone/77)

2.11.0
======

- Total issues resolved: **7**
- Total pull requests resolved: **55**
- Total contributors: **8**

Improvement,Prepared Statements,SQL Server,Types,pdo_sqlsrv,sqlsrv
------------------------------------------------------------------

 - [4274: Support ASCII parameter binding](doctrine#4274) thanks to @gjdanis

Documentation
-------------

 - [4271: Add explanation about implicit indexes](doctrine#4271) thanks to @greg0ire

Deprecation,Error Handling
--------------------------

 - [4253: Deprecate DBAL\DBALException in favor of DBAL\Exception](doctrine#4253) thanks to @morozov

CI
--

 - [4251: Setup automatic release workflow](doctrine#4251) thanks to @greg0ire

Deprecation,Schema Managers
---------------------------

 - [4230: Deprecate the functionality of dropping client connections when dropping a database](doctrine#4230) thanks to @morozov

Deprecation,Platforms
---------------------

 - [4229: Deprecate more AbstractPlatform methods](doctrine#4229) thanks to @morozov
 - [4132: Deprecate AbstractPlatform::fixSchemaElementName()](doctrine#4132) thanks to @morozov

Improvement,Test Suite
----------------------

 - [4215: Remove test group configuration leftovers](doctrine#4215) thanks to @morozov
 - [4080: Update PHPUnit to 9.2](doctrine#4080) thanks to @morozov
 - [4079: Forward compatibility with PHPUnit 9.3](doctrine#4079) thanks to @morozov
 - [3923: Removed performance tests](doctrine#3923) thanks to @morozov

Deprecation,Schema
------------------

 - [4213: Deprecate the Synchronizer package](doctrine#4213) thanks to @morozov

Blocker,Improvement,PHP,Test Suite
----------------------------------

 - [4201: Update PHPUnit to 9.3](doctrine#4201) thanks to @morozov

Blocker,PHP,Test Suite
----------------------

 - [4196: The test suite uses the deprecated at() matcher](doctrine#4196) thanks to @morozov

Connections,Deprecation,Documentation
-------------------------------------

 - [4175: Additional deprecation note for PrimaryReplicaConnection::query()](doctrine#4175) thanks to @morozov

Connections,Deprecation,Prepared Statements
-------------------------------------------

 - [4165: Deprecated usage of wrapper components as implementations of driver-level interfaces](doctrine#4165) thanks to @morozov
 - [4020: Deprecated Connection::project(), Statement::errorCode() and errorInfo()](doctrine#4020) thanks to @morozov

Connections,Deprecation
-----------------------

 - [4163: Deprecate duplicate and ambiguous wrapper connection methods](doctrine#4163) thanks to @morozov

Error Handling,Improvement,Types
--------------------------------

 - [4145: Add TypeRegistry constructor](doctrine#4145) thanks to @morozov

Deprecation,Drivers,Improvement,pdo_mysql,pdo_oci,pdo_pgsql,pdo_sqlite,pdo_sqlsrv
---------------------------------------------------------------------------------

 - [4144: Deprecate classes in Driver\PDO* namespaces](doctrine#4144) thanks to @morozov

Connections,Documentation,Improvement
-------------------------------------

 - [4139: Mark connection constructors internal](doctrine#4139) thanks to @morozov

Deprecation,Drivers,Error Handling
----------------------------------

 - [4137: Deprecate driver exception conversion APIs](doctrine#4137) thanks to @morozov
 - [4112: Deprecate DriverException::getErrorCode()](doctrine#4112) thanks to @morozov

Configuration,Connections,Deprecation,Error Handling
----------------------------------------------------

 - [4134: Deprecate some DBALException factory methods](doctrine#4134) thanks to @morozov

Code Style,Documentation
------------------------

 - [4133: Fix more issues introduced by the deprecation of driver classes](doctrine#4133) thanks to @morozov

BC Break,Drivers,Error Handling,pdo_sqlsrv,sqlsrv
-------------------------------------------------

 - [4131: Restore the PortWithoutHost exception parent class](doctrine#4131) thanks to @morozov

Code Style,Improvement,Static Analysis
--------------------------------------

 - [4123: Remove the no longer needed error suppressions](doctrine#4123) thanks to @morozov

Deprecation,Drivers,Error Handling,Improvement
----------------------------------------------

 - [4118: Deprecate ExceptionConverterDriver](doctrine#4118) thanks to @morozov

Bug,Connections,Improvement,Prepared Statements
-----------------------------------------------

 - [4117: Fixes for the recently introduced driver-level deprecations](doctrine#4117) thanks to @morozov

Connections,Deprecation,Platform Detection
------------------------------------------

 - [4114: Deprecate ServerInfoAwareConnection#requiresQueryForServerVersion() as an implementation detail](doctrine#4114) thanks to @morozov

Deprecation,Prepared Statements,SQL Parser,oci8
-----------------------------------------------

 - [4110: Mark non-interface OCI8 driver methods internal](doctrine#4110) thanks to @morozov

Connections,Deprecation,Drivers,Improvement,Prepared Statements
---------------------------------------------------------------

 - [4100: Deprecate inconsistently and ambiguously named driver-level classes](doctrine#4100) thanks to @morozov

Connections,Improvement
-----------------------

 - [4092: Remove Connection::$isConnected](doctrine#4092) thanks to @morozov

Configuration,Connections
-------------------------

 - [4086: Mark Connection::getParams() internal](doctrine#4086) thanks to @morozov

Bug,Drivers,ibm_db2
-------------------

 - [4085: The IBM DB2 driver Exception class must implement the DriverException interface](doctrine#4085) thanks to @morozov

PHP
---

 - [4078: Bump PHP requirement to 7.3 as of DBAL 2.11.0](doctrine#4078) thanks to @morozov

Connections,Databases,Deprecation,Drivers
-----------------------------------------

 - [4068: Deprecate Driver::getDatabase()](doctrine#4068) thanks to @morozov

Deprecation,Improvement,Portability
-----------------------------------

 - [4061: Deprecated platform-specific portability mode constants](doctrine#4061) thanks to @morozov

 - [4054: &doctrine#91;doctrineGH-4052&doctrine#93; Deprecate MasterSlaveConnection and rename to PrimaryReplicaConnection](doctrine#4054) thanks to @beberlei and @albe
 - [4017: Improve help of dbal:run-sql command](doctrine#4017) thanks to @ostrolucky

Code Style,Improvement
----------------------

 - [4050: Update doctrine/coding-standard to 8.0](doctrine#4050) thanks to @morozov

Cache,Deprecation,Improvement,Prepared Statements
-------------------------------------------------

 - [4049: Replace forward-compatible ResultStatement interfaces with Result](doctrine#4049) thanks to @morozov

Cache,Improvement,Prepared Statements
-------------------------------------

 - [4048: Make caching layer not rely on closeCursor()](doctrine#4048) thanks to @morozov

Deprecation,Improvement,Prepared Statements
-------------------------------------------

 - [4037: Introduce Statement::fetchFirstColumn()](doctrine#4037) thanks to @morozov
 - [4019: Deprecated the concept of the fetch mode](doctrine#4019) thanks to @morozov

Bug,Documentation,Improvement,Prepared Statements
-------------------------------------------------

 - [4034: Additional changes based on the discussion in doctrine#4007](doctrine#4034) thanks to @morozov

Connections,Console,Improvement
-------------------------------

 - [3956: allow using multiple connections for CLI commands](doctrine#3956) thanks to @dmaicher

Deprecation,Logging
-------------------

 - [3935: Deprecate EchoSQLLogger](doctrine#3935) thanks to @morozov

Improvement,Packaging
---------------------

 - [3924: Actualize the content of the .gitattributes file](doctrine#3924) thanks to @morozov

Azure,Deprecation,Drivers,Drizzle,MariaDB,Platforms,PostgreSQL,SQL Anywhere,SQL Server,Sharding,pdo_ibm
-------------------------------------------------------------------------------------------------------

 - [3905: Deprecate the usage of the legacy platforms and drivers](doctrine#3905) thanks to @morozov

Deprecation,Query
-----------------

 - [3864: CompositeExpression and()/or() factory methods](doctrine#3864) thanks to @BenMorel
 - [3853: Deprecate calling QueryBuilder methods with an array argument](doctrine#3853) thanks to @BenMorel and @morozov

Deprecation,Tools
-----------------

 - [3861: Deprecated the usage of the Version class](doctrine#3861) thanks to @morozov

Improvement,Query
-----------------

 - [3852: First parameter of ExpressionBuilder::and/or() mandatory](doctrine#3852) thanks to @BenMorel

Deprecation,Improvement,Query
-----------------------------

 - [3851: Rename andX() / orX() methods](doctrine#3851) thanks to @BenMorel
 - [3850: Prepare CompositeExpression for immutability](doctrine#3850) thanks to @BenMorel

# gpg: Signature made Mon Sep 21 01:47:31 2020
# gpg:                using DSA key 1BEDEE0A820BC30D858F9F0C2C3A645671828132
# gpg: Can't check signature: No public key

# Conflicts:
#	README.md
#	lib/Doctrine/DBAL/Driver/AbstractOracleDriver.php
#	lib/Doctrine/DBAL/Driver/OCI8/Driver.php
#	lib/Doctrine/DBAL/Version.php
beberlei added a commit to beberlei/dbal that referenced this pull request Mar 22, 2021
symfony-splitter pushed a commit to symfony/messenger that referenced this pull request Sep 28, 2021
… 2.11+ (xabbuh)

This PR was merged into the 5.1 branch.

Discussion
----------

[Messenger] fix forward compatibility with Doctrine DBAL 2.11+

| Q             | A
| ------------- | ---
| Branch?       | 5.1
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Tickets       |
| License       | MIT
| Doc PR        |

The methods will be deprecated in 2.11 (see doctrine/dbal#4019), but the forward compatibility layer is only present in 3.0 (see doctrine/dbal#4007).

Commits
-------

bca4f9970b fix forward compatibility with Doctrine DBAL 2.11+
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 29, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants