Changeset 3108

Show
Ignore:
Timestamp:
04/13/08 08:44:24 (3 months ago)
Author:
pmjones
Message:

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.

Files:

Legend:

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

    r3058 r3108  
    114114     */ 
    115115    protected $_parts = array( 
    116         'distinct' => false
     116        'distinct' => null
    117117        'cols'     => array(), 
    118118        'from'     => array(), 
     
    226226     *  
    227227     * @param bool $flag Whether or not the SELECT is DISTINCT (default 
    228      * true). 
     228     * true).  If null, the current distinct setting is not changed. 
    229229     *  
    230230     * @return Solar_Sql_Select 
     
    233233    public function distinct($flag = true) 
    234234    { 
    235         $this->_parts['distinct'] = (bool) $flag; 
     235        if ($flag !== null) { 
     236            $this->_parts['distinct'] = (bool) $flag; 
     237        } 
    236238        return $this; 
    237239    } 
     
    11721174    public function countPages($col = 'id') 
    11731175    { 
    1174         $select = clone($this); 
    1175         $select->clear('limit'); 
    1176         $select->clear('order'); 
     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'); 
    11771181         
    11781182        // clear all columns so there are no name conflicts 
    1179         // @todo Replace with $select->clear('cols') ? 
    1180         foreach ($select->_sources as $key => $val) { 
    1181             $select->_sources[$key]['cols'] = array(); 
    1182         } 
    1183          
    1184         // add a single COUNT() column 
    1185         $select->_addSource( 
     1183        foreach ($inner->_sources as $key => $val) { 
     1184            $inner->_sources[$key]['cols'] = array(); 
     1185        } 
     1186         
     1187        // add the one column we're counting on 
     1188        $inner->_addSource( 
    11861189            'cols',         // type 
    11871190            null,           // name 
     
    11891192            null,           // join 
    11901193            null,           // cond 
    1191             "COUNT($col)" 
     1194            $col 
    11921195        ); 
    11931196         
     1197        // does the counting column have a dot in it? 
     1198        $pos = strpos($col, '.'); 
     1199        if ($pos) { 
     1200            // alias the subselect to the same table name as the column 
     1201            $alias = substr($col, 0, $pos); 
     1202            $col   = substr($col, $pos + 1); 
     1203        } else { 
     1204            // default alias 'subselect' in lieu of an explicit one 
     1205            $alias = 'subselect'; 
     1206        } 
     1207         
     1208        // build the outer select, which will do the actual count. 
     1209        // wrapping with an outer select lets us have all manner of weirdness 
     1210        // in the inner query, so that it doesn't conflict with the count. 
     1211        $outer = clone($this); 
     1212        $outer->clear(); 
     1213        $outer->fromSelect($inner, $alias, "COUNT($alias.$col)"); 
     1214         
    11941215        // get the count and calculate pages 
    1195         $count = $select->fetchValue(); 
     1216        $count = $outer->fetchValue(); 
    11961217        $pages = 0; 
    11971218        if ($count > 0) {