Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Zend paginator dbselect count #4590

Closed
wants to merge 2 commits into from

2 participants

fatmuemoo Ralph Schindler
fatmuemoo

Fixes row count issue when you use GROUP with original query.

Ralph Schindler
Collaborator

For changes like this, I really need to be able to test the approach on multiple databases. Can you create a generic schema with generic data that shows the usage of group and what you think the expected output should be? It would really assist me in the testing of this across multiple platforms.

fatmuemoo

@ralphschindler I will get that to you soon

fatmuemoo

@ralphschindler
SQL Script http://pastebin.com/NhHLxTnd

MySQL Query: http://pastebin.com/rm2amQd6

Expected output(ie pull request): 10
Actual output(ie current issue): 13

Please let me know if there is more I can do.

Ralph Schindler
Collaborator

I'm working on this, but at current, it doesn't seem like COUNT(DISTINCT expr) is portable in the sense that expr can be multiple columns (like in Postgresql). The answer might lie in subselects though.

Ralph Schindler
Collaborator

For example, this seems more portable (with your use case tables):

SELECT COUNT(1) as "the_count" FROM (
    SELECT DISTINCT u.id, p.id
    FROM transaction_line tl
    INNER JOIN transactions t ON tl.transaction_id = t.id
    INNER JOIN users u ON t.user_id = u.id
    INNER JOIN products p ON tl.product_id = p.id
) as c
Ralph Schindler
Collaborator

Could you have a look at the solution in #4641 and let me know if it works for you?

fatmuemoo

Yes, #4641 works! Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
17 library/Zend/Paginator/Adapter/DbSelect.php
View
@@ -107,16 +107,27 @@ public function count()
$select->reset(Select::LIMIT);
$select->reset(Select::OFFSET);
$select->reset(Select::ORDER);
- $select->reset(Select::GROUP);
+ //get join info, clear, and use for DISTINCT count
+ $groups = $select->getRawState(Select::GROUP);
+ $select->reset(Select::GROUP);
+ $expr = '1';
+ if ($groups) {
+ $platform = $this->sql->getAdapter()->getPlatform();
+ array_walk($groups, function(&$group) use ($platform) {
+ $group = $platform->quoteIdentifierInFragment($group);
+ });
+ $expr = 'DISTINCT ' . implode(', ', $groups);
+ }
+
// get join information, clear, and repopulate without columns
$joins = $select->getRawState(Select::JOINS);
$select->reset(Select::JOINS);
foreach ($joins as $join) {
$select->join($join['name'], $join['on'], array(), $join['type']);
}
-
- $select->columns(array('c' => new Expression('COUNT(1)')));
+
+ $select->columns(array('c' => new Expression(sprintf('COUNT(%s)', $expr))));
$statement = $this->sql->prepareStatementForSqlObject($select);
$result = $statement->execute();
4 tests/ZendTest/Paginator/Adapter/DbSelectTest.php
View
@@ -64,7 +64,9 @@ public function testCount()
$this->mockResult->expects($this->any())->method('current')->will($this->returnValue(array('c' => 5)));
$this->mockSelect->expects($this->exactly(6))->method('reset'); // called for columns, limit, offset, order
- $this->mockSelect->expects($this->once())->method('getRawState')->with($this->equalTo(Select::JOINS))
+ $this->mockSelect->expects($this->at(4))->method('getRawState')->with($this->equalTo(Select::GROUP))
+ ->will($this->returnValue(NULL));
+ $this->mockSelect->expects($this->at(6))->method('getRawState')->with($this->equalTo(Select::JOINS))
->will($this->returnValue(array(array('name' => 'Foo', 'on' => 'On Stuff', 'columns' => array('foo', 'bar'), 'type' => Select::JOIN_INNER))));
$this->mockSelect->expects($this->once())->method('join')->with(
'Foo',
Something went wrong with that request. Please try again.