Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[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

Merged
merged 2 commits into from
Apr 18, 2014
Merged

Conversation

Tobion
Copy link
Contributor

@Tobion Tobion commented Apr 16, 2014

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).

try {
$this->con->executeQuery("DELETE FROM {$this->tableName} WHERE sess_id = :id", array(
Copy link
Contributor Author

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

Copy link
Member

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

Copy link
Contributor Author

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.

Copy link
Member

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

Copy link
Contributor Author

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, ...

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in #10723

Tobion added 2 commits April 16, 2014 17:38
…ace compliance, compatibility with all drivers (oci8, mysqli, pdo with mysql, sqlsrv, sqlite)
…arameters of all handlers according to interface
@Tobion Tobion changed the title Fix doctrine session [HttpFoundation] Fix DbalSessionHandler Apr 16, 2014
"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)";
}
Copy link
Member

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.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

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

Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Member

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

Copy link

Choose a reason for hiding this comment

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

Copy link
Contributor Author

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

@fabpot
Copy link
Member

fabpot commented Apr 18, 2014

Thank you @Tobion.

@fabpot fabpot merged commit 524bf84 into symfony:2.3 Apr 18, 2014
fabpot added a commit that referenced this pull request Apr 18, 2014
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)
@Tobion Tobion deleted the fix-doctrine-session branch April 18, 2014 23:48
fabpot added a commit that referenced this pull request Apr 21, 2014
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants