Changeset 429

Show
Ignore:
Timestamp:
11/07/07 12:07:24 (1 year ago)
Author:
kaste
Message:

sql constructors now handle limit and offset clause. Added addLimitAndOffset to AkDbAdapter?. Refactored findBySql and findWithAssociations so they wont delegate limit/offset to the DbAdapter?, but will delegate bindings.

fixed a bug in test/unit/lib/AkActiveRecord/AkDbAdapter.php introduced in [428].

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/kaste/framework/lib/Ak.php

    r419 r429  
    6767        if (empty($dsn) || !is_array($dsn)) $dsn = array(); 
    6868        return AkDbAdapter::getConnection($dsn); 
     69    } 
     70     
     71    /** 
     72     * @param string $message 
     73     * @param [OPTIONAL] $fatal triggers even in production-mode 
     74     */ 
     75    function DeprecateWarning($message,$fatal=false) 
     76    { 
     77        if (!$fatal && AK_ENVIRONMENT == 'production') return; 
     78        if (is_array($message)){ 
     79            //$args = func_get_args(); 
     80            //$message = array_shift($message); 
     81            trigger_error(Ak::t("DEPRECATED WARNING: ".array_shift($message),$message), E_USER_NOTICE);     
     82        } else 
     83            trigger_error(Ak::t("DEPRECATED WARNING: ".$message), E_USER_NOTICE);     
    6984    } 
    7085 
  • branches/kaste/framework/lib/AkActiveRecord.php

    r427 r429  
    987987     
    988988        if((!empty($options['include']) && $this->hasAssociations())){ 
    989             $result =& $this->findWithAssociations($options,  $limit, $offset); 
     989            $result =& $this->findWithAssociations($options); 
    990990        }else{ 
    991             $result =& $this->findBySql($sql, $limit, $offset); 
     991            $result =& $this->findBySql($sql); 
    992992        } 
    993993     
     
    11301130    function &findBySql($sql, $limit = null, $offset = null, $bindings = null) 
    11311131    { 
     1132        if ($limit || $offset){ 
     1133            Ak::DeprecateWarning("You're calling AR::findBySql with \$limit or \$offset parameters. This has been deprecated."); 
     1134            $this->_db->addLimitAndOffset($sql, array('limit'=>$limit,'offset'=>$offset)); 
     1135        } 
    11321136        if(!isset($this->_activeRecordHasBeenInstantiated)){ 
    11331137            return Ak::handleStaticCall(); 
    11341138        } 
    1135         if(is_array($sql)){ 
    1136             $sql_query = array_shift($sql); 
    1137             $bindings = is_array($sql) && count($sql) > 0 ? $sql : array($sql); 
    1138             $sql = $sql_query; 
    1139         } 
    1140         //$this->setConnection(); 
     1139 
     1140        $objects = array(); 
     1141        $results = $this->_db->sqlexecute ($sql,'selecting'); 
     1142        if (!$results) return $objects; 
    11411143         
    1142         AK_LOG_EVENTS ? $this->_startSqlBlockLog() : null; 
    1143                  
    1144         $objects = array(); 
    1145         if(is_integer($limit)){ 
    1146             if(is_integer($offset)){ 
    1147                 $results = !empty($bindings) ? $this->_db->SelectLimit($sql, $limit, $offset, $bindings) : $this->_db->SelectLimit($sql, $limit, $offset); 
    1148             }else { 
    1149                 $results = !empty($bindings) ? $this->_db->SelectLimit($sql, $limit, -1, $bindings) : $this->_db->SelectLimit($sql, $limit); 
    1150             } 
    1151         }else{ 
    1152             $results = !empty($bindings) ? $this->_db->Execute($sql, $bindings) : $this->_db->Execute($sql); 
    1153         } 
    1154          
    1155         AK_LOG_EVENTS ? $this->_endSqlBlockLog() : null; 
    1156  
    1157         if(!$results){ 
    1158             AK_DEBUG ? trigger_error($this->_db->ErrorMsg(), E_USER_NOTICE) : null; 
    1159         }else{ 
    1160             $objects = array(); 
    1161             while ($record = $results->FetchRow()) { 
    1162                 $objects[] =& $this->instantiate($this->getOnlyAvailableAtrributes($record), false); 
    1163             } 
    1164         } 
    1165  
     1144        while ($record = $results->FetchRow()) { 
     1145            $objects[] =& $this->instantiate($this->getOnlyAvailableAtrributes($record), false); 
     1146        } 
    11661147        return $objects; 
    11671148    } 
     
    13751356 
    13761357        $sql  .= !empty($options['order']) ? ' ORDER BY  '.$options['order'] : ''; 
     1358         
     1359        $this->_db->addLimitAndOffset($sql,$options); 
    13771360 
    13781361        return $sql; 
  • branches/kaste/framework/lib/AkActiveRecord/AkAssociatedActiveRecord.php

    r333 r429  
    229229    } 
    230230 
    231     function &findWithAssociations($options, $limit = null, $offset = null
     231    function &findWithAssociations($options
    232232    { 
    233233        $result = false; 
     
    273273 
    274274        $sql = trim($this->constructFinderSqlWithAssociations($options)); 
    275         $sql = substr($sql, -5) == 'AND =' ? substr($sql, 0,-5) : $sql; 
     275        //$sql = substr($sql, -5) == 'AND =' ? substr($sql, 0,-5) : $sql; // never called! 
    276276 
    277277        if(!empty($options['bind']) && is_array($options['bind']) && strstr($sql,'?')){ 
    278278            $sql = array_merge(array($sql),$options['bind']); 
    279279        } 
    280         $result =& $this->_findBySqlWithAssociations($sql, $limit, $offset, $options['include'], empty($options['virtual_limit']) ? false : $options['virtual_limit']); 
     280        $result =& $this->_findBySqlWithAssociations($sql, $options['include'], empty($options['virtual_limit']) ? false : $options['virtual_limit']); 
    281281 
    282282        return $result; 
     
    305305    function constructFinderSqlWithAssociations($options, $include_owner_as_selection = true) 
    306306    { 
     307        $sql = 'SELECT '; 
    307308        $selection = ''; 
    308309        if($include_owner_as_selection){ 
     
    310311                $selection .= '__owner.'.$column_name.' AS __owner_'.$column_name.', '; 
    311312            } 
    312  
    313             $sql  = 'SELECT '.trim($selection.@$options['selection'], ', ').' '. 
    314             'FROM '.$this->getTableName().' AS __owner '. 
    315             (!empty($options['joins']) ? $options['joins'].' ' : ''); 
    316         }else{ 
    317             $sql  = 'SELECT '.$options['selection'].'.* '. 
    318             'FROM '.$options['selection'].' '. 
    319             (!empty($options['joins']) ? $options['joins'].' ' : ''); 
    320         } 
     313            $selection .= @$options['selection'].' '; 
     314            $selection = trim($selection,', ').' '; // never used by the unit tests 
     315        }else{  
     316            // used only by HasOne::findAssociated 
     317            $selection .= $options['selection'].'.* '; 
     318        } 
     319        $sql .= $selection; 
     320        $sql .= 'FROM '.($include_owner_as_selection ? $this->getTableName().' AS __owner ' : $options['selection'].' '); 
     321        $sql .= (!empty($options['joins']) ? $options['joins'].' ' : ''); 
    321322 
    322323        empty($options['conditions']) ? null : $this->addConditions($sql, $options['conditions']); 
     
    327328        } 
    328329        $sql  .= !empty($options['order']) ? ' ORDER BY  '.$options['order'] : ''; 
     330         
     331        $this->_db->addLimitAndOffset($sql,$options); 
    329332        return $sql; 
    330333    } 
     
    334337     * @todo Refactor in order to increase performance of associated inclussions 
    335338     */ 
    336     function &_findBySqlWithAssociations($sql, $limit = null, $offset = null, $included_associations = array(), $virtual_limit = false) 
    337     { 
    338         if(is_array($sql)){ 
    339             $sql_query = array_shift($sql); 
    340             $bindings = is_array($sql) && count($sql) > 0 ? $sql : array($sql); 
    341             $sql = $sql_query; 
    342         } 
    343         $this->setConnection(); 
    344  
    345         AK_LOG_EVENTS ? $this->_startSqlBlockLog() : null; 
    346  
     339    function &_findBySqlWithAssociations($sql, $included_associations = array(), $virtual_limit = false) 
     340    { 
    347341        $objects = array(); 
     342        $results = $this->_db->sqlexecute ($sql,'find with associations'); 
     343        if (!$results) return $objects; 
     344 
     345        $i = 0; 
     346        $associated_ids = $this->getAssociatedIds(); 
     347        $number_of_associates = count($associated_ids); 
    348348        $_included_results = array(); // Used only in conjuntion with virtual limits for doing find('first',...include'=>... 
    349         if(is_integer($limit)){ 
    350             if(is_integer($offset)){ 
    351                 $results = !empty($bindings) ? 
    352                 $this->_db->SelectLimit($sql, $limit, $offset, $bindings) : 
    353                 $this->_db->SelectLimit($sql, $limit, $offset); 
    354             }else { 
    355                 $results = !empty($bindings) ? 
    356                 $this->_db->SelectLimit($sql, $limit, -1, $bindings) : 
    357                 $this->_db->SelectLimit($sql, $limit); 
    358             } 
    359         }else{ 
    360             $results = !empty($bindings) ? 
    361             $this->_db->Execute($sql, $bindings) : 
    362             $this->_db->Execute($sql); 
    363         } 
    364  
    365         AK_LOG_EVENTS ? $this->_endSqlBlockLog() : null; 
    366  
    367         if(!$results && AK_DEBUG){ 
    368             trigger_error($this->_db->ErrorMsg(), E_USER_NOTICE); 
    369         }else{ 
    370             $objects = array(); 
    371             $i = 0; 
    372             $associated_ids = $this->getAssociatedIds(); 
    373             $number_of_associates = count($associated_ids); 
    374             $object_associates_details = array(); 
    375  
    376             $ids = array(); 
    377             while ($record = $results->FetchRow()) { 
    378                 $this_item_attributes = array(); 
    379                 $associated_items = array(); 
    380                 foreach ($record as $column=>$value){ 
    381                     if(!is_numeric($column)){ 
    382                         if(substr($column,0,8) == '__owner_'){ 
    383                             $attribute_name = substr($column,8); 
    384                             $this_item_attributes[$attribute_name] = $value; 
    385                         }elseif(preg_match('/^_('.join('|',$associated_ids).')_(.+)/',$column, $match)){ 
    386                             $associated_items[$match[1]][$match[2]] = $value; 
    387                         } 
     349        $object_associates_details = array(); 
     350        $ids = array(); 
     351        while ($record = $results->FetchRow()) { 
     352            $this_item_attributes = array(); 
     353            $associated_items = array(); 
     354            foreach ($record as $column=>$value){ 
     355                if(!is_numeric($column)){ 
     356                    if(substr($column,0,8) == '__owner_'){ 
     357                        $attribute_name = substr($column,8); 
     358                        $this_item_attributes[$attribute_name] = $value; 
     359                    }elseif(preg_match('/^_('.join('|',$associated_ids).')_(.+)/',$column, $match)){ 
     360                        $associated_items[$match[1]][$match[2]] = $value; 
    388361                    } 
    389362                } 
    390  
    391  
    392                 // We need to keep a pointer to unique parent elements in order to add associates to the first loaded item 
    393                 $e = null; 
    394                 $object_id = $this_item_attributes[$this->getPrimaryKey()]; 
    395  
    396                 if(!empty($virtual_limit)){ 
    397                     $_included_results[$object_id] = $object_id; 
    398                     if(count($_included_results) > $virtual_limit * $number_of_associates){ 
    399                         continue; 
    400                     } 
    401                 } 
    402  
    403                 if(!isset($ids[$object_id])){ 
    404                     $ids[$object_id] = $i; 
    405                     $attributes_for_instantation = $this->getOnlyAvailableAtrributes($this_item_attributes); 
    406                     $attributes_for_instantation['load_associations'] = true; 
    407                     $objects[$i] =& $this->instantiate($attributes_for_instantation, false); 
    408                 }else{ 
    409                     $e = $i; 
    410                     $i = $ids[$object_id]; 
    411                 } 
    412  
    413                 foreach ($associated_items as $association_id=>$attributes){ 
    414                     if(count(array_diff($attributes, array(''))) > 0){ 
    415                         $object_associates_details[$i][$association_id][md5(serialize($attributes))] = $attributes; 
    416                     } 
    417                 } 
    418  
    419                 $i = !is_null($e) ? $e : $i+1; 
    420             } 
     363            } 
     364 
     365            // We need to keep a pointer to unique parent elements in order to add associates to the first loaded item 
     366            $e = null; 
     367            $object_id = $this_item_attributes[$this->getPrimaryKey()]; 
     368 
     369            if(!empty($virtual_limit)){ 
     370                $_included_results[$object_id] = $object_id; 
     371                if(count($_included_results) > $virtual_limit * $number_of_associates){ 
     372                    continue; 
     373                } 
     374            } 
     375 
     376            if(!isset($ids[$object_id])){ 
     377                $ids[$object_id] = $i; 
     378                $attributes_for_instantation = $this->getOnlyAvailableAtrributes($this_item_attributes); 
     379                $attributes_for_instantation['load_associations'] = true; 
     380                $objects[$i] =& $this->instantiate($attributes_for_instantation, false); 
     381            }else{ 
     382                $e = $i; 
     383                $i = $ids[$object_id]; 
     384            } 
     385 
     386            foreach ($associated_items as $association_id=>$attributes){ 
     387                if(count(array_diff($attributes, array(''))) > 0){ 
     388                    $object_associates_details[$i][$association_id][md5(serialize($attributes))] = $attributes; 
     389                } 
     390            } 
     391 
     392            $i = !is_null($e) ? $e : $i+1; 
    421393        } 
    422394 
     
    439411        } 
    440412 
    441         if(!empty($objects)){ 
    442             $result =& $objects; 
    443         }else{ 
    444             $result = false; 
    445         } 
    446  
     413        $result =& $objects; 
    447414        return $result; 
    448415    } 
  • branches/kaste/framework/lib/AkActiveRecord/AkDbAdapter.php

    r428 r429  
    183183    } 
    184184     
     185    function addLimitAndOffset(&$sql,$options) 
     186    { 
     187        if (isset($options['limit']) && $limit = $options['limit']){ 
     188            $sql .= " LIMIT $limit"; 
     189            if (isset($options['offset']) && $offset = $options['offset']){ 
     190                $sql .= " OFFSET $offset"; 
     191            } 
     192        } 
     193        return $sql; 
     194    } 
     195     
    185196    /* DATABASE STATEMENTS - CRUD */ 
    186197     
  • branches/kaste/framework/lib/AkActiveRecord/AkDbAdapter_mysql.php

    r416 r429  
    4343        return 'mysql'; 
    4444    } 
     45 
     46    function addLimitAndOffset(&$sql,$options) 
     47    { 
     48        if (isset($options['limit']) && $limit = $options['limit']){ 
     49            if (isset($options['offset']) && $offset = $options['offset']) 
     50                $sql .= " LIMIT $offset, $limit"; 
     51            else 
     52                $sql .= " LIMIT $limit"; 
     53        } 
     54        return $sql; 
     55    } 
     56     
    4557} 
    4658?> 
  • branches/kaste/framework/lib/AkActiveRecord/AkHasOne.php

    r407 r429  
    243243    function &findAssociated($association_id) 
    244244    { 
    245         $result = false; 
    246         if(!$this->Owner->getId()){ 
    247             return $result; 
    248         } 
     245        if(!$this->Owner->getId()) return false; 
    249246 
    250247        if(empty($this->Owner->$association_id->__activeRecordObject)){ 
     
    260257        'order' => trim($this->Owner->$association_id->_addTableAliasesToAssociatedSql($table_name, $this->Owner->$association_id->getAssociationOption('order'))) 
    261258        ); 
    262          
    263         if($results =& $this->Owner->$association_id->findBySql($this->Owner->constructFinderSqlWithAssociations($finder_options, false),1)){ 
     259 
     260        // TODO: we will use a select statement later 
     261        $sql = $this->Owner->constructFinderSqlWithAssociations($finder_options, false);//.' LIMIT 1'; 
     262        if($results =& $this->Owner->$association_id->findBySql($sql)){ 
    264263            $result =& $results[0]; 
    265264        } 
  • branches/kaste/framework/test/unit/lib/AkActiveRecord/AkDbAdapter.php

    r428 r429  
    2525    function test_execute_should_handle_bindings() 
    2626    { 
    27         $db =& AkDbAdapter::getConnection(null,false); 
     27        $db =& new AkDbAdapter(array()); 
    2828        Mock::generate('ADOConnection'); 
    2929        $connection =& new MockADOConnection(); 
     
    3535        $db->sqlexecute(array('SELECT * FROM articles WHERE id=?',1)); 
    3636    } 
     37     
     38    function test_should_add_limit_and_offset_mysql_style() 
     39    { 
     40        $mysql_db =& AkDbAdapter::getConnection(array('type'=>'mysql'),false); 
     41        $sql = 'SELECT * FROM articles'; 
     42        $mysql_db->addLimitAndOffset($sql,array('limit'=>2,'offset'=>10)); 
     43        $this->assertEqual('SELECT * FROM articles LIMIT 10, 2',$sql); 
     44         
     45        $sql = 'SELECT * FROM articles'; 
     46        $mysql_db->addLimitAndOffset($sql,array('offset'=>10)); 
     47        $this->assertEqual('SELECT * FROM articles',$sql); 
     48 
     49        $sql = 'SELECT * FROM articles'; 
     50        $mysql_db->addLimitAndOffset($sql,array('limit'=>10)); 
     51        $this->assertEqual('SELECT * FROM articles LIMIT 10',$sql); 
     52    } 
     53 
     54    function test_should_add_limit_and_offset_common_style() 
     55    { 
     56        $mysql_db =& AkDbAdapter::getConnection(array('type'=>'postgre'),false); 
     57        $sql = 'SELECT * FROM articles'; 
     58        $mysql_db->addLimitAndOffset($sql,array('limit'=>2,'offset'=>10)); 
     59        $this->assertEqual('SELECT * FROM articles LIMIT 2 OFFSET 10',$sql); 
     60         
     61        $sql = 'SELECT * FROM articles'; 
     62        $mysql_db->addLimitAndOffset($sql,array('offset'=>10)); 
     63        $this->assertEqual('SELECT * FROM articles',$sql); 
     64 
     65        $sql = 'SELECT * FROM articles'; 
     66        $mysql_db->addLimitAndOffset($sql,array('limit'=>10)); 
     67        $this->assertEqual('SELECT * FROM articles LIMIT 10',$sql); 
     68    } 
    3769} 
    3870 
  • branches/kaste/framework/test/unit/lib/AkActiveRecord/_AkActiveRecord_2.php

    r407 r429  
    449449        $FoundUsers = $Users->findBySql("SELECT * FROM ak_test_users",6); 
    450450        $this->assertEqual(count($FoundUsers), 6); 
     451        $this->assertErrorPattern("/DEPRECATED WARNING.*findBySql.*/"); 
    451452         
    452453        $FoundUsers = $Users->findBySql("SELECT * FROM ak_test_users",6,6); 
    453454        $this->assertEqual(count($FoundUsers), 3); 
    454  
     455        $this->assertErrorPattern("/DEPRECATED WARNING.*findBySql.*/"); 
     456 
     457        $FoundUsers = $Users->findBySql("SELECT * FROM ak_test_users WHERE iad=123"); 
     458        $this->assertEqual(count($FoundUsers), 0); 
     459        $this->assertError(); 
     460         
    455461    } 
    456462