mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
API CHANGE: Allow passing of temporary option to Database::createTable()
BUGFIX: Made Versioned's archive table functions (show deleted pages and show site at a particular date) db agnostic. git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@77551 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
90ebeaf741
commit
9effc74de3
@ -159,11 +159,16 @@ class DB {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new table.
|
* Create a new table.
|
||||||
* The table will have a single field - the integer key ID.
|
* @param $tableName The name of the table
|
||||||
* @param string $table Name of table to create.
|
* @param $fields A map of field names to field types
|
||||||
|
* @param $indexes A map of indexes
|
||||||
|
* @param $options An map of additional options. The available keys are as follows:
|
||||||
|
* - 'MSSQLDatabase'/'MySQLDatabase'/'PostgreSQLDatabase' - database-specific options such as "engine" for MySQL.
|
||||||
|
* - 'temporary' - If true, then a temporary table will be created
|
||||||
|
* @return The table name generated. This may be different from the table name, for example with temporary tables.
|
||||||
*/
|
*/
|
||||||
static function createTable($table) {
|
static function createTable($table, $fields = null, $indexes = null, $options = null) {
|
||||||
return DB::$globalConn->createTable($table);
|
return DB::$globalConn->createTable($table, $fields, $indexes, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,12 +70,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.
|
* @param $tableName The name of the table
|
||||||
* @param string $table
|
* @param $fields A map of field names to field types
|
||||||
* @param array $fields
|
* @param $indexes A map of indexes
|
||||||
* @param array $indexes
|
* @param $options An map of additional options. The available keys are as follows:
|
||||||
* @param string $driver
|
* - 'MSSQLDatabase'/'MySQLDatabase'/'PostgreSQLDatabase' - database-specific options such as "engine" for MySQL.
|
||||||
* @param array $options
|
* - 'temporary' - If true, then a temporary table will be created
|
||||||
|
* @return The table name generated. This may be different from the table name, for example with temporary tables.
|
||||||
*/
|
*/
|
||||||
abstract function createTable($table, $fields = null, $indexes = null, $options = null);
|
abstract function createTable($table, $fields = null, $indexes = null, $options = null);
|
||||||
|
|
||||||
|
@ -191,10 +191,14 @@ class MySQLDatabase extends Database {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $table
|
* Create a new table.
|
||||||
* @param array $fields
|
* @param $tableName The name of the table
|
||||||
* @param array $indexes
|
* @param $fields A map of field names to field types
|
||||||
* @param string $options
|
* @param $indexes A map of indexes
|
||||||
|
* @param $options An map of additional options. The available keys are as follows:
|
||||||
|
* - 'MSSQLDatabase'/'MySQLDatabase'/'PostgreSQLDatabase' - database-specific options such as "engine" for MySQL.
|
||||||
|
* - 'temporary' - If true, then a temporary table will be created
|
||||||
|
* @return The table name generated. This may be different from the table name, for example with temporary tables.
|
||||||
*/
|
*/
|
||||||
public function createTable($table, $fields = null, $indexes = null, $options = null) {
|
public function createTable($table, $fields = null, $indexes = null, $options = null) {
|
||||||
$fieldSchemas = $indexSchemas = "";
|
$fieldSchemas = $indexSchemas = "";
|
||||||
@ -204,11 +208,16 @@ class MySQLDatabase extends Database {
|
|||||||
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 \"$table\" (
|
// Switch to "CREATE TEMPORARY TABLE" for temporary tables
|
||||||
|
$temporary = empty($options['temporary']) ? "" : "TEMPORARY";
|
||||||
|
|
||||||
|
$this->query("CREATE $temporary TABLE \"$table\" (
|
||||||
$fieldSchemas
|
$fieldSchemas
|
||||||
$indexSchemas
|
$indexSchemas
|
||||||
primary key (ID)
|
primary key (ID)
|
||||||
) {$addOptions}");
|
) {$addOptions}");
|
||||||
|
|
||||||
|
return $table;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -724,6 +733,22 @@ class MySQLDatabase extends Database {
|
|||||||
function modifyIndex($index){
|
function modifyIndex($index){
|
||||||
return $index;
|
return $index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a SQL fragment for querying a fulltext search index
|
||||||
|
* @param $fields array The list of field names to search on
|
||||||
|
* @param $keywords string The search query
|
||||||
|
* @param $booleanSearch A MySQL-specific flag to switch to boolean search
|
||||||
|
*/
|
||||||
|
function fullTextSearchSQL($fields, $keywords, $booleanSearch = false) {
|
||||||
|
$boolean = $booleanSearch ? "IN BOOLEAN MODE" : "";
|
||||||
|
$fieldNames = '"' . implode('", "', $fields) . '"';
|
||||||
|
|
||||||
|
$SQL_keywords = Convert::raw2sql($keywords);
|
||||||
|
$SQL_htmlEntityKeywords = Convert::raw2sql(htmlentities($keywords));
|
||||||
|
|
||||||
|
return "(MATCH ($fieldNames) AGAINST ('$SQL_keywords' $boolean) + MATCH ($fieldNames) AGAINST ('$SQL_htmlEntityKeywords' $boolean))";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -119,10 +119,10 @@ class Versioned extends DataObjectDecorator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Link to the version archived on that date
|
// Link to the version archived on that date
|
||||||
$this->requireArchiveTempTable($baseTable, $date);
|
$archiveTable = $this->requireArchiveTempTable($baseTable, $date);
|
||||||
$query->from["_Archive$baseTable"] = "INNER JOIN \"_Archive$baseTable\"
|
$query->from[$archiveTable] = "INNER JOIN \"$archiveTable\"
|
||||||
ON \"_Archive$baseTable\".\"RecordID\" = \"{$baseTable}_versions\".\"RecordID\"
|
ON \"$archiveTable\".\"ID\" = \"{$baseTable}_versions\".\"RecordID\"
|
||||||
AND \"_Archive$baseTable\".\"Version\" = \"{$baseTable}_versions\".\"Version\"";
|
AND \"$archiveTable\".\"Version\" = \"{$baseTable}_versions\".\"Version\"";
|
||||||
|
|
||||||
// Get a specific stage
|
// Get a specific stage
|
||||||
} else if(Versioned::$reading_stage && Versioned::$reading_stage != $this->defaultStage
|
} else if(Versioned::$reading_stage && Versioned::$reading_stage != $this->defaultStage
|
||||||
@ -133,6 +133,11 @@ class Versioned extends DataObjectDecorator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep track of the archive tables that have been created
|
||||||
|
*/
|
||||||
|
private static $archive_tables = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a temporary table mapping each database record to its version on the given date.
|
* Create a temporary table mapping each database record to its version on the given date.
|
||||||
* This is used by the versioning system to return database content on that date.
|
* This is used by the versioning system to return database content on that date.
|
||||||
@ -141,20 +146,24 @@ class Versioned extends DataObjectDecorator {
|
|||||||
* @todo Ensure that this is DB abstracted
|
* @todo Ensure that this is DB abstracted
|
||||||
*/
|
*/
|
||||||
protected static function requireArchiveTempTable($baseTable, $date = null) {
|
protected static function requireArchiveTempTable($baseTable, $date = null) {
|
||||||
DB::query("CREATE TEMPORARY TABLE IF NOT EXISTS \"_Archive$baseTable\" (
|
if(!isset(self::$archive_tables[$baseTable])) {
|
||||||
\"RecordID\" INT NOT NULL PRIMARY KEY,
|
self::$archive_tables[$baseTable] = DB::createTable("_Archive$baseTable", array(
|
||||||
\"Version\" INT NOT NULL
|
"ID" => "INT NOT NULL",
|
||||||
)");
|
"Version" => "INT NOT NULL",
|
||||||
|
), null, array('temporary' => true));
|
||||||
|
}
|
||||||
|
|
||||||
if(!DB::query("SELECT COUNT(*) FROM \"_Archive$baseTable\"")->value()) {
|
if(!DB::query("SELECT COUNT(*) FROM \"" . self::$archive_tables[$baseTable] . "\"")->value()) {
|
||||||
if($date) $dateClause = "WHERE \"LastEdited\" <= '$date'";
|
if($date) $dateClause = "WHERE \"LastEdited\" <= '$date'";
|
||||||
else $dateClause = "";
|
else $dateClause = "";
|
||||||
|
|
||||||
DB::query("INSERT INTO \"_Archive$baseTable\"
|
DB::query("INSERT INTO \"" . self::$archive_tables[$baseTable] . "\"
|
||||||
SELECT \"RecordID\", max(\"Version\") FROM \"{$baseTable}_versions\"
|
SELECT \"RecordID\", max(\"Version\") FROM \"{$baseTable}_versions\"
|
||||||
$dateClause
|
$dateClause
|
||||||
GROUP BY \"RecordID\"");
|
GROUP BY \"RecordID\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return self::$archive_tables[$baseTable];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -781,10 +790,10 @@ class Versioned extends DataObjectDecorator {
|
|||||||
// Build query
|
// Build query
|
||||||
$query = $SNG->buildVersionSQL($filter, $sort);
|
$query = $SNG->buildVersionSQL($filter, $sort);
|
||||||
$baseTable = ClassInfo::baseDataClass($class);
|
$baseTable = ClassInfo::baseDataClass($class);
|
||||||
self::requireArchiveTempTable($baseTable);
|
$archiveTable = self::requireArchiveTempTable($baseTable);
|
||||||
$query->from["_Archive$baseTable"] = "INNER JOIN `_Archive$baseTable`
|
$query->from[$archiveTable] = "INNER JOIN \"$archiveTable\"
|
||||||
ON `_Archive$baseTable`.RecordID = `{$baseTable}_versions`.RecordID
|
ON \"$archiveTable\".\"ID\" = \"{$baseTable}_versions\".\"RecordID\"
|
||||||
AND `_Archive$baseTable`.Version = `{$baseTable}_versions`.Version";
|
AND \"$archiveTable\".\"Version\" = \"{$baseTable}_versions\".\"Version\"";
|
||||||
|
|
||||||
// Process into a DataObjectSet
|
// Process into a DataObjectSet
|
||||||
$result = $SNG->buildDataObjectSet($query->execute());
|
$result = $SNG->buildDataObjectSet($query->execute());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user