Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]

   1  <?php
   2  /*
   3  
   4  @version   v5.20.16  12-Jan-2020
   5  @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
   6  @copyright (c) 2014      Damien Regad, Mark Newnham and the ADOdb community
   7    Latest version is available at http://adodb.org/
   8  
   9    Released under both BSD license and Lesser GPL library license.
  10    Whenever there is any discrepancy between the two licenses,
  11    the BSD license will take precedence.
  12  
  13    Active Record implementation. Superset of Zend Framework's.
  14  
  15    Version 0.92
  16  
  17    See http://www-128.ibm.com/developerworks/java/library/j-cb03076/?ca=dgr-lnxw01ActiveRecord
  18    	 for info on Ruby on Rails Active Record implementation
  19  */
  20  
  21  
  22  global $_ADODB_ACTIVE_DBS;
  23  global $ADODB_ACTIVE_CACHESECS; // set to true to enable caching of metadata such as field info
  24  global $ACTIVE_RECORD_SAFETY; // set to false to disable safety checks
  25  global $ADODB_ACTIVE_DEFVALS; // use default values of table definition when creating new active record.
  26  
  27  // array of ADODB_Active_DB's, indexed by ADODB_Active_Record->_dbat
  28  $_ADODB_ACTIVE_DBS = array();
  29  $ACTIVE_RECORD_SAFETY = true;
  30  $ADODB_ACTIVE_DEFVALS = false;
  31  $ADODB_ACTIVE_CACHESECS = 0;
  32  
  33  class ADODB_Active_DB {
  34  	 var $db; // ADOConnection
  35  	 var $tables; // assoc array of ADODB_Active_Table objects, indexed by tablename
  36  }
  37  
  38  class ADODB_Active_Table {
  39  	 var $name; // table name
  40  	 var $flds; // assoc array of adofieldobjs, indexed by fieldname
  41  	 var $keys; // assoc array of primary keys, indexed by fieldname
  42  	 var $_created; // only used when stored as a cached file
  43  	 var $_belongsTo = array();
  44  	 var $_hasMany = array();
  45  }
  46  
  47  // $db = database connection
  48  // $index = name of index - can be associative, for an example see
  49  //    http://phplens.com/lens/lensforum/msgs.php?id=17790
  50  // returns index into $_ADODB_ACTIVE_DBS
  51  function ADODB_SetDatabaseAdapter(&$db, $index=false)
  52  {
  53  	 global $_ADODB_ACTIVE_DBS;
  54  
  55  	 	 foreach($_ADODB_ACTIVE_DBS as $k => $d) {
  56  	 	 	 if (PHP_VERSION >= 5) {
  57  	 	 	 	 if ($d->db === $db) {
  58  	 	 	 	 	 return $k;
  59  	 	 	 	 }
  60  	 	 	 } else {
  61  	 	 	 	 if ($d->db->_connectionID === $db->_connectionID && $db->database == $d->db->database) {
  62  	 	 	 	 	 return $k;
  63  	 	 	 	 }
  64  	 	 	 }
  65  	 	 }
  66  
  67  	 	 $obj = new ADODB_Active_DB();
  68  	 	 $obj->db = $db;
  69  	 	 $obj->tables = array();
  70  
  71  	 	 if ($index == false) {
  72  	 	 	 $index = sizeof($_ADODB_ACTIVE_DBS);
  73  	 	 }
  74  
  75  	 	 $_ADODB_ACTIVE_DBS[$index] = $obj;
  76  
  77  	 	 return sizeof($_ADODB_ACTIVE_DBS)-1;
  78  }
  79  
  80  
  81  class ADODB_Active_Record {
  82  	 static $_changeNames = true; // dynamically pluralize table names
  83  	 static $_quoteNames = false;
  84  
  85  	 static $_foreignSuffix = '_id'; //
  86  	 var $_dbat; // associative index pointing to ADODB_Active_DB eg. $ADODB_Active_DBS[_dbat]
  87  	 var $_table; // tablename, if set in class definition then use it as table name
  88  	 var $_tableat; // associative index pointing to ADODB_Active_Table, eg $ADODB_Active_DBS[_dbat]->tables[$this->_tableat]
  89  	 var $_where; // where clause set in Load()
  90  	 var $_saved = false; // indicates whether data is already inserted.
  91  	 var $_lasterr = false; // last error message
  92  	 var $_original = false; // the original values loaded or inserted, refreshed on update
  93  
  94  	 var $foreignName; // CFR: class name when in a relationship
  95  
  96  	 var $lockMode = ' for update '; // you might want to change to
  97  
  98  	static function UseDefaultValues($bool=null)
  99  	 {
 100  	 global $ADODB_ACTIVE_DEFVALS;
 101  	 	 if (isset($bool)) {
 102  	 	 	 $ADODB_ACTIVE_DEFVALS = $bool;
 103  	 	 }
 104  	 	 return $ADODB_ACTIVE_DEFVALS;
 105  	 }
 106  
 107  	 // should be static
 108  	static function SetDatabaseAdapter(&$db, $index=false)
 109  	 {
 110  	 	 return ADODB_SetDatabaseAdapter($db, $index);
 111  	 }
 112  
 113  
 114  	public function __set($name, $value)
 115  	 {
 116  	 	 $name = str_replace(' ', '_', $name);
 117  	 	 $this->$name = $value;
 118  	 }
 119  
 120  	 // php5 constructor
 121  	function __construct($table = false, $pkeyarr=false, $db=false)
 122  	 {
 123  	 global $_ADODB_ACTIVE_DBS;
 124  
 125  	 	 if ($db == false && is_object($pkeyarr)) {
 126  	 	 	 $db = $pkeyarr;
 127  	 	 	 $pkeyarr = false;
 128  	 	 }
 129  
 130  	 	 if (!$table) {
 131  	 	 	 if (!empty($this->_table)) {
 132  	 	 	 	 $table = $this->_table;
 133  	 	 	 }
 134  	 	 	 else $table = $this->_pluralize(get_class($this));
 135  	 	 }
 136  	 	 $this->foreignName = strtolower(get_class($this)); // CFR: default foreign name
 137  	 	 if ($db) {
 138  	 	 	 $this->_dbat = ADODB_Active_Record::SetDatabaseAdapter($db);
 139  	 	 } else if (!isset($this->_dbat)) {
 140  	 	 	 if (sizeof($_ADODB_ACTIVE_DBS) == 0) {
 141  	 	 	 	 $this->Error(
 142  	 	 	 	 	 "No database connection set; use ADOdb_Active_Record::SetDatabaseAdapter(\$db)",
 143  	 	 	 	 	 'ADODB_Active_Record::__constructor'
 144  	 	 	 	 );
 145  	 	 	 }
 146  	 	 	 end($_ADODB_ACTIVE_DBS);
 147  	 	 	 $this->_dbat = key($_ADODB_ACTIVE_DBS);
 148  	 	 }
 149  
 150  	 	 $this->_table = $table;
 151  	 	 $this->_tableat = $table; # reserved for setting the assoc value to a non-table name, eg. the sql string in future
 152  
 153  	 	 $this->UpdateActiveTable($pkeyarr);
 154  	 }
 155  
 156  	function __wakeup()
 157  	 {
 158    	 	 $class = get_class($this);
 159    	 	 new $class;
 160  	 }
 161  
 162  	function _pluralize($table)
 163  	 {
 164  	 	 if (!ADODB_Active_Record::$_changeNames) {
 165  	 	 	 return $table;
 166  	 	 }
 167  
 168  	 	 $ut = strtoupper($table);
 169  	 	 $len = strlen($table);
 170  	 	 $lastc = $ut[$len-1];
 171  	 	 $lastc2 = substr($ut,$len-2);
 172  	 	 switch ($lastc) {
 173  	 	 case 'S':
 174  	 	 	 return $table.'es';
 175  	 	 case 'Y':
 176  	 	 	 return substr($table,0,$len-1).'ies';
 177  	 	 case 'X':
 178  	 	 	 return $table.'es';
 179  	 	 case 'H':
 180  	 	 	 if ($lastc2 == 'CH' || $lastc2 == 'SH') {
 181  	 	 	 	 return $table.'es';
 182  	 	 	 }
 183  	 	 default:
 184  	 	 	 return $table.'s';
 185  	 	 }
 186  	 }
 187  
 188  	 // CFR Lamest singular inflector ever - @todo Make it real!
 189  	 // Note: There is an assumption here...and it is that the argument's length >= 4
 190  	function _singularize($tables)
 191  	 {
 192  
 193  	 	 if (!ADODB_Active_Record::$_changeNames) {
 194  	 	 	 return $table;
 195  	 	 }
 196  
 197  	 	 $ut = strtoupper($tables);
 198  	 	 $len = strlen($tables);
 199  	 	 if($ut[$len-1] != 'S') {
 200  	 	 	 return $tables; // I know...forget oxen
 201  	 	 }
 202  	 	 if($ut[$len-2] != 'E') {
 203  	 	 	 return substr($tables, 0, $len-1);
 204  	 	 }
 205  	 	 switch($ut[$len-3]) {
 206  	 	 	 case 'S':
 207  	 	 	 case 'X':
 208  	 	 	 	 return substr($tables, 0, $len-2);
 209  	 	 	 case 'I':
 210  	 	 	 	 return substr($tables, 0, $len-3) . 'y';
 211  	 	 	 case 'H';
 212  	 	 	 	 if($ut[$len-4] == 'C' || $ut[$len-4] == 'S') {
 213  	 	 	 	 	 return substr($tables, 0, $len-2);
 214  	 	 	 	 }
 215  	 	 	 default:
 216  	 	 	 	 return substr($tables, 0, $len-1); // ?
 217  	 	 }
 218  	 }
 219  
 220  	function hasMany($foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record')
 221  	 {
 222  	 	 $ar = new $foreignClass($foreignRef);
 223  	 	 $ar->foreignName = $foreignRef;
 224  	 	 $ar->UpdateActiveTable();
 225  	 	 $ar->foreignKey = ($foreignKey) ? $foreignKey : $foreignRef.ADODB_Active_Record::$_foreignSuffix;
 226  	 	 $table =& $this->TableInfo();
 227  	 	 $table->_hasMany[$foreignRef] = $ar;
 228  	 #	 $this->$foreignRef = $this->_hasMany[$foreignRef]; // WATCHME Removed assignment by ref. to please __get()
 229  	 }
 230  
 231  	 // use when you don't want ADOdb to auto-pluralize tablename
 232  	static function TableHasMany($table, $foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record')
 233  	 {
 234  	 	 $ar = new ADODB_Active_Record($table);
 235  	 	 $ar->hasMany($foreignRef, $foreignKey, $foreignClass);
 236  	 }
 237  
 238  	 // use when you don't want ADOdb to auto-pluralize tablename
 239  	static function TableKeyHasMany($table, $tablePKey, $foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record')
 240  	 {
 241  	 	 if (!is_array($tablePKey)) {
 242  	 	 	 $tablePKey = array($tablePKey);
 243  	 	 }
 244  	 	 $ar = new ADODB_Active_Record($table,$tablePKey);
 245  	 	 $ar->hasMany($foreignRef, $foreignKey, $foreignClass);
 246  	 }
 247  
 248  
 249  	 // use when you want ADOdb to auto-pluralize tablename for you. Note that the class must already be defined.
 250  	 // e.g. class Person will generate relationship for table Persons
 251  	static function ClassHasMany($parentclass, $foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record')
 252  	 {
 253  	 	 $ar = new $parentclass();
 254  	 	 $ar->hasMany($foreignRef, $foreignKey, $foreignClass);
 255  	 }
 256  
 257  
 258  	function belongsTo($foreignRef,$foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record')
 259  	 {
 260  	 	 global $inflector;
 261  
 262  	 	 $ar = new $parentClass($this->_pluralize($foreignRef));
 263  	 	 $ar->foreignName = $foreignRef;
 264  	 	 $ar->parentKey = $parentKey;
 265  	 	 $ar->UpdateActiveTable();
 266  	 	 $ar->foreignKey = ($foreignKey) ? $foreignKey : $foreignRef.ADODB_Active_Record::$_foreignSuffix;
 267  
 268  	 	 $table =& $this->TableInfo();
 269  	 	 $table->_belongsTo[$foreignRef] = $ar;
 270  	 #	 $this->$foreignRef = $this->_belongsTo[$foreignRef];
 271  	 }
 272  
 273  	static function ClassBelongsTo($class, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record')
 274  	 {
 275  	 	 $ar = new $class();
 276  	 	 $ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass);
 277  	 }
 278  
 279  	static function TableBelongsTo($table, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record')
 280  	 {
 281  	 	 $ar = new ADOdb_Active_Record($table);
 282  	 	 $ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass);
 283  	 }
 284  
 285  	static function TableKeyBelongsTo($table, $tablePKey, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record')
 286  	 {
 287  	 	 if (!is_array($tablePKey)) {
 288  	 	 	 $tablePKey = array($tablePKey);
 289  	 	 }
 290  	 	 $ar = new ADOdb_Active_Record($table, $tablePKey);
 291  	 	 $ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass);
 292  	 }
 293  
 294  
 295  	 /**
 296  	  * __get Access properties - used for lazy loading
 297  	  *
 298  	  * @param mixed $name
 299  	  * @access protected
 300  	  * @return mixed
 301  	  */
 302  	 function __get($name)
 303  	 {
 304  	 	 return $this->LoadRelations($name, '', -1, -1);
 305  	 }
 306  
 307  	 /**
 308  	  * @param string $name
 309  	  * @param string $whereOrderBy : eg. ' AND field1 = value ORDER BY field2'
 310  	  * @param offset
 311  	  * @param limit
 312  	  * @return mixed
 313  	  */
 314  	function LoadRelations($name, $whereOrderBy='', $offset=-1,$limit=-1)
 315  	 {
 316  	 	 $extras = array();
 317  	 	 $table = $this->TableInfo();
 318  	 	 if ($limit >= 0) {
 319  	 	 	 $extras['limit'] = $limit;
 320  	 	 }
 321  	 	 if ($offset >= 0) {
 322  	 	 	 $extras['offset'] = $offset;
 323  	 	 }
 324  
 325  	 	 if (strlen($whereOrderBy)) {
 326  	 	 	 if (!preg_match('/^[ \n\r]*AND/i', $whereOrderBy)) {
 327  	 	 	 	 if (!preg_match('/^[ \n\r]*ORDER[ \n\r]/i', $whereOrderBy)) {
 328  	 	 	 	 	 $whereOrderBy = 'AND ' . $whereOrderBy;
 329  	 	 	 	 }
 330  	 	 	 }
 331  	 	 }
 332  
 333  	 	 if(!empty($table->_belongsTo[$name])) {
 334  	 	 	 $obj = $table->_belongsTo[$name];
 335  	 	 	 $columnName = $obj->foreignKey;
 336  	 	 	 if(empty($this->$columnName)) {
 337  	 	 	 	 $this->$name = null;
 338  	 	 	 }
 339  	 	 	 else {
 340  	 	 	 	 if ($obj->parentKey) {
 341  	 	 	 	 	 $key = $obj->parentKey;
 342  	 	 	 	 }
 343  	 	 	 	 else {
 344  	 	 	 	 	 $key = reset($table->keys);
 345  	 	 	 	 }
 346  
 347  	 	 	 	 $arrayOfOne = $obj->Find($key.'='.$this->$columnName.' '.$whereOrderBy,false,false,$extras);
 348  	 	 	 	 if ($arrayOfOne) {
 349  	 	 	 	 	 $this->$name = $arrayOfOne[0];
 350  	 	 	 	 	 return $arrayOfOne[0];
 351  	 	 	 	 }
 352  	 	 	 }
 353  	 	 }
 354  	 	 if(!empty($table->_hasMany[$name])) {
 355  	 	 	 $obj = $table->_hasMany[$name];
 356  	 	 	 $key = reset($table->keys);
 357  	 	 	 $id = @$this->$key;
 358  	 	 	 if (!is_numeric($id)) {
 359  	 	 	 	 $db = $this->DB();
 360  	 	 	 	 $id = $db->qstr($id);
 361  	 	 	 }
 362  	 	 	 $objs = $obj->Find($obj->foreignKey.'='.$id. ' '.$whereOrderBy,false,false,$extras);
 363  	 	 	 if (!$objs) {
 364  	 	 	 	 $objs = array();
 365  	 	 	 }
 366  	 	 	 $this->$name = $objs;
 367  	 	 	 return $objs;
 368  	 	 }
 369  
 370  	 	 return array();
 371  	 }
 372  	 //////////////////////////////////
 373  
 374  	 // update metadata
 375  	function UpdateActiveTable($pkeys=false,$forceUpdate=false)
 376  	 {
 377  	 global $_ADODB_ACTIVE_DBS , $ADODB_CACHE_DIR, $ADODB_ACTIVE_CACHESECS;
 378  	 global $ADODB_ACTIVE_DEFVALS,$ADODB_FETCH_MODE;
 379  
 380  	 	 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];
 381  
 382  	 	 $table = $this->_table;
 383  	 	 $tables = $activedb->tables;
 384  	 	 $tableat = $this->_tableat;
 385  	 	 if (!$forceUpdate && !empty($tables[$tableat])) {
 386  
 387  	 	 	 $acttab = $tables[$tableat];
 388  	 	 	 foreach($acttab->flds as $name => $fld) {
 389  	 	 	 	 if ($ADODB_ACTIVE_DEFVALS && isset($fld->default_value)) {
 390  	 	 	 	 	 $this->$name = $fld->default_value;
 391  	 	 	 	 }
 392  	 	 	 	 else {
 393  	 	 	 	 	 $this->$name = null;
 394  	 	 	 	 }
 395  	 	 	 }
 396  	 	 	 return;
 397  	 	 }
 398  	 	 $db = $activedb->db;
 399  	 	 $fname = $ADODB_CACHE_DIR . '/adodb_' . $db->databaseType . '_active_'. $table . '.cache';
 400  	 	 if (!$forceUpdate && $ADODB_ACTIVE_CACHESECS && $ADODB_CACHE_DIR && file_exists($fname)) {
 401  	 	 	 $fp = fopen($fname,'r');
 402  	 	 	 @flock($fp, LOCK_SH);
 403  	 	 	 $acttab = unserialize(fread($fp,100000));
 404  	 	 	 fclose($fp);
 405  	 	 	 if ($acttab->_created + $ADODB_ACTIVE_CACHESECS - (abs(rand()) % 16) > time()) {
 406  	 	 	 	 // abs(rand()) randomizes deletion, reducing contention to delete/refresh file
 407  	 	 	 	 // ideally, you should cache at least 32 secs
 408  
 409  	 	 	 	 foreach($acttab->flds as $name => $fld) {
 410  	 	 	 	 	 if ($ADODB_ACTIVE_DEFVALS && isset($fld->default_value)) {
 411  	 	 	 	 	 	 $this->$name = $fld->default_value;
 412  	 	 	 	 	 }
 413  	 	 	 	 	 else {
 414  	 	 	 	 	 	 $this->$name = null;
 415  	 	 	 	 	 }
 416  	 	 	 	 }
 417  
 418  	 	 	 	 $activedb->tables[$table] = $acttab;
 419  
 420  	 	 	 	 //if ($db->debug) ADOConnection::outp("Reading cached active record file: $fname");
 421  	 	 	   	 return;
 422  	 	 	 } else if ($db->debug) {
 423  	 	 	 	 ADOConnection::outp("Refreshing cached active record file: $fname");
 424  	 	 	 }
 425  	 	 }
 426  	 	 $activetab = new ADODB_Active_Table();
 427  	 	 $activetab->name = $table;
 428  
 429  	 	 $save = $ADODB_FETCH_MODE;
 430  	 	 $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
 431  	 	 if ($db->fetchMode !== false) {
 432  	 	 	 $savem = $db->SetFetchMode(false);
 433  	 	 }
 434  
 435  	 	 $cols = $db->MetaColumns($table);
 436  
 437  	 	 if (isset($savem)) {
 438  	 	 	 $db->SetFetchMode($savem);
 439  	 	 }
 440  	 	 $ADODB_FETCH_MODE = $save;
 441  
 442  	 	 if (!$cols) {
 443  	 	 	 $this->Error("Invalid table name: $table",'UpdateActiveTable');
 444  	 	 	 return false;
 445  	 	 }
 446  	 	 $fld = reset($cols);
 447  	 	 if (!$pkeys) {
 448  	 	 	 if (isset($fld->primary_key)) {
 449  	 	 	 	 $pkeys = array();
 450  	 	 	 	 foreach($cols as $name => $fld) {
 451  	 	 	 	 	 if (!empty($fld->primary_key)) {
 452  	 	 	 	 	 	 $pkeys[] = $name;
 453  	 	 	 	 	 }
 454  	 	 	 	 }
 455  	 	 	 } else
 456  	 	 	 	 $pkeys = $this->GetPrimaryKeys($db, $table);
 457  	 	 }
 458  	 	 if (empty($pkeys)) {
 459  	 	 	 $this->Error("No primary key found for table $table",'UpdateActiveTable');
 460  	 	 	 return false;
 461  	 	 }
 462  
 463  	 	 $attr = array();
 464  	 	 $keys = array();
 465  
 466  	 	 switch (ADODB_ASSOC_CASE) {
 467  	 	 case ADODB_ASSOC_CASE_LOWER:
 468  	 	 	 foreach($cols as $name => $fldobj) {
 469  	 	 	 	 $name = strtolower($name);
 470  	 	 	 	 if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value)) {
 471  	 	 	 	 	 $this->$name = $fldobj->default_value;
 472  	 	 	 	 }
 473  	 	 	 	 else {
 474  	 	 	 	 	 $this->$name = null;
 475  	 	 	 	 }
 476  	 	 	 	 $attr[$name] = $fldobj;
 477  	 	 	 }
 478  	 	 	 foreach($pkeys as $k => $name) {
 479  	 	 	 	 $keys[strtolower($name)] = strtolower($name);
 480  	 	 	 }
 481  	 	 	 break;
 482  
 483  	 	 case ADODB_ASSOC_CASE_UPPER:
 484  	 	 	 foreach($cols as $name => $fldobj) {
 485  	 	 	 	 $name = strtoupper($name);
 486  
 487  	 	 	 	 if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value)) {
 488  	 	 	 	 	 $this->$name = $fldobj->default_value;
 489  	 	 	 	 }
 490  	 	 	 	 else {
 491  	 	 	 	 	 $this->$name = null;
 492  	 	 	 	 }
 493  	 	 	 	 $attr[$name] = $fldobj;
 494  	 	 	 }
 495  
 496  	 	 	 foreach($pkeys as $k => $name) {
 497  	 	 	 	 $keys[strtoupper($name)] = strtoupper($name);
 498  	 	 	 }
 499  	 	 	 break;
 500  	 	 default:
 501  	 	 	 foreach($cols as $name => $fldobj) {
 502  	 	 	 	 $name = ($fldobj->name);
 503  
 504  	 	 	 	 if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value)) {
 505  	 	 	 	 	 $this->$name = $fldobj->default_value;
 506  	 	 	 	 }
 507  	 	 	 	 else {
 508  	 	 	 	 	 $this->$name = null;
 509  	 	 	 	 }
 510  	 	 	 	 $attr[$name] = $fldobj;
 511  	 	 	 }
 512  	 	 	 foreach($pkeys as $k => $name) {
 513  	 	 	 	 $keys[$name] = $cols[$name]->name;
 514  	 	 	 }
 515  	 	 	 break;
 516  	 	 }
 517  
 518  	 	 $activetab->keys = $keys;
 519  	 	 $activetab->flds = $attr;
 520  
 521  	 	 if ($ADODB_ACTIVE_CACHESECS && $ADODB_CACHE_DIR) {
 522  	 	 	 $activetab->_created = time();
 523  	 	 	 $s = serialize($activetab);
 524  	 	 	 if (!function_exists('adodb_write_file')) {
 525  	 	 	 	 include (ADODB_DIR.'/adodb-csvlib.inc.php');
 526  	 	 	 }
 527  	 	 	 adodb_write_file($fname,$s);
 528  	 	 }
 529  	 	 if (isset($activedb->tables[$table])) {
 530  	 	 	 $oldtab = $activedb->tables[$table];
 531  
 532  	 	 	 if ($oldtab) {
 533  	 	 	 	 $activetab->_belongsTo = $oldtab->_belongsTo;
 534  	 	 	 	 $activetab->_hasMany = $oldtab->_hasMany;
 535  	 	 	 }
 536  	 	 }
 537  	 	 $activedb->tables[$table] = $activetab;
 538  	 }
 539  
 540  	function GetPrimaryKeys(&$db, $table)
 541  	 {
 542  	 	 return $db->MetaPrimaryKeys($table);
 543  	 }
 544  
 545  	 // error handler for both PHP4+5.
 546  	function Error($err,$fn)
 547  	 {
 548  	 global $_ADODB_ACTIVE_DBS;
 549  
 550  	 	 $fn = get_class($this).'::'.$fn;
 551  	 	 $this->_lasterr = $fn.': '.$err;
 552  
 553  	 	 if ($this->_dbat < 0) {
 554  	 	 	 $db = false;
 555  	 	 }
 556  	 	 else {
 557  	 	 	 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];
 558  	 	 	 $db = $activedb->db;
 559  	 	 }
 560  
 561  	 	 if (function_exists('adodb_throw')) {
 562  	 	 	 if (!$db) {
 563  	 	 	 	 adodb_throw('ADOdb_Active_Record', $fn, -1, $err, 0, 0, false);
 564  	 	 	 }
 565  	 	 	 else {
 566  	 	 	 	 adodb_throw($db->databaseType, $fn, -1, $err, 0, 0, $db);
 567  	 	 	 }
 568  	 	 } else {
 569  	 	 	 if (!$db || $db->debug) {
 570  	 	 	 	 ADOConnection::outp($this->_lasterr);
 571  	 	 	 }
 572  	 	 }
 573  
 574  	 }
 575  
 576  	 // return last error message
 577  	function ErrorMsg()
 578  	 {
 579  	 	 if (!function_exists('adodb_throw')) {
 580  	 	 	 if ($this->_dbat < 0) {
 581  	 	 	 	 $db = false;
 582  	 	 	 }
 583  	 	 	 else {
 584  	 	 	 	 $db = $this->DB();
 585  	 	 	 }
 586  
 587  	 	 	 // last error could be database error too
 588  	 	 	 if ($db && $db->ErrorMsg()) {
 589  	 	 	 	 return $db->ErrorMsg();
 590  	 	 	 }
 591  	 	 }
 592  	 	 return $this->_lasterr;
 593  	 }
 594  
 595  	function ErrorNo()
 596  	 {
 597  	 	 if ($this->_dbat < 0) {
 598  	 	 	 return -9999; // no database connection...
 599  	 	 }
 600  	 	 $db = $this->DB();
 601  
 602  	 	 return (int) $db->ErrorNo();
 603  	 }
 604  
 605  
 606  	 // retrieve ADOConnection from _ADODB_Active_DBs
 607  	 function DB()
 608  	 {
 609  	 global $_ADODB_ACTIVE_DBS;
 610  
 611  	 	 if ($this->_dbat < 0) {
 612  	 	 	 $false = false;
 613  	 	 	 $this->Error("No database connection set: use ADOdb_Active_Record::SetDatabaseAdaptor(\$db)", "DB");
 614  	 	 	 return $false;
 615  	 	 }
 616  	 	 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];
 617  	 	 $db = $activedb->db;
 618  	 	 return $db;
 619  	 }
 620  
 621  	 // retrieve ADODB_Active_Table
 622  	 function &TableInfo()
 623  	 {
 624  	 global $_ADODB_ACTIVE_DBS;
 625  	 	 $activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];
 626  	 	 $table = $activedb->tables[$this->_tableat];
 627  	 	 return $table;
 628  	 }
 629  
 630  
 631  	 // I have an ON INSERT trigger on a table that sets other columns in the table.
 632  	 // So, I find that for myTable, I want to reload an active record after saving it. -- Malcolm Cook
 633  	function Reload()
 634  	 {
 635  	 	 $db = $this->DB();
 636  	 	 if (!$db) {
 637  	 	 	 return false;
 638  	 	 }
 639  	 	 $table = $this->TableInfo();
 640  	 	 $where = $this->GenWhere($db, $table);
 641  	 	 return($this->Load($where));
 642  	 }
 643  
 644  
 645  	 // set a numeric array (using natural table field ordering) as object properties
 646  	function Set(&$row)
 647  	 {
 648  	 global $ACTIVE_RECORD_SAFETY;
 649  
 650  	 	 $db = $this->DB();
 651  
 652  	 	 if (!$row) {
 653  	 	 	 $this->_saved = false;
 654  	 	 	 return false;
 655  	 	 }
 656  
 657  	 	 $this->_saved = true;
 658  
 659  	 	 $table = $this->TableInfo();
 660  	 	 if ($ACTIVE_RECORD_SAFETY && sizeof($table->flds) != sizeof($row)) {
 661  	 	 	 # <AP>
 662  	 	 	 $bad_size = TRUE;
 663  	 	 	 if (sizeof($row) == 2 * sizeof($table->flds)) {
 664  	 	 	 	 // Only keep string keys
 665  	 	 	 	 $keys = array_filter(array_keys($row), 'is_string');
 666  	 	 	 	 if (sizeof($keys) == sizeof($table->flds)) {
 667  	 	 	 	 	 $bad_size = FALSE;
 668  	 	 	 	 }
 669  	 	 	 }
 670  	 	 	 if ($bad_size) {
 671  	 	 	 $this->Error("Table structure of $this->_table has changed","Load");
 672  	 	 	 return false;
 673  	 	 }
 674  	 	 	 # </AP>
 675  	 	 }
 676  	 	 else
 677  	 	 	 $keys = array_keys($row);
 678  
 679  	 	 # <AP>
 680  	 	 reset($keys);
 681  	 	 $this->_original = array();
 682  	 	 foreach($table->flds as $name=>$fld) {
 683  	 	 	 $value = $row[current($keys)];
 684  	 	 	 $this->$name = $value;
 685  	 	 	 $this->_original[] = $value;
 686  	 	 	 next($keys);
 687  	 	 }
 688  
 689  	 	 # </AP>
 690  	 	 return true;
 691  	 }
 692  
 693  	 // get last inserted id for INSERT
 694  	function LastInsertID(&$db,$fieldname)
 695  	 {
 696  	 	 if ($db->hasInsertID) {
 697  	 	 	 $val = $db->Insert_ID($this->_table,$fieldname);
 698  	 	 }
 699  	 	 else {
 700  	 	 	 $val = false;
 701  	 	 }
 702  
 703  	 	 if (is_null($val) || $val === false) {
 704  	 	 	 // this might not work reliably in multi-user environment
 705  	 	 	 return $db->GetOne("select max(".$fieldname.") from ".$this->_table);
 706  	 	 }
 707  	 	 return $val;
 708  	 }
 709  
 710  	 // quote data in where clause
 711  	function doquote(&$db, $val,$t)
 712  	 {
 713  	 	 switch($t) {
 714  	 	 case 'L':
 715  	 	 	 if (strpos($db->databaseType,'postgres') !== false) {
 716  	 	 	 	 return $db->qstr($val);
 717  	 	 	 }
 718  	 	 case 'D':
 719  	 	 case 'T':
 720  	 	 	 if (empty($val)) {
 721  	 	 	 	 return 'null';
 722  	 	 	 }
 723  	 	 case 'B':
 724  	 	 case 'N':
 725  	 	 case 'C':
 726  	 	 case 'X':
 727  	 	 	 if (is_null($val)) {
 728  	 	 	 	 return 'null';
 729  	 	 	 }
 730  
 731  	 	 	 if (strlen($val)>0 &&
 732  	 	 	 	 (strncmp($val,"'",1) != 0 || substr($val,strlen($val)-1,1) != "'")
 733  	 	 	 ) {
 734  	 	 	 	 return $db->qstr($val);
 735  	 	 	 	 break;
 736  	 	 	 }
 737  	 	 default:
 738  	 	 	 return $val;
 739  	 	 	 break;
 740  	 	 }
 741  	 }
 742  
 743  	 // generate where clause for an UPDATE/SELECT
 744  	function GenWhere(&$db, &$table)
 745  	 {
 746  	 	 $keys = $table->keys;
 747  	 	 $parr = array();
 748  
 749  	 	 foreach($keys as $k) {
 750  	 	 	 $f = $table->flds[$k];
 751  	 	 	 if ($f) {
 752  	 	 	 	 $parr[] = $k.' = '.$this->doquote($db,$this->$k,$db->MetaType($f->type));
 753  	 	 	 }
 754  	 	 }
 755  	 	 return implode(' and ', $parr);
 756  	 }
 757  
 758  
 759  	function _QName($n,$db=false)
 760  	 {
 761  	 	 if (!ADODB_Active_Record::$_quoteNames) {
 762  	 	 	 return $n;
 763  	 	 }
 764  	 	 if (!$db) {
 765  	 	 	 $db = $this->DB();
 766  	 	 	 if (!$db) {
 767  	 	 	 	 return false;
 768  	 	 	 }
 769  	 	 }
 770  	 	 return $db->nameQuote.$n.$db->nameQuote;
 771  	 }
 772  
 773  	 //------------------------------------------------------------ Public functions below
 774  
 775  	function Load($where=null,$bindarr=false, $lock = false)
 776  	 {
 777  	 global $ADODB_FETCH_MODE;
 778  
 779  	 	 $db = $this->DB();
 780  	 	 if (!$db) {
 781  	 	 	 return false;
 782  	 	 }
 783  	 	 $this->_where = $where;
 784  
 785  	 	 $save = $ADODB_FETCH_MODE;
 786  	 	 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 787  	 	 if ($db->fetchMode !== false) {
 788  	 	 	 $savem = $db->SetFetchMode(false);
 789  	 	 }
 790  
 791  	 	 $qry = "select * from ".$this->_table;
 792  
 793  	 	 if($where) {
 794  	 	 	 $qry .= ' WHERE '.$where;
 795  	 	 }
 796  	 	 if ($lock) {
 797  	 	 	 $qry .= $this->lockMode;
 798  	 	 }
 799  
 800  	 	 $row = $db->GetRow($qry,$bindarr);
 801  
 802  	 	 if (isset($savem)) {
 803  	 	 	 $db->SetFetchMode($savem);
 804  	 	 }
 805  	 	 $ADODB_FETCH_MODE = $save;
 806  
 807  	 	 return $this->Set($row);
 808  	 }
 809  
 810  	function LoadLocked($where=null, $bindarr=false)
 811  	 {
 812  	 	 $this->Load($where,$bindarr,true);
 813  	 }
 814  
 815  	 # useful for multiple record inserts
 816  	 # see http://phplens.com/lens/lensforum/msgs.php?id=17795
 817  	function Reset()
 818  	 {
 819  	 	 $this->_where=null;
 820  	 	 $this->_saved = false;
 821  	 	 $this->_lasterr = false;
 822  	 	 $this->_original = false;
 823  	 	 $vars=get_object_vars($this);
 824  	 	 foreach($vars as $k=>$v){
 825  	 	 	 if(substr($k,0,1)!=='_'){
 826  	 	 	 	 $this->{$k}=null;
 827  	 	 	 }
 828  	 	 }
 829  	 	 $this->foreignName=strtolower(get_class($this));
 830  	 	 return true;
 831  	 }
 832  
 833  	 // false on error
 834  	function Save()
 835  	 {
 836  	 	 if ($this->_saved) {
 837  	 	 	 $ok = $this->Update();
 838  	 	 }
 839  	 	 else {
 840  	 	 	 $ok = $this->Insert();
 841  	 	 }
 842  
 843  	 	 return $ok;
 844  	 }
 845  
 846  
 847  	 // false on error
 848  	function Insert()
 849  	 {
 850  	 	 $db = $this->DB();
 851  	 	 if (!$db) {
 852  	 	 	 return false;
 853  	 	 }
 854  	 	 $cnt = 0;
 855  	 	 $table = $this->TableInfo();
 856  
 857  	 	 $valarr = array();
 858  	 	 $names = array();
 859  	 	 $valstr = array();
 860  
 861  	 	 foreach($table->flds as $name=>$fld) {
 862  	 	 	 $val = $this->$name;
 863  	 	 	 if(!is_array($val) || !is_null($val) || !array_key_exists($name, $table->keys)) {
 864  	 	 	 	 $valarr[] = $val;
 865  	 	 	 	 $names[] = $this->_QName($name,$db);
 866  	 	 	 	 $valstr[] = $db->Param($cnt);
 867  	 	 	 	 $cnt += 1;
 868  	 	 	 }
 869  	 	 }
 870  
 871  	 	 if (empty($names)){
 872  	 	 	 foreach($table->flds as $name=>$fld) {
 873  	 	 	 	 $valarr[] = null;
 874  	 	 	 	 $names[] = $name;
 875  	 	 	 	 $valstr[] = $db->Param($cnt);
 876  	 	 	 	 $cnt += 1;
 877  	 	 	 }
 878  	 	 }
 879  	 	 $sql = 'INSERT INTO '.$this->_table."(".implode(',',$names).') VALUES ('.implode(',',$valstr).')';
 880  	 	 $ok = $db->Execute($sql,$valarr);
 881  
 882  	 	 if ($ok) {
 883  	 	 	 $this->_saved = true;
 884  	 	 	 $autoinc = false;
 885  	 	 	 foreach($table->keys as $k) {
 886  	 	 	 	 if (is_null($this->$k)) {
 887  	 	 	 	 	 $autoinc = true;
 888  	 	 	 	 	 break;
 889  	 	 	 	 }
 890  	 	 	 }
 891  	 	 	 if ($autoinc && sizeof($table->keys) == 1) {
 892  	 	 	 	 $k = reset($table->keys);
 893  	 	 	 	 $this->$k = $this->LastInsertID($db,$k);
 894  	 	 	 }
 895  	 	 }
 896  
 897  	 	 $this->_original = $valarr;
 898  	 	 return !empty($ok);
 899  	 }
 900  
 901  	function Delete()
 902  	 {
 903  	 	 $db = $this->DB();
 904  	 	 if (!$db) {
 905  	 	 	 return false;
 906  	 	 }
 907  	 	 $table = $this->TableInfo();
 908  
 909  	 	 $where = $this->GenWhere($db,$table);
 910  	 	 $sql = 'DELETE FROM '.$this->_table.' WHERE '.$where;
 911  	 	 $ok = $db->Execute($sql);
 912  
 913  	 	 return $ok ? true : false;
 914  	 }
 915  
 916  	 // returns an array of active record objects
 917  	function Find($whereOrderBy,$bindarr=false,$pkeysArr=false,$extra=array())
 918  	 {
 919  	 	 $db = $this->DB();
 920  	 	 if (!$db || empty($this->_table)) {
 921  	 	 	 return false;
 922  	 	 }
 923  	 	 $arr = $db->GetActiveRecordsClass(get_class($this),$this->_table, $whereOrderBy,$bindarr,$pkeysArr,$extra);
 924  	 	 return $arr;
 925  	 }
 926  
 927  	 // returns 0 on error, 1 on update, 2 on insert
 928  	function Replace()
 929  	 {
 930  	 	 $db = $this->DB();
 931  	 	 if (!$db) {
 932  	 	 	 return false;
 933  	 	 }
 934  	 	 $table = $this->TableInfo();
 935  
 936  	 	 $pkey = $table->keys;
 937  
 938  	 	 foreach($table->flds as $name=>$fld) {
 939  	 	 	 $val = $this->$name;
 940  	 	 	 /*
 941  	 	 	 if (is_null($val)) {
 942  	 	 	 	 if (isset($fld->not_null) && $fld->not_null) {
 943  	 	 	 	 	 if (isset($fld->default_value) && strlen($fld->default_value)) {
 944  	 	 	 	 	 	 continue;
 945  	 	 	 	 	 }
 946  	 	 	 	 	 else {
 947  	 	 	 	 	 	 $this->Error("Cannot update null into $name","Replace");
 948  	 	 	 	 	 	 return false;
 949  	 	 	 	 	 }
 950  	 	 	 	 }
 951  	 	 	 }*/
 952  	 	 	 if (is_null($val) && !empty($fld->auto_increment)) {
 953  	 	 	 	 continue;
 954  	 	 	 }
 955  
 956  	 	 	 if (is_array($val)) {
 957  	 	 	 	 continue;
 958  	 	 	 }
 959  
 960  	 	 	 $t = $db->MetaType($fld->type);
 961  	 	 	 $arr[$name] = $this->doquote($db,$val,$t);
 962  	 	 	 $valarr[] = $val;
 963  	 	 }
 964  
 965  	 	 if (!is_array($pkey)) {
 966  	 	 	 $pkey = array($pkey);
 967  	 	 }
 968  
 969  	 	 switch (ADODB_ASSOC_CASE) {
 970  	 	 	 case ADODB_ASSOC_CASE_LOWER:
 971  	 	 	 	 foreach ($pkey as $k => $v) {
 972  	 	 	 	 	 $pkey[$k] = strtolower($v);
 973  	 	 	 	 }
 974  	 	 	 	 break;
 975  	 	 	 case ADODB_ASSOC_CASE_UPPER:
 976  	 	 	 	 foreach ($pkey as $k => $v) {
 977  	 	 	 	 	 $pkey[$k] = strtoupper($v);
 978  	 	 	 	 }
 979  	 	 	 	 break;
 980  	 	 }
 981  
 982  	 	 $ok = $db->Replace($this->_table,$arr,$pkey);
 983  	 	 if ($ok) {
 984  	 	 	 $this->_saved = true; // 1= update 2=insert
 985  	 	 	 if ($ok == 2) {
 986  	 	 	 	 $autoinc = false;
 987  	 	 	 	 foreach($table->keys as $k) {
 988  	 	 	 	 	 if (is_null($this->$k)) {
 989  	 	 	 	 	 	 $autoinc = true;
 990  	 	 	 	 	 	 break;
 991  	 	 	 	 	 }
 992  	 	 	 	 }
 993  	 	 	 	 if ($autoinc && sizeof($table->keys) == 1) {
 994  	 	 	 	 	 $k = reset($table->keys);
 995  	 	 	 	 	 $this->$k = $this->LastInsertID($db,$k);
 996  	 	 	 	 }
 997  	 	 	 }
 998  
 999  	 	 	 $this->_original = $valarr;
1000  	 	 }
1001  	 	 return $ok;
1002  	 }
1003  
1004  	 // returns 0 on error, 1 on update, -1 if no change in data (no update)
1005  	function Update()
1006  	 {
1007  	 	 $db = $this->DB();
1008  	 	 if (!$db) {
1009  	 	 	 return false;
1010  	 	 }
1011  	 	 $table = $this->TableInfo();
1012  
1013  	 	 $where = $this->GenWhere($db, $table);
1014  
1015  	 	 if (!$where) {
1016  	 	 	 $this->error("Where missing for table $table", "Update");
1017  	 	 	 return false;
1018  	 	 }
1019  	 	 $valarr = array();
1020  	 	 $neworig = array();
1021  	 	 $pairs = array();
1022  	 	 $i = -1;
1023  	 	 $cnt = 0;
1024  	 	 foreach($table->flds as $name=>$fld) {
1025  	 	 	 $i += 1;
1026  	 	 	 $val = $this->$name;
1027  	 	 	 $neworig[] = $val;
1028  
1029  	 	 	 if (isset($table->keys[$name]) || is_array($val)) {
1030  	 	 	 	 continue;
1031  	 	 	 }
1032  
1033  	 	 	 if (is_null($val)) {
1034  	 	 	 	 if (isset($fld->not_null) && $fld->not_null) {
1035  	 	 	 	 	 if (isset($fld->default_value) && strlen($fld->default_value)) {
1036  	 	 	 	 	 	 continue;
1037  	 	 	 	 	 }
1038  	 	 	 	 	 else {
1039  	 	 	 	 	 	 $this->Error("Cannot set field $name to NULL","Update");
1040  	 	 	 	 	 	 return false;
1041  	 	 	 	 	 }
1042  	 	 	 	 }
1043  	 	 	 }
1044  
1045  	 	 	 if (isset($this->_original[$i]) && strcmp($val,$this->_original[$i]) == 0) {
1046  	 	 	 	 continue;
1047  	 	 	 }
1048  
1049  	 	 	 if (is_null($this->_original[$i]) && is_null($val)) {
1050  	 	 	 	 continue;
1051  	 	 	 }
1052  
1053  	 	 	 $valarr[] = $val;
1054  	 	 	 $pairs[] = $this->_QName($name,$db).'='.$db->Param($cnt);
1055  	 	 	 $cnt += 1;
1056  	 	 }
1057  
1058  
1059  	 	 if (!$cnt) {
1060  	 	 	 return -1;
1061  	 	 }
1062  
1063  	 	 $sql = 'UPDATE '.$this->_table." SET ".implode(",",$pairs)." WHERE ".$where;
1064  	 	 $ok = $db->Execute($sql,$valarr);
1065  	 	 if ($ok) {
1066  	 	 	 $this->_original = $neworig;
1067  	 	 	 return 1;
1068  	 	 }
1069  	 	 return 0;
1070  	 }
1071  
1072  	function GetAttributeNames()
1073  	 {
1074  	 	 $table = $this->TableInfo();
1075  	 	 if (!$table) {
1076  	 	 	 return false;
1077  	 	 }
1078  	 	 return array_keys($table->flds);
1079  	 }
1080  
1081  };
1082  
1083  function adodb_GetActiveRecordsClass(&$db, $class, $table,$whereOrderBy,$bindarr, $primkeyArr,
1084  	 	 	 $extra)
1085  {
1086  global $_ADODB_ACTIVE_DBS;
1087  
1088  
1089  	 $save = $db->SetFetchMode(ADODB_FETCH_NUM);
1090  	 $qry = "select * from ".$table;
1091  
1092  	 if (!empty($whereOrderBy)) {
1093  	 	 $qry .= ' WHERE '.$whereOrderBy;
1094  	 }
1095  	 if(isset($extra['limit'])) {
1096  	 	 $rows = false;
1097  	 	 if(isset($extra['offset'])) {
1098  	 	 	 $rs = $db->SelectLimit($qry, $extra['limit'], $extra['offset'],$bindarr);
1099  	 	 } else {
1100  	 	 	 $rs = $db->SelectLimit($qry, $extra['limit'],-1,$bindarr);
1101  	 	 }
1102  	 	 if ($rs) {
1103  	 	 	 while (!$rs->EOF) {
1104  	 	 	 	 $rows[] = $rs->fields;
1105  	 	 	 	 $rs->MoveNext();
1106  	 	 	 }
1107  	 	 }
1108  	 } else
1109  	 	 $rows = $db->GetAll($qry,$bindarr);
1110  
1111  	 $db->SetFetchMode($save);
1112  
1113  	 $false = false;
1114  
1115  	 if ($rows === false) {
1116  	 	 return $false;
1117  	 }
1118  
1119  
1120  	 if (!class_exists($class)) {
1121  	 	 $db->outp_throw("Unknown class $class in GetActiveRecordsClass()",'GetActiveRecordsClass');
1122  	 	 return $false;
1123  	 }
1124  	 $arr = array();
1125  	 // arrRef will be the structure that knows about our objects.
1126  	 // It is an associative array.
1127  	 // We will, however, return arr, preserving regular 0.. order so that
1128  	 // obj[0] can be used by app developpers.
1129  	 $arrRef = array();
1130  	 $bTos = array(); // Will store belongTo's indices if any
1131  	 foreach($rows as $row) {
1132  
1133  	 	 $obj = new $class($table,$primkeyArr,$db);
1134  	 	 if ($obj->ErrorNo()){
1135  	 	 	 $db->_errorMsg = $obj->ErrorMsg();
1136  	 	 	 return $false;
1137  	 	 }
1138  	 	 $obj->Set($row);
1139  	 	 $arr[] = $obj;
1140  	 } // foreach($rows as $row)
1141  
1142  	 return $arr;
1143  }