diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 545f11f..2b8e3b0 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -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 #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 #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) diff --git a/framework/db/Connection.php b/framework/db/Connection.php index 2ea8224..be19d21 100644 --- a/framework/db/Connection.php +++ b/framework/db/Connection.php @@ -425,6 +425,15 @@ class Connection extends Component 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 */ private $_transaction; @@ -851,7 +860,10 @@ class Connection extends Component $config = !is_array($this->schemaMap[$driver]) ? ['class' => $this->schemaMap[$driver]] : $this->schemaMap[$driver]; $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."); @@ -875,6 +887,25 @@ class Connection extends Component public function setQueryBuilder($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); + } } /** diff --git a/tests/framework/db/ConnectionTest.php b/tests/framework/db/ConnectionTest.php index be5ed4e..2136e01 100644 --- a/tests/framework/db/ConnectionTest.php +++ b/tests/framework/db/ConnectionTest.php @@ -10,6 +10,9 @@ namespace yiiunit\framework\db; use Yii; use yii\base\InvalidConfigException; 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\Transaction; @@ -46,6 +49,50 @@ abstract class ConnectionTest extends DatabaseTestCase $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() { $connection = $this->getConnection(false, false);