mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #9749 from gurucomkz/patch-9453-mysql8-ints
FIX Don't use int width for mysql >= 8.0.17 #9453
This commit is contained in:
commit
27d7c2fe85
@ -56,6 +56,17 @@ setting. It is generally recommended to leave this setting as-is because it resu
|
|||||||
some advanced cases, the sql_mode can be configured on the database connection via the configuration API (
|
some advanced cases, the sql_mode can be configured on the database connection via the configuration API (
|
||||||
see `MySQLDatabase::$sql_mode` for more details.) This setting is only available in Silverstripe CMS 4.7 and later.
|
see `MySQLDatabase::$sql_mode` for more details.) This setting is only available in Silverstripe CMS 4.7 and later.
|
||||||
|
|
||||||
|
### MySQL/MariaDB Int width in schema
|
||||||
|
|
||||||
|
MySQL 8.0.17 stopped reporting the width attribute for integers while MariaDB did not change its behaviour.
|
||||||
|
This results in constant rebuilding of the schema when MySQLSchemaManager expects a field to look like e.g.
|
||||||
|
`INT(8)` and MySQL server reports it simply as `INT`. MySQLSchemaManager has been updated to detect the MySQL
|
||||||
|
server implementation and act accordingly. In cases when auto-detection fails, you can force the desired behaviour like this:
|
||||||
|
```yml
|
||||||
|
SilverStripe\ORM\Connect\MySQLSchemaManager:
|
||||||
|
schema_use_int_width: true # or false when INT widths should be ignored
|
||||||
|
```
|
||||||
|
|
||||||
## Webserver Configuration
|
## Webserver Configuration
|
||||||
|
|
||||||
### Overview
|
### Overview
|
||||||
|
@ -241,6 +241,23 @@ class MySQLSchemaManager extends DBSchemaManager
|
|||||||
|
|
||||||
protected static $_cache_collation_info = [];
|
protected static $_cache_collation_info = [];
|
||||||
|
|
||||||
|
private function shouldUseIntegerWidth()
|
||||||
|
{
|
||||||
|
// MySQL 8.0.17 stopped reporting the width attribute for integers
|
||||||
|
// https://github.com/silverstripe/silverstripe-framework/issues/9453
|
||||||
|
// Note: MariaDB did not change its behaviour
|
||||||
|
$forceWidth = Config::inst()->get(self::class, 'schema_use_int_width');
|
||||||
|
if ($forceWidth !== null) {
|
||||||
|
return $forceWidth;
|
||||||
|
}
|
||||||
|
$v = $this->database->getVersion();
|
||||||
|
if (false !== strpos($v, 'MariaDB')) {
|
||||||
|
// MariaDB is included in the version string: https://mariadb.com/kb/en/version/
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return version_compare($v, '8.0.17', '<');
|
||||||
|
}
|
||||||
|
|
||||||
public function fieldList($table)
|
public function fieldList($table)
|
||||||
{
|
{
|
||||||
$fields = $this->query("SHOW FULL FIELDS IN \"$table\"");
|
$fields = $this->query("SHOW FULL FIELDS IN \"$table\"");
|
||||||
@ -405,7 +422,8 @@ class MySQLSchemaManager extends DBSchemaManager
|
|||||||
//'default'=>$this->default);
|
//'default'=>$this->default);
|
||||||
//DB::requireField($this->tableName, $this->name, "tinyint(1) unsigned not null default
|
//DB::requireField($this->tableName, $this->name, "tinyint(1) unsigned not null default
|
||||||
//'{$this->defaultVal}'");
|
//'{$this->defaultVal}'");
|
||||||
return 'tinyint(1) unsigned not null' . $this->defaultClause($values);
|
$width = $this->shouldUseIntegerWidth() ? '(1)' : '';
|
||||||
|
return 'tinyint' . $width . ' unsigned not null' . $this->defaultClause($values);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -518,7 +536,8 @@ class MySQLSchemaManager extends DBSchemaManager
|
|||||||
//For reference, this is what typically gets passed to this function:
|
//For reference, this is what typically gets passed to this function:
|
||||||
//$parts=Array('datatype'=>'int', 'precision'=>11, 'null'=>'not null', 'default'=>(int)$this->default);
|
//$parts=Array('datatype'=>'int', 'precision'=>11, 'null'=>'not null', 'default'=>(int)$this->default);
|
||||||
//DB::requireField($this->tableName, $this->name, "int(11) not null default '{$this->defaultVal}'");
|
//DB::requireField($this->tableName, $this->name, "int(11) not null default '{$this->defaultVal}'");
|
||||||
return "int(11) not null" . $this->defaultClause($values);
|
$width = $this->shouldUseIntegerWidth() ? '(11)' : '';
|
||||||
|
return 'int' . $width . ' not null' . $this->defaultClause($values);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -534,8 +553,8 @@ class MySQLSchemaManager extends DBSchemaManager
|
|||||||
// 'arrayValue'=>$this->arrayValue);
|
// 'arrayValue'=>$this->arrayValue);
|
||||||
//$values=Array('type'=>'bigint', 'parts'=>$parts);
|
//$values=Array('type'=>'bigint', 'parts'=>$parts);
|
||||||
//DB::requireField($this->tableName, $this->name, $values);
|
//DB::requireField($this->tableName, $this->name, $values);
|
||||||
|
$width = $this->shouldUseIntegerWidth() ? '(20)' : '';
|
||||||
return 'bigint(20) not null' . $this->defaultClause($values);
|
return 'bigint' . $width . ' not null' . $this->defaultClause($values);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -616,7 +635,8 @@ class MySQLSchemaManager extends DBSchemaManager
|
|||||||
|
|
||||||
public function IdColumn($asDbValue = false, $hasAutoIncPK = true)
|
public function IdColumn($asDbValue = false, $hasAutoIncPK = true)
|
||||||
{
|
{
|
||||||
return 'int(11) not null auto_increment';
|
$width = $this->shouldUseIntegerWidth() ? '(11)' : '';
|
||||||
|
return 'int' . $width . ' not null auto_increment';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
209
tests/php/ORM/MySQLSchemaManagerTest.php
Normal file
209
tests/php/ORM/MySQLSchemaManagerTest.php
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\ORM\Tests;
|
||||||
|
|
||||||
|
use SilverStripe\Core\Config\Config;
|
||||||
|
use SilverStripe\ORM\Connect\MySQLSchemaManager;
|
||||||
|
use SilverStripe\Dev\SapphireTest;
|
||||||
|
use SilverStripe\ORM\Tests\MySQLSchemaManagerTest\MySQLDBDummy;
|
||||||
|
|
||||||
|
class MySQLSchemaManagerTest extends SapphireTest
|
||||||
|
{
|
||||||
|
public function testMYSQL_8_0_16()
|
||||||
|
{
|
||||||
|
Config::forClass(MySQLSchemaManager::class)->set('schema_use_int_width', null);
|
||||||
|
|
||||||
|
$mysqlDBdummy = new MySQLDBDummy('8.0.16-standard');
|
||||||
|
$mgr = new MySQLSchemaManager();
|
||||||
|
$mgr->setDatabase($mysqlDBdummy);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'tinyint(1) unsigned not null',
|
||||||
|
$mgr->boolean([]),
|
||||||
|
'mysql 8.0.16 boolean has width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'int(11) not null',
|
||||||
|
$mgr->int([]),
|
||||||
|
'mysql 8.0.16 int has width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'bigint(20) not null',
|
||||||
|
$mgr->bigint([]),
|
||||||
|
'mysql 8.0.16 bigint has width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'int(11) not null auto_increment',
|
||||||
|
$mgr->IdColumn([]),
|
||||||
|
'mysql 8.0.16 IdColumn has width'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMYSQL_8_0_17()
|
||||||
|
{
|
||||||
|
Config::forClass(MySQLSchemaManager::class)->set('schema_use_int_width', null);
|
||||||
|
|
||||||
|
$mysqlDBdummy = new MySQLDBDummy('8.0.17');
|
||||||
|
$mgr = new MySQLSchemaManager();
|
||||||
|
$mgr->setDatabase($mysqlDBdummy);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'tinyint unsigned not null',
|
||||||
|
$mgr->boolean([]),
|
||||||
|
'mysql 8.0.17 boolean has no width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'int not null',
|
||||||
|
$mgr->int([]),
|
||||||
|
'mysql 8.0.17 int has no width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'bigint not null',
|
||||||
|
$mgr->bigint([]),
|
||||||
|
'mysql 8.0.17 bigint has no width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'int not null auto_increment',
|
||||||
|
$mgr->IdColumn([]),
|
||||||
|
'mysql 8.0.17 IdColumn has no width'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMariaDB()
|
||||||
|
{
|
||||||
|
Config::forClass(MySQLSchemaManager::class)->set('schema_use_int_width', null);
|
||||||
|
|
||||||
|
$mariaDBdummy = new MySQLDBDummy('10.4.7-MariaDB');
|
||||||
|
$mgr = new MySQLSchemaManager();
|
||||||
|
$mgr->setDatabase($mariaDBdummy);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'tinyint(1) unsigned not null',
|
||||||
|
$mgr->boolean([]),
|
||||||
|
'mariadb boolean has width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'int(11) not null',
|
||||||
|
$mgr->int([]),
|
||||||
|
'mariadb int has width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'bigint(20) not null',
|
||||||
|
$mgr->bigint([]),
|
||||||
|
'mariadb bigint has width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'int(11) not null auto_increment',
|
||||||
|
$mgr->IdColumn([]),
|
||||||
|
'mariadb IdColumn has width'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMySQLForcedON()
|
||||||
|
{
|
||||||
|
Config::forClass(MySQLSchemaManager::class)->set('schema_use_int_width', true);
|
||||||
|
|
||||||
|
$mysqlDBdummy = new MySQLDBDummy('8.0.17-standard');
|
||||||
|
$mgr = new MySQLSchemaManager();
|
||||||
|
$mgr->setDatabase($mysqlDBdummy);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'tinyint(1) unsigned not null',
|
||||||
|
$mgr->boolean([]),
|
||||||
|
'mysql 8.0.17 boolean forced on has width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'int(11) not null',
|
||||||
|
$mgr->int([]),
|
||||||
|
'mysql 8.0.17 int forced on has width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'bigint(20) not null',
|
||||||
|
$mgr->bigint([]),
|
||||||
|
'mysql 8.0.17 bigint forced on has width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'int(11) not null auto_increment',
|
||||||
|
$mgr->IdColumn([]),
|
||||||
|
'mysql 8.0.17 IdColumn forced on has width'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMySQLForcedOFF()
|
||||||
|
{
|
||||||
|
Config::forClass(MySQLSchemaManager::class)->set('schema_use_int_width', false);
|
||||||
|
|
||||||
|
$mysqlDBdummy = new MySQLDBDummy('8.0.16-standard');
|
||||||
|
$mgr = new MySQLSchemaManager();
|
||||||
|
$mgr->setDatabase($mysqlDBdummy);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'tinyint unsigned not null',
|
||||||
|
$mgr->boolean([]),
|
||||||
|
'mysql 8.0.16 boolean forced off has no width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'int not null',
|
||||||
|
$mgr->int([]),
|
||||||
|
'mysql 8.0.16 int forced off has no width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'bigint not null',
|
||||||
|
$mgr->bigint([]),
|
||||||
|
'mysql 8.0.16 bigint forced off has no width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'int not null auto_increment',
|
||||||
|
$mgr->IdColumn([]),
|
||||||
|
'mysql 8.0.16 IdColumn forced off has no width'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMariaDBForcedOFF()
|
||||||
|
{
|
||||||
|
Config::forClass(MySQLSchemaManager::class)->set('schema_use_int_width', false);
|
||||||
|
|
||||||
|
$mysqlDBdummy = new MySQLDBDummy('10.0.1-MariaDB');
|
||||||
|
$mgr = new MySQLSchemaManager();
|
||||||
|
$mgr->setDatabase($mysqlDBdummy);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'tinyint unsigned not null',
|
||||||
|
$mgr->boolean([]),
|
||||||
|
'mariadb boolean forced off has no width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'int not null',
|
||||||
|
$mgr->int([]),
|
||||||
|
'mariadb int forced off has no width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'bigint not null',
|
||||||
|
$mgr->bigint([]),
|
||||||
|
'mariadb bigint forced off has no width'
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
'int not null auto_increment',
|
||||||
|
$mgr->IdColumn([]),
|
||||||
|
'mariadb IdColumn forced off has no width'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
21
tests/php/ORM/MySQLSchemaManagerTest/MySQLDBDummy.php
Normal file
21
tests/php/ORM/MySQLSchemaManagerTest/MySQLDBDummy.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace SilverStripe\ORM\Tests\MySQLSchemaManagerTest;
|
||||||
|
|
||||||
|
use SilverStripe\Dev\TestOnly;
|
||||||
|
use SilverStripe\ORM\Connect\MySQLDatabase;
|
||||||
|
|
||||||
|
class MySQLDBDummy extends MySQLDatabase implements TestOnly
|
||||||
|
{
|
||||||
|
private $dbVersion;
|
||||||
|
|
||||||
|
public function __construct($version)
|
||||||
|
{
|
||||||
|
$this->dbVersion = $version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVersion()
|
||||||
|
{
|
||||||
|
return $this->dbVersion;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user