Changeset 3134

Show
Ignore:
Timestamp:
04/27/08 11:35:41 (2 months ago)
Author:
pmjones
Message:

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.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/Solar/Sql/Select.php

    r3108 r3134  
    11741174    public function countPages($col = 'id') 
    11751175    { 
    1176         // prepare the current query to become a subselect of all matching 
    1177         // rows; this means no limit, and no need to order them. 
    1178         $inner = clone($this); 
    1179         $inner->clear('limit'); 
    1180         $inner->clear('order'); 
     1176        // prepare a copy of this object as a COUNT query 
     1177        $select = clone($this); 
     1178         
     1179        // no limit, and no need to order rows 
     1180        $select->clear('limit'); 
     1181        $select->clear('order'); 
    11811182         
    11821183        // clear all columns so there are no name conflicts 
    1183         foreach ($inner->_sources as $key => $val) { 
    1184             $inner->_sources[$key]['cols'] = array(); 
    1185         } 
    1186          
    1187         // add the one column we're counting on 
     1184        foreach ($select->_sources as $key => $val) { 
     1185            $select->_sources[$key]['cols'] = array(); 
     1186        } 
     1187         
     1188        // look in the WHERE and HAVING clauses for a `COUNT` condition 
     1189        $has_count_cond = $this->_hasCountCond($select->_parts['where']) || 
     1190                          $this->_hasCountCond($select->_parts['having']); 
     1191         
     1192        // is there a count condition? 
     1193        if ($has_count_cond) { 
     1194             
     1195            // count on a sub-select instead. 
     1196            $count = $this->_countSubSelect($select, $col); 
     1197             
     1198        } else { 
     1199             
     1200            // "normal" case (no count condition in WHERE or HAVING). 
     1201            // add the one column we're counting on... 
     1202            $select->_addSource( 
     1203                'cols',         // type 
     1204                null,           // name 
     1205                null,           // orig 
     1206                null,           // join 
     1207                null,           // cond 
     1208                "COUNT($col)" 
     1209            ); 
     1210             
     1211            // ... and do the count. 
     1212            $count = $select->fetchValue(); 
     1213        } 
     1214         
     1215        // calculate pages 
     1216        $pages = 0; 
     1217        if ($count > 0) { 
     1218            $pages = ceil($count / $this->_paging); 
     1219        } 
     1220         
     1221        // done! 
     1222        return array( 
     1223            'count' => $count, 
     1224            'pages' => $pages, 
     1225        ); 
     1226    } 
     1227     
     1228    protected function _hasCountCond($parts) 
     1229    { 
     1230        foreach ($parts as $key => $val) { 
     1231            if (is_int($key)) { 
     1232                // val is a literal condition 
     1233                $cond = strtoupper($val); 
     1234            } else { 
     1235                // key is a condition with a placeholder, 
     1236                // and val is the placeholder value. 
     1237                $cond = strtoupper($key); 
     1238            } 
     1239            // does the condition have COUNT in it? 
     1240            if (strpos($cond, 'COUNT') !== false) { 
     1241                return true; 
     1242            } 
     1243        } 
     1244        // no COUNT condition found 
     1245        return false; 
     1246    } 
     1247     
     1248    protected function _countSubSelect($inner, $col) 
     1249    { 
     1250        // add the one column we're counting on, to the inner subselect 
    11881251        $inner->_addSource( 
    11891252            'cols',         // type 
     
    12021265            $col   = substr($col, $pos + 1); 
    12031266        } else { 
    1204             // default alias 'subselect' in lieu of an explicit one 
     1267            // default alias 'subselect' in lieu of an explicit alias 
    12051268            $alias = 'subselect'; 
    12061269        } 
     
    12131276        $outer->fromSelect($inner, $alias, "COUNT($alias.$col)"); 
    12141277         
    1215         // get the count and calculate pages 
    1216         $count = $outer->fetchValue(); 
    1217         $pages = 0; 
    1218         if ($count > 0) { 
    1219             $pages = ceil($count / $this->_paging); 
    1220         } 
    1221          
    1222         // done! 
    1223         return array( 
    1224             'count' => $count, 
    1225             'pages' => $pages, 
    1226         ); 
     1278        // get the count 
     1279        return $outer->fetchValue(); 
    12271280    } 
    12281281