Browse Source

Fixes #11401: Fixed `yii\web\DbSession` concurrency issues when writing and regenerating IDs

tags/2.0.14
Alexander Makarov 7 years ago committed by GitHub
parent
commit
64d57043b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      framework/CHANGELOG.md
  2. 29
      framework/web/DbSession.php
  3. 2
      tests/framework/db/sqlite/CommandTest.php
  4. 11
      tests/framework/web/session/sqlite/DbSessionTest.php

1
framework/CHANGELOG.md

@ -4,6 +4,7 @@ Yii Framework 2 Change Log
2.0.14 under development
------------------------
- Bug #11401: Fixed `yii\web\DbSession` concurrency issues when writing and regenerating IDs (samdark, andreasanta, cebe)
- Bug #15523: `yii\web\Session` settings could now be configured after session is started (StalkAlex, rob006, daniel1302, samdark)
- Enh #15216: Added `yii\web\ErrorHandler::$traceLine` to allow opening file at line clicked in IDE (vladis84)
- Enh #14488: Added support for X-Forwarded-Host to `yii\web\Request`, fixed `getServerPort()` usage (si294r, samdark)

29
framework/web/DbSession.php

@ -112,11 +112,13 @@ class DbSession extends MultiFieldSession
return;
}
$query = new Query();
$row = $query->from($this->sessionTable)
->where(['id' => $oldID])
->createCommand($this->db)
->queryOne();
$row = $this->db->useMaster(function() use ($oldID) {
return (new Query())->from($this->sessionTable)
->where(['id' => $oldID])
->createCommand($this->db)
->queryOne();
});
if ($row !== false) {
if ($deleteOldSession) {
$this->db->createCommand()
@ -169,24 +171,9 @@ class DbSession extends MultiFieldSession
// exception must be caught in session write handler
// http://us.php.net/manual/en/function.session-set-save-handler.php#refsect1-function.session-set-save-handler-notes
try {
$query = new Query();
$exists = $query->select(['id'])
->from($this->sessionTable)
->where(['id' => $id])
->createCommand($this->db)
->queryScalar();
$fields = $this->composeFields($id, $data);
$fields = $this->typecastFields($fields);
if ($exists === false) {
$this->db->createCommand()
->insert($this->sessionTable, $fields)
->execute();
} else {
unset($fields['id']);
$this->db->createCommand()
->update($this->sessionTable, $fields, ['id' => $id])
->execute();
}
$this->db->createCommand()->upsert($this->sessionTable, $fields)->execute();
} catch (\Exception $e) {
Yii::$app->errorHandler->handleException($e);
return false;

2
tests/framework/db/sqlite/CommandTest.php

@ -32,7 +32,7 @@ class CommandTest extends \yiiunit\framework\db\CommandTest
public function testUpsert(array $firstData, array $secondData)
{
if (version_compare($this->getConnection(false)->getServerVersion(), '3.8.3', '<')) {
$this->markTestSkipped('SQLite < 3.8.3 does nt support "WITH" keyword.');
$this->markTestSkipped('SQLite < 3.8.3 does not support "WITH" keyword.');
return;
}

11
tests/framework/web/session/sqlite/DbSessionTest.php

@ -7,6 +7,8 @@
namespace yiiunit\framework\web\session\sqlite;
use Yii;
/**
* Class DbSessionTest.
*
@ -17,6 +19,15 @@ namespace yiiunit\framework\web\session\sqlite;
*/
class DbSessionTest extends \yiiunit\framework\web\session\AbstractDbSessionTest
{
protected function setUp()
{
parent::setUp();
if (version_compare(Yii::$app->get('db')->getServerVersion(), '3.8.3', '<')) {
$this->markTestSkipped('SQLite < 3.8.3 does not support "WITH" keyword.');
}
}
protected function getDriverNames()
{
return ['sqlite'];

Loading…
Cancel
Save