Implemented 'group' by conditions for model finds. Added tests from 'wluigi' Closes #2833

git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@7057 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
mark_story 2008-05-29 12:27:23 +00:00
parent 4bafc397f9
commit 78ff2ad4bd
3 changed files with 87 additions and 11 deletions

View file

@ -1008,7 +1008,8 @@ class DboSource extends DataSource {
'offset' => $queryData['offset'],
'joins' => $queryData['joins'],
'conditions' => $queryData['conditions'],
'order' => $queryData['order']
'order' => $queryData['order'],
'group' => $queryData['group']
),
$model
);
@ -1028,6 +1029,7 @@ class DboSource extends DataSource {
$assocData['offset'] = ($assocData['page'] - 1) * $assocData['limit'];
}
$assocData['limit'] = $this->limit($assocData['limit'], $assocData['offset']);
switch($type) {
case 'hasOne':
@ -1041,7 +1043,8 @@ class DboSource extends DataSource {
'conditions' => $conditions,
'table' => $this->fullTableName($linkModel),
'fields' => $fields,
'alias' => $alias
'alias' => $alias,
'group' => null
));
$query = array_merge(array('order' => $assocData['order'], 'limit' => $assocData['limit']), $query);
} else {
@ -1073,7 +1076,8 @@ class DboSource extends DataSource {
'table' => $this->fullTableName($linkModel),
'alias' => $alias,
'order' => $assocData['order'],
'limit' => $assocData['limit']
'limit' => $assocData['limit'],
'group' => null,
);
break;
case 'hasAndBelongsToMany':
@ -1104,6 +1108,7 @@ class DboSource extends DataSource {
'alias' => $alias,
'fields' => array_merge($this->fields($linkModel, $alias, $assocData['fields']), $joinFields),
'order' => $assocData['order'],
'group' => null,
'joins' => array(array(
'table' => $joinTbl,
'alias' => $joinAssoc,
@ -1203,7 +1208,8 @@ class DboSource extends DataSource {
'alias' => $this->alias . $this->name($query['alias']),
'order' => $this->order($query['order']),
'limit' => $this->limit($query['limit'], $query['offset']),
'joins' => join(' ', $query['joins'])
'joins' => join(' ', $query['joins']),
'group' => $this->group($query['group'])
));
}
/**
@ -1229,7 +1235,7 @@ class DboSource extends DataSource {
switch (strtolower($type)) {
case 'select':
return "SELECT {$fields} FROM {$table} {$alias} {$joins} {$conditions} {$order} {$limit}";
return "SELECT {$fields} FROM {$table} {$alias} {$joins} {$conditions} {$order} {$limit}{$group}";
break;
case 'update':
if (!empty($alias)) {
@ -1566,7 +1572,7 @@ class DboSource extends DataSource {
* @return array
*/
function __scrubQueryData($data) {
foreach (array('conditions', 'fields', 'joins', 'order', 'limit', 'offset') as $key) {
foreach (array('conditions', 'fields', 'joins', 'order', 'limit', 'offset', 'group') as $key) {
if (!isset($data[$key]) || empty($data[$key])) {
$data[$key] = array();
}
@ -1984,6 +1990,18 @@ class DboSource extends DataSource {
return ' ORDER BY ' . $keys . $direction;
}
}
/**
* Create a GROUP BY SQL clause
*
* @param string $group Group By Condition
* @return mixed string condition or null
**/
function group($group) {
if ($group) {
return ' GROUP BY ' . $this->__quoteFields($group);
}
return null;
}
/**
* Disconnects database, kills the connection and says the connection is closed,
* and if DEBUG is turned on, the log for this object is shown.

View file

@ -1715,7 +1715,8 @@ class Model extends Overloadable {
* 'conditions' => array('name' => 'Thomas Anderson'),
* 'fields' => array('name', 'email'),
* 'order' => 'field3 DESC',
* 'recursive' => 2));
* 'recursive' => 2,
* 'group' => 'type'));
*
* Specifying 'fields' for new-notation 'list':
* - If no fields are specified, then 'id' is used for key and 'model->displayField' is used for value.
@ -1745,7 +1746,7 @@ class Model extends Overloadable {
$query = array_merge(
array(
'conditions' => null, 'fields' => null, 'joins' => array(),
'limit' => null, 'offset' => null, 'order' => null, 'page' => null
'limit' => null, 'offset' => null, 'order' => null, 'page' => null, 'group' => null
),
$query
);

View file

@ -49,7 +49,7 @@ class ModelTest extends CakeTestCase {
'core.document', 'core.device', 'core.document_directory', 'core.primary_model', 'core.secondary_model', 'core.something',
'core.something_else', 'core.join_thing', 'core.join_a', 'core.join_b', 'core.join_c', 'core.join_a_b', 'core.join_a_c',
'core.uuid', 'core.data_test', 'core.posts_tag', 'core.the_paper_monkies', 'core.person', 'core.underscore_field',
'core.node', 'core.dependency'
'core.node', 'core.dependency', 'core.product'
);
function start() {
@ -167,7 +167,8 @@ class ModelTest extends CakeTestCase {
)
)),
'conditions' => array(),
'order' => null
'order' => null,
'group' => null
),
$Article
);
@ -425,8 +426,64 @@ class ModelTest extends CakeTestCase {
'Mother' => array(),
'Father' => array())));
$this->assertEqual($result, $expected);
}
}
function testGroupByFind() {
$this->loadFixtures('Product');
$Product =& new Product();
$result = $Product->find('all',array('fields'=>array('Product.type','MIN(Product.price) as price'), 'group'=> 'Product.type'));
$expected = array(
0 => array(
'Product' => array(
'type' => 'Clothing',
'price' => 32)
),
1 => array(
'Product' => array(
'type' => 'Food',
'price' => 9)
),
2 => array(
'Product' => array(
'type' => 'Music',
'price' => 4)
),
3 => array(
'Product' => array(
'type' => 'Toy',
'price' => 3)
),
);
$this->assertEqual($result, $expected);
}
function testGroupByFindAssociations() {
$this->loadFixtures('Project', 'Thread', 'Message', 'Bid');
$Thread =& new Thread();
$result = $Thread->find('all', array('conditions' => array('Thread.project_id' => 1 ), 'group' => 'Thread.project_id'));
$expected = array(
array(
'Thread' => array(
'id' => '1',
'project_id' => 1,
'name' => 'Project 1, Thread 1',
),
'Message' => array(
array( 'id' => 1,
'thread_id' => 1,
'name' => 'Thread 1, Message 1'
)
)
),
);
$this->assertEqual($result, $expected);
}
function testIdentity() {
$TestModel =& new Test();
$result = $TestModel->alias;