BUG Sort column order maintained correctly when using expressions in SQLQuery and DataQuery

This commit is contained in:
Damian Mooyman 2013-10-03 14:20:31 +13:00
parent 6e72262c96
commit afaf7f6b4e
4 changed files with 49 additions and 10 deletions

View File

@ -256,7 +256,10 @@ class DataQuery {
$baseClass = array_shift($tableClasses); $baseClass = array_shift($tableClasses);
if($orderby = $query->getOrderBy()) { if($orderby = $query->getOrderBy()) {
$newOrderby = array();
foreach($orderby as $k => $dir) { foreach($orderby as $k => $dir) {
$newOrderby[$k] = $dir;
// don't touch functions in the ORDER BY or public function calls // don't touch functions in the ORDER BY or public function calls
// selected as fields // selected as fields
if(strpos($k, '(') !== false) continue; if(strpos($k, '(') !== false) continue;
@ -284,9 +287,9 @@ class DataQuery {
} }
// remove original sort // remove original sort
unset($orderby[$k]); unset($newOrderby[$k]);
// add new columns sort // add new columns sort
$orderby[$qualCol] = $dir; $newOrderby[$qualCol] = $dir;
// To-do: Remove this if block once SQLQuery::$select has been refactored to store getSelect() // To-do: Remove this if block once SQLQuery::$select has been refactored to store getSelect()
// format internally; then this check can be part of selectField() // format internally; then this check can be part of selectField()
@ -305,7 +308,7 @@ class DataQuery {
} }
} }
$query->setOrderBy($orderby); $query->setOrderBy($newOrderby);
} }
} }

View File

@ -519,7 +519,7 @@ class SQLQuery {
* @example $sql->orderby("Column", "DESC"); * @example $sql->orderby("Column", "DESC");
* @example $sql->orderby(array("Column" => "ASC", "ColumnTwo" => "DESC")); * @example $sql->orderby(array("Column" => "ASC", "ColumnTwo" => "DESC"));
* *
* @param string|array $orderby Clauses to add (escaped SQL statements) * @param string|array $clauses Clauses to add (escaped SQL statements)
* @param string $dir Sort direction, ASC or DESC * @param string $dir Sort direction, ASC or DESC
* *
* @return SQLQuery * @return SQLQuery
@ -566,21 +566,23 @@ class SQLQuery {
// directly in the ORDER BY // directly in the ORDER BY
if($this->orderby) { if($this->orderby) {
$i = 0; $i = 0;
$orderby = array();
foreach($this->orderby as $clause => $dir) { foreach($this->orderby as $clause => $dir) {
// public function calls and multi-word columns like "CASE WHEN ..." // public function calls and multi-word columns like "CASE WHEN ..."
if(strpos($clause, '(') !== false || strpos($clause, " ") !== false ) { if(strpos($clause, '(') !== false || strpos($clause, " ") !== false ) {
// remove the old orderby
unset($this->orderby[$clause]);
// Move the clause to the select fragment, substituting a placeholder column in the sort fragment.
$clause = trim($clause); $clause = trim($clause);
$column = "_SortColumn{$i}"; $column = "_SortColumn{$i}";
$this->selectField($clause, $column); $this->selectField($clause, $column);
$this->addOrderBy('"' . $column . '"', $dir); $clause = '"' . $column . '"';
$i++; $i++;
} }
$orderby[$clause] = $dir;
} }
$this->orderby = $orderby;
} }
return $this; return $this;

View File

@ -115,6 +115,15 @@ class DataQueryTest extends SapphireTest {
$this->assertEquals($dq->sql(), $orgDq->sql()); $this->assertEquals($dq->sql(), $orgDq->sql());
} }
public function testOrderByMultiple() {
$dq = new DataQuery('SQLQueryTest_DO');
$dq = $dq->sort('"Name" ASC, MID("Name", 8, 1) DESC');
$this->assertContains(
'ORDER BY "Name" ASC, "_SortColumn0" DESC',
$dq->sql()
);
}
} }

View File

@ -480,6 +480,31 @@ class SQLQueryTest extends SapphireTest {
$this->assertEquals('2012-05-01 09:00:00', $records['0']['_SortColumn0']); $this->assertEquals('2012-05-01 09:00:00', $records['0']['_SortColumn0']);
} }
/**
* Test that multiple order elements are maintained in the given order
*/
public function testOrderByMultiple() {
if(DB::getConn() instanceof MySQLDatabase) {
$query = new SQLQuery();
$query->setSelect(array('"Name"', '"Meta"'));
$query->setFrom('"SQLQueryTest_DO"');
$query->setOrderBy(array('MID("Name", 8, 1) DESC', '"Name" ASC'));
$records = array();
foreach($query->execute() as $record) {
$records[] = $record;
}
$this->assertCount(2, $records);
$this->assertEquals('Object 2', $records[0]['Name']);
$this->assertEquals('2', $records[0]['_SortColumn0']);
$this->assertEquals('Object 1', $records[1]['Name']);
$this->assertEquals('1', $records[1]['_SortColumn0']);
}
}
/** /**
* Test passing in a LIMIT with OFFSET clause string. * Test passing in a LIMIT with OFFSET clause string.
*/ */