mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
ENH Exclude a list of models for checking and repairs (#10746)
This commit is contained in:
parent
c1427ff9c4
commit
2c874a1e94
@ -4,8 +4,10 @@ namespace SilverStripe\ORM\Connect;
|
||||
|
||||
use Exception;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DB;
|
||||
use SilverStripe\ORM\FieldType\DBField;
|
||||
use SilverStripe\ORM\FieldType\DBPrimaryKey;
|
||||
@ -28,6 +30,16 @@ abstract class DBSchemaManager
|
||||
*/
|
||||
private static $check_and_repair_on_build = true;
|
||||
|
||||
/**
|
||||
* For large databases you can declare a list of DataObject classes which will be excluded from
|
||||
* CHECK TABLE and REPAIR TABLE queries during dev/build. Note that the entire inheritance chain
|
||||
* for that class will be excluded, including both ancestors and descendants.
|
||||
*
|
||||
* Only use this configuration if you know what you are doing and have identified specific models
|
||||
* as being problematic during your dev/build process.
|
||||
*/
|
||||
private static array $exclude_models_from_db_checks = [];
|
||||
|
||||
/**
|
||||
* Check if tables should be renamed in a case-sensitive fashion.
|
||||
* Note: This should still work even on case-insensitive databases.
|
||||
@ -366,7 +378,7 @@ abstract class DBSchemaManager
|
||||
if (Config::inst()->get(static::class, 'fix_table_case_on_build')) {
|
||||
$this->fixTableCase($table);
|
||||
}
|
||||
if (Config::inst()->get(static::class, 'check_and_repair_on_build')) {
|
||||
if ($this->canCheckAndRepairTable($table)) {
|
||||
$this->checkAndRepairTable($table);
|
||||
}
|
||||
|
||||
@ -849,6 +861,29 @@ abstract class DBSchemaManager
|
||||
*/
|
||||
abstract public function checkAndRepairTable($tableName);
|
||||
|
||||
/**
|
||||
* Determines if we should be checking and repairing tables generally, and whether the passed in table
|
||||
* is on the ignore list.
|
||||
*/
|
||||
private function canCheckAndRepairTable(string $tableName): bool
|
||||
{
|
||||
if (!Config::inst()->get(static::class, 'check_and_repair_on_build')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return false if $tableName belongs to any model in the data hierarchy of any class in the ignore list
|
||||
$ignoreModels = Config::inst()->get(static::class, 'exclude_models_from_db_checks');
|
||||
if (!empty($ignoreModels)) {
|
||||
$modelForTable = ClassInfo::class_name(DataObject::getSchema()->tableClass($tableName));
|
||||
foreach ($ignoreModels as $ignoreModel) {
|
||||
if (in_array($modelForTable, ClassInfo::dataClassesFor($ignoreModel))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the given table has the correct case
|
||||
|
77
tests/php/ORM/DBSchemaManagerTest.php
Normal file
77
tests/php/ORM/DBSchemaManagerTest.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\ORM\Tests;
|
||||
|
||||
use ReflectionMethod;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\ORM\Connect\DBSchemaManager;
|
||||
use SilverStripe\ORM\Tests\DBSchemaManagerTest\ChildClass;
|
||||
|
||||
class DBSchemaManagerTest extends SapphireTest
|
||||
{
|
||||
protected $usesDatabase = false;
|
||||
|
||||
public function provideCanCheckAndRepairTable()
|
||||
{
|
||||
return [
|
||||
// not ignored, but globally not allowed
|
||||
[
|
||||
'tableName' => 'DBSchemaManagerTest_SomeModel',
|
||||
'checkAndRepairOnBuild' => false,
|
||||
'expected' => false,
|
||||
],
|
||||
// allowed because it's not in the ignore list
|
||||
[
|
||||
'tableName' => 'DBSchemaManagerTest_SomeModel',
|
||||
'checkAndRepairOnBuild' => true,
|
||||
'expected' => true,
|
||||
],
|
||||
// not allowed because it's the base class for an ignored class
|
||||
[
|
||||
'tableName' => 'DBSchemaManagerTest_BaseClass',
|
||||
'checkAndRepairOnBuild' => true,
|
||||
'expected' => false,
|
||||
],
|
||||
// not allowed because it's explicitly in the ignore list
|
||||
[
|
||||
'tableName' => 'DBSchemaManagerTest_ChildClass',
|
||||
'checkAndRepairOnBuild' => true,
|
||||
'expected' => false,
|
||||
],
|
||||
// not allowed because it's a subclass of an ignored class
|
||||
[
|
||||
'tableName' => 'DBSchemaManagerTest_GrandChildClass',
|
||||
'checkAndRepairOnBuild' => true,
|
||||
'expected' => false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideCanCheckAndRepairTable
|
||||
*/
|
||||
public function testCanCheckAndRepairTable(string $tableName, bool $checkAndRepairOnBuild, bool $expected)
|
||||
{
|
||||
// set config
|
||||
Config::modify()->set(DBSchemaManager::class, 'check_and_repair_on_build', $checkAndRepairOnBuild);
|
||||
Config::modify()->set(DBSchemaManager::class, 'exclude_models_from_db_checks', [ChildClass::class]);
|
||||
|
||||
$manager = $this->getConcreteSchemaManager();
|
||||
$reflectionCanCheck = new ReflectionMethod($manager, 'canCheckAndRepairTable');
|
||||
$reflectionCanCheck->setAccessible(true);
|
||||
$result = $reflectionCanCheck->invoke($manager, $tableName);
|
||||
|
||||
$this->assertSame($expected, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* DBSchemaManager is an abstract class - this gives us an instance of a concrete subclass.
|
||||
* This allows us to test the original abstract implementations of methods without risking accidentally
|
||||
* testing overridden methods on something like MySQLSchemaManager
|
||||
*/
|
||||
private function getConcreteSchemaManager(): DBSchemaManager
|
||||
{
|
||||
return $this->getMockBuilder(DBSchemaManager::class)->getMockForAbstractClass();
|
||||
}
|
||||
}
|
15
tests/php/ORM/DBSchemaManagerTest/BaseClass.php
Normal file
15
tests/php/ORM/DBSchemaManagerTest/BaseClass.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\ORM\Tests\DBSchemaManagerTest;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class BaseClass extends DataObject implements TestOnly
|
||||
{
|
||||
private static $table_name = 'DBSchemaManagerTest_BaseClass';
|
||||
|
||||
private static $db = [
|
||||
'BaseClassField' => 'Varchar',
|
||||
];
|
||||
}
|
12
tests/php/ORM/DBSchemaManagerTest/ChildClass.php
Normal file
12
tests/php/ORM/DBSchemaManagerTest/ChildClass.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\ORM\Tests\DBSchemaManagerTest;
|
||||
|
||||
class ChildClass extends BaseClass
|
||||
{
|
||||
private static $table_name = 'DBSchemaManagerTest_ChildClass';
|
||||
|
||||
private static $db = [
|
||||
'ChildField' => 'Varchar',
|
||||
];
|
||||
}
|
12
tests/php/ORM/DBSchemaManagerTest/GrandChildClass.php
Normal file
12
tests/php/ORM/DBSchemaManagerTest/GrandChildClass.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\ORM\Tests\DBSchemaManagerTest;
|
||||
|
||||
class GrandChildClass extends ChildClass
|
||||
{
|
||||
private static $table_name = 'DBSchemaManagerTest_GrandChildClass';
|
||||
|
||||
private static $db = [
|
||||
'GrandChildField' => 'Varchar',
|
||||
];
|
||||
}
|
15
tests/php/ORM/DBSchemaManagerTest/SomeModel.php
Normal file
15
tests/php/ORM/DBSchemaManagerTest/SomeModel.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\ORM\Tests\DBSchemaManagerTest;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class SomeModel extends DataObject implements TestOnly
|
||||
{
|
||||
private static $table_name = 'DBSchemaManagerTest_SomeModel';
|
||||
|
||||
private static $db = [
|
||||
'SomeField' => 'Varchar',
|
||||
];
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user