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.
|
||||
* The table will have a single field - the integer key ID.
|
||||
* @param string $table Name of table to create.
|
||||
* @param $tableName The name of the table
|
||||
* @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) {
|
||||
return DB::$globalConn->createTable($table);
|
||||
static function createTable($table, $fields = null, $indexes = null, $options = null) {
|
||||
return DB::$globalConn->createTable($table, $fields, $indexes, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,12 +70,13 @@ abstract class Database extends Object {
|
||||
|
||||
/**
|
||||
* Create a new table.
|
||||
* The table will have a single field - the integer key ID.
|
||||
* @param string $table
|
||||
* @param array $fields
|
||||
* @param array $indexes
|
||||
* @param string $driver
|
||||
* @param array $options
|
||||
* @param $tableName The name of the table
|
||||
* @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.
|
||||
*/
|
||||
abstract function createTable($table, $fields = null, $indexes = null, $options = null);
|
||||
|
||||
|
@ -191,10 +191,14 @@ class MySQLDatabase extends Database {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $table
|
||||
* @param array $fields
|
||||
* @param array $indexes
|
||||
* @param string $options
|
||||
* Create a new table.
|
||||
* @param $tableName The name of the table
|
||||
* @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.
|
||||
*/
|
||||
public function createTable($table, $fields = null, $indexes = null, $options = null) {
|
||||
$fieldSchemas = $indexSchemas = "";
|
||||
@ -204,11 +208,16 @@ class MySQLDatabase extends Database {
|
||||
if($fields) foreach($fields as $k => $v) $fieldSchemas .= "\"$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
|
||||
$indexSchemas
|
||||
primary key (ID)
|
||||
) {$addOptions}");
|
||||
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -724,6 +733,22 @@ class MySQLDatabase extends Database {
|
||||
function modifyIndex($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
|
||||
$this->requireArchiveTempTable($baseTable, $date);
|
||||
$query->from["_Archive$baseTable"] = "INNER JOIN \"_Archive$baseTable\"
|
||||
ON \"_Archive$baseTable\".\"RecordID\" = \"{$baseTable}_versions\".\"RecordID\"
|
||||
AND \"_Archive$baseTable\".\"Version\" = \"{$baseTable}_versions\".\"Version\"";
|
||||
$archiveTable = $this->requireArchiveTempTable($baseTable, $date);
|
||||
$query->from[$archiveTable] = "INNER JOIN \"$archiveTable\"
|
||||
ON \"$archiveTable\".\"ID\" = \"{$baseTable}_versions\".\"RecordID\"
|
||||
AND \"$archiveTable\".\"Version\" = \"{$baseTable}_versions\".\"Version\"";
|
||||
|
||||
// Get a specific stage
|
||||
} 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.
|
||||
* 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
|
||||
*/
|
||||
protected static function requireArchiveTempTable($baseTable, $date = null) {
|
||||
DB::query("CREATE TEMPORARY TABLE IF NOT EXISTS \"_Archive$baseTable\" (
|
||||
\"RecordID\" INT NOT NULL PRIMARY KEY,
|
||||
\"Version\" INT NOT NULL
|
||||
)");
|
||||
if(!isset(self::$archive_tables[$baseTable])) {
|
||||
self::$archive_tables[$baseTable] = DB::createTable("_Archive$baseTable", array(
|
||||
"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'";
|
||||
else $dateClause = "";
|
||||
|
||||
DB::query("INSERT INTO \"_Archive$baseTable\"
|
||||
DB::query("INSERT INTO \"" . self::$archive_tables[$baseTable] . "\"
|
||||
SELECT \"RecordID\", max(\"Version\") FROM \"{$baseTable}_versions\"
|
||||
$dateClause
|
||||
GROUP BY \"RecordID\"");
|
||||
}
|
||||
|
||||
return self::$archive_tables[$baseTable];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -781,10 +790,10 @@ class Versioned extends DataObjectDecorator {
|
||||
// Build query
|
||||
$query = $SNG->buildVersionSQL($filter, $sort);
|
||||
$baseTable = ClassInfo::baseDataClass($class);
|
||||
self::requireArchiveTempTable($baseTable);
|
||||
$query->from["_Archive$baseTable"] = "INNER JOIN `_Archive$baseTable`
|
||||
ON `_Archive$baseTable`.RecordID = `{$baseTable}_versions`.RecordID
|
||||
AND `_Archive$baseTable`.Version = `{$baseTable}_versions`.Version";
|
||||
$archiveTable = self::requireArchiveTempTable($baseTable);
|
||||
$query->from[$archiveTable] = "INNER JOIN \"$archiveTable\"
|
||||
ON \"$archiveTable\".\"ID\" = \"{$baseTable}_versions\".\"RecordID\"
|
||||
AND \"$archiveTable\".\"Version\" = \"{$baseTable}_versions\".\"Version\"";
|
||||
|
||||
// Process into a DataObjectSet
|
||||
$result = $SNG->buildDataObjectSet($query->execute());
|
||||
|
Loading…
x
Reference in New Issue
Block a user