Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Zend paginator dbselect count #4590

Closed
wants to merge 2 commits into from

2 participants

@fatmuemoo

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

@ralphschindler
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.

@ralphschindler
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.

@ralphschindler
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
@ralphschindler
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.
View
17 library/Zend/Paginator/Adapter/DbSelect.php
@@ -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();
View
4 tests/ZendTest/Paginator/Adapter/DbSelectTest.php
@@ -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.