mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #9454 from open-sausages/pulls/4/myisam
NEW Allow InnoDB for FULLTEXT indexes
This commit is contained in:
commit
03239f9dcc
55
docs/en/04_Changelogs/4.6.0.md
Normal file
55
docs/en/04_Changelogs/4.6.0.md
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# 4.6.0 (Unreleased)
|
||||||
|
|
||||||
|
## Overview {#overview}
|
||||||
|
|
||||||
|
* [MySQL tables are auto-converted from MyISAM to InnoDB](#myisam)
|
||||||
|
|
||||||
|
## MySQL tables are auto-converted from MyISAM to InnoDB {#myisam}
|
||||||
|
|
||||||
|
Beginning with [4.4.0](https://docs.silverstripe.org/en/4/changelogs/4.4.0/),
|
||||||
|
our minimum requirement for MySQL is 5.6 (since MySQL 5.5 end of life reached in December 2018).
|
||||||
|
Starting with MySQL 5.6, [InnoDB](https://dev.mysql.com/doc/refman/5.6/en/innodb-introduction.html)
|
||||||
|
is the new default storage engine,
|
||||||
|
replacing the older [MyISAM](https://dev.mysql.com/doc/refman/5.6/en/myisam-storage-engine.html) engine.
|
||||||
|
|
||||||
|
Silverstripe CMS already creates InnoDB tables by default,
|
||||||
|
mainly in order to benefit from their better support for database transactions.
|
||||||
|
Before MySQL 5.6, InnoDB didn't have a `FULLTEXT` search index,
|
||||||
|
requiring us to enforce the MyISAM engine when devs opted into this index type
|
||||||
|
in their particular setup. There are a few ways in which this opt-in can happen:
|
||||||
|
|
||||||
|
* Adding the [FulltextSearchable](https://github.com/silverstripe/silverstripe-framework/blob/4/src/ORM/Search/FulltextSearchable.php)
|
||||||
|
extension to a DataObject, as described in our
|
||||||
|
[search docs](https://docs.silverstripe.org/en/4/developer_guides/search/fulltextsearch/)
|
||||||
|
* Defining `'type' => 'fulltext'` in `DataObject::$db` column definitions
|
||||||
|
* Implementing [DBIndexable](https://github.com/silverstripe/silverstripe-framework/blob/4/src/ORM/FieldType/DBIndexable.php)
|
||||||
|
on a custom `DBField` subclass.
|
||||||
|
* Setting `'ENGINE=MyISAM'` in `DataObject::$create_table_options`
|
||||||
|
|
||||||
|
This search index is not required to enable simple text search
|
||||||
|
in the "Pages" section of the CMS, or any ModelAdmin implementations.
|
||||||
|
We generally recommend to choose a more powerful
|
||||||
|
[search addon](https://addons.silverstripe.org/add-ons?search=fulltext&type=&sort=downloads)
|
||||||
|
(e.g. based on Solr or ElasticSearch) for website frontend search use cases.
|
||||||
|
|
||||||
|
As of 4.6.0, a `dev/build` will automatically switch MyISAM tables to InnoDB,
|
||||||
|
which automatically recreates any indexes required. If you have large indexes,
|
||||||
|
this can extend the duration if this task. As usual, back up your database
|
||||||
|
before upgrading, and test upgrades on non-production systems first.
|
||||||
|
Our tests indicate that indexes with thousands of records and screen pages
|
||||||
|
worth of content (15MB index size) are converted in a few seconds.
|
||||||
|
|
||||||
|
In order to opt out of this change, you can set the engine explicitly
|
||||||
|
for your DataObject implementations:
|
||||||
|
|
||||||
|
```php
|
||||||
|
use SilverStripe\ORM\Connect\MySQLSchemaManager;
|
||||||
|
use SilverStripe\ORM\DataObject;
|
||||||
|
|
||||||
|
class MyDataObject extends DataObject
|
||||||
|
{
|
||||||
|
private static $create_table_options = [
|
||||||
|
MySQLSchemaManager::ID => 'ENGINE=MyISAM'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
```
|
@ -144,6 +144,12 @@ class MySQLDatabase extends Database implements TransactionManager
|
|||||||
* The core search engine, used by this class and its subclasses to do fun stuff.
|
* The core search engine, used by this class and its subclasses to do fun stuff.
|
||||||
* Searches both SiteTree and File.
|
* Searches both SiteTree and File.
|
||||||
*
|
*
|
||||||
|
* Caution: While the $keywords argument is escaped for safe use in a query context,
|
||||||
|
* you need to ensure that it is also a valid boolean expression when opting into $booleanSearch.
|
||||||
|
* For example, the "asterisk" and "greater than" characters have a special meaning in this context,
|
||||||
|
* and can only be placed in certain parts of the keywords. You will need to preprocess and sanitise
|
||||||
|
* user input accordingly in order to avoid query errors.
|
||||||
|
*
|
||||||
* @param array $classesToSearch
|
* @param array $classesToSearch
|
||||||
* @param string $keywords Keywords as a string.
|
* @param string $keywords Keywords as a string.
|
||||||
* @param int $start
|
* @param int $start
|
||||||
@ -221,8 +227,9 @@ class MySQLDatabase extends Database implements TransactionManager
|
|||||||
$match[$fileClass] = "MATCH (Name, Title) AGAINST ('$keywords' $boolean) AND ClassName = '$fileClassSQL'";
|
$match[$fileClass] = "MATCH (Name, Title) AGAINST ('$keywords' $boolean) AND ClassName = '$fileClassSQL'";
|
||||||
|
|
||||||
// We make the relevance search by converting a boolean mode search into a normal one
|
// We make the relevance search by converting a boolean mode search into a normal one
|
||||||
$relevanceKeywords = str_replace(array('*', '+', '-'), '', $keywords);
|
$booleanChars = ['*', '+', '@', '-', '(', ')', '<', '>'];
|
||||||
$htmlEntityRelevanceKeywords = str_replace(array('*', '+', '-'), '', $htmlEntityKeywords);
|
$relevanceKeywords = str_replace($booleanChars, '', $keywords);
|
||||||
|
$htmlEntityRelevanceKeywords = str_replace($booleanChars, '', $htmlEntityKeywords);
|
||||||
$relevance[$pageClass] = "MATCH (Title, MenuTitle, Content, MetaDescription) "
|
$relevance[$pageClass] = "MATCH (Title, MenuTitle, Content, MetaDescription) "
|
||||||
. "AGAINST ('$relevanceKeywords') "
|
. "AGAINST ('$relevanceKeywords') "
|
||||||
. "+ MATCH (Title, MenuTitle, Content, MetaDescription) AGAINST ('$htmlEntityRelevanceKeywords')";
|
. "+ MATCH (Title, MenuTitle, Content, MetaDescription) AGAINST ('$htmlEntityRelevanceKeywords')";
|
||||||
|
@ -40,10 +40,6 @@ class MySQLSchemaManager extends DBSchemaManager
|
|||||||
}
|
}
|
||||||
if ($indexes) {
|
if ($indexes) {
|
||||||
foreach ($indexes as $k => $v) {
|
foreach ($indexes as $k => $v) {
|
||||||
// force MyISAM if we have a fulltext index
|
|
||||||
if ($v['type'] === 'fulltext') {
|
|
||||||
$addOptions = 'ENGINE=MyISAM';
|
|
||||||
}
|
|
||||||
$indexSchemas .= $this->getIndexSqlDefinition($k, $v) . ",\n";
|
$indexSchemas .= $this->getIndexSqlDefinition($k, $v) . ",\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,30 +100,11 @@ class MySQLSchemaManager extends DBSchemaManager
|
|||||||
|
|
||||||
$dbID = self::ID;
|
$dbID = self::ID;
|
||||||
if ($alteredOptions && isset($alteredOptions[$dbID])) {
|
if ($alteredOptions && isset($alteredOptions[$dbID])) {
|
||||||
$indexList = $this->indexList($tableName);
|
$this->query(sprintf("ALTER TABLE \"%s\" %s", $tableName, $alteredOptions[$dbID]));
|
||||||
$skip = false;
|
$this->alterationMessage(
|
||||||
foreach ($indexList as $index) {
|
sprintf("Table %s options changed: %s", $tableName, $alteredOptions[$dbID]),
|
||||||
if ($index['type'] === 'fulltext') {
|
"changed"
|
||||||
$skip = true;
|
);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($skip) {
|
|
||||||
$this->alterationMessage(
|
|
||||||
sprintf(
|
|
||||||
"Table %s options not changed to %s due to fulltextsearch index",
|
|
||||||
$tableName,
|
|
||||||
$alteredOptions[$dbID]
|
|
||||||
),
|
|
||||||
"changed"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$this->query(sprintf("ALTER TABLE \"%s\" %s", $tableName, $alteredOptions[$dbID]));
|
|
||||||
$this->alterationMessage(
|
|
||||||
sprintf("Table %s options changed: %s", $tableName, $alteredOptions[$dbID]),
|
|
||||||
"changed"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$alterations = implode(",\n", $alterList);
|
$alterations = implode(",\n", $alterList);
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace SilverStripe\ORM\Filters;
|
namespace SilverStripe\ORM\Filters;
|
||||||
|
|
||||||
use SilverStripe\Core\Convert;
|
|
||||||
use SilverStripe\ORM\DataQuery;
|
use SilverStripe\ORM\DataQuery;
|
||||||
use SilverStripe\ORM\DataObject;
|
use SilverStripe\ORM\DataObject;
|
||||||
use Exception;
|
use Exception;
|
||||||
@ -10,8 +9,7 @@ use Exception;
|
|||||||
/**
|
/**
|
||||||
* Filters by full-text matching on the given field.
|
* Filters by full-text matching on the given field.
|
||||||
*
|
*
|
||||||
* Full-text indexes are only available with MyISAM tables. The following column types are
|
* The following column types are supported:
|
||||||
* supported:
|
|
||||||
* - Char
|
* - Char
|
||||||
* - Varchar
|
* - Varchar
|
||||||
* - Text
|
* - Text
|
||||||
|
@ -25,12 +25,6 @@ class DataObjectSchemaGenerationTest extends SapphireTest
|
|||||||
// Start tests
|
// Start tests
|
||||||
static::start();
|
static::start();
|
||||||
|
|
||||||
// enable fulltext option on this table
|
|
||||||
TestIndexObject::config()->update(
|
|
||||||
'create_table_options',
|
|
||||||
array(MySQLSchemaManager::ID => 'ENGINE=MyISAM')
|
|
||||||
);
|
|
||||||
|
|
||||||
parent::setUpBeforeClass();
|
parent::setUpBeforeClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,8 +34,4 @@ class TestObject extends DataObject implements TestOnly
|
|||||||
'columns' => ['ColumnE'],
|
'columns' => ['ColumnE'],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
private static $create_table_options = array(
|
|
||||||
MySQLSchemaManager::ID => "ENGINE=MyISAM",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user