Fixes #14367: In yii\db\mysql\QueryBuilder added support fractional seconds for time types for MySQL >= 5.6.4

This commit is contained in:
Konstantin Voloshchuk
2018-10-11 17:43:32 +06:00
committed by Alexander Makarov
parent 5d7c5f8ae2
commit 9f383ab228
4 changed files with 107 additions and 11 deletions

View File

@ -4,6 +4,7 @@ Yii Framework 2 Change Log
2.0.16 under development 2.0.16 under development
------------------------ ------------------------
- Enh #14367: In `yii\db\mysql\QueryBuilder` added support fractional seconds for time types for MySQL >= 5.6.4 (konstantin-vl)
- Bug #16766: `yii\filters\ContentNegotiator` was not setting `Vary` header to inform cache recipients (koteq, cebe, samdark) - Bug #16766: `yii\filters\ContentNegotiator` was not setting `Vary` header to inform cache recipients (koteq, cebe, samdark)
- Bug #11960: Fixed `checked` option ignore in `yii\helpers\BaseHtml::checkbox()` (misantron) - Bug #11960: Fixed `checked` option ignore in `yii\helpers\BaseHtml::checkbox()` (misantron)
- Bug #14759: Fixed `yii\web\JsonResponseFormatter` output for `null` data (misantron) - Bug #14759: Fixed `yii\web\JsonResponseFormatter` output for `null` data (misantron)

View File

@ -39,9 +39,6 @@ class QueryBuilder extends \yii\db\QueryBuilder
Schema::TYPE_FLOAT => 'float', Schema::TYPE_FLOAT => 'float',
Schema::TYPE_DOUBLE => 'double', Schema::TYPE_DOUBLE => 'double',
Schema::TYPE_DECIMAL => 'decimal(10,0)', Schema::TYPE_DECIMAL => 'decimal(10,0)',
Schema::TYPE_DATETIME => 'datetime',
Schema::TYPE_TIMESTAMP => 'timestamp',
Schema::TYPE_TIME => 'time',
Schema::TYPE_DATE => 'date', Schema::TYPE_DATE => 'date',
Schema::TYPE_BINARY => 'blob', Schema::TYPE_BINARY => 'blob',
Schema::TYPE_BOOLEAN => 'tinyint(1)', Schema::TYPE_BOOLEAN => 'tinyint(1)',
@ -49,6 +46,15 @@ class QueryBuilder extends \yii\db\QueryBuilder
Schema::TYPE_JSON => 'json' Schema::TYPE_JSON => 'json'
]; ];
/**
* {@inheritdoc}
*/
public function init()
{
parent::init();
$this->typeMap = array_merge($this->typeMap, $this->defaultTimeTypeMap());
}
/** /**
* {@inheritdoc} * {@inheritdoc}
@ -362,4 +368,41 @@ class QueryBuilder extends \yii\db\QueryBuilder
return null; return null;
} }
/**
* Checks the ability to use fractional seconds.
*
* @return bool
* @see https://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html
*/
private function supportsFractionalSeconds()
{
$version = $this->db->getSlavePdo()->getAttribute(\PDO::ATTR_SERVER_VERSION);
return version_compare($version, '5.6.4', '>=');
}
/**
* Returns the map for default time type.
* If the version of MySQL is lower than 5.6.4, then the types will be without fractional seconds,
* otherwise with fractional seconds.
*
* @return array
*/
private function defaultTimeTypeMap()
{
$map = [
Schema::TYPE_DATETIME => 'datetime',
Schema::TYPE_TIMESTAMP => 'timestamp',
Schema::TYPE_TIME => 'time',
];
if ($this->supportsFractionalSeconds()) {
$map = [
Schema::TYPE_DATETIME => 'datetime(0)',
Schema::TYPE_TIMESTAMP => 'timestamp(0)',
Schema::TYPE_TIME => 'time(0)',
];
}
return $map;
}
} }

View File

