[Solar-svn] Revision 3134
pmjones at solarphp.com
pmjones at solarphp.com
Sun Apr 27 11:35:42 CDT 2008
Solar_Sql_Select: [CHG] Method countPages() now uses the previous, more-efficient strategy for counting records, but only if there is no COUNT() in the WHERE or HAVING clauses. This still allows for counts on more-complex queries, without lowering the efficiency of less-complex but more common queries.
Modified: trunk/Solar/Sql/Select.php
===================================================================
--- trunk/Solar/Sql/Select.php 2008-04-27 16:33:27 UTC (rev 3133)
+++ trunk/Solar/Sql/Select.php 2008-04-27 16:35:41 UTC (rev 3134)
@@ -1173,18 +1173,81 @@
*/
public function countPages($col = 'id')
{
- // 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');
+ // prepare a copy of this object as a COUNT query
+ $select = clone($this);
+ // no limit, and no need to order rows
+ $select->clear('limit');
+ $select->clear('order');
+
// clear all columns so there are no name conflicts
- foreach ($inner->_sources as $key => $val) {
- $inner->_sources[$key]['cols'] = array();
+ foreach ($select->_sources as $key => $val) {
+ $select->_sources[$key]['cols'] = array();
}
- // add the one column we're counting on
+ // look in the WHERE and HAVING clauses for a `COUNT` condition
+ $has_count_cond = $this->_hasCountCond($select->_parts['where']) ||
+ $this->_hasCountCond($select->_parts['having']);
+
+ // is there a count condition?
+ if ($has_count_cond) {
+
+ // count on a sub-select instead.
+ $count = $this->_countSubSelect($select, $col);
+
+ } else {
+
+ // "normal" case (no count condition in WHERE or HAVING).
+ // add the one column we're counting on...
+ $select->_addSource(
+ 'cols', // type
+ null, // name
+ null, // orig
+ null, // join
+ null, // cond
+ "COUNT($col)"
+ );
+
+ // ... and do the count.
+ $count = $select->fetchValue();
+ }
+
+ // calculate pages
+ $pages = 0;
+ if ($count > 0) {
+ $pages = ceil($count / $this->_paging);
+ }
+
+ // done!
+ return array(
+ 'count' => $count,
+ 'pages' => $pages,
+ );
+ }
+
+ protected function _hasCountCond($parts)
+ {
+ foreach ($parts as $key => $val) {
+ if (is_int($key)) {
+ // val is a literal condition
+ $cond = strtoupper($val);
+ } else {
+ // key is a condition with a placeholder,
+ // and val is the placeholder value.
+ $cond = strtoupper($key);
+ }
+ // does the condition have COUNT in it?
+ if (strpos($cond, 'COUNT') !== false) {
+ return true;
+ }
+ }
+ // no COUNT condition found
+ return false;
+ }
+
+ protected function _countSubSelect($inner, $col)
+ {
+ // add the one column we're counting on, to the inner subselect
$inner->_addSource(
'cols', // type
null, // name
@@ -1201,7 +1264,7 @@
$alias = substr($col, 0, $pos);
$col = substr($col, $pos + 1);
} else {
- // default alias 'subselect' in lieu of an explicit one
+ // default alias 'subselect' in lieu of an explicit alias
$alias = 'subselect';
}
@@ -1212,18 +1275,8 @@
$outer->clear();
$outer->fromSelect($inner, $alias, "COUNT($alias.$col)");
- // get the count and calculate pages
- $count = $outer->fetchValue();
- $pages = 0;
- if ($count > 0) {
- $pages = ceil($count / $this->_paging);
- }
-
- // done!
- return array(
- 'count' => $count,
- 'pages' => $pages,
- );
+ // get the count
+ return $outer->fetchValue();
}
/**
More information about the Solar-svn
mailing list