mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
NEW Allow index type to be configured per DBField instance
This commit is contained in:
parent
c9c4390619
commit
bd5782adca
@ -525,9 +525,9 @@ class DataObjectSchema
|
||||
foreach ($fieldSpecs as $field => $spec) {
|
||||
/** @var DBField $fieldObj */
|
||||
$fieldObj = Injector::inst()->create($spec, $field);
|
||||
if ($fieldObj->getIndexed()) {
|
||||
if ($type = $fieldObj->getIndexType()) {
|
||||
$this->defaultDatabaseIndexes[$class][$field] = [
|
||||
'type' => 'index',
|
||||
'type' => $type,
|
||||
'columns' => $fieldObj->getIndexSpecs(),
|
||||
];
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class DBClassName extends DBEnum
|
||||
*/
|
||||
protected static $classname_cache = array();
|
||||
|
||||
private static $indexed = true;
|
||||
private static $index = true;
|
||||
|
||||
/**
|
||||
* Clear all cached classname specs. It's necessary to clear all cached subclassed names
|
||||
|
@ -43,7 +43,7 @@ use SilverStripe\View\ViewableData;
|
||||
*
|
||||
* @todo remove MySQL specific code from subclasses
|
||||
*/
|
||||
abstract class DBField extends ViewableData
|
||||
abstract class DBField extends ViewableData implements DBIndexable
|
||||
{
|
||||
|
||||
/**
|
||||
@ -98,14 +98,13 @@ abstract class DBField extends ViewableData
|
||||
private static $default_search_filter_class = 'PartialMatchFilter';
|
||||
|
||||
/**
|
||||
* Whether this field type should be indexed by default. Can be overridden by {@link setOptions()}
|
||||
* with "indexed" => true or via a DBField constructor, e.g. "MyField" => "Varchar(255, ['indexed' => false])".
|
||||
* Note: if doing this, be aware of the existing field constructor arguments, like the length above.
|
||||
* The type of index to use for this field. Can either be a string (one of the DBIndexable type options) or a
|
||||
* boolean. When a boolean is given, false will not index the field, and true will use the default index type.
|
||||
*
|
||||
* @var bool
|
||||
* @var string|bool
|
||||
* @config
|
||||
*/
|
||||
private static $indexed = false;
|
||||
private static $index = false;
|
||||
|
||||
private static $casting = array(
|
||||
'ATT' => 'HTMLFragment',
|
||||
@ -128,7 +127,7 @@ abstract class DBField extends ViewableData
|
||||
protected $defaultVal;
|
||||
|
||||
/**
|
||||
* Provide the DBField name and an array of options, e.g. ['indexed' => true], or ['nullifyEmpty' => false]
|
||||
* Provide the DBField name and an array of options, e.g. ['index' => true], or ['nullifyEmpty' => false]
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $options
|
||||
@ -277,31 +276,36 @@ abstract class DBField extends ViewableData
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this DBField instance should be indexed
|
||||
*
|
||||
* @param bool $indexed
|
||||
* @return $this
|
||||
*/
|
||||
public function setIndexed($indexed)
|
||||
public function setIndexType($type)
|
||||
{
|
||||
$this->options['indexed'] = (bool) $indexed;
|
||||
if (!is_bool($type)
|
||||
&& !in_array($type, [DBIndexable::TYPE_INDEX, DBIndexable::TYPE_UNIQUE, DBIndexable::TYPE_FULLTEXT])
|
||||
) {
|
||||
throw new \InvalidArgumentException(
|
||||
"{$type} is not a valid index type or boolean. Please see DBIndexable."
|
||||
);
|
||||
}
|
||||
|
||||
$this->options['index'] = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether this DBField should be indexed
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getIndexed()
|
||||
public function getIndexType()
|
||||
{
|
||||
if (array_key_exists('indexed', $this->options)) {
|
||||
return (bool) $this->options['indexed'];
|
||||
if (array_key_exists('index', $this->options)) {
|
||||
$type = $this->options['index'];
|
||||
} else {
|
||||
$type = static::config()->get('index');
|
||||
}
|
||||
|
||||
// Default to global configuration per DBField instance
|
||||
return (bool) static::config()->get('indexed');
|
||||
if (is_bool($type)) {
|
||||
if (!$type) {
|
||||
return false;
|
||||
}
|
||||
$type = DBIndexable::TYPE_DEFAULT;
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -629,11 +633,6 @@ DBG;
|
||||
return $this->RAW();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the field(s) that should be used if this field is indexed
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getIndexSpecs()
|
||||
{
|
||||
return [$this->getName()];
|
||||
|
@ -29,7 +29,7 @@ class DBForeignKey extends DBInt
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
private static $indexed = true;
|
||||
private static $index = true;
|
||||
|
||||
private static $default_search_filter_class = 'ExactMatchFilter';
|
||||
|
||||
|
50
src/ORM/FieldType/DBIndexable.php
Normal file
50
src/ORM/FieldType/DBIndexable.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\ORM\FieldType;
|
||||
|
||||
/**
|
||||
* Classes that implement the DBIndexable interface will provide options to set various index types and index
|
||||
* contents, which will be processed by {@link \SilverStripe\ORM\DataObjectSchema}
|
||||
*/
|
||||
interface DBIndexable
|
||||
{
|
||||
/**
|
||||
* Index types that can be used. Please check your database driver to ensure choices are supported.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TYPE_INDEX = 'index';
|
||||
const TYPE_UNIQUE = 'unique';
|
||||
const TYPE_FULLTEXT = 'fulltext';
|
||||
|
||||
/**
|
||||
* If "true" is provided to setIndexType, this default index type will be returned
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TYPE_DEFAULT = 'index';
|
||||
|
||||
/**
|
||||
* Set the desired index type to use
|
||||
*
|
||||
* @param string|bool $indexType Either of the types listed in {@link SilverStripe\ORM\FieldType\DBIndexable}, or
|
||||
* boolean true to indicate that the default index type should be used.
|
||||
* @return $this
|
||||
* @throws InvalidArgumentException If $type is not one of TYPE_INDEX, TYPE_UNIQUE or TYPE_FULLTEXT
|
||||
*/
|
||||
public function setIndexType($type);
|
||||
|
||||
/**
|
||||
* Return the desired index type to use. Will return false if the field instance should not be indexed.
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public function getIndexType();
|
||||
|
||||
/**
|
||||
* Get the field(s) that should be used if this instance is indexed
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getIndexSpecs();
|
||||
}
|
@ -9,11 +9,11 @@ use SilverStripe\ORM\DataObject;
|
||||
*/
|
||||
class DBPolymorphicForeignKey extends DBComposite
|
||||
{
|
||||
private static $indexed = true;
|
||||
private static $index = true;
|
||||
|
||||
private static $composite_db = array(
|
||||
'ID' => 'Int',
|
||||
'Class' => "DBClassName('" . DataObject::class . "', ['indexed' => false])"
|
||||
'Class' => "DBClassName('" . DataObject::class . "', ['index' => false])"
|
||||
);
|
||||
|
||||
public function scaffoldFormField($title = null, $params = null)
|
||||
|
@ -4,8 +4,8 @@ namespace SilverStripe\ORM\Tests;
|
||||
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\ORM\FieldType\DBMoney;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\ORM\FieldType\DBMoney;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DataObjectSchema;
|
||||
use SilverStripe\ORM\Tests\DataObjectSchemaTest\AllIndexes;
|
||||
@ -298,8 +298,9 @@ class DataObjectSchemaTest extends SapphireTest
|
||||
|
||||
public function testCompositeFieldsCanBeIndexedByDefaultConfiguration()
|
||||
{
|
||||
Config::modify()->set(DBMoney::class, 'indexed', true);
|
||||
Config::modify()->set(DBMoney::class, 'index', true);
|
||||
$indexes = DataObject::getSchema()->databaseIndexes(HasComposites::class);
|
||||
|
||||
$this->assertCount(4, $indexes);
|
||||
$this->assertArrayHasKey('Amount', $indexes);
|
||||
$this->assertEquals([
|
||||
@ -308,6 +309,19 @@ class DataObjectSchemaTest extends SapphireTest
|
||||
], $indexes['Amount']);
|
||||
}
|
||||
|
||||
public function testIndexTypeIsConfigurable()
|
||||
{
|
||||
Config::modify()->set(DBMoney::class, 'index', 'unique');
|
||||
|
||||
$indexes = DataObject::getSchema()->databaseIndexes(HasComposites::class);
|
||||
$this->assertCount(4, $indexes);
|
||||
$this->assertArrayHasKey('Amount', $indexes);
|
||||
$this->assertEquals([
|
||||
'type' => 'unique',
|
||||
'columns' => ['AmountCurrency', 'AmountAmount']
|
||||
], $indexes['Amount']);
|
||||
}
|
||||
|
||||
public function testFieldsCanBeIndexedFromFieldSpecs()
|
||||
{
|
||||
$indexes = DataObject::getSchema()->databaseIndexes(HasIndexesInFieldSpecs::class);
|
||||
@ -317,7 +331,7 @@ class DataObjectSchemaTest extends SapphireTest
|
||||
|
||||
$this->assertArrayHasKey('IndexedTitle', $indexes);
|
||||
$this->assertEquals([
|
||||
'type' => 'index',
|
||||
'type' => 'fulltext',
|
||||
'columns' => ['IndexedTitle']
|
||||
], $indexes['IndexedTitle']);
|
||||
|
||||
|
@ -3,6 +3,7 @@ namespace SilverStripe\ORM\Tests\DataObjectSchemaTest;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\FieldType\DBIndexable;
|
||||
|
||||
class AllIndexes extends DataObject implements TestOnly
|
||||
{
|
||||
@ -18,7 +19,7 @@ class AllIndexes extends DataObject implements TestOnly
|
||||
'Content' => true,
|
||||
'IndexCols' => ['Title', 'Content'],
|
||||
'IndexUnique' => [
|
||||
'type' => 'unique',
|
||||
'type' => DBIndexable::TYPE_UNIQUE,
|
||||
'columns' => ['Number'],
|
||||
],
|
||||
'IndexNormal' => [
|
||||
|
@ -9,8 +9,8 @@ class HasIndexesInFieldSpecs extends DataObject implements TestOnly
|
||||
{
|
||||
private static $db = [
|
||||
'Normal' => 'Varchar',
|
||||
'IndexedTitle' => 'Varchar(255, ["indexed" => true])',
|
||||
'IndexedTitle' => 'Varchar(255, ["index" => "fulltext"])',
|
||||
'NormalMoney' => 'Money',
|
||||
'IndexedMoney' => 'Money(["indexed" => true])'
|
||||
'IndexedMoney' => 'Money(["index" => true])'
|
||||
];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user