@ -280,7 +280,6 @@ abstract class QueryBuilderTest extends DatabaseTestCase
Schema::TYPE_DATETIME . ' NOT NULL', Schema::TYPE_DATETIME . ' NOT NULL',
$this->dateTime()->notNull(), $this->dateTime()->notNull(),
[ [
'mysql' => 'datetime NOT NULL',
'postgres' => 'timestamp(0) NOT NULL', 'postgres' => 'timestamp(0) NOT NULL',
'sqlite' => 'datetime NOT NULL', 'sqlite' => 'datetime NOT NULL',
'oci' => 'TIMESTAMP NOT NULL', 'oci' => 'TIMESTAMP NOT NULL',
@ -292,7 +291,6 @@ abstract class QueryBuilderTest extends DatabaseTestCase
Schema::TYPE_DATETIME, Schema::TYPE_DATETIME,
$this->dateTime(), $this->dateTime(),
[ [
'mysql' => 'datetime',
'postgres' => 'timestamp(0)', 'postgres' => 'timestamp(0)',
'sqlite' => 'datetime', 'sqlite' => 'datetime',
'oci' => 'TIMESTAMP', 'oci' => 'TIMESTAMP',
@ -871,7 +869,6 @@ abstract class QueryBuilderTest extends DatabaseTestCase
Schema::TYPE_TIME . ' NOT NULL', Schema::TYPE_TIME . ' NOT NULL',
$this->time()->notNull(), $this->time()->notNull(),
[ [
'mysql' => 'time NOT NULL',
'postgres' => 'time(0) NOT NULL', 'postgres' => 'time(0) NOT NULL',
'sqlite' => 'time NOT NULL', 'sqlite' => 'time NOT NULL',
'oci' => 'TIMESTAMP NOT NULL', 'oci' => 'TIMESTAMP NOT NULL',
@ -883,7 +880,6 @@ abstract class QueryBuilderTest extends DatabaseTestCase
Schema::TYPE_TIME, Schema::TYPE_TIME,
$this->time(), $this->time(),
[ [
'mysql' => 'time',
'postgres' => 'time(0)', 'postgres' => 'time(0)',
'sqlite' => 'time', 'sqlite' => 'time',
'oci' => 'TIMESTAMP', 'oci' => 'TIMESTAMP',
@ -906,7 +902,6 @@ abstract class QueryBuilderTest extends DatabaseTestCase
Schema::TYPE_TIMESTAMP . ' NOT NULL', Schema::TYPE_TIMESTAMP . ' NOT NULL',
$this->timestamp()->notNull(), $this->timestamp()->notNull(),
[ [
'mysql' => 'timestamp NOT NULL',
'postgres' => 'timestamp(0) NOT NULL', 'postgres' => 'timestamp(0) NOT NULL',
'sqlite' => 'timestamp NOT NULL', 'sqlite' => 'timestamp NOT NULL',
'oci' => 'TIMESTAMP NOT NULL', 'oci' => 'TIMESTAMP NOT NULL',
@ -934,7 +929,6 @@ abstract class QueryBuilderTest extends DatabaseTestCase
Schema::TYPE_TIMESTAMP . ' NULL DEFAULT NULL', Schema::TYPE_TIMESTAMP . ' NULL DEFAULT NULL',
$this->timestamp()->defaultValue(null), $this->timestamp()->defaultValue(null),
[ [
'mysql' => 'timestamp NULL DEFAULT NULL',
'postgres' => 'timestamp(0) NULL DEFAULT NULL', 'postgres' => 'timestamp(0) NULL DEFAULT NULL',
'sqlite' => 'timestamp NULL DEFAULT NULL', 'sqlite' => 'timestamp NULL DEFAULT NULL',
'sqlsrv' => 'timestamp NULL DEFAULT NULL', 'sqlsrv' => 'timestamp NULL DEFAULT NULL',

View File

@ -85,6 +85,64 @@ class QueryBuilderTest extends \yiiunit\framework\db\QueryBuilderTest
]; ];
} }
return array_merge(parent::columnTypes(), $this->columnTimeTypes(), $columns);
}
public function columnTimeTypes()
{
$columns = [
[
Schema::TYPE_DATETIME . ' NOT NULL',
$this->dateTime()->notNull(),
'datetime NOT NULL',
],
[
Schema::TYPE_DATETIME,
$this->dateTime(),
'datetime',
],
[
Schema::TYPE_TIME . ' NOT NULL',
$this->time()->notNull(),
'time NOT NULL',
],
[
Schema::TYPE_TIME,
$this->time(),
'time',
],
[
Schema::TYPE_TIMESTAMP . ' NOT NULL',
$this->timestamp()->notNull(),
'timestamp NOT NULL',
],
[
Schema::TYPE_TIMESTAMP . ' NULL DEFAULT NULL',
$this->timestamp()->defaultValue(null),
'timestamp NULL DEFAULT NULL',
],
];
/**
* @link https://github.com/yiisoft/yii2/issues/14367
*/
$mysqlVersion = $this->getDb()->getSlavePdo()->getAttribute(\PDO::ATTR_SERVER_VERSION);
$supportsFractionalSeconds = version_compare($mysqlVersion,'5.6.4', '>=');
if ($supportsFractionalSeconds) {
$expectedValues = [
'datetime(0) NOT NULL',
'datetime(0)',
'time(0) NOT NULL',
'time(0)',
'timestamp(0) NOT NULL',
'timestamp(0) NULL DEFAULT NULL',
];
foreach ($expectedValues as $index => $expected) {
$columns[$index][2] = $expected;
}
}
/** /**
* @link https://github.com/yiisoft/yii2/issues/14834 * @link https://github.com/yiisoft/yii2/issues/14834
*/ */
@ -99,11 +157,11 @@ class QueryBuilderTest extends \yiiunit\framework\db\QueryBuilderTest
$columns[] = [ $columns[] = [
Schema::TYPE_TIMESTAMP, Schema::TYPE_TIMESTAMP,
$this->timestamp(), $this->timestamp(),
'timestamp', $supportsFractionalSeconds ? 'timestamp(0)' : 'timestamp',
]; ];
} }
return array_merge(parent::columnTypes(), $columns); return $columns;
} }
public function primaryKeysProvider() public function primaryKeysProvider()