-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[HttpFoundation] Fix DbalSessionHandler #10720
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
try { | ||
$this->con->executeQuery("DELETE FROM {$this->tableName} WHERE sess_id = :id", array( |
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.
executeQuery is not part of Doctrine\DBAL\Driver\Connection (only in Doctrine\DBAL\Connection) so this wasn't working without wrapper
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 expectation of the class was actually Doctrine\DBAL\Connection
, which is the public facade of Doctrine.
Given the class is throwing a fatal error if usign the internal connection instead of the public class anyway, we can fix the typehint without breaking BC. It will simplify your implementation a lot
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.
Maybe, but typehinting the interface instead of the wrapper makes sense. And I already found a solution now which is only relevant for the MERGE SQL.
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 in this case. Doctrine\DBAL\Driver\Connection
is the interface for internal implementations for each driver. Doctrine\DBAL\Connection
is the public API of DBAL. The fact that Doctrine\DBAL\Connection
implements Doctrine\DBAL\Driver\Connection
is a legacy mistake which cannot be fixed until Doctrine 3.0 because of BC. It totally makes sense to depend on the public API rather than on the internal one
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 that case the doctrine phpdoc needs an update. Driver connection should be marked as internal and the description of Connection is also irritating
A wrapper around a Doctrine\DBAL\Driver\Connection that adds features like events, ...
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.
agreed. reported as http://www.doctrine-project.org/jira/browse/DBAL-867
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.
Btw, Symfony\Component\Security\Acl\Dbal\AclProvider and Symfony\Component\Security\Acl\Dbal\MutableAclProvider also use the wrong connection typehint.
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.
Fixed in #10723
…ace compliance, compatibility with all drivers (oci8, mysqli, pdo with mysql, sqlsrv, sqlite)
…arameters of all handlers according to interface
"WHEN MATCHED THEN UPDATE SET $this->dataCol = :data;"; | ||
case $platform instanceof SqlitePlatform || 'sqlite' === $pdoDriver: | ||
return "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time)"; | ||
} |
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.
PostgreSQL is missing here... like in the other PR but I totally forgot to mention it back then. The problem is that PostgreSQL does not support upserts but there are some workarounds.
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.
Yes I already read that when researching for upserts in each database engine. And this article says that postgresql does not have upserts and wishes there was one. So I'm not sure what you expect here?
The workaround, that I already implemented as fallback, is to use DELETE -> INSERT
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 could use a custom database function, but that will require someone manual work trough.
http://koo.fi/blog/2014/01/04/upsert-methods-for-postgresql/
For PostgreSQL 9.1 you can use a writable CTE.
http://stackoverflow.com/questions/1109061/insert-on-duplicate-update-in-postgresql/8702291#8702291
I wonder if checking if the id exists is faster then deleting it and then directly inserting it.
Knowing that id is unique (indexed) it should not be to slow.
Edit. To bad there is no clear answer on the performance question.
http://stackoverflow.com/questions/4901475/using-postgres-sql-what-is-the-fastest-transaction-to-emulate-an-upsert-for-a-s
Edit2. Ah wait! you can update and then check the affected-rows count to see if any changes have happened.
But its vulnerable for race conditions. Is this really an issue for the session-id?
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.
update -> affected rows = 0 -> insert
does not work well when the row did not change (two simultaneoes writes with same data) or. then the insert will create duplicate key again. it's also not safe against race conditions in high concurrency (even in serializable isolation level, mysql will throw a deadlock when using two such parallel transactions, same for delete -> insert though)
one could also catch exceptions on duplicate key and ignore them. but it's not easily possible to do this correcly for all databases because each one has different subclasses of 23xxx sql state.
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.
@Tobion DBAL 2.5 is throwing a specific exception for constraint violations, so this will help
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.
http://www.depesz.com/2012/06/10/why-is-upsert-so-complicated/ is an importand read for postgresql.
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.
@stof but there are many different types of constraint violations and we only need to ignore one of it
Thank you @Tobion. |
This PR was merged into the 2.3 branch. Discussion ---------- [HttpFoundation] Fix DbalSessionHandler | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT This is basically the same as #10652 for the DbalSessionHandler. - First commit fixes fix DbalSessionHandler for high concurrency, interface compliance, compatibility with all drivers (oci8, mysqli, pdo with mysql, sqlsrv, sqlite). - Second commit updates phpdoc of SessionHandlerInterface and unifies parameters of all handlers according to interface (so inheritdoc actually makes sense). Commits ------- 524bf84 [HttpFoundation] update phpdoc of SessionHandlerInterface and unify parameters of all handlers according to interface ccdfbe6 [Doctrine Bridge] fix DbalSessionHandler for high concurrency, interface compliance, compatibility with all drivers (oci8, mysqli, pdo with mysql, sqlsrv, sqlite)
This PR was merged into the 2.3 branch. Discussion ---------- [Doctrine Bridge] simplify session handler | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no because the driver connection could not be used anyway before | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT Use main connection as discussed in #10720 Commits ------- 6518b74 [Doctrine Bridge] simplify session handler by using main connection
This is basically the same as #10652 for the DbalSessionHandler.