Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

FIXED: Issue where temporary table would cause unpredictable behaviou…

…r. Temporary table functionality was substituted with subqueries in each use case.

ADDED: Test case for version archive functionality.
  • Loading branch information...
commit 0f09305e3d31a98e41cfb9158dda14ba584931db 1 parent c55b018
Damian Mooyman tractorcow authored
Showing with 77 additions and 35 deletions.
  1. +24 −35 model/Versioned.php
  2. +53 −0 tests/model/VersionedTest.php
59 model/Versioned.php
View
@@ -160,10 +160,19 @@ function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null) {
}
// Link to the version archived on that date
- $archiveTable = $this->requireArchiveTempTable($baseTable, $date);
- $query->addFrom(array($archiveTable => "INNER JOIN \"$archiveTable\"
- ON \"$archiveTable\".\"ID\" = \"{$baseTable}_versions\".\"RecordID\"
- AND \"$archiveTable\".\"Version\" = \"{$baseTable}_versions\".\"Version\""));
+ $safeDate = Convert::raw2sql($date);
+ $query->addWhere(
+ "`{$baseTable}_versions`.`Version` IN
+ (SELECT LatestVersion FROM
+ (SELECT
+ `{$baseTable}_versions`.`RecordID`,
+ MAX(`{$baseTable}_versions`.`Version`) AS LatestVersion
+ FROM `{$baseTable}_versions`
+ WHERE `{$baseTable}_versions`.`LastEdited` <= '$safeDate'
+ GROUP BY `{$baseTable}_versions`.`RecordID`
+ ) AS `{$baseTable}_versions_latest`
+ WHERE `{$baseTable}_versions_latest`.`RecordID` = `{$baseTable}_versions`.`RecordID`
+ )");
break;
// Reading a specific stage (Stage or Live)
@@ -204,10 +213,18 @@ function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null) {
// Return latest version instances, regardless of whether they are on a particular stage
// This provides "show all, including deleted" functonality
if($dataQuery->getQueryParam('Versioned.mode') == 'latest_versions') {
- $archiveTable = self::requireArchiveTempTable($baseTable);
- $query->addInnerJoin($archiveTable, "\"$archiveTable\".\"ID\" = \"{$baseTable}_versions\".\"RecordID\" AND \"$archiveTable\".\"Version\" = \"{$baseTable}_versions\".\"Version\"");
+ $query->addWhere(
+ "`{$alias}_versions`.`Version` IN
+ (SELECT LatestVersion FROM
+ (SELECT
+ `{$alias}_versions`.`RecordID`,
+ MAX(`{$alias}_versions`.`Version`) AS LatestVersion
+ FROM `{$alias}_versions`
+ GROUP BY `{$alias}_versions`.`RecordID`
+ ) AS `{$alias}_versions_latest`
+ WHERE `{$alias}_versions_latest`.`RecordID` = `{$alias}_versions`.`RecordID`
+ )");
}
-
break;
default:
throw new InvalidArgumentException("Bad value for query parameter Versioned.mode: " . $dataQuery->getQueryParam('Versioned.mode'));
@@ -234,34 +251,6 @@ public static function on_db_reset() {
// Remove references to them
self::$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.
- * @param string $baseTable The base table.
- * @param string $date The date. If omitted, then the latest version of each page will be returned.
- * @todo Ensure that this is DB abstracted
- */
- protected static function requireArchiveTempTable($baseTable, $date = 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 \"" . self::$archive_tables[$baseTable] . "\"")->value()) {
- if($date) $dateClause = "WHERE \"LastEdited\" <= '$date'";
- else $dateClause = "";
-
- DB::query("INSERT INTO \"" . self::$archive_tables[$baseTable] . "\"
- SELECT \"RecordID\", max(\"Version\") FROM \"{$baseTable}_versions\"
- $dateClause
- GROUP BY \"RecordID\"");
- }
-
- return self::$archive_tables[$baseTable];
- }
/**
* An array of DataObject extensions that may require versioning for extra tables
53 tests/model/VersionedTest.php
View
@@ -266,6 +266,59 @@ public function testGetVersionWhenClassnameChanged() {
$this->assertInstanceOf("VersionedTest_DataObject", $obj3);
}
+
+ public function testArchiveVersion() {
+
+ // In 2005 this file was created
+ SS_Datetime::set_mock_now('2005-01-01 00:00:00');
+ $testPage = new VersionedTest_Subclass();
+ $testPage->Title = 'Archived page';
+ $testPage->Content = 'This is the content from 2005';
+ $testPage->ExtraField = '2005';
+ $testPage->write();
+ $testPage->publish('Stage', 'Live');
+
+ // In 2007 we updated it
+ SS_Datetime::set_mock_now('2007-01-01 00:00:00');
+ $testPage->Content = "It's 2007 already!";
+ $testPage->ExtraField = '2007';
+ $testPage->write();
+ $testPage->publish('Stage', 'Live');
+
+ // In 2009 we updated it again
+ SS_Datetime::set_mock_now('2009-01-01 00:00:00');
+ $testPage->Content = "I'm enjoying 2009";
+ $testPage->ExtraField = '2009';
+ $testPage->write();
+ $testPage->publish('Stage', 'Live');
+
+ // End mock, back to the present day:)
+ SS_Datetime::clear_mock_now();
+
+ // Test 1 - 2006 Content
+ singleton('VersionedTest_Subclass')->flushCache(true);
+ Versioned::set_reading_mode('Archive.2006-01-01 00:00:00');
+ $testPage2006 = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))->first();
+ $this->assertInstanceOf("VersionedTest_Subclass", $testPage2006);
+ $this->assertEquals("2005", $testPage2006->ExtraField);
+ $this->assertEquals("This is the content from 2005", $testPage2006->Content);
+
+ // Test 2 - 2008 Content
+ singleton('VersionedTest_Subclass')->flushCache(true);
+ Versioned::set_reading_mode('Archive.2008-01-01 00:00:00');
+ $testPage2008 = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))->first();
+ $this->assertInstanceOf("VersionedTest_Subclass", $testPage2008);
+ $this->assertEquals("2007", $testPage2008->ExtraField);
+ $this->assertEquals("It's 2007 already!", $testPage2008->Content);
+
+ // Test 3 - Today
+ singleton('VersionedTest_Subclass')->flushCache(true);
+ Versioned::set_reading_mode('Stage.Stage');
+ $testPageCurrent = DataObject::get('VersionedTest_Subclass')->filter(array('Title' => 'Archived page'))->first();
+ $this->assertInstanceOf("VersionedTest_Subclass", $testPageCurrent);
+ $this->assertEquals("2009", $testPageCurrent->ExtraField);
+ $this->assertEquals("I'm enjoying 2009", $testPageCurrent->Content);
+ }
}
class VersionedTest_DataObject extends DataObject implements TestOnly {
Please sign in to comment.
Something went wrong with that request. Please try again.