mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
BUGFIX DataQuery: ensuring ORDER BY columns are set in SELECT clauses
This commit is contained in:
parent
f4643e1b4a
commit
3bf983200b
@ -297,7 +297,7 @@ class DataList extends ViewableData implements SS_List {
|
|||||||
*/
|
*/
|
||||||
function setByIDList($idList) {
|
function setByIDList($idList) {
|
||||||
$has = array();
|
$has = array();
|
||||||
|
|
||||||
// Index current data
|
// Index current data
|
||||||
foreach($this->column() as $id) {
|
foreach($this->column() as $id) {
|
||||||
$has[$id] = true;
|
$has[$id] = true;
|
||||||
@ -310,7 +310,9 @@ class DataList extends ViewableData implements SS_List {
|
|||||||
// $id is the database ID of the record
|
// $id is the database ID of the record
|
||||||
if($idList) foreach($idList as $id) {
|
if($idList) foreach($idList as $id) {
|
||||||
unset($itemsToDelete[$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
|
// Remove any items that haven't been mentioned
|
||||||
@ -468,5 +470,3 @@ class DataList extends ViewableData implements SS_List {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
|
@ -2699,11 +2699,11 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
if(is_numeric($id)) {
|
if(is_numeric($id)) {
|
||||||
if(is_subclass_of($callerClass, 'DataObject')) {
|
if(is_subclass_of($callerClass, 'DataObject')) {
|
||||||
$baseClass = ClassInfo::baseDataClass($callerClass);
|
$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
|
// This simpler code will be used by non-DataObject classes that implement DataObjectInterface
|
||||||
} else {
|
} else {
|
||||||
return DataObject::get_one($callerClass,"\"ID\" = $id", $cache, 1);
|
return DataObject::get_one($callerClass,"\"ID\" = $id", $cache);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
user_error("DataObject::get_by_id passed a non-numeric ID #$id", E_USER_WARNING);
|
user_error("DataObject::get_by_id passed a non-numeric ID #$id", E_USER_WARNING);
|
||||||
|
@ -111,7 +111,7 @@ class DataQuery {
|
|||||||
$baseClass = array_shift($tableClasses);
|
$baseClass = array_shift($tableClasses);
|
||||||
|
|
||||||
$collidingFields = array();
|
$collidingFields = array();
|
||||||
|
|
||||||
// Join all the tables
|
// Join all the tables
|
||||||
if($this->querySubclasses) {
|
if($this->querySubclasses) {
|
||||||
foreach($tableClasses as $tableClass) {
|
foreach($tableClasses as $tableClass) {
|
||||||
@ -152,13 +152,72 @@ class DataQuery {
|
|||||||
|
|
||||||
$query->select[] = "\"$baseClass\".\"ID\"";
|
$query->select[] = "\"$baseClass\".\"ID\"";
|
||||||
$query->select[] = "CASE WHEN \"$baseClass\".\"ClassName\" IS NOT NULL THEN \"$baseClass\".\"ClassName\" ELSE '$baseClass' END AS \"RecordClassName\"";
|
$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
|
// TODO: Versioned, Translatable, SiteTreeSubsites, etc, could probably be better implemented as subclasses of DataQuery
|
||||||
singleton($this->dataClass)->extend('augmentSQL', $query, $this);
|
singleton($this->dataClass)->extend('augmentSQL', $query, $this);
|
||||||
|
|
||||||
|
$this->ensureSelectContainsOrderbyColumns($query);
|
||||||
|
|
||||||
return $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.
|
* Execute the query and return the result as {@link Query} object.
|
||||||
*/
|
*/
|
||||||
@ -444,7 +503,9 @@ class DataQuery {
|
|||||||
public function column($field = 'ID') {
|
public function column($field = 'ID') {
|
||||||
$query = $this->getFinalisedQuery();
|
$query = $this->getFinalisedQuery();
|
||||||
$query->select($this->expressionForField($field, $query));
|
$query->select($this->expressionForField($field, $query));
|
||||||
return $query->execute()->column();
|
$this->ensureSelectContainsOrderbyColumns($query);
|
||||||
|
|
||||||
|
return $query->execute()->column($field);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function expressionForField($field, $query) {
|
protected function expressionForField($field, $query) {
|
||||||
@ -499,5 +560,3 @@ class DataQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
|
Loading…
Reference in New Issue
Block a user