Browse Source

Fix #18447: Do not use `getLastInsertID` to get PK from insert query to lower collision probability for concurrent inserts

tags/2.0.41
Valerii Gorbachev 4 years ago committed by GitHub
parent
commit
0571e806b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      framework/CHANGELOG.md
  2. 7
      framework/db/mssql/Schema.php
  3. 20
      tests/framework/db/mssql/SchemaTest.php

2
framework/CHANGELOG.md

@ -4,7 +4,7 @@ Yii Framework 2 Change Log
2.0.41 under development
------------------------
- no changes in this release.
- Enh #18447: Do not use `getLastInsertID` to get PK from insert query to lower collision probability for concurrent inserts (darkdef)
2.0.40 December 23, 2020

7
framework/db/mssql/Schema.php

@ -789,13 +789,12 @@ SQL;
$tableSchema = $this->getTableSchema($table);
$result = [];
foreach ($tableSchema->primaryKey as $name) {
if ($tableSchema->columns[$name]->autoIncrement) {
$result[$name] = $this->getLastInsertID($tableSchema->sequenceName);
break;
}
// @see https://github.com/yiisoft/yii2/issues/13828 & https://github.com/yiisoft/yii2/issues/17474
if (isset($inserted[$name])) {
$result[$name] = $inserted[$name];
} elseif ($tableSchema->columns[$name]->autoIncrement) {
// for a version earlier than 2005
$result[$name] = $this->getLastInsertID($tableSchema->sequenceName);
} elseif (isset($columns[$name])) {
$result[$name] = $columns[$name];
} else {

20
tests/framework/db/mssql/SchemaTest.php

@ -8,6 +8,7 @@
namespace yiiunit\framework\db\mssql;
use yii\db\DefaultValueConstraint;
use yii\db\mssql\Schema;
use yiiunit\framework\db\AnyValue;
/**
@ -180,4 +181,23 @@ class SchemaTest extends \yiiunit\framework\db\SchemaTest
return $columns;
}
public function testGetPrimaryKey()
{
$db = $this->getConnection();
if ($db->getSchema()->getTableSchema('testPKTable') !== null) {
$db->createCommand()->dropTable('testPKTable')->execute();
}
$db->createCommand()->createTable(
'testPKTable',
['id' => Schema::TYPE_PK, 'bar' => Schema::TYPE_INTEGER]
)->execute();
$insertResult = $db->getSchema()->insert('testPKTable', ['bar' => 1]);
$selectResult = $db->createCommand('select [id] from [testPKTable] where [bar]=1')->queryOne();
$this->assertEquals($selectResult['id'], $insertResult['id']);
}
}

Loading…
Cancel
Save