Merge branch '3' into 4

This commit is contained in:
Daniel Hensby 2018-01-16 10:31:50 +00:00
commit ebeaf3e40d
No known key found for this signature in database
GPG Key ID: B00D1E9767F0B06E
5 changed files with 136 additions and 4 deletions

View File

@ -1,7 +1,7 @@
# Nginx # Nginx
These instructions are also covered on the These instructions are also covered on the
[Nginx Wiki](http://wiki.nginx.org/SilverStripe). [Nginx Wiki](https://www.nginx.com/resources/wiki/start/topics/recipes/silverstripe/).
The prerequisite is that you have already installed Nginx and you are The prerequisite is that you have already installed Nginx and you are
able to run PHP files via the FastCGI-wrapper from Nginx. able to run PHP files via the FastCGI-wrapper from Nginx.

View File

@ -93,6 +93,9 @@ other columns. If this is indexed, smaller and reasonably unique it might be fas
Indexes are generated and removed automatically during a `dev/build`. Caution if you're working with large tables and Indexes are generated and removed automatically during a `dev/build`. Caution if you're working with large tables and
modify an index as the next `dev/build` will `DROP` the index, and then `ADD` it. modify an index as the next `dev/build` will `DROP` the index, and then `ADD` it.
As of 3.7.0 `default_sort` fields will automatically become database indexes as this provides significant performance
benefits.
## API Documentation ## API Documentation
* [DataObject](api:SilverStripe\ORM\DataObject) * [DataObject](api:SilverStripe\ORM\DataObject)

View File

@ -219,7 +219,7 @@ class DataObjectSchema
// Record specification // Record specification
foreach ($fields as $name => $specification) { foreach ($fields as $name => $specification) {
$prefix = $includeClass ? "{$tableClass}." : ""; $prefix = $includeClass ? "{$tableClass}." : "";
$db[$name] = $prefix . $specification; $db[$name] = $prefix . $specification;
} }
} }
return $db; return $db;
@ -524,6 +524,7 @@ class DataObjectSchema
{ {
if (!array_key_exists($class, $this->databaseIndexes)) { if (!array_key_exists($class, $this->databaseIndexes)) {
$this->databaseIndexes[$class] = array_merge( $this->databaseIndexes[$class] = array_merge(
$this->buildSortDatabaseIndexes($class),
$this->cacheDefaultDatabaseIndexes($class), $this->cacheDefaultDatabaseIndexes($class),
$this->buildCustomDatabaseIndexes($class) $this->buildCustomDatabaseIndexes($class)
); );
@ -604,6 +605,53 @@ class DataObjectSchema
return $indexes; return $indexes;
} }
protected function buildSortDatabaseIndexes($class)
{
$sort = Config::inst()->get($class, 'default_sort', Config::UNINHERITED);
$indexes = [];
if ($sort && is_string($sort)) {
$sort = preg_split('/,(?![^()]*+\\))/', $sort);
foreach ($sort as $value) {
try {
list ($table, $column) = $this->parseSortColumn(trim($value));
$table = trim($table, '"');
$column = trim($column, '"');
if ($table && strtolower($table) !== strtolower(self::tableName($class))) {
continue;
}
if ($this->databaseField($class, $column, false)) {
$indexes[$column] = [
'type' => 'index',
'columns' => [$column],
];
}
} catch (InvalidArgumentException $e) {
}
}
}
return $indexes;
}
/**
* Parses a specified column into a sort field and direction
*
* @param string $column String to parse containing the column name
* @return array Resolved table and column.
*/
protected function parseSortColumn($column)
{
// Parse column specification, considering possible ansi sql quoting
// Note that table prefix is allowed, but discarded
if (preg_match('/^("?(?<table>[^"\s]+)"?\\.)?"?(?<column>[^"\s]+)"?(\s+(?<direction>((asc)|(desc))(ending)?))?$/i', $column, $match)) {
$table = $match['table'];
$column = $match['column'];
} else {
throw new InvalidArgumentException("Invalid sort() column");
}
return array($table, $column);
}
/** /**
* Returns the table name in the class hierarchy which contains a given * Returns the table name in the class hierarchy which contains a given
* field column for a {@link DataObject}. If the field does not exist, this * field column for a {@link DataObject}. If the field does not exist, this
@ -714,7 +762,6 @@ class DataObjectSchema
} }
/** /**
* Parse a belongs_many_many component to extract class and relationship name * Parse a belongs_many_many component to extract class and relationship name
* *

View File

@ -2,11 +2,13 @@
namespace SilverStripe\ORM\Tests; namespace SilverStripe\ORM\Tests;
use SilverStripe\Core\Config\Config;
use SilverStripe\ORM\Connect\MySQLSchemaManager; use SilverStripe\ORM\Connect\MySQLSchemaManager;
use SilverStripe\ORM\DB; use SilverStripe\ORM\DB;
use SilverStripe\ORM\FieldType\DBClassName; use SilverStripe\ORM\FieldType\DBClassName;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
use SilverStripe\Dev\SapphireTest; use SilverStripe\Dev\SapphireTest;
use SilverStripe\ORM\Tests\DataObjectSchemaGenerationTest\SortedObject;
use SilverStripe\ORM\Tests\DataObjectSchemaGenerationTest\TestIndexObject; use SilverStripe\ORM\Tests\DataObjectSchemaGenerationTest\TestIndexObject;
use SilverStripe\ORM\Tests\DataObjectSchemaGenerationTest\TestObject; use SilverStripe\ORM\Tests\DataObjectSchemaGenerationTest\TestObject;
@ -14,7 +16,8 @@ class DataObjectSchemaGenerationTest extends SapphireTest
{ {
protected static $extra_dataobjects = array( protected static $extra_dataobjects = array(
TestObject::class, TestObject::class,
TestIndexObject::class TestIndexObject::class,
SortedObject::class,
); );
public static function setUpBeforeClass() public static function setUpBeforeClass()
@ -260,4 +263,65 @@ class DataObjectSchemaGenerationTest extends SapphireTest
$item1->delete(); $item1->delete();
$item2->delete(); $item2->delete();
} }
public function testSortFieldBecomeIndexes()
{
$indexes = DataObject::getSchema()->databaseIndexes(SortedObject::class);
$this->assertContains([
'type' => 'index',
'columns' => ['Sort'],
], $indexes);
DataObject::getSchema()->reset();
Config::inst()->update(SortedObject::class, 'default_sort', 'Sort ASC');
$indexes = DataObject::getSchema()->databaseIndexes(SortedObject::class);
$this->assertContains([
'type' => 'index',
'columns' => ['Sort'],
], $indexes);
DataObject::getSchema()->reset();
Config::inst()->update(SortedObject::class, 'default_sort', 'Sort DESC');
$indexes = DataObject::getSchema()->databaseIndexes(SortedObject::class);
$this->assertContains([
'type' => 'index',
'columns' => ['Sort'],
], $indexes);
DataObject::getSchema()->reset();
Config::inst()->update(SortedObject::class, 'default_sort', '"Sort" DESC');
$indexes = DataObject::getSchema()->databaseIndexes(SortedObject::class);
$this->assertContains([
'type' => 'index',
'columns' => ['Sort'],
], $indexes);
DataObject::getSchema()->reset();
Config::inst()->update(SortedObject::class, 'default_sort', '"DataObjectSchemaGenerationTest_SortedObject"."Sort" ASC');
$indexes = DataObject::getSchema()->databaseIndexes(SortedObject::class);
$this->assertContains([
'type' => 'index',
'columns' => ['Sort'],
], $indexes);
DataObject::getSchema()->reset();
Config::inst()->update(SortedObject::class, 'default_sort', '"Sort" DESC, "Title" ASC');
$indexes = DataObject::getSchema()->databaseIndexes(SortedObject::class);
$this->assertContains([
'type' => 'index',
'columns' => ['Sort'],
], $indexes);
$this->assertContains([
'type' => 'index',
'columns' => ['Title'],
], $indexes);
DataObject::getSchema()->reset();
// make sure that specific indexes aren't overwritten
Config::inst()->update(SortedObject::class, 'indexes', [
'Sort' => [
'type' => 'unique',
'columns' => ['Sort'],
],
]);
$indexes = DataObject::getSchema()->databaseIndexes(SortedObject::class);
$this->assertContains([
'type' => 'unique',
'columns' => ['Sort'],
], $indexes);
}
} }

View File

@ -0,0 +1,18 @@
<?php
namespace SilverStripe\ORM\Tests\DataObjectSchemaGenerationTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\DataObject;
class SortedObject extends DataObject implements TestOnly
{
private static $table_name = 'DataObjectSchemaGenerationTest_SortedObject';
private static $db = [
'Title' => 'Varchar',
'Sort' => 'Int',
];
private static $default_sort = 'Sort';
}