mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
ENHANCEMENT Added DataObject::$create_table_options to pass through special options to Database->requireTable(). Contains a keyed array by database driver. Example use is specifying different storage engines for MySQL: array('MySQLDatabase'=>'ENGINE=InnoDB')
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@77160 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
0b9edf2a39
commit
336bce8bf8
@ -187,9 +187,10 @@ class DB {
|
|||||||
* - true: Create a single column index on the field named the same as the index.
|
* - true: Create a single column index on the field named the same as the index.
|
||||||
* - array('fields' => array('A','B','C'), 'type' => 'index/unique/fulltext'): This gives you full
|
* - array('fields' => array('A','B','C'), 'type' => 'index/unique/fulltext'): This gives you full
|
||||||
* control over the index.
|
* control over the index.
|
||||||
|
* @param string $options SQL statement to append to the CREATE TABLE call.
|
||||||
*/
|
*/
|
||||||
static function requireTable($table, $fieldSchema = null, $indexSchema = null, $hasAutoIncPK=true) {
|
static function requireTable($table, $fieldSchema = null, $indexSchema = null, $hasAutoIncPK=true, $options = null) {
|
||||||
return DB::$globalConn->requireTable($table, $fieldSchema, $indexSchema, $hasAutoIncPK);
|
return DB::$globalConn->requireTable($table, $fieldSchema, $indexSchema, $hasAutoIncPK, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2666,7 +2666,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
|
|
||||||
if($fields) {
|
if($fields) {
|
||||||
$hasAutoIncPK = ($this->class == ClassInfo::baseDataClass($this->class));
|
$hasAutoIncPK = ($this->class == ClassInfo::baseDataClass($this->class));
|
||||||
DB::requireTable($this->class, $fields, $indexes, $hasAutoIncPK);
|
DB::requireTable($this->class, $fields, $indexes, $hasAutoIncPK, $this->stat('create_table_options'));
|
||||||
} else {
|
} else {
|
||||||
DB::dontRequireTable($this->class);
|
DB::dontRequireTable($this->class);
|
||||||
}
|
}
|
||||||
@ -3019,6 +3019,24 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
"Created" => "SSDatetime",
|
"Created" => "SSDatetime",
|
||||||
"Title" => 'Text',
|
"Title" => 'Text',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify custom options for a CREATE TABLE call.
|
||||||
|
* Can be used to specify a custom storage engine for specific database table.
|
||||||
|
* All options have to be keyed for a specific database implementation,
|
||||||
|
* identified by their class name (extending from {@link Database}).
|
||||||
|
*
|
||||||
|
* <code>
|
||||||
|
* array(
|
||||||
|
* 'MySQLDatabase' => 'ENGINE=MyISAM'
|
||||||
|
* )
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
static $create_table_options = array(
|
||||||
|
'MySQLDatabase' => 'ENGINE=MyISAM'
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If a field is in this array, then create a database index
|
* If a field is in this array, then create a database index
|
||||||
|
@ -71,9 +71,13 @@ abstract class Database extends Object {
|
|||||||
/**
|
/**
|
||||||
* Create a new table.
|
* Create a new table.
|
||||||
* The table will have a single field - the integer key ID.
|
* The table will have a single field - the integer key ID.
|
||||||
* @param string $table Name of table to create.
|
* @param string $table
|
||||||
|
* @param array $fields
|
||||||
|
* @param array $indexes
|
||||||
|
* @param string $driver
|
||||||
|
* @param array $options
|
||||||
*/
|
*/
|
||||||
abstract function createTable($table, $fields = null, $indexes = null);
|
abstract function createTable($table, $fields = null, $indexes = null, $options = null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alter a table's schema.
|
* Alter a table's schema.
|
||||||
@ -177,12 +181,12 @@ abstract class Database extends Object {
|
|||||||
foreach($this->schemaUpdateTransaction as $tableName => $changes) {
|
foreach($this->schemaUpdateTransaction as $tableName => $changes) {
|
||||||
switch($changes['command']) {
|
switch($changes['command']) {
|
||||||
case 'create':
|
case 'create':
|
||||||
$this->createTable($tableName, $changes['newFields'], $changes['newIndexes']);
|
$this->createTable($tableName, $changes['newFields'], $changes['newIndexes'], $changes['options']);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'alter':
|
case 'alter':
|
||||||
$this->alterTable($tableName, $changes['newFields'], $changes['newIndexes'],
|
$this->alterTable($tableName, $changes['newFields'], $changes['newIndexes'],
|
||||||
$changes['alteredFields'], $changes['alteredIndexes']);
|
$changes['alteredFields'], $changes['alteredIndexes'], $changes['alteredOptions']);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,9 +195,23 @@ abstract class Database extends Object {
|
|||||||
|
|
||||||
// Transactional schema altering functions - they don't do anyhting except for update schemaUpdateTransaction
|
// Transactional schema altering functions - they don't do anyhting except for update schemaUpdateTransaction
|
||||||
|
|
||||||
function transCreateTable($table) {
|
/**
|
||||||
$this->schemaUpdateTransaction[$table] = array('command' => 'create', 'newFields' => array(), 'newIndexes' => array());
|
* @param string $table
|
||||||
|
* @param string $options
|
||||||
|
*/
|
||||||
|
function transCreateTable($table, $options = null) {
|
||||||
|
$this->schemaUpdateTransaction[$table] = array('command' => 'create', 'newFields' => array(), 'newIndexes' => array(), 'options' => $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $table
|
||||||
|
* @param array $options
|
||||||
|
*/
|
||||||
|
function transAlterTable($table, $options) {
|
||||||
|
$this->transInitTable($table);
|
||||||
|
$this->schemaUpdateTransaction[$table]['alteredOptions'] = $options;
|
||||||
|
}
|
||||||
|
|
||||||
function transCreateField($table, $field, $schema) {
|
function transCreateField($table, $field, $schema) {
|
||||||
$this->transInitTable($table);
|
$this->transInitTable($table);
|
||||||
$this->schemaUpdateTransaction[$table]['newFields'][$field] = $schema;
|
$this->schemaUpdateTransaction[$table]['newFields'][$field] = $schema;
|
||||||
@ -223,6 +241,7 @@ abstract class Database extends Object {
|
|||||||
'newIndexes' => array(),
|
'newIndexes' => array(),
|
||||||
'alteredFields' => array(),
|
'alteredFields' => array(),
|
||||||
'alteredIndexes' => array(),
|
'alteredIndexes' => array(),
|
||||||
|
'alteredOptions' => ''
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,16 +250,36 @@ abstract class Database extends Object {
|
|||||||
/**
|
/**
|
||||||
* Generate the following table in the database, modifying whatever already exists
|
* Generate the following table in the database, modifying whatever already exists
|
||||||
* as necessary.
|
* as necessary.
|
||||||
|
* @todo Change detection for CREATE TABLE $options other than "Engine"
|
||||||
|
*
|
||||||
* @param string $table The name of the table
|
* @param string $table The name of the table
|
||||||
* @param string $fieldSchema A list of the fields to create, in the same form as DataObject::$db
|
* @param string $fieldSchema A list of the fields to create, in the same form as DataObject::$db
|
||||||
* @param string $indexSchema A list of indexes to create. See {@link requireIndex()}
|
* @param string $indexSchema A list of indexes to create. See {@link requireIndex()}
|
||||||
|
* @param array $options
|
||||||
*/
|
*/
|
||||||
function requireTable($table, $fieldSchema = null, $indexSchema = null, $hasAutoIncPK=true) {
|
function requireTable($table, $fieldSchema = null, $indexSchema = null, $hasAutoIncPK=true, $options = null) {
|
||||||
if(!isset($this->tableList[strtolower($table)])) {
|
if(!isset($this->tableList[strtolower($table)])) {
|
||||||
$this->transCreateTable($table);
|
$this->transCreateTable($table, $options);
|
||||||
Database::alteration_message("Table $table: created","created");
|
Database::alteration_message("Table $table: created","created");
|
||||||
} else {
|
} else {
|
||||||
$this->checkAndRepairTable($table);
|
$this->checkAndRepairTable($table, $options);
|
||||||
|
|
||||||
|
// Check if options changed
|
||||||
|
if($options && isset($options[$this->class])) {
|
||||||
|
$tableOptionsChanged = false;
|
||||||
|
if(preg_match('/ENGINE=([^\s]*)/', $options[$this->class], $alteredEngineMatches)) {
|
||||||
|
$alteredEngine = $alteredEngineMatches[1];
|
||||||
|
$tableStatus = DB::query(sprintf(
|
||||||
|
'SHOW TABLE STATUS WHERE "Name" = \'%s\'',
|
||||||
|
$table
|
||||||
|
))->first();
|
||||||
|
$tableOptionsChanged = ($tableStatus['Engine'] != $alteredEngine);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($tableOptionsChanged) {
|
||||||
|
$this->transAlterTable($table, $options);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//DB ABSTRACTION: we need to convert this to a db-specific version:
|
//DB ABSTRACTION: we need to convert this to a db-specific version:
|
||||||
@ -253,7 +292,7 @@ abstract class Database extends Object {
|
|||||||
$fieldObj->setTable($table);
|
$fieldObj->setTable($table);
|
||||||
$fieldObj->requireField();
|
$fieldObj->requireField();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create custom indexes
|
// Create custom indexes
|
||||||
if($indexSchema) {
|
if($indexSchema) {
|
||||||
|
@ -190,18 +190,25 @@ class MySQLDatabase extends Database {
|
|||||||
return $this->query("SHOW DATABASES")->column();
|
return $this->query("SHOW DATABASES")->column();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createTable($tableName, $fields = null, $indexes = null) {
|
/**
|
||||||
|
* @param string $table
|
||||||
|
* @param array $fields
|
||||||
|
* @param array $indexes
|
||||||
|
* @param string $options
|
||||||
|
*/
|
||||||
|
public function createTable($table, $fields = null, $indexes = null, $options = null) {
|
||||||
$fieldSchemas = $indexSchemas = "";
|
$fieldSchemas = $indexSchemas = "";
|
||||||
|
$addOptions = (isset($options[$this->class])) ? $options[$this->class] : null;
|
||||||
|
|
||||||
if(!isset($fields['ID'])) $fields['ID'] = "int(11) not null auto_increment";
|
if(!isset($fields['ID'])) $fields['ID'] = "int(11) not null auto_increment";
|
||||||
if($fields) foreach($fields as $k => $v) $fieldSchemas .= "\"$k\" $v,\n";
|
if($fields) foreach($fields as $k => $v) $fieldSchemas .= "\"$k\" $v,\n";
|
||||||
if($indexes) foreach($indexes as $k => $v) $indexSchemas .= $this->getIndexSqlDefinition($k, $v) . ",\n";
|
if($indexes) foreach($indexes as $k => $v) $indexSchemas .= $this->getIndexSqlDefinition($k, $v) . ",\n";
|
||||||
|
|
||||||
$this->query("CREATE TABLE \"$tableName\" (
|
$this->query("CREATE TABLE \"$table\" (
|
||||||
$fieldSchemas
|
$fieldSchemas
|
||||||
$indexSchemas
|
$indexSchemas
|
||||||
primary key (ID)
|
primary key (ID)
|
||||||
) TYPE=MyISAM");
|
) {$addOptions}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -211,9 +218,11 @@ class MySQLDatabase extends Database {
|
|||||||
* @param $newIndexes New indexes, a map of index name => index type
|
* @param $newIndexes New indexes, a map of index name => index type
|
||||||
* @param $alteredFields Updated fields, a map of field name => field schema
|
* @param $alteredFields Updated fields, a map of field name => field schema
|
||||||
* @param $alteredIndexes Updated indexes, a map of index name => index type
|
* @param $alteredIndexes Updated indexes, a map of index name => index type
|
||||||
|
* @param $alteredOptions
|
||||||
*/
|
*/
|
||||||
public function alterTable($tableName, $newFields = null, $newIndexes = null, $alteredFields = null, $alteredIndexes = null) {
|
public function alterTable($tableName, $newFields = null, $newIndexes = null, $alteredFields = null, $alteredIndexes = null, $alteredOptions = null) {
|
||||||
$fieldSchemas = $indexSchemas = "";
|
$fieldSchemas = $indexSchemas = "";
|
||||||
|
$alterList = array();
|
||||||
|
|
||||||
if($newFields) foreach($newFields as $k => $v) $alterList[] .= "ADD \"$k\" $v";
|
if($newFields) foreach($newFields as $k => $v) $alterList[] .= "ADD \"$k\" $v";
|
||||||
if($newIndexes) foreach($newIndexes as $k => $v) $alterList[] .= "ADD " . $this->getIndexSqlDefinition($k, $v);
|
if($newIndexes) foreach($newIndexes as $k => $v) $alterList[] .= "ADD " . $this->getIndexSqlDefinition($k, $v);
|
||||||
@ -225,6 +234,14 @@ class MySQLDatabase extends Database {
|
|||||||
|
|
||||||
$alterations = implode(",\n", $alterList);
|
$alterations = implode(",\n", $alterList);
|
||||||
$this->query("ALTER TABLE \"$tableName\" $alterations");
|
$this->query("ALTER TABLE \"$tableName\" $alterations");
|
||||||
|
|
||||||
|
if($alteredOptions && isset($alteredOptions[$this->class])) {
|
||||||
|
$this->query(sprintf("ALTER TABLE \"%s\" %s", $tableName, $alteredOptions[$this->class]));
|
||||||
|
Database::alteration_message(
|
||||||
|
sprintf("Table %s options changed: %s", $tableName, $alteredOptions[$this->class]),
|
||||||
|
"changed"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function renameTable($oldTableName, $newTableName) {
|
public function renameTable($oldTableName, $newTableName) {
|
||||||
|
@ -45,9 +45,25 @@ class DatabaseTest extends SapphireTest {
|
|||||||
self::create_temp_db();
|
self::create_temp_db();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testMySQLCreateTableOptions() {
|
||||||
|
if(DB::getConn() instanceof MySQLDatabase) {
|
||||||
|
$ret = DB::query(sprintf(
|
||||||
|
'SHOW TABLE STATUS WHERE "Name" = \'%s\'',
|
||||||
|
'DatabaseTest_MyObject'
|
||||||
|
))->first();
|
||||||
|
$this->assertEquals($ret['Engine'],'InnoDB',
|
||||||
|
"MySQLDatabase tables can be changed to InnoDB through DataObject::\$create_table_options"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DatabaseTest_MyObject extends DataObject implements TestOnly {
|
class DatabaseTest_MyObject extends DataObject implements TestOnly {
|
||||||
|
|
||||||
|
static $create_table_options = array('MySQLDatabase' => 'ENGINE=InnoDB');
|
||||||
|
|
||||||
static $db = array(
|
static $db = array(
|
||||||
'MyField' => 'Varchar'
|
'MyField' => 'Varchar'
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user