-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Messenger] use database platform to convert correctly the DateTime #32456
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
Conversation
':created_at' => self::formatDateTime($now), | ||
':available_at' => self::formatDateTime($availableAt), | ||
':created_at' => $this->convertDateTime($now), | ||
':available_at' => $this->convertDateTime($availableAt), |
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.
We could even use the datetime directly as parameter and pass the Doctrine DBAL types (in the third argument) for these, so that DBAL handles the conversion calls for us (and would avoid the need to create a public convertDateTime
too, as tests can do the same)
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 I don't understand.
Because in this file, the executeQuery
method is not the same method of https://github.com/doctrine/dbal/blob/66f28111d57fdc3508d4c97989257291702176cf/lib/Doctrine/DBAL/Connection.php#L883.
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.
it is the same. The driverConnection
propert contains a Doctrine\DBAL\Connection
, which is exactly the code I linked.
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.
I think @stof means we could use \Doctrine\DBAL\Connection::executeQuery
which has the types as parameter.
* | ||
* @deprecated since Symfony 4.4, use convertDateTime instead | ||
*/ | ||
public static function formatDateTime(\DateTimeInterface $dateTime, AbstractPlatform $platform) |
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.
adding a required argument is a BC break, which is a bad idea for a method kept as a BC layer...
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.
Oh yes, I will add a new commit to fix this.
* | ||
* @deprecated since Symfony 4.4, use convertDateTime instead | ||
*/ | ||
public static function formatDateTime(\DateTimeInterface $dateTime, AbstractPlatform $platform = null) |
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.
You've added a second parameter to the method, but I can find any calls with that parameter being set.
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.
See my commits in order and you will understand my logic :)
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.
that's a BC break, can't be done
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.
it is not a question of commits in order. The existing method that you want to deprecate must not change signature.
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.
you should remove the new argument and always use $dateTime->format('Y-m-d\TH:i:s')
in this deprecated method. Your current change still requires changing the caller to add the platform to benefit from the fix, at which point it is as easy to switch to the new method instead.
/** | ||
* @throws DBALException | ||
* | ||
* @deprecated since Symfony 4.4, use convertDateTime instead |
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 deprecation must be done in a separate PR, targetting 4.4 (this PR is for 4.3)
* | ||
* @deprecated since Symfony 4.4, use convertDateTime instead | ||
*/ | ||
public static function formatDateTime(\DateTimeInterface $dateTime, AbstractPlatform $platform = null) |
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.
you should remove the new argument and always use $dateTime->format('Y-m-d\TH:i:s')
in this deprecated method. Your current change still requires changing the caller to add the platform to benefit from the fix, at which point it is as easy to switch to the new method instead.
} | ||
|
||
/** | ||
* @throws DBALException |
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.
should be removed. We don't care about this one here (and anyway, this API should not be public, so this would be useless)
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.
#32456 (comment)
@roukmoute do you have time to finish the PR?
yep, I've finally received my laptop today so I can fix it this week-end |
src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php
Outdated
Show resolved
Hide resolved
@Tobion Any news? |
|
||
private function getDateTimeType() | ||
{ | ||
if (!class_exists('\Doctrine\DBAL\Types\Types')) { |
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.
please use \Doctrine\DBAL\Types\Types::class
src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php
Outdated
Show resolved
Hide resolved
':redeliver_limit' => self::formatDateTime($redeliverLimit), | ||
':redeliver_limit' => $redeliverLimit, | ||
], [ | ||
':now' => Type::getType($this->getDateTimeType()), |
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.
do you really need to pass the type instance here with Type::getType
? I don't think so. Passing the constant value should be enough.
@@ -281,22 +290,17 @@ private function createQueryBuilder(): QueryBuilder | |||
->from($this->configuration['table_name'], 'm'); | |||
} | |||
|
|||
private function executeQuery(string $sql, array $parameters = []) | |||
private function executeQuery(string $sql, array $parameters = [], ?array $types = []) |
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.
why does $types need to be nullable?
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.
Without that, few tests does not passes.
1) Symfony\Component\Messenger\Tests\Transport\Doctrine\ConnectionTest::testGetAMessageWillChangeItsStatus
TypeError: Argument 3 passed to Symfony\Component\Messenger\Transport\Doctrine\Connection::executeQuery() must be of the type array, null given, called in /home/roukmoute/workspace/symfony/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php on line 150
Would you prefer I change theses tests to pass without this nullable?
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 mocks probably need to be fixed so it's does not return a null which violates the contract.
@@ -306,20 +314,20 @@ private function getSchema(): Schema | |||
{ | |||
$schema = new Schema([], [], $this->driverConnection->getSchemaManager()->createSchemaConfig()); | |||
$table = $schema->createTable($this->configuration['table_name']); | |||
$table->addColumn('id', Type::BIGINT) | |||
$table->addColumn('id', Types::BIGINT) |
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.
you cannot require Types
as it's not released in dbal yet. please just keep using Type
everywhere. we can handle the deprecation of it in the future when it's actually released.
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.
You're right!
Would like a method equivalent with checking if the class exist?
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.
only use Type in this PR please. feel free to create a second PR with a solution for the future deprecation
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.
It's still not consistent. Here you implemented the fallback
symfony/src/Symfony/Component/Messenger/Transport/Doctrine/Connection.php
Lines 346 to 352 in 1e04345
private function getDateTimeType() | |
{ | |
if (!class_exists(\Doctrine\DBAL\Types\Types::class)) { | |
return Type::DATETIME; | |
} | |
return \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE; |
$table->addColumn('created_at', Type::DATETIME) |
getDateTimeType
helper everywhere, or don't add it at all.
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.
I asked to not use the new Types
class because in order to fully fix the deprcation of Type
, you would also need to add the fallback of the other types like "text" in
$table->addColumn('headers', Type::TEXT) |
@@ -108,7 +108,7 @@ public function send(string $body, array $headers, int $delay = 0): string | |||
$now = new \DateTime(); | |||
$availableAt = (clone $now)->modify(sprintf('+%d seconds', $delay / 1000)); | |||
|
|||
$queryBuilder = $this->driverConnection->createQueryBuilder() | |||
$queryBuilder = $this->createQueryBuilder() |
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.
Why changing this? It's doing an insert, so the helper method seems useless here.
null, | ||
null, | ||
null, | ||
Type::getType($this->getDateTimeType()), |
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.
you don't need to call Type::getType
. it should be enough to pass the string constant like it's done in other places
$this->getDateTimeType(), |
return Type::DATETIME; | ||
} | ||
|
||
return \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE; |
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.
please add a use statement
@@ -280,12 +292,11 @@ private function createQueryBuilder(): QueryBuilder | |||
->from($this->configuration['table_name'], 'm'); | |||
} | |||
|
|||
private function executeQuery(string $sql, array $parameters = []) | |||
private function executeQuery(string $sql, array $parameters = [], array $types = []) | |||
{ | |||
$stmt = null; |
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 needed anymore
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.
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.
I commented on the line $stmt = null;
. The initialization is not needed anymore because it's always set.
null, | ||
null, | ||
null, | ||
Type::getType(Type::DATETIME), |
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.
In #32456 (comment) I asked to only pass the constant. No need to call Type::getType
anywhere. Please it's very painful to review this PR over and over and the same problems keep being there.
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.
Please squash all commits to a single commit. Our tool cannot do it because of different commiters.
... and one more bug fixed, thank you @roukmoute. |
… DateTime (roukmoute) This PR was merged into the 4.3 branch. Discussion ---------- [Messenger] use database platform to convert correctly the DateTime | Q | A | ------------- | --- | Branch? | 4.3 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | yes <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tests pass? | yes | Fixed tickets | #32427 | License | MIT In Doctrine Messenger the method `\Symfony\Component\Messenger\Transport\Doctrine\Connection::formatDateTime()` is used to format dateTime into this: `Y-m-d\TH:i:s`. But this is not supported in all databases platform. Here we use the database platform to convert correctly the dateTime. Commits ------- cfa1156 Format DateTime depending on database platform
Thanks for all your time @Tobion |
In Doctrine Messenger the method
\Symfony\Component\Messenger\Transport\Doctrine\Connection::formatDateTime()
is used to format dateTime into this:Y-m-d\TH:i:s
.But this is not supported in all databases platform.
Here we use the database platform to convert correctly the dateTime.