Browse Source

Fix #17449: Ensure `CHECK` statement goes after `COMMENT` in MySQL `QueryBuilder::addCommentOnColumn()`

tags/2.0.26
Manu311 5 years ago committed by Alexander Makarov
parent
commit
cc5bb71f75
  1. 1
      framework/CHANGELOG.md
  2. 11
      framework/db/mysql/QueryBuilder.php
  3. 2
      tests/README.md
  4. 4
      tests/data/config-docker.php
  5. 4
      tests/docker-compose.yml
  6. 24
      tests/framework/db/mysql/QueryBuilderTest.php

1
framework/CHANGELOG.md

@ -11,6 +11,7 @@ Yii Framework 2 Change Log
- Bug #17355: Fixed Pjax after request event bug (kamarton)
- Bug #17522: `DbManager::isEmptyUserId()` is now protected (samdark)
- Bug #17434: Fixed Internet Explorer 11 AJAX redirect bug in case of 301 and 302 response codes (`XMLHttpRequest: Network Error 0x800c0008`) (kamarton)
- Bug #17449: Ensure `CHECK` statement goes after `COMMENT` in MySQL `QueryBuilder::addCommentOnColumn()` (Manu311)
2.0.25 August 13, 2019

11
framework/db/mysql/QueryBuilder.php

@ -306,11 +306,20 @@ class QueryBuilder extends \yii\db\QueryBuilder
$definition = trim(preg_replace("/COMMENT '(?:''|[^'])*'/i", '',
$this->getColumnDefinition($table, $column)));
return 'ALTER TABLE ' . $this->db->quoteTableName($table)
$checkRegex = '/CHECK *(\(([^()]|(?-2))*\))/';
$check = preg_match($checkRegex, $definition, $checkMatches);
if ($check === 1) {
$definition = preg_replace($checkRegex, '', $definition);
}
$alterSql = 'ALTER TABLE ' . $this->db->quoteTableName($table)
. ' CHANGE ' . $this->db->quoteColumnName($column)
. ' ' . $this->db->quoteColumnName($column)
. (empty($definition) ? '' : ' ' . $definition)
. ' COMMENT ' . $this->db->quoteValue($comment);
if ($check === 1) {
$alterSql .= ' ' . $checkMatches[0];
}
return $alterSql;
}
/**

2
tests/README.md

@ -168,4 +168,4 @@ Execute jobs via shell runner (with docker-compose support)
$ gitlab-runner exec shell build
$ gitlab-runner exec shell test

4
tests/data/config-docker.php

@ -29,8 +29,8 @@ $config = [
],
'mysql' => [
'dsn' => 'mysql:host=mysql;dbname=yiitest',
'username' => 'travis',
'password' => 'travis',
'username' => 'root',
'password' => 'secret',
'fixture' => __DIR__ . '/mysql.sql',
],
'sqlite' => [

4
tests/docker-compose.yml

@ -10,8 +10,8 @@ services:
volumes:
- ../tests/data/config-docker.php:/project/tests/data/config.php
# Enable for debugging, enabling tests might be slow for file access (data) on host-volume
#- ../tests:/project/tests
# - ../framework:/project/framework
- ../tests:/project/tests
- ../framework:/project/framework
# Tmpfs volume (experimental, asset tests may fail)
#tmpfs:
# - /project/tests/runtime

24
tests/framework/db/mysql/QueryBuilderTest.php

@ -343,4 +343,28 @@ class QueryBuilderTest extends \yiiunit\framework\db\QueryBuilderTest
return $items;
}
public function testIssue17449()
{
$db = $this->getConnection();
$pdo = $db->pdo;
$pdo->exec('DROP TABLE IF EXISTS `issue_17449`');
$tableQuery = <<<MySqlStatement
CREATE TABLE `issue_17449` (
`test_column` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'some comment' CHECK (json_valid(`test_column`))
) ENGINE=InnoDB DEFAULT CHARSET=latin1
MySqlStatement;
$db->createCommand($tableQuery)->execute();
$actual = $db->createCommand()->addCommentOnColumn('issue_17449', 'test_column', 'Some comment')->rawSql;
$checkPos = stripos($actual, 'check');
if ($checkPos === false) {
$this->markTestSkipped("The used MySql-Server removed or moved the CHECK from the column line, so the original bug doesn't affect it");
}
$commentPos = stripos($actual, 'comment');
$this->assertNotFalse($commentPos);
$this->assertLessThan($checkPos, $commentPos);
}
}

Loading…
Cancel
Save