Fix #17203: Fix yii\db\Connection to persist customized queryBuilder configuration after the close()open() cycle

This commit is contained in:
Dmytro Naumenko
2021-04-01 01:10:16 +03:00
committed by GitHub
parent 42e8aa4ea5
commit 10bb71a822
3 changed files with 80 additions and 1 deletions

View File

@ -15,6 +15,7 @@ Yii Framework 2 Change Log
- Bug #18526: Fix `yii\caching\DbCache` to work with MSSQL, add `normalizeTableRowData()` to `yii\db\mssql\QueryBuilder::upsert()` (darkdef) - Bug #18526: Fix `yii\caching\DbCache` to work with MSSQL, add `normalizeTableRowData()` to `yii\db\mssql\QueryBuilder::upsert()` (darkdef)
- Bug #14343: Fix `yii\test\ActiveFixture` to use model's DB connection instead of the default one (margori, bizley) - Bug #14343: Fix `yii\test\ActiveFixture` to use model's DB connection instead of the default one (margori, bizley)
- Bug #17631: Fix `yii\widgets\BaseListView` to properly render custom summary (sjaakp, bizley) - Bug #17631: Fix `yii\widgets\BaseListView` to properly render custom summary (sjaakp, bizley)
- Bug #17203: Fix `yii\db\Connection` to persist customized `queryBuilder` configuration after the `close()``open()` cycle (silverfire)
- Bug #18325: Fix `yii\db\pgsql\Schema` to respect non-default PgSQL schema name for data types (theonedemon, silverfire) - Bug #18325: Fix `yii\db\pgsql\Schema` to respect non-default PgSQL schema name for data types (theonedemon, silverfire)

View File

@ -424,6 +424,15 @@ class Connection extends Component
*/ */
public $isSybase = false; public $isSybase = false;
/**
* @var array An array of [[setQueryBuilder()]] calls, holding the passed arguments.
* Is used to restore a QueryBuilder configuration after the connection close/open cycle.
*
* @see restoreQueryBuilderConfiguration()
* @since 2.0.42
*/
private $_queryBuilderConfigurations = [];
/** /**
* @var Transaction the currently active transaction * @var Transaction the currently active transaction
*/ */
@ -851,7 +860,10 @@ class Connection extends Component
$config = !is_array($this->schemaMap[$driver]) ? ['class' => $this->schemaMap[$driver]] : $this->schemaMap[$driver]; $config = !is_array($this->schemaMap[$driver]) ? ['class' => $this->schemaMap[$driver]] : $this->schemaMap[$driver];
$config['db'] = $this; $config['db'] = $this;
return $this->_schema = Yii::createObject($config); $this->_schema = Yii::createObject($config);
$this->restoreQueryBuilderConfiguration();
return $this->_schema;
} }
throw new NotSupportedException("Connection does not support reading schema information for '$driver' DBMS."); throw new NotSupportedException("Connection does not support reading schema information for '$driver' DBMS.");
@ -875,6 +887,25 @@ class Connection extends Component
public function setQueryBuilder($value) public function setQueryBuilder($value)
{ {
Yii::configure($this->getQueryBuilder(), $value); Yii::configure($this->getQueryBuilder(), $value);
$this->_queryBuilderConfigurations[] = $value;
}
/**
* Restores custom QueryBuilder configuration after the connection close/open cycle
*
* @since 2.0.42
*/
private function restoreQueryBuilderConfiguration()
{
if ($this->_queryBuilderConfigurations === []) {
return;
}
$queryBuilderConfigurations = $this->_queryBuilderConfigurations;
$this->_queryBuilderConfigurations = [];
foreach ($queryBuilderConfigurations as $queryBuilderConfiguration) {
$this->setQueryBuilder($queryBuilderConfiguration);
}
} }
/** /**

View File

@ -10,6 +10,9 @@ namespace yiiunit\framework\db;
use Yii; use Yii;
use yii\base\InvalidConfigException; use yii\base\InvalidConfigException;
use yii\caching\ArrayCache; use yii\caching\ArrayCache;
use yii\db\conditions\AndCondition;
use yii\db\conditions\ExistsConditionBuilder;
use yii\db\conditions\OrCondition;
use yii\db\Connection; use yii\db\Connection;
use yii\db\Transaction; use yii\db\Transaction;
@ -46,6 +49,50 @@ abstract class ConnectionTest extends DatabaseTestCase
$connection->open(); $connection->open();
} }
public function testQueryBuilderConfigurationAfterOpenClose()
{
$connection = $this->getConnection(false, false);
$connection->setQueryBuilder([
'expressionBuilders' => [
// Just a dumb mapping to make sure it's applied
'yii\db\conditions\OrCondition' => 'yii\db\conditions\ExistsConditionBuilder'
],
]);
// Second call to make sure that consecutive calls are handled correctly
$connection->setQueryBuilder([
'expressionBuilders' => [
'yii\db\conditions\AndCondition' => 'yii\db\conditions\InConditionBuilder'
],
]);
$orCondition = new OrCondition(['dumb']);
$andCondition = new AndCondition(['dumb']);
$connection->open();
$this->assertInstanceOf(
'\yii\db\conditions\ExistsConditionBuilder',
$connection->getQueryBuilder()->getExpressionBuilder($orCondition)
);
$this->assertInstanceOf(
'\yii\db\conditions\InConditionBuilder',
$connection->getQueryBuilder()->getExpressionBuilder($andCondition)
);
$connection->close();
$this->assertNull($connection->pdo);
$connection->open();
$this->assertInstanceOf(
'\yii\db\conditions\ExistsConditionBuilder',
$connection->getQueryBuilder()->getExpressionBuilder($orCondition)
);
$this->assertInstanceOf(
'\yii\db\conditions\InConditionBuilder',
$connection->getQueryBuilder()->getExpressionBuilder($andCondition)
);
}
public function testSerialize() public function testSerialize()
{ {
$connection = $this->getConnection(false, false); $connection = $this->getConnection(false, false);