BUGFIX DataQuery: ensuring ORDER BY columns are set in SELECT clauses

This commit is contained in:
Sean Harvey 2011-10-29 17:27:21 +13:00
parent f4643e1b4a
commit 3bf983200b
3 changed files with 72 additions and 13 deletions

View File

@ -297,7 +297,7 @@ class DataList extends ViewableData implements SS_List {
*/
function setByIDList($idList) {
$has = array();
// Index current data
foreach($this->column() as $id) {
$has[$id] = true;
@ -310,7 +310,9 @@ class DataList extends ViewableData implements SS_List {
// $id is the database ID of the record
if($idList) foreach($idList as $id) {
unset($itemsToDelete[$id]);
if($id && !isset($has[$id])) $this->add($id);
if($id && !isset($has[$id])) {
$this->add($id);
}
}
// Remove any items that haven't been mentioned
@ -468,5 +470,3 @@ class DataList extends ViewableData implements SS_List {
}
}
?>

View File

@ -2699,11 +2699,11 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
if(is_numeric($id)) {
if(is_subclass_of($callerClass, 'DataObject')) {
$baseClass = ClassInfo::baseDataClass($callerClass);
return DataObject::get_one($callerClass,"\"$baseClass\".\"ID\" = $id", $cache, 1);
return DataObject::get_one($callerClass,"\"$baseClass\".\"ID\" = $id", $cache);
// This simpler code will be used by non-DataObject classes that implement DataObjectInterface
} else {
return DataObject::get_one($callerClass,"\"ID\" = $id", $cache, 1);
return DataObject::get_one($callerClass,"\"ID\" = $id", $cache);
}
} else {
user_error("DataObject::get_by_id passed a non-numeric ID #$id", E_USER_WARNING);

View File

@ -111,7 +111,7 @@ class DataQuery {
$baseClass = array_shift($tableClasses);
$collidingFields = array();
// Join all the tables
if($this->querySubclasses) {
foreach($tableClasses as $tableClass) {
@ -152,13 +152,72 @@ class DataQuery {
$query->select[] = "\"$baseClass\".\"ID\"";
$query->select[] = "CASE WHEN \"$baseClass\".\"ClassName\" IS NOT NULL THEN \"$baseClass\".\"ClassName\" ELSE '$baseClass' END AS \"RecordClassName\"";
// TODO: Versioned, Translatable, SiteTreeSubsites, etc, could probably be better implemented as subclasses of DataQuery
singleton($this->dataClass)->extend('augmentSQL', $query, $this);
$this->ensureSelectContainsOrderbyColumns($query);
return $query;
}
/**
* Ensure that if a query has an order by clause, those columns are present in the select.
*
* @param SQLQuery $query
* @return null
*/
protected function ensureSelectContainsOrderbyColumns($query) {
$tableClasses = ClassInfo::dataClassesFor($this->dataClass);
$baseClass = array_shift($tableClasses);
if($query->orderby) {
$orderByFields = explode(',', $query->orderby);
foreach($orderByFields as $ob => $col) {
$col = trim($col);
// don't touch functions in the ORDER BY
if(strpos($col, '(') !== false) continue;
$columnParts = explode(' ', $col);
if (count($columnParts) == 2) {
$dir = $columnParts[1];
$col = $columnParts[0];
} else {
$dir = '';
}
$orderByFields[$ob] = $col;
$col = str_replace('"', '', $col);
$parts = explode('.', $col);
if(count($parts) == 1) {
$databaseFields = DataObject::database_fields($baseClass);
// database_fields() doesn't return ID, so we need to manually add it here
$databaseFields['ID'] = true;
if(isset($databaseFields[$parts[0]])) {
$qualCol = "\"$baseClass\".\"{$parts[0]}\"";
$orderByFields[$ob] = trim($qualCol . " " . $dir);
} else {
$qualCol = "\"$parts[0]\"";
}
if(!isset($query->select[$parts[0]]) && !in_array($qualCol, $query->select)) {
$query->select[] = $qualCol;
}
} else {
$qualCol = '"' . implode('"."', $parts) . '"';
if(!in_array($qualCol, $query->select)) {
$query->select[] = $qualCol;
}
}
}
$query->orderby = implode(',', $orderByFields);
}
}
/**
* Execute the query and return the result as {@link Query} object.
*/
@ -444,7 +503,9 @@ class DataQuery {
public function column($field = 'ID') {
$query = $this->getFinalisedQuery();
$query->select($this->expressionForField($field, $query));
return $query->execute()->column();
$this->ensureSelectContainsOrderbyColumns($query);
return $query->execute()->column($field);
}
protected function expressionForField($field, $query) {
@ -499,5 +560,3 @@ class DataQuery {
}
}
?>