/src/typo3_src-4.2.0alpha1/typo3/sysext/adodb/adodb/adodb.inc.php

00001 <?php 
00002 /*
00003  * Set tabs to 4 for best viewing.
00004  * 
00005  * Latest version is available at http://adodb.sourceforge.net
00006  * 
00007  * This is the main include file for ADOdb.
00008  * Database specific drivers are stored in the adodb/drivers/adodb-*.inc.php
00009  *
00010  * The ADOdb files are formatted so that doxygen can be used to generate documentation.
00011  * Doxygen is a documentation generation tool and can be downloaded from http://doxygen.org/
00012  */
00013 
00035  if (!defined('_ADODB_LAYER')) {
00036         define('_ADODB_LAYER',1);
00037         
00038         //==============================================================================================        
00039         // CONSTANT DEFINITIONS
00040         //==============================================================================================        
00041 
00042 
00047         if (!defined('ADODB_DIR')) define('ADODB_DIR',dirname(__FILE__));
00048         
00049         //==============================================================================================        
00050         // GLOBAL VARIABLES
00051         //==============================================================================================        
00052 
00053         GLOBAL 
00054                 $ADODB_vers,            // database version
00055                 $ADODB_COUNTRECS,       // count number of records returned - slows down query
00056                 $ADODB_CACHE_DIR,       // directory to cache recordsets
00057                 $ADODB_EXTENSION,   // ADODB extension installed
00058                 $ADODB_COMPAT_FETCH, // If $ADODB_COUNTRECS and this is true, $rs->fields is available on EOF
00059                 $ADODB_FETCH_MODE,      // DEFAULT, NUM, ASSOC or BOTH. Default follows native driver default...
00060                 $ADODB_QUOTE_FIELDNAMES; // Allows you to force quotes (backticks) around field names in queries generated by getinsertsql and getupdatesql.    
00061         
00062         //==============================================================================================        
00063         // GLOBAL SETUP
00064         //==============================================================================================        
00065         
00066         $ADODB_EXTENSION = defined('ADODB_EXTENSION');
00067         
00068         //********************************************************//
00069         /*
00070         Controls $ADODB_FORCE_TYPE mode. Default is ADODB_FORCE_VALUE (3).
00071         Used in GetUpdateSql and GetInsertSql functions. Thx to Niko, nuko#mbnet.fi
00072 
00073                 0 = ignore empty fields. All empty fields in array are ignored.
00074                 1 = force null. All empty, php null and string 'null' fields are changed to sql NULL values.
00075                 2 = force empty. All empty, php null and string 'null' fields are changed to sql empty '' or 0 values.
00076                 3 = force value. Value is left as it is. Php null and string 'null' are set to sql NULL values and empty fields '' are set to empty '' sql values.
00077         */
00078         define('ADODB_FORCE_IGNORE',0);
00079         define('ADODB_FORCE_NULL',1);
00080         define('ADODB_FORCE_EMPTY',2);
00081         define('ADODB_FORCE_VALUE',3);
00082     //********************************************************//
00083 
00084 
00085         if (!$ADODB_EXTENSION || ADODB_EXTENSION < 4.0) {
00086                 
00087                 define('ADODB_BAD_RS','<p>Bad $rs in %s. Connection or SQL invalid. Try using $connection->debug=true;</p>');
00088         
00089         // allow [ ] @ ` " and . in table names
00090                 define('ADODB_TABLE_REGEX','([]0-9a-z_\:\"\`\.\@\[-]*)');
00091         
00092         // prefetching used by oracle
00093                 if (!defined('ADODB_PREFETCH_ROWS')) define('ADODB_PREFETCH_ROWS',10);
00094         
00095         
00096         /*
00097         Controls ADODB_FETCH_ASSOC field-name case. Default is 2, use native case-names.
00098         This currently works only with mssql, odbc, oci8po and ibase derived drivers.
00099         
00100                 0 = assoc lowercase field names. $rs->fields['orderid']
00101                 1 = assoc uppercase field names. $rs->fields['ORDERID']
00102                 2 = use native-case field names. $rs->fields['OrderID']
00103         */
00104         
00105                 define('ADODB_FETCH_DEFAULT',0);
00106                 define('ADODB_FETCH_NUM',1);
00107                 define('ADODB_FETCH_ASSOC',2);
00108                 define('ADODB_FETCH_BOTH',3);
00109                 
00110                 if (!defined('TIMESTAMP_FIRST_YEAR')) define('TIMESTAMP_FIRST_YEAR',100);
00111         
00112                 // PHP's version scheme makes converting to numbers difficult - workaround
00113                 $_adodb_ver = (float) PHP_VERSION;
00114                 if ($_adodb_ver >= 5.2) {
00115                         define('ADODB_PHPVER',0x5200);
00116                 } else if ($_adodb_ver >= 5.0) {
00117                         define('ADODB_PHPVER',0x5000);
00118                 } else if ($_adodb_ver > 4.299999) { # 4.3
00119                         define('ADODB_PHPVER',0x4300);
00120                 } else if ($_adodb_ver > 4.199999) { # 4.2
00121                         define('ADODB_PHPVER',0x4200);
00122                 } else if (strnatcmp(PHP_VERSION,'4.0.5')>=0) {
00123                         define('ADODB_PHPVER',0x4050);
00124                 } else {
00125                         define('ADODB_PHPVER',0x4000);
00126                 }
00127         }
00128         
00129         //if (!defined('ADODB_ASSOC_CASE')) define('ADODB_ASSOC_CASE',2);
00130 
00131         
00135         function ADODB_str_replace($src, $dest, $data)
00136         {
00137                 if (ADODB_PHPVER >= 0x4050) return str_replace($src,$dest,$data);
00138                 
00139                 $s = reset($src);
00140                 $d = reset($dest);
00141                 while ($s !== false) {
00142                         $data = str_replace($s,$d,$data);
00143                         $s = next($src);
00144                         $d = next($dest);
00145                 }
00146                 return $data;
00147         }
00148         
00149         function ADODB_Setup()
00150         {
00151         GLOBAL 
00152                 $ADODB_vers,            // database version
00153                 $ADODB_COUNTRECS,       // count number of records returned - slows down query
00154                 $ADODB_CACHE_DIR,       // directory to cache recordsets
00155                 $ADODB_FETCH_MODE,
00156                 $ADODB_FORCE_TYPE,
00157                 $ADODB_QUOTE_FIELDNAMES;
00158                 
00159                 $ADODB_FETCH_MODE = ADODB_FETCH_DEFAULT;
00160                 $ADODB_FORCE_TYPE = ADODB_FORCE_VALUE;
00161 
00162 
00163                 if (!isset($ADODB_CACHE_DIR)) {
00164                         $ADODB_CACHE_DIR = '/tmp'; //(isset($_ENV['TMP'])) ? $_ENV['TMP'] : '/tmp';
00165                 } else {
00166                         // do not accept url based paths, eg. http:/ or ftp:/
00167                         if (strpos($ADODB_CACHE_DIR,'://') !== false) 
00168                                 die("Illegal path http:// or ftp://");
00169                 }
00170                 
00171                         
00172                 // Initialize random number generator for randomizing cache flushes
00173                 // -- note Since PHP 4.2.0, the seed  becomes optional and defaults to a random value if omitted.
00174                  srand(((double)microtime())*1000000);
00175                 
00179                 $ADODB_vers = 'V4.94 23 Jan 2007 (c) 2000-2007 John Lim (jlim#natsoft.com.my). All rights reserved. Released BSD & LGPL.';
00180         
00186                 if (!isset($ADODB_COUNTRECS)) $ADODB_COUNTRECS = true; 
00187         }
00188         
00189         
00190         //==============================================================================================        
00191         // CHANGE NOTHING BELOW UNLESS YOU ARE DESIGNING ADODB
00192         //==============================================================================================        
00193         
00194         ADODB_Setup();
00195 
00196         //==============================================================================================        
00197         // CLASS ADOFieldObject
00198         //==============================================================================================        
00202         class ADOFieldObject { 
00203                 var $name = '';
00204                 var $max_length=0;
00205                 var $type="";
00206 /*
00207                 // additional fields by dannym... (danny_milo@yahoo.com)
00208                 var $not_null = false; 
00209                 // actually, this has already been built-in in the postgres, fbsql AND mysql module? ^-^
00210                 // so we can as well make not_null standard (leaving it at "false" does not harm anyways)
00211 
00212                 var $has_default = false; // this one I have done only in mysql and postgres for now ... 
00213                         // others to come (dannym)
00214                 var $default_value; // default, if any, and supported. Check has_default first.
00215 */
00216         }
00217         
00218 
00219         
00220         function ADODB_TransMonitor($dbms, $fn, $errno, $errmsg, $p1, $p2, &$thisConnection)
00221         {
00222                 //print "Errorno ($fn errno=$errno m=$errmsg) ";
00223                 $thisConnection->_transOK = false;
00224                 if ($thisConnection->_oldRaiseFn) {
00225                         $fn = $thisConnection->_oldRaiseFn;
00226                         $fn($dbms, $fn, $errno, $errmsg, $p1, $p2,$thisConnection);
00227                 }
00228         }
00229         
00230         //==============================================================================================        
00231         // CLASS ADOConnection
00232         //==============================================================================================        
00233         
00237         class ADOConnection {
00238         //
00239         // PUBLIC VARS 
00240         //
00241         var $dataProvider = 'native';
00242         var $databaseType = '';         
00243         var $database = '';                     
00244         var $host = '';                         
00245         var $user = '';                         
00246         var $password = '';             
00247         var $debug = false;             
00248         var $maxblobsize = 262144;      
00249         var $concat_operator = '+'; 
00250         var $substr = 'substr';         
00251         var $length = 'length';         
00252         var $random = 'rand()';         
00253         var $upperCase = 'upper';               
00254         var $fmtDate = "'Y-m-d'";       
00255         var $fmtTimeStamp = "'Y-m-d, h:i:s A'"; 
00256         var $true = '1';                        
00257         var $false = '0';                       
00258         var $replaceQuote = "\\'";      
00259         var $nameQuote = '"';           
00260         var $charSet=false;             
00261         var $metaDatabasesSQL = '';
00262         var $metaTablesSQL = '';
00263         var $uniqueOrderBy = false; 
00264         var $emptyDate = '&nbsp;';
00265         var $emptyTimeStamp = '&nbsp;';
00266         var $lastInsID = false;
00267         //--
00268         var $hasInsertID = false;               
00269         var $hasAffectedRows = false;   
00270         var $hasTop = false;                    
00271         var $hasLimit = false;                  
00272         var $readOnly = false;                  
00273         var $hasMoveFirst = false;  
00274         var $hasGenID = false;          
00275         var $hasTransactions = true; 
00276         //--
00277         var $genID = 0;                         
00278         var $raiseErrorFn = false;      
00279         var $isoDates = false; 
00280         var $cacheSecs = 3600; 
00281 
00282         // memcache
00283         var $memCache = false; 
00284         var $memCacheHost; 
00285         var $memCachePort = 11211; 
00286         var $memCacheCompress = false; 
00287 
00288         var $sysDate = false; 
00289         var $sysTimeStamp = false; 
00290         var $arrayClass = 'ADORecordSet_array'; 
00291         
00292         var $noNullStrings = false; 
00293         var $numCacheHits = 0; 
00294         var $numCacheMisses = 0;
00295         var $pageExecuteCountRows = true;
00296         var $uniqueSort = false; 
00297         var $leftOuter = false; 
00298         var $rightOuter = false; 
00299         var $ansiOuter = false; 
00300         var $autoRollback = false; // autoRollback on PConnect().
00301         var $poorAffectedRows = false; // affectedRows not working or unreliable
00302         
00303         var $fnExecute = false;
00304         var $fnCacheExecute = false;
00305         var $blobEncodeType = false; // false=not required, 'I'=encode to integer, 'C'=encode to char
00306         var $rsPrefix = "ADORecordSet_";
00307         
00308         var $autoCommit = true;         
00309         var $transOff = 0;                      
00310         var $transCnt = 0;                      
00311         
00312         var $fetchMode=false;
00313         
00314         var $null2null = 'null'; // in autoexecute/getinsertsql/getupdatesql, this value will be converted to a null
00315          //
00316          // PRIVATE VARS
00317          //
00318         var $_oldRaiseFn =  false;
00319         var $_transOK = null;
00320         var $_connectionID      = false;        
00321         var $_errorMsg = false;         
00322 
00323         var $_errorCode = false;        
00324         var $_queryID = false;          
00325         
00326         var $_isPersistentConnection = false;   
00327         var $_bindInputArray = false; 
00328         var $_evalAll = false;
00329         var $_affected = false;
00330         var $_logsql = false;
00331         var $_transmode = ''; // transaction mode
00332         
00333 
00334         
00338         function ADOConnection()                        
00339         {
00340                 die('Virtual Class -- cannot instantiate');
00341         }
00342         
00343         function Version()
00344         {
00345         global $ADODB_vers;
00346         
00347                 return (float) substr($ADODB_vers,1);
00348         }
00349         
00356         function ServerInfo()
00357         {
00358                 return array('description' => '', 'version' => '');
00359         }
00360         
00361         function IsConnected()
00362         {
00363         return !empty($this->_connectionID);
00364         }
00365         
00366         function _findvers($str)
00367         {
00368                 if (preg_match('/([0-9]+\.([0-9\.])+)/',$str, $arr)) return $arr[1];
00369                 else return '';
00370         }
00371         
00376         function outp($msg,$newline=true)
00377         {
00378         global $ADODB_FLUSH,$ADODB_OUTP;
00379         
00380                 if (defined('ADODB_OUTP')) {
00381                         $fn = ADODB_OUTP;
00382                         $fn($msg,$newline);
00383                         return;
00384                 } else if (isset($ADODB_OUTP)) {
00385                         $fn = $ADODB_OUTP;
00386                         $fn($msg,$newline);
00387                         return;
00388                 }
00389                 
00390                 if ($newline) $msg .= "<br>\n";
00391                 
00392                 if (isset($_SERVER['HTTP_USER_AGENT']) || !$newline) echo $msg;
00393                 else echo strip_tags($msg);
00394         
00395                 
00396                 if (!empty($ADODB_FLUSH) && ob_get_length() !== false) flush(); //  do not flush if output buffering enabled - useless - thx to Jesse Mullan 
00397                 
00398         }
00399         
00400         function Time()
00401         {
00402                 $rs =& $this->_Execute("select $this->sysTimeStamp");
00403                 if ($rs && !$rs->EOF) return $this->UnixTimeStamp(reset($rs->fields));
00404                 
00405                 return false;
00406         }
00407         
00419         function Connect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "", $forceNew = false) 
00420         {
00421                 if ($argHostname != "") $this->host = $argHostname;
00422                 if ($argUsername != "") $this->user = $argUsername;
00423                 if ($argPassword != "") $this->password = $argPassword; // not stored for security reasons
00424                 if ($argDatabaseName != "") $this->database = $argDatabaseName;         
00425                 
00426                 $this->_isPersistentConnection = false; 
00427                 if ($forceNew) {
00428                         if ($rez=$this->_nconnect($this->host, $this->user, $this->password, $this->database)) return true;
00429                 } else {
00430                          if ($rez=$this->_connect($this->host, $this->user, $this->password, $this->database)) return true;
00431                 }
00432                 if (isset($rez)) {
00433                         $err = $this->ErrorMsg();
00434                         if (empty($err)) $err = "Connection error to server '$argHostname' with user '$argUsername'";
00435                         $ret = false;
00436                 } else {
00437                         $err = "Missing extension for ".$this->dataProvider;
00438                         $ret = 0;
00439                 }
00440                 if ($fn = $this->raiseErrorFn) 
00441                         $fn($this->databaseType,'CONNECT',$this->ErrorNo(),$err,$this->host,$this->database,$this);
00442                 
00443                 
00444                 $this->_connectionID = false;
00445                 if ($this->debug) ADOConnection::outp( $this->host.': '.$err);
00446                 return $ret;
00447         }       
00448         
00449         function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName)
00450         {
00451                 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName);
00452         }
00453         
00454         
00465         function NConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "") 
00466         {
00467                 return $this->Connect($argHostname, $argUsername, $argPassword, $argDatabaseName, true);
00468         }
00469         
00480         function PConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "")
00481         {
00482                 if (defined('ADODB_NEVER_PERSIST')) 
00483                         return $this->Connect($argHostname,$argUsername,$argPassword,$argDatabaseName);
00484                 
00485                 if ($argHostname != "") $this->host = $argHostname;
00486                 if ($argUsername != "") $this->user = $argUsername;
00487                 if ($argPassword != "") $this->password = $argPassword;
00488                 if ($argDatabaseName != "") $this->database = $argDatabaseName;         
00489                         
00490                 $this->_isPersistentConnection = true;  
00491                 if ($rez = $this->_pconnect($this->host, $this->user, $this->password, $this->database)) return true;
00492                 if (isset($rez)) {
00493                         $err = $this->ErrorMsg();
00494                         if (empty($err)) $err = "Connection error to server '$argHostname' with user '$argUsername'";
00495                         $ret = false;
00496                 } else {
00497                         $err = "Missing extension for ".$this->dataProvider;
00498                         $ret = 0;
00499                 }
00500                 if ($fn = $this->raiseErrorFn) {
00501                         $fn($this->databaseType,'PCONNECT',$this->ErrorNo(),$err,$this->host,$this->database,$this);
00502                 }
00503                 
00504                 $this->_connectionID = false;
00505                 if ($this->debug) ADOConnection::outp( $this->host.': '.$err);
00506                 return $ret;
00507         }
00508 
00509         // Format date column in sql string given an input format that understands Y M D
00510         function SQLDate($fmt, $col=false)
00511         {       
00512                 if (!$col) $col = $this->sysDate;
00513                 return $col; // child class implement
00514         }
00515         
00531         function Prepare($sql)
00532         {
00533                 return $sql;
00534         }
00535         
00550         function PrepareSP($sql,$param=true)
00551         {
00552                 return $this->Prepare($sql,$param);
00553         }
00554         
00558         function Quote($s)
00559         {
00560                 return $this->qstr($s,false);
00561         }
00562         
00566         function QMagic($s)
00567         {
00568                 return $this->qstr($s,get_magic_quotes_gpc());
00569         }
00570 
00571         function q(&$s)
00572         {
00573                 #if (!empty($this->qNull)) if ($s == 'null') return $s;
00574                 $s = $this->qstr($s,false);
00575         }
00576         
00580         function ErrorNative()
00581         {
00582                 return $this->ErrorNo();
00583         }
00584 
00585         
00589         function nextId($seq_name)
00590         {
00591                 return $this->GenID($seq_name);
00592         }
00593 
00601         function RowLock($table,$where)
00602         {
00603                 return false;
00604         }
00605         
00606         function CommitLock($table)
00607         {
00608                 return $this->CommitTrans();
00609         }
00610         
00611         function RollbackLock($table)
00612         {
00613                 return $this->RollbackTrans();
00614         }
00615         
00625         function SetFetchMode($mode)
00626         {       
00627                 $old = $this->fetchMode;
00628                 $this->fetchMode = $mode;
00629                 
00630                 if ($old === false) {
00631                 global $ADODB_FETCH_MODE;
00632                         return $ADODB_FETCH_MODE;
00633                 }
00634                 return $old;
00635         }
00636         
00637 
00641         function &Query($sql, $inputarr=false)
00642         {
00643                 $rs = &$this->Execute($sql, $inputarr);
00644                 if (!$rs && defined('ADODB_PEAR')) return ADODB_PEAR_Error();
00645                 return $rs;
00646         }
00647 
00648         
00652         function &LimitQuery($sql, $offset, $count, $params=false)
00653         {
00654                 $rs = &$this->SelectLimit($sql, $count, $offset, $params); 
00655                 if (!$rs && defined('ADODB_PEAR')) return ADODB_PEAR_Error();
00656                 return $rs;
00657         }
00658 
00659         
00663         function Disconnect()
00664         {
00665                 return $this->Close();
00666         }
00667         
00668         /*
00669                  Returns placeholder for parameter, eg.
00670                  $DB->Param('a')
00671                  
00672                  will return ':a' for Oracle, and '?' for most other databases...
00673                  
00674                  For databases that require positioned params, eg $1, $2, $3 for postgresql,
00675                         pass in Param(false) before setting the first parameter.
00676         */
00677         function Param($name,$type='C')
00678         {
00679                 return '?';
00680         }
00681         
00682         /*
00683                 InParameter and OutParameter are self-documenting versions of Parameter().
00684         */
00685         function InParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false)
00686         {
00687                 return $this->Parameter($stmt,$var,$name,false,$maxLen,$type);
00688         }
00689         
00690         /*
00691         */
00692         function OutParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false)
00693         {
00694                 return $this->Parameter($stmt,$var,$name,true,$maxLen,$type);
00695         
00696         }
00697 
00698         
00699         /* 
00700         Usage in oracle
00701                 $stmt = $db->Prepare('select * from table where id =:myid and group=:group');
00702                 $db->Parameter($stmt,$id,'myid');
00703                 $db->Parameter($stmt,$group,'group',64);
00704                 $db->Execute();
00705                 
00706                 @param $stmt Statement returned by Prepare() or PrepareSP().
00707                 @param $var PHP variable to bind to
00708                 @param $name Name of stored procedure variable name to bind to.
00709                 @param [$isOutput] Indicates direction of parameter 0/false=IN  1=OUT  2= IN/OUT. This is ignored in oci8.
00710                 @param [$maxLen] Holds an maximum length of the variable.
00711                 @param [$type] The data type of $var. Legal values depend on driver.
00712 
00713         */
00714         function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false)
00715         {
00716                 return false;
00717         }
00718         
00719         
00720         function IgnoreErrors($saveErrs=false)
00721         {
00722                 if (!$saveErrs) {
00723                         $saveErrs = array($this->raiseErrorFn,$this->_transOK);
00724                         $this->raiseErrorFn = false;
00725                         return $saveErrs;
00726                 } else {
00727                         $this->raiseErrorFn = $saveErrs[0];
00728                         $this->_transOK = $saveErrs[1];
00729                 }
00730         }
00731         
00742         function StartTrans($errfn = 'ADODB_TransMonitor')
00743         {
00744                 if ($this->transOff > 0) {
00745                         $this->transOff += 1;
00746                         return;
00747                 }
00748                 
00749                 $this->_oldRaiseFn = $this->raiseErrorFn;
00750                 $this->raiseErrorFn = $errfn;
00751                 $this->_transOK = true;
00752                 
00753                 if ($this->debug && $this->transCnt > 0) ADOConnection::outp("Bad Transaction: StartTrans called within BeginTrans");
00754                 $this->BeginTrans();
00755                 $this->transOff = 1;
00756         }
00757         
00758         
00767         function CompleteTrans($autoComplete = true)
00768         {
00769                 if ($this->transOff > 1) {
00770                         $this->transOff -= 1;
00771                         return true;
00772                 }
00773                 $this->raiseErrorFn = $this->_oldRaiseFn;
00774                 
00775                 $this->transOff = 0;
00776                 if ($this->_transOK && $autoComplete) {
00777                         if (!$this->CommitTrans()) {
00778                                 $this->_transOK = false;
00779                                 if ($this->debug) ADOConnection::outp("Smart Commit failed");
00780                         } else
00781                                 if ($this->debug) ADOConnection::outp("Smart Commit occurred");
00782                 } else {
00783                         $this->_transOK = false;
00784                         $this->RollbackTrans();
00785                         if ($this->debug) ADOCOnnection::outp("Smart Rollback occurred");
00786                 }
00787                 
00788                 return $this->_transOK;
00789         }
00790         
00791         /*
00792                 At the end of a StartTrans/CompleteTrans block, perform a rollback.
00793         */
00794         function FailTrans()
00795         {
00796                 if ($this->debug) 
00797                         if ($this->transOff == 0) {
00798                                 ADOConnection::outp("FailTrans outside StartTrans/CompleteTrans");
00799                         } else {
00800                                 ADOConnection::outp("FailTrans was called");
00801                                 adodb_backtrace();
00802                         }
00803                 $this->_transOK = false;
00804         }
00805         
00809         function HasFailedTrans()
00810         {
00811                 if ($this->transOff > 0) return $this->_transOK == false;
00812                 return false;
00813         }
00814         
00822         function &Execute($sql,$inputarr=false) 
00823         {
00824                 if ($this->fnExecute) {
00825                         $fn = $this->fnExecute;
00826                         $ret =& $fn($this,$sql,$inputarr);
00827                         if (isset($ret)) return $ret;
00828                 }
00829                 if ($inputarr) {
00830                         if (!is_array($inputarr)) $inputarr = array($inputarr);
00831                         
00832                         $element0 = reset($inputarr);
00833                         # is_object check because oci8 descriptors can be passed in
00834                         $array_2d = is_array($element0) && !is_object(reset($element0));
00835                         //remove extra memory copy of input -mikefedyk
00836                         unset($element0);
00837                         
00838                         if (!is_array($sql) && !$this->_bindInputArray) {
00839                                 $sqlarr = explode('?',$sql);
00840                                         
00841                                 if (!$array_2d) $inputarr = array($inputarr);
00842                                 foreach($inputarr as $arr) {
00843                                         $sql = ''; $i = 0;
00844                                         //Use each() instead of foreach to reduce memory usage -mikefedyk
00845                                         while(list(, $v) = each($arr)) {
00846                                                 $sql .= $sqlarr[$i];
00847                                                 // from Ron Baldwin <ron.baldwin#sourceprose.com>
00848                                                 // Only quote string types      
00849                                                 $typ = gettype($v);
00850                                                 if ($typ == 'string')
00851                                                         //New memory copy of input created here -mikefedyk
00852                                                         $sql .= $this->qstr($v);
00853                                                 else if ($typ == 'double')
00854                                                         $sql .= str_replace(',','.',$v); // locales fix so 1.1 does not get converted to 1,1
00855                                                 else if ($typ == 'boolean')
00856                                                         $sql .= $v ? $this->true : $this->false;
00857                                                 else if ($typ == 'object') {
00858                                                         if (method_exists($v, '__toString')) $sql .= $this->qstr($v->__toString());
00859                                                         else $sql .= $this->qstr((string) $v);
00860                                                 } else if ($v === null)
00861                                                         $sql .= 'NULL';
00862                                                 else
00863                                                         $sql .= $v;
00864                                                 $i += 1;
00865                                         }
00866                                         if (isset($sqlarr[$i])) {
00867                                                 $sql .= $sqlarr[$i];
00868                                                 if ($i+1 != sizeof($sqlarr)) ADOConnection::outp( "Input Array does not match ?: ".htmlspecialchars($sql));
00869                                         } else if ($i != sizeof($sqlarr))       
00870                                                 ADOConnection::outp( "Input array does not match ?: ".htmlspecialchars($sql));
00871                 
00872                                         $ret =& $this->_Execute($sql);
00873                                         if (!$ret) return $ret;
00874                                 }       
00875                         } else {
00876                                 if ($array_2d) {
00877                                         if (is_string($sql))
00878                                                 $stmt = $this->Prepare($sql);
00879                                         else
00880                                                 $stmt = $sql;
00881                                                 
00882                                         foreach($inputarr as $arr) {
00883                                                 $ret =& $this->_Execute($stmt,$arr);
00884                                                 if (!$ret) return $ret;
00885                                         }
00886                                 } else {
00887                                         $ret =& $this->_Execute($sql,$inputarr);
00888                                 }
00889                         }
00890                 } else {
00891                         $ret =& $this->_Execute($sql,false);
00892                 }
00893 
00894                 return $ret;
00895         }
00896         
00897         
00898         function &_Execute($sql,$inputarr=false)
00899         {
00900                 if ($this->debug) {
00901                         global $ADODB_INCLUDED_LIB;
00902                         if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR.'/adodb-lib.inc.php');
00903                         $this->_queryID = _adodb_debug_execute($this, $sql,$inputarr);
00904                 } else {
00905                         $this->_queryID = @$this->_query($sql,$inputarr);
00906                 }
00907                 
00908                 /************************
00909                 // OK, query executed
00910                 *************************/
00911 
00912                 if ($this->_queryID === false) { // error handling if query fails
00913                         if ($this->debug == 99) adodb_backtrace(true,5);        
00914                         $fn = $this->raiseErrorFn;
00915                         if ($fn) {
00916                                 $fn($this->databaseType,'EXECUTE',$this->ErrorNo(),$this->ErrorMsg(),$sql,$inputarr,$this);
00917                         } 
00918                         $false = false;
00919                         return $false;
00920                 } 
00921                 
00922                 if ($this->_queryID === true) { // return simplified recordset for inserts/updates/deletes with lower overhead
00923                         $rs = new ADORecordSet_empty();
00924                         return $rs;
00925                 }
00926                 
00927                 // return real recordset from select statement
00928                 $rsclass = $this->rsPrefix.$this->databaseType;
00929                 $rs = new $rsclass($this->_queryID,$this->fetchMode);
00930                 $rs->connection = &$this; // Pablo suggestion
00931                 $rs->Init();
00932                 if (is_array($sql)) $rs->sql = $sql[0];
00933                 else $rs->sql = $sql;
00934                 if ($rs->_numOfRows <= 0) {
00935                 global $ADODB_COUNTRECS;
00936                         if ($ADODB_COUNTRECS) {
00937                                 if (!$rs->EOF) { 
00938                                         $rs = &$this->_rs2rs($rs,-1,-1,!is_array($sql));
00939                                         $rs->_queryID = $this->_queryID;
00940                                 } else
00941                                         $rs->_numOfRows = 0;
00942                         }
00943                 }
00944                 return $rs;
00945         }
00946 
00947         function CreateSequence($seqname='adodbseq',$startID=1)
00948         {
00949                 if (empty($this->_genSeqSQL)) return false;
00950                 return $this->Execute(sprintf($this->_genSeqSQL,$seqname,$startID));
00951         }
00952 
00953         function DropSequence($seqname='adodbseq')
00954         {
00955                 if (empty($this->_dropSeqSQL)) return false;
00956                 return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
00957         }
00958 
00967         function GenID($seqname='adodbseq',$startID=1)
00968         {
00969                 if (!$this->hasGenID) {
00970                         return 0; // formerly returns false pre 1.60
00971                 }
00972                 
00973                 $getnext = sprintf($this->_genIDSQL,$seqname);
00974                 
00975                 $holdtransOK = $this->_transOK;
00976                 
00977                 $save_handler = $this->raiseErrorFn;
00978                 $this->raiseErrorFn = '';
00979                 @($rs = $this->Execute($getnext));
00980                 $this->raiseErrorFn = $save_handler;
00981                 
00982                 if (!$rs) {
00983                         $this->_transOK = $holdtransOK; //if the status was ok before reset
00984                         $createseq = $this->Execute(sprintf($this->_genSeqSQL,$seqname,$startID));
00985                         $rs = $this->Execute($getnext);
00986                 }
00987                 if ($rs && !$rs->EOF) $this->genID = reset($rs->fields);
00988                 else $this->genID = 0; // false
00989         
00990                 if ($rs) $rs->Close();
00991 
00992                 return $this->genID;
00993         }       
00994 
01000         function Insert_ID($table='',$column='')
01001         {
01002                 if ($this->_logsql && $this->lastInsID) return $this->lastInsID;
01003                 if ($this->hasInsertID) return $this->_insertid($table,$column);
01004                 if ($this->debug) {
01005                         ADOConnection::outp( '<p>Insert_ID error</p>');
01006                         adodb_backtrace();
01007                 }
01008                 return false;
01009         }
01010 
01011 
01018         function PO_Insert_ID($table="", $id="") 
01019         {
01020            if ($this->hasInsertID){
01021                    return $this->Insert_ID($table,$id);
01022            } else {
01023                    return $this->GetOne("SELECT MAX($id) FROM $table");
01024            }
01025         }
01026 
01030         function Affected_Rows()
01031         {
01032                 if ($this->hasAffectedRows) {
01033                         if ($this->fnExecute === 'adodb_log_sql') {
01034                                 if ($this->_logsql && $this->_affected !== false) return $this->_affected;
01035                         }
01036                         $val = $this->_affectedrows();
01037                         return ($val < 0) ? false : $val;
01038                 }
01039                                   
01040                 if ($this->debug) ADOConnection::outp( '<p>Affected_Rows error</p>',false);
01041                 return false;
01042         }
01043         
01044         
01048         function ErrorMsg()
01049         {
01050                 if ($this->_errorMsg) return '!! '.strtoupper($this->dataProvider.' '.$this->databaseType).': '.$this->_errorMsg;
01051                 else return '';
01052         }
01053         
01054         
01058         function ErrorNo() 
01059         {
01060                 return ($this->_errorMsg) ? -1 : 0;
01061         }
01062         
01063         function MetaError($err=false)
01064         {
01065                 include_once(ADODB_DIR."/adodb-error.inc.php");
01066                 if ($err === false) $err = $this->ErrorNo();
01067                 return adodb_error($this->dataProvider,$this->databaseType,$err);
01068         }
01069         
01070         function MetaErrorMsg($errno)
01071         {
01072                 include_once(ADODB_DIR."/adodb-error.inc.php");
01073                 return adodb_errormsg($errno);
01074         }
01075         
01079         function MetaPrimaryKeys($table, $owner=false)
01080         {
01081         // owner not used in base class - see oci8
01082                 $p = array();
01083                 $objs =& $this->MetaColumns($table);
01084                 if ($objs) {
01085                         foreach($objs as $v) {
01086                                 if (!empty($v->primary_key))
01087                                         $p[] = $v->name;
01088                         }
01089                 }
01090                 if (sizeof($p)) return $p;
01091                 if (function_exists('ADODB_VIEW_PRIMARYKEYS'))
01092                         return ADODB_VIEW_PRIMARYKEYS($this->databaseType, $this->database, $table, $owner);
01093                 return false;
01094         }
01095         
01099         function MetaForeignKeys($table, $owner=false, $upper=false)
01100         {
01101                 return false;
01102         }
01109         function SelectDB($dbName) 
01110         {return false;}
01111         
01112         
01132         function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
01133         {
01134                 if ($this->hasTop && $nrows > 0) {
01135                 // suggested by Reinhard Balling. Access requires top after distinct 
01136                  // Informix requires first before distinct - F Riosa
01137                         $ismssql = (strpos($this->databaseType,'mssql') !== false);
01138                         if ($ismssql) $isaccess = false;
01139                         else $isaccess = (strpos($this->databaseType,'access') !== false);
01140                         
01141                         if ($offset <=  0) {
01142                                 
01143                                         // access includes ties in result
01144                                         if ($isaccess) {
01145                                                 $sql = preg_replace(
01146                                                 '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop.' '.((integer)$nrows).' ',$sql);
01147 
01148                                                 if ($secs2cache != 0) {
01149                                                         $ret =& $this->CacheExecute($secs2cache, $sql,$inputarr);
01150                                                 } else {
01151                                                         $ret =& $this->Execute($sql,$inputarr);
01152                                                 }
01153                                                 return $ret; // PHP5 fix
01154                                         } else if ($ismssql){
01155                                                 $sql = preg_replace(
01156                                                 '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop.' '.((integer)$nrows).' ',$sql);
01157                                         } else {
01158                                                 $sql = preg_replace(
01159                                                 '/(^\s*select\s)/i','\\1 '.$this->hasTop.' '.((integer)$nrows).' ',$sql);
01160                                         }
01161                         } else {
01162                                 $nn = $nrows + $offset;
01163                                 if ($isaccess || $ismssql) {
01164                                         $sql = preg_replace(
01165                                         '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop.' '.$nn.' ',$sql);
01166                                 } else {
01167                                         $sql = preg_replace(
01168                                         '/(^\s*select\s)/i','\\1 '.$this->hasTop.' '.$nn.' ',$sql);
01169                                 }
01170                         }
01171                 }
01172                 
01173                 // if $offset>0, we want to skip rows, and $ADODB_COUNTRECS is set, we buffer  rows
01174                 // 0 to offset-1 which will be discarded anyway. So we disable $ADODB_COUNTRECS.
01175                 global $ADODB_COUNTRECS;
01176                 
01177                 $savec = $ADODB_COUNTRECS;
01178                 $ADODB_COUNTRECS = false;
01179                         
01180                 if ($offset>0){
01181                         if ($secs2cache != 0) $rs = &$this->CacheExecute($secs2cache,$sql,$inputarr);
01182                         else $rs = &$this->Execute($sql,$inputarr);
01183                 } else {
01184                         if ($secs2cache != 0) $rs = &$this->CacheExecute($secs2cache,$sql,$inputarr);
01185                         else $rs = &$this->Execute($sql,$inputarr);
01186                 }
01187                 $ADODB_COUNTRECS = $savec;
01188                 if ($rs && !$rs->EOF) {
01189                         $rs =& $this->_rs2rs($rs,$nrows,$offset);
01190                 }
01191                 //print_r($rs);
01192                 return $rs;
01193         }
01194         
01200         function &SerializableRS(&$rs)
01201         {
01202                 $rs2 =& $this->_rs2rs($rs);
01203                 $ignore = false;
01204                 $rs2->connection =& $ignore;
01205                 
01206                 return $rs2;
01207         }
01208         
01219         function &_rs2rs(&$rs,$nrows=-1,$offset=-1,$close=true)
01220         {
01221                 if (! $rs) {
01222                         $false = false;
01223                         return $false;
01224                 }
01225                 $dbtype = $rs->databaseType;
01226                 if (!$dbtype) {
01227                         $rs = &$rs;  // required to prevent crashing in 4.2.1, but does not happen in 4.3.1 -- why ?
01228                         return $rs;
01229                 }
01230                 if (($dbtype == 'array' || $dbtype == 'csv') && $nrows == -1 && $offset == -1) {
01231                         $rs->MoveFirst();
01232                         $rs = &$rs; // required to prevent crashing in 4.2.1, but does not happen in 4.3.1-- why ?
01233                         return $rs;
01234                 }
01235                 $flds = array();
01236                 for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) {
01237                         $flds[] = $rs->FetchField($i);
01238                 }
01239 
01240                 $arr =& $rs->GetArrayLimit($nrows,$offset);
01241                 //print_r($arr);
01242                 if ($close) $rs->Close();
01243                 
01244                 $arrayClass = $this->arrayClass;
01245                 
01246                 $rs2 = new $arrayClass();
01247                 $rs2->connection = &$this;
01248                 $rs2->sql = $rs->sql;
01249                 $rs2->dataProvider = $this->dataProvider;
01250                 $rs2->InitArrayFields($arr,$flds);
01251                 $rs2->fetchMode = isset($rs->adodbFetchMode) ? $rs->adodbFetchMode : $rs->fetchMode;
01252                 return $rs2;
01253         }
01254         
01255         /*
01256         * Return all rows. Compat with PEAR DB
01257         */
01258         function &GetAll($sql, $inputarr=false)
01259         {
01260                 $arr =& $this->GetArray($sql,$inputarr);
01261                 return $arr;
01262         }
01263         
01264         function &GetAssoc($sql, $inputarr=false,$force_array = false, $first2cols = false)
01265         {
01266                 $rs =& $this->Execute($sql, $inputarr);
01267                 if (!$rs) {
01268                         $false = false;
01269                         return $false;
01270                 }
01271                 $arr =& $rs->GetAssoc($force_array,$first2cols);
01272                 return $arr;
01273         }
01274         
01275         function &CacheGetAssoc($secs2cache, $sql=false, $inputarr=false,$force_array = false, $first2cols = false)
01276         {
01277                 if (!is_numeric($secs2cache)) {
01278                         $first2cols = $force_array;
01279                         $force_array = $inputarr;
01280                 }
01281                 $rs =& $this->CacheExecute($secs2cache, $sql, $inputarr);
01282                 if (!$rs) {
01283                         $false =