[Solar-svn] Revision 3108
pmjones at solarphp.com
pmjones at solarphp.com
Sun Apr 13 08:44:30 CDT 2008
Solar_Sql_Select
----------------
* [BRK] Method distinct() now **does not** change the value of DISTINCT when
the flag is null.
* [CHG] Method countPages() now has very different implementation. To support
all manner of weirdness in the original query, such as COUNT() with GROUP BY
and HAVING COUNT() (as with tagging), we now wrap the original query as an
inner/subselect within an outer query. The outer query counts the rows on
the inner query. I suspect this is inefficient in a lot of cases, so the
plan is to build in some more logic to see if the outer wrapping select is
really needed.
Modified: trunk/Solar/Sql/Select.php
===================================================================
--- trunk/Solar/Sql/Select.php 2008-04-13 13:06:52 UTC (rev 3107)
+++ trunk/Solar/Sql/Select.php 2008-04-13 13:44:24 UTC (rev 3108)
@@ -113,7 +113,7 @@
*
*/
protected $_parts = array(
- 'distinct' => false,
+ 'distinct' => null,
'cols' => array(),
'from' => array(),
'join' => array(),
@@ -225,14 +225,16 @@
* Makes the query SELECT DISTINCT.
*
* @param bool $flag Whether or not the SELECT is DISTINCT (default
- * true).
+ * true). If null, the current distinct setting is not changed.
*
* @return Solar_Sql_Select
*
*/
public function distinct($flag = true)
{
- $this->_parts['distinct'] = (bool) $flag;
+ if ($flag !== null) {
+ $this->_parts['distinct'] = (bool) $flag;
+ }
return $this;
}
@@ -1171,28 +1173,47 @@
*/
public function countPages($col = 'id')
{
- $select = clone($this);
- $select->clear('limit');
- $select->clear('order');
+ // prepare the current query to become a subselect of all matching
+ // rows; this means no limit, and no need to order them.
+ $inner = clone($this);
+ $inner->clear('limit');
+ $inner->clear('order');
// clear all columns so there are no name conflicts
- // @todo Replace with $select->clear('cols') ?
- foreach ($select->_sources as $key => $val) {
- $select->_sources[$key]['cols'] = array();
+ foreach ($inner->_sources as $key => $val) {
+ $inner->_sources[$key]['cols'] = array();
}
- // add a single COUNT() column
- $select->_addSource(
+ // add the one column we're counting on
+ $inner->_addSource(
'cols', // type
null, // name
null, // orig
null, // join
null, // cond
- "COUNT($col)"
+ $col
);
+ // does the counting column have a dot in it?
+ $pos = strpos($col, '.');
+ if ($pos) {
+ // alias the subselect to the same table name as the column
+ $alias = substr($col, 0, $pos);
+ $col = substr($col, $pos + 1);
+ } else {
+ // default alias 'subselect' in lieu of an explicit one
+ $alias = 'subselect';
+ }
+
+ // build the outer select, which will do the actual count.
+ // wrapping with an outer select lets us have all manner of weirdness
+ // in the inner query, so that it doesn't conflict with the count.
+ $outer = clone($this);
+ $outer->clear();
+ $outer->fromSelect($inner, $alias, "COUNT($alias.$col)");
+
// get the count and calculate pages
- $count = $select->fetchValue();
+ $count = $outer->fetchValue();
$pages = 0;
if ($count > 0) {
$pages = ceil($count / $this->_paging);
More information about the Solar-svn
mailing list