-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Improve forward compatibility between 2.x and 3.0 #4529
Improve forward compatibility between 2.x and 3.0 #4529
Conversation
3173be4
to
d1b7d7d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is very important, however I think we should be bolder and move the V3Result
to be Doctrine\DBAL\Result
otherwise the API will change again in 3.0 and you cannot rely on typing the result tpye, example:
use Doctrine\DBAL\Result;
public function performQuery()
{
$result = $this->connection->executeQuery('SELECT * FROM orders');
return $this->convertQueryResult($result);
}
private function convertQueryResult(Result $result)
{
}
3a45490
to
42249a0
Compare
@morozov Drivers statements no longer implements wrapper level Result. It break some unit tests because of ResultStatement wrapper. The following code will no longer work for example. $statement = $connection->executeQuery('SELECT "something"');
if ($statement instanceof ArrayStatement) {
// True in 2.12.x version, false in this branch
} I can't see any generic solution for this kind of edge case. Maybe we should let the user enable the Statement wrapper on purpose. We will avoid the risk of regression and allow to resolve deprecation on 2.x. It can be implemented by adding a ForwardCompatibility\Connection wrapper for example. |
If it's an opt-in layer, then there will be no improvement for static analysis, because the analyzers won't be able to detect the opt-in. As for the examples that currently don't work, e.g.: $connection->executeQuery('SELECT "something"')->fetchNumeric(); There's already an alternative: $connection->fetchNumeric('SELECT "something"'); |
Yes this edge case break is ok imho, the api is returning a statement, expecting a specific statement is not part of the interface |
ea422e9
to
9868993
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
@@ -238,25 +238,25 @@ public function testFetchingAllRowsSavesCache(callable $fetchAll): void | |||
public static function fetchAllProvider(): iterable | |||
{ | |||
yield 'fetchAll' => [ | |||
static function (ResultCacheStatement $statement): void { | |||
static function (ForwardCompatibility\Result $statement): void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The expected ResultCacheStatement
type was unnecessarily specific. Let's loosen it to Driver\ResultStatement
. If it had been implemented this way, it wouldn't require a change now.
$statement->fetchAllNumeric(); | ||
}, | ||
]; | ||
|
||
yield 'fetchFirstColumn' => [ | ||
static function (ResultCacheStatement $result): void { | ||
static function (ForwardCompatibility\Result $result): void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#4529 (comment) applies to all the above cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure to understand here. ResultStament interface does not contain the fetchAllAssociative(), fetchAllNumeric() & fetchFirstColumn() methods. I can use the Doctrine\DBAL\Result interface, if we prefer not relying on concrete object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, it should have been Driver\Result
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, so the expected type was not unnecessarily specific: it was the type that implemented both of the old and new APIs. It still implements them but now the fetch*()
methods return another class that implements both interfaces as well. Looks good 👍
@mdumoulin It looks good. I'd like all the changes to be squashed in one commit. Please do or otherwise, I'll do it later before the merge. |
ef2eb93
to
0beb8c2
Compare
@morozov Great ! I just squashed all my commits in a single one. |
Make Doctrine\DBAL\Connection executeQuery() & executeCachedQuery() return a result implementing the following v3.0 features : - fetchNumeric() - fetchAssociative() - fetchOne() - fetchAllNumeric() - fetchAllAssociative() - fetchAllKeyValue() - fetchAllAssociativeIndexed() - fetchFirstColumn() - iterateNumeric() - iterateAssociative() - iterateKeyValue() - iterateAssociativeIndexed() - iterateColumn() - rowCount() - columnCount() - free()
0beb8c2
to
4297f50
Compare
Thanks, @mdumoulin! |
Summary
The current Doctrine\DBAL\Connection executeQuery(...) and executeCacheQuery() return a ResultStatement interface object. This PR try to improve forward compatibility between v2.x & v3.0 by adding some of missing features to Result returned by Connection :
I used this version as reference : https://github.com/doctrine/dbal/blob/3.0.x/src/Result.php
Examples
Static analysis error
Here under, methods which throw a static analysis error in phpstan but actually work. This is all methods defined in Abstraction\Result interface :
The outpout pattern when running phpstan is the following :
Not available methods
Here under, methods which throw undefined method fatal & static analyse errors. This is all methods added in Abstraction\V3Result interface :
The output pattern when trying to use one of those methods :
Implementation key points
The strategy is to :