diff --git a/phpgwapi/inc/adodb/adodb.inc.php b/phpgwapi/inc/adodb/adodb.inc.php index d7fecc76e6..9e6cab9fb4 100644 --- a/phpgwapi/inc/adodb/adodb.inc.php +++ b/phpgwapi/inc/adodb/adodb.inc.php @@ -1,9 +1,9 @@ - Manual is at http://php.weblogs.com/adodb_manual - + */ - + if (!defined('_ADODB_LAYER')) { define('_ADODB_LAYER',1); - - //============================================================================================== + + //============================================================================================== // CONSTANT DEFINITIONS - //============================================================================================== + //============================================================================================== - /** + /** * Set ADODB_DIR to the directory where this file resides... * This constant was formerly called $ADODB_RootPath */ if (!defined('ADODB_DIR')) define('ADODB_DIR',dirname(__FILE__)); - - //============================================================================================== - // GLOBAL VARIABLES - //============================================================================================== - GLOBAL + //============================================================================================== + // GLOBAL VARIABLES + //============================================================================================== + + GLOBAL $ADODB_vers, // database version $ADODB_COUNTRECS, // count number of records returned - slows down query $ADODB_CACHE_DIR, // directory to cache recordsets $ADODB_EXTENSION, // ADODB extension installed $ADODB_COMPAT_FETCH, // If $ADODB_COUNTRECS and this is true, $rs->fields is available on EOF $ADODB_FETCH_MODE; // DEFAULT, NUM, ASSOC or BOTH. Default follows native driver default... - - //============================================================================================== + + //============================================================================================== // GLOBAL SETUP - //============================================================================================== - + //============================================================================================== + $ADODB_EXTENSION = defined('ADODB_EXTENSION'); - + //********************************************************// /* Controls $ADODB_FORCE_TYPE mode. Default is ADODB_FORCE_VALUE (3). @@ -83,32 +83,32 @@ if (!$ADODB_EXTENSION || ADODB_EXTENSION < 4.0) { - + define('ADODB_BAD_RS','

Bad $rs in %s. Connection or SQL invalid. Try using $connection->debug=true;

'); - + // allow [ ] @ ` " and . in table names define('ADODB_TABLE_REGEX','([]0-9a-z_\:\"\`\.\@\[-]*)'); - + // prefetching used by oracle if (!defined('ADODB_PREFETCH_ROWS')) define('ADODB_PREFETCH_ROWS',10); - - + + /* Controls ADODB_FETCH_ASSOC field-name case. Default is 2, use native case-names. This currently works only with mssql, odbc, oci8po and ibase derived drivers. - + 0 = assoc lowercase field names. $rs->fields['orderid'] 1 = assoc uppercase field names. $rs->fields['ORDERID'] 2 = use native-case field names. $rs->fields['OrderID'] */ - + define('ADODB_FETCH_DEFAULT',0); define('ADODB_FETCH_NUM',1); define('ADODB_FETCH_ASSOC',2); define('ADODB_FETCH_BOTH',3); - + if (!defined('TIMESTAMP_FIRST_YEAR')) define('TIMESTAMP_FIRST_YEAR',100); - + // PHP's version scheme makes converting to numbers difficult - workaround $_adodb_ver = (float) PHP_VERSION; if ($_adodb_ver >= 5.0) { @@ -123,17 +123,17 @@ define('ADODB_PHPVER',0x4000); } } - + //if (!defined('ADODB_ASSOC_CASE')) define('ADODB_ASSOC_CASE',2); - + /** Accepts $src and $dest arrays, replacing string $data */ function ADODB_str_replace($src, $dest, $data) { if (ADODB_PHPVER >= 0x4050) return str_replace($src,$dest,$data); - + $s = reset($src); $d = reset($dest); while ($s !== false) { @@ -143,16 +143,16 @@ } return $data; } - + function ADODB_Setup() { - GLOBAL + GLOBAL $ADODB_vers, // database version $ADODB_COUNTRECS, // count number of records returned - slows down query $ADODB_CACHE_DIR, // directory to cache recordsets $ADODB_FETCH_MODE, $ADODB_FORCE_TYPE; - + $ADODB_FETCH_MODE = ADODB_FETCH_DEFAULT; $ADODB_FORCE_TYPE = ADODB_FORCE_VALUE; @@ -161,58 +161,58 @@ $ADODB_CACHE_DIR = '/tmp'; //(isset($_ENV['TMP'])) ? $_ENV['TMP'] : '/tmp'; } else { // do not accept url based paths, eg. http:/ or ftp:/ - if (strpos($ADODB_CACHE_DIR,'://') !== false) + if (strpos($ADODB_CACHE_DIR,'://') !== false) die("Illegal path http:// or ftp://"); } - - + + // Initialize random number generator for randomizing cache flushes srand(((double)microtime())*1000000); - + /** * ADODB version as a string. */ $ADODB_vers = 'V4.65 22 July 2005 (c) 2000-2005 John Lim (jlim#natsoft.com.my). All rights reserved. Released BSD & LGPL.'; - + /** - * Determines whether recordset->RecordCount() is used. + * Determines whether recordset->RecordCount() is used. * Set to false for highest performance -- RecordCount() will always return -1 then * for databases that provide "virtual" recordcounts... */ - if (!isset($ADODB_COUNTRECS)) $ADODB_COUNTRECS = true; + if (!isset($ADODB_COUNTRECS)) $ADODB_COUNTRECS = true; } - - - //============================================================================================== + + + //============================================================================================== // CHANGE NOTHING BELOW UNLESS YOU ARE DESIGNING ADODB - //============================================================================================== - + //============================================================================================== + ADODB_Setup(); - //============================================================================================== + //============================================================================================== // CLASS ADOFieldObject - //============================================================================================== + //============================================================================================== /** * Helper class for FetchFields -- holds info on a column */ - class ADOFieldObject { + class ADOFieldObject { var $name = ''; var $max_length=0; var $type=""; /* // additional fields by dannym... (danny_milo@yahoo.com) - var $not_null = false; + var $not_null = false; // actually, this has already been built-in in the postgres, fbsql AND mysql module? ^-^ // so we can as well make not_null standard (leaving it at "false" does not harm anyways) - var $has_default = false; // this one I have done only in mysql and postgres for now ... + var $has_default = false; // this one I have done only in mysql and postgres for now ... // others to come (dannym) var $default_value; // default, if any, and supported. Check has_default first. */ } - - + + function ADODB_TransMonitor($dbms, $fn, $errno, $errmsg, $p1, $p2, &$thisConnection) { //print "Errorno ($fn errno=$errno m=$errmsg) "; @@ -222,27 +222,27 @@ $fn($dbms, $fn, $errno, $errmsg, $p1, $p2,$thisConnection); } } - - //============================================================================================== + + //============================================================================================== // CLASS ADOConnection - //============================================================================================== - + //============================================================================================== + /** * Connection object. For connecting to databases, and executing queries. - */ + */ class ADOConnection { // - // PUBLIC VARS + // PUBLIC VARS // var $dataProvider = 'native'; - var $databaseType = ''; /// RDBMS currently in use, eg. odbc, mysql, mssql - var $database = ''; /// Name of database to be used. - var $host = ''; /// The hostname of the database server - var $user = ''; /// The username which is used to connect to the database server. + var $databaseType = ''; /// RDBMS currently in use, eg. odbc, mysql, mssql + var $database = ''; /// Name of database to be used. + var $host = ''; /// The hostname of the database server + var $user = ''; /// The username which is used to connect to the database server. var $password = ''; /// Password for the username. For security, we no longer store it. var $debug = false; /// if set to true will output sql statements var $maxblobsize = 262144; /// maximum size of blobs or large text fields (262144 = 256K)-- some db's die otherwise like foxpro - var $concat_operator = '+'; /// default concat operator -- change to || for Oracle/Interbase + var $concat_operator = '+'; /// default concat operator -- change to || for Oracle/Interbase var $substr = 'substr'; /// substring operator var $length = 'length'; /// string length ofperator var $random = 'rand()'; /// random function @@ -277,9 +277,9 @@ var $sysDate = false; /// name of function that returns the current date var $sysTimeStamp = false; /// name of function that returns the current timestamp var $arrayClass = 'ADORecordSet_array'; /// name of class used to generate array recordsets, which are pre-downloaded recordsets - + var $noNullStrings = false; /// oracle specific stuff - if true ensures that '' is converted to ' ' - var $numCacheHits = 0; + var $numCacheHits = 0; var $numCacheMisses = 0; var $pageExecuteCountRows = true; var $uniqueSort = false; /// indicates that all fields in order by must be unique @@ -288,73 +288,73 @@ var $ansiOuter = false; /// whether ansi outer join syntax supported var $autoRollback = false; // autoRollback on PConnect(). var $poorAffectedRows = false; // affectedRows not working or unreliable - + var $fnExecute = false; var $fnCacheExecute = false; var $blobEncodeType = false; // false=not required, 'I'=encode to integer, 'C'=encode to char var $rsPrefix = "ADORecordSet_"; - + var $autoCommit = true; /// do not modify this yourself - actually private var $transOff = 0; /// temporarily disable transactions var $transCnt = 0; /// count of nested transactions - + var $fetchMode=false; // // PRIVATE VARS // var $_oldRaiseFn = false; var $_transOK = null; - var $_connectionID = false; /// The returned link identifier whenever a successful database connection is made. + var $_connectionID = false; /// The returned link identifier whenever a successful database connection is made. var $_errorMsg = false; /// A variable which was used to keep the returned last error message. The value will - /// then returned by the errorMsg() function - var $_errorCode = false; /// Last error code, not guaranteed to be used - only by oci8 + /// then returned by the errorMsg() function + var $_errorCode = false; /// Last error code, not guaranteed to be used - only by oci8 var $_queryID = false; /// This variable keeps the last created result link identifier - + var $_isPersistentConnection = false; /// A boolean variable to state whether its a persistent connection or normal connection. */ var $_bindInputArray = false; /// set to true if ADOConnection.Execute() permits binding of array parameters. var $_evalAll = false; var $_affected = false; var $_logsql = false; - - + + /** * Constructor */ - function ADOConnection() + function ADOConnection() { die('Virtual Class -- cannot instantiate'); } - + function Version() { global $ADODB_vers; - + return (float) substr($ADODB_vers,1); } - + /** Get server version info... - - @returns An array with 2 elements: $arr['string'] is the description string, + + @returns An array with 2 elements: $arr['string'] is the description string, and $arr[version] is the version (also a string). */ function ServerInfo() { return array('description' => '', 'version' => ''); } - + function IsConnected() { return !empty($this->_connectionID); } - + function _findvers($str) { if (preg_match('/([0-9]+\.([0-9\.])+)/',$str, $arr)) return $arr[1]; else return ''; } - + /** * All error messages go through this bottleneck function. * You can define your own handler by defining the function name in ADODB_OUTP. @@ -362,7 +362,7 @@ function outp($msg,$newline=true) { global $ADODB_FLUSH,$ADODB_OUTP; - + if (defined('ADODB_OUTP')) { $fn = ADODB_OUTP; $fn($msg,$newline); @@ -372,25 +372,25 @@ $fn($msg,$newline); return; } - + if ($newline) $msg .= "
\n"; - + if (isset($_SERVER['HTTP_USER_AGENT']) || !$newline) echo $msg; else echo strip_tags($msg); - - - if (!empty($ADODB_FLUSH) && ob_get_length() !== false) flush(); // do not flush if output buffering enabled - useless - thx to Jesse Mullan - + + + if (!empty($ADODB_FLUSH) && ob_get_length() !== false) flush(); // do not flush if output buffering enabled - useless - thx to Jesse Mullan + } - + function Time() { $rs =& $this->_Execute("select $this->sysTimeStamp"); if ($rs && !$rs->EOF) return $this->UnixTimeStamp(reset($rs->fields)); - + return false; } - + /** * Connect to database * @@ -401,15 +401,15 @@ * @param [forceNew] force new connection * * @return true or false - */ - function Connect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "", $forceNew = false) + */ + function Connect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "", $forceNew = false) { if ($argHostname != "") $this->host = $argHostname; if ($argUsername != "") $this->user = $argUsername; if ($argPassword != "") $this->password = $argPassword; // not stored for security reasons - if ($argDatabaseName != "") $this->database = $argDatabaseName; - - $this->_isPersistentConnection = false; + if ($argDatabaseName != "") $this->database = $argDatabaseName; + + $this->_isPersistentConnection = false; if ($forceNew) { if ($rez=$this->_nconnect($this->host, $this->user, $this->password, $this->database)) return true; } else { @@ -423,21 +423,21 @@ $err = "Missing extension for ".$this->dataProvider; $ret = 0; } - if ($fn = $this->raiseErrorFn) + if ($fn = $this->raiseErrorFn) $fn($this->databaseType,'CONNECT',$this->ErrorNo(),$err,$this->host,$this->database,$this); - - + + $this->_connectionID = false; if ($this->debug) ADOConnection::outp( $this->host.': '.$err); return $ret; - } - + } + function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName) { return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName); } - - + + /** * Always force a new connection to database - currently only works with oracle * @@ -447,12 +447,12 @@ * @param [argDatabaseName] database * * @return true or false - */ - function NConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "") + */ + function NConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "") { return $this->Connect($argHostname, $argUsername, $argPassword, $argDatabaseName, true); } - + /** * Establish persistent connect to database * @@ -462,18 +462,18 @@ * @param [argDatabaseName] database * * @return return true or false - */ + */ function PConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "") { - if (defined('ADODB_NEVER_PERSIST')) + if (defined('ADODB_NEVER_PERSIST')) return $this->Connect($argHostname,$argUsername,$argPassword,$argDatabaseName); - + if ($argHostname != "") $this->host = $argHostname; if ($argUsername != "") $this->user = $argUsername; if ($argPassword != "") $this->password = $argPassword; - if ($argDatabaseName != "") $this->database = $argDatabaseName; - - $this->_isPersistentConnection = true; + if ($argDatabaseName != "") $this->database = $argDatabaseName; + + $this->_isPersistentConnection = true; if ($rez = $this->_pconnect($this->host, $this->user, $this->password, $this->database)) return true; if (isset($rez)) { $err = $this->ErrorMsg(); @@ -486,7 +486,7 @@ if ($fn = $this->raiseErrorFn) { $fn($this->databaseType,'PCONNECT',$this->ErrorNo(),$err,$this->host,$this->database,$this); } - + $this->_connectionID = false; if ($this->debug) ADOConnection::outp( $this->host.': '.$err); return $ret; @@ -494,11 +494,11 @@ // Format date column in sql string given an input format that understands Y M D function SQLDate($fmt, $col=false) - { + { if (!$col) $col = $this->sysDate; return $col; // child class implement } - + /** * Should prepare the sql statement and return the stmt resource. * For databases that do not support this, we return the $sql. To ensure @@ -513,12 +513,12 @@ * @return return FALSE, or the prepared statement, or the original sql if * if the database does not support prepare. * - */ + */ function Prepare($sql) { return $sql; } - + /** * Some databases, eg. mssql require a different function for preparing * stored procedures. So we cannot use Prepare(). @@ -532,12 +532,12 @@ * @return return FALSE, or the prepared statement, or the original sql if * if the database does not support prepare. * - */ + */ function PrepareSP($sql,$param=true) { return $this->Prepare($sql,$param); } - + /** * PEAR DB Compat */ @@ -545,7 +545,7 @@ { return $this->qstr($s,false); } - + /** Requested by "Karsten Dambekalns" */ @@ -558,18 +558,18 @@ { $s = $this->qstr($s,false); } - + /** - * PEAR DB Compat - do not use internally. + * PEAR DB Compat - do not use internally. */ function ErrorNative() { return $this->ErrorNo(); } - + /** - * PEAR DB Compat - do not use internally. + * PEAR DB Compat - do not use internally. */ function nextId($seq_name) { @@ -587,19 +587,19 @@ { return false; } - + function CommitLock($table) { return $this->CommitTrans(); } - + function RollbackLock($table) { return $this->RollbackTrans(); } - + /** - * PEAR DB Compat - do not use internally. + * PEAR DB Compat - do not use internally. * * The fetch modes for NUMERIC and ASSOC for PEAR DB and ADODB are identical * for easy porting :-) @@ -608,20 +608,20 @@ * @returns The previous fetch mode */ function SetFetchMode($mode) - { + { $old = $this->fetchMode; $this->fetchMode = $mode; - + if ($old === false) { global $ADODB_FETCH_MODE; return $ADODB_FETCH_MODE; } return $old; } - + /** - * PEAR DB Compat - do not use internally. + * PEAR DB Compat - do not use internally. */ function &Query($sql, $inputarr=false) { @@ -630,18 +630,18 @@ return $rs; } - + /** * PEAR DB Compat - do not use internally */ function &LimitQuery($sql, $offset, $count, $params=false) { - $rs = &$this->SelectLimit($sql, $count, $offset, $params); + $rs = &$this->SelectLimit($sql, $count, $offset, $params); if (!$rs && defined('ADODB_PEAR')) return ADODB_PEAR_Error(); return $rs; } - + /** * PEAR DB Compat - do not use internally */ @@ -649,13 +649,13 @@ { return $this->Close(); } - + /* Returns placeholder for parameter, eg. $DB->Param('a') - + will return ':a' for Oracle, and '?' for most other databases... - + For databases that require positioned params, eg $1, $2, $3 for postgresql, pass in Param(false) before setting the first parameter. */ @@ -663,7 +663,7 @@ { return '?'; } - + /* InParameter and OutParameter are self-documenting versions of Parameter(). */ @@ -671,22 +671,22 @@ { return $this->Parameter($stmt,$var,$name,false,$maxLen,$type); } - + /* */ function OutParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false) { return $this->Parameter($stmt,$var,$name,true,$maxLen,$type); - + } - - /* + + /* Usage in oracle $stmt = $db->Prepare('select * from table where id =:myid and group=:group'); $db->Parameter($stmt,$id,'myid'); $db->Parameter($stmt,$group,'group',64); $db->Execute(); - + @param $stmt Statement returned by Prepare() or PrepareSP(). @param $var PHP variable to bind to @param $name Name of stored procedure variable name to bind to. @@ -699,11 +699,11 @@ { return false; } - + /** Improved method of initiating a transaction. Used together with CompleteTrans(). Advantages include: - + a. StartTrans/CompleteTrans is nestable, unlike BeginTrans/CommitTrans/RollbackTrans. Only the outermost block is treated as a transaction.
b. CompleteTrans auto-detects SQL errors, and will rollback on errors, commit otherwise.
@@ -716,22 +716,22 @@ $this->transOff += 1; return; } - + $this->_oldRaiseFn = $this->raiseErrorFn; $this->raiseErrorFn = $errfn; $this->_transOK = true; - + if ($this->debug && $this->transCnt > 0) ADOConnection::outp("Bad Transaction: StartTrans called within BeginTrans"); $this->BeginTrans(); $this->transOff = 1; } - - + + /** Used together with StartTrans() to end a transaction. Monitors connection for sql errors, and will commit or rollback as appropriate. - - @autoComplete if true, monitor sql errors and commit and rollback as appropriate, + + @autoComplete if true, monitor sql errors and commit and rollback as appropriate, and if set to false force rollback even if no SQL error detected. @returns true on commit, false on rollback. */ @@ -742,7 +742,7 @@ return true; } $this->raiseErrorFn = $this->_oldRaiseFn; - + $this->transOff = 0; if ($this->_transOK && $autoComplete) { if (!$this->CommitTrans()) { @@ -755,16 +755,16 @@ $this->RollbackTrans(); if ($this->debug) ADOCOnnection::outp("Smart Rollback occurred"); } - + return $this->_transOK; } - + /* At the end of a StartTrans/CompleteTrans block, perform a rollback. */ function FailTrans() { - if ($this->debug) + if ($this->debug) if ($this->transOff == 0) { ADOConnection::outp("FailTrans outside StartTrans/CompleteTrans"); } else { @@ -773,7 +773,7 @@ } $this->_transOK = false; } - + /** Check if transaction has failed, only for Smart Transactions. */ @@ -782,15 +782,15 @@ if ($this->transOff > 0) return $this->_transOK == false; return false; } - + /** - * Execute SQL + * Execute SQL * * @param sql SQL statement to execute, or possibly an array holding prepared statement ($sql[0] will hold sql text) * @param [inputarr] holds the input data to bind to. Null elements will be set to null. * @return RecordSet or false */ - function &Execute($sql,$inputarr=false) + function &Execute($sql,$inputarr=false) { if ($this->fnExecute) { $fn = $this->fnExecute; @@ -799,21 +799,21 @@ } if ($inputarr) { if (!is_array($inputarr)) $inputarr = array($inputarr); - + $element0 = reset($inputarr); # is_object check because oci8 descriptors can be passed in $array_2d = is_array($element0) && !is_object(reset($element0)); - + if (!is_array($sql) && !$this->_bindInputArray) { $sqlarr = explode('?',$sql); - + if (!$array_2d) $inputarr = array($inputarr); foreach($inputarr as $arr) { $sql = ''; $i = 0; foreach($arr as $v) { $sql .= $sqlarr[$i]; // from Ron Baldwin - // Only quote string types + // Only quote string types $typ = gettype($v); if ($typ == 'string') $sql .= $this->qstr($v); @@ -830,19 +830,19 @@ if (isset($sqlarr[$i])) { $sql .= $sqlarr[$i]; if ($i+1 != sizeof($sqlarr)) ADOConnection::outp( "Input Array does not match ?: ".htmlspecialchars($sql)); - } else if ($i != sizeof($sqlarr)) + } else if ($i != sizeof($sqlarr)) ADOConnection::outp( "Input array does not match ?: ".htmlspecialchars($sql)); - + $ret =& $this->_Execute($sql); if (!$ret) return $ret; - } + } } else { if ($array_2d) { if (is_string($sql)) $stmt = $this->Prepare($sql); else $stmt = $sql; - + foreach($inputarr as $arr) { $ret =& $this->_Execute($stmt,$arr); if (!$ret) return $ret; @@ -857,8 +857,8 @@ return $ret; } - - + + function &_Execute($sql,$inputarr=false) { @@ -869,26 +869,26 @@ } else { $this->_queryID = @$this->_query($sql,$inputarr); } - + /************************ // OK, query executed *************************/ if ($this->_queryID === false) { // error handling if query fails - if ($this->debug == 99) adodb_backtrace(true,5); + if ($this->debug == 99) adodb_backtrace(true,5); $fn = $this->raiseErrorFn; if ($fn) { $fn($this->databaseType,'EXECUTE',$this->ErrorNo(),$this->ErrorMsg(),$sql,$inputarr,$this); - } + } $false = false; return $false; - } - + } + if ($this->_queryID === true) { // return simplified recordset for inserts/updates/deletes with lower overhead $rs =& new ADORecordSet_empty(); return $rs; } - + // return real recordset from select statement $rsclass = $this->rsPrefix.$this->databaseType; $rs = new $rsclass($this->_queryID,$this->fetchMode); @@ -899,7 +899,7 @@ if ($rs->_numOfRows <= 0) { global $ADODB_COUNTRECS; if ($ADODB_COUNTRECS) { - if (!$rs->EOF) { + if (!$rs->EOF) { $rs = &$this->_rs2rs($rs,-1,-1,!is_array($sql)); $rs->_queryID = $this->_queryID; } else @@ -934,16 +934,16 @@ if (!$this->hasGenID) { return 0; // formerly returns false pre 1.60 } - + $getnext = sprintf($this->_genIDSQL,$seqname); - + $holdtransOK = $this->_transOK; - + $save_handler = $this->raiseErrorFn; $this->raiseErrorFn = ''; @($rs = $this->Execute($getnext)); $this->raiseErrorFn = $save_handler; - + if (!$rs) { $this->_transOK = $holdtransOK; //if the status was ok before reset $createseq = $this->Execute(sprintf($this->_genSeqSQL,$seqname,$startID)); @@ -951,17 +951,17 @@ } if ($rs && !$rs->EOF) $this->genID = reset($rs->fields); else $this->genID = 0; // false - + if ($rs) $rs->Close(); return $this->genID; - } + } /** * @param $table string name of the table, not needed by all databases (eg. mysql), default '' * @param $column string name of the column, not needed by all databases (eg. mysql), default '' * @return the last inserted ID. Not all databases support this. - */ + */ function Insert_ID($table='',$column='') { if ($this->_logsql && $this->lastInsID) return $this->lastInsID; @@ -979,8 +979,8 @@ * * @return the last inserted ID. All databases support this. But aware possible * problems in multiuser environments. Heavy test this before deploying. - */ - function PO_Insert_ID($table="", $id="") + */ + function PO_Insert_ID($table="", $id="") { if ($this->hasInsertID){ return $this->Insert_ID($table,$id); @@ -991,7 +991,7 @@ /** * @return # rows affected by UPDATE/DELETE - */ + */ function Affected_Rows() { if ($this->hasAffectedRows) { @@ -1001,12 +1001,12 @@ $val = $this->_affectedrows(); return ($val < 0) ? false : $val; } - + if ($this->debug) ADOConnection::outp( '

Affected_Rows error

',false); return false; } - - + + /** * @return the last error message */ @@ -1015,29 +1015,29 @@ if ($this->_errorMsg) return '!! '.strtoupper($this->dataProvider.' '.$this->databaseType).': '.$this->_errorMsg; else return ''; } - - + + /** * @return the last error number. Normally 0 means no error. */ - function ErrorNo() + function ErrorNo() { return ($this->_errorMsg) ? -1 : 0; } - + function MetaError($err=false) { include_once(ADODB_DIR."/adodb-error.inc.php"); if ($err === false) $err = $this->ErrorNo(); return adodb_error($this->dataProvider,$this->databaseType,$err); } - + function MetaErrorMsg($errno) { include_once(ADODB_DIR."/adodb-error.inc.php"); return adodb_errormsg($errno); } - + /** * @returns an array with the primary key columns in it. */ @@ -1057,7 +1057,7 @@ return ADODB_VIEW_PRIMARYKEYS($this->databaseType, $this->database, $table, $owner); return false; } - + /** * @returns assoc array where keys are tables, and values are foreign keys */ @@ -1071,16 +1071,16 @@ * @param dbName is the name of the database to select * @return true or false */ - function SelectDB($dbName) + function SelectDB($dbName) {return false;} - - + + /** - * Will select, getting rows from $offset (1-based), for $nrows. + * Will select, getting rows from $offset (1-based), for $nrows. * This simulates the MySQL "select * from table limit $offset,$nrows" , and * the PostgreSQL "select * from table limit $nrows offset $offset". Note that * MySQL and PostgreSQL parameter ordering is the opposite of the other. - * eg. + * eg. * SelectLimit('select * from table',3); will return rows 1 to 3 (1-based) * SelectLimit('select * from table',3,2); will return rows 3 to 5 (1-based) * @@ -1097,14 +1097,14 @@ function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) { if ($this->hasTop && $nrows > 0) { - // suggested by Reinhard Balling. Access requires top after distinct + // suggested by Reinhard Balling. Access requires top after distinct // Informix requires first before distinct - F Riosa $ismssql = (strpos($this->databaseType,'mssql') !== false); if ($ismssql) $isaccess = false; else $isaccess = (strpos($this->databaseType,'access') !== false); - + if ($offset <= 0) { - + // access includes ties in result if ($isaccess) { $sql = preg_replace( @@ -1134,14 +1134,14 @@ } } } - + // if $offset>0, we want to skip rows, and $ADODB_COUNTRECS is set, we buffer rows // 0 to offset-1 which will be discarded anyway. So we disable $ADODB_COUNTRECS. global $ADODB_COUNTRECS; - + $savec = $ADODB_COUNTRECS; $ADODB_COUNTRECS = false; - + if ($offset>0){ if ($secs2cache>0) $rs = &$this->CacheExecute($secs2cache,$sql,$inputarr); else $rs = &$this->Execute($sql,$inputarr); @@ -1156,7 +1156,7 @@ //print_r($rs); return $rs; } - + /** * Create serializable recordset. Breaks rs link to connection. * @@ -1167,10 +1167,10 @@ $rs2 =& $this->_rs2rs($rs); $ignore = false; $rs2->connection =& $ignore; - + return $rs2; } - + /** * Convert database recordset to an array recordset * input recordset's cursor should be at beginning, and @@ -1205,9 +1205,9 @@ $arr =& $rs->GetArrayLimit($nrows,$offset); //print_r($arr); if ($close) $rs->Close(); - + $arrayClass = $this->arrayClass; - + $rs2 = new $arrayClass(); $rs2->connection = &$this; $rs2->sql = $rs->sql; @@ -1216,7 +1216,7 @@ $rs2->fetchMode = isset($rs->adodbFetchMode) ? $rs->adodbFetchMode : $rs->fetchMode; return $rs2; } - + /* * Return all rows. Compat with PEAR DB */ @@ -1225,7 +1225,7 @@ $arr =& $this->GetArray($sql,$inputarr); return $arr; } - + function &GetAssoc($sql, $inputarr=false,$force_array = false, $first2cols = false) { $rs =& $this->Execute($sql, $inputarr); @@ -1236,7 +1236,7 @@ $arr =& $rs->GetAssoc($force_array,$first2cols); return $arr; } - + function &CacheGetAssoc($secs2cache, $sql=false, $inputarr=false,$force_array = false, $first2cols = false) { if (!is_numeric($secs2cache)) { @@ -1251,7 +1251,7 @@ $arr =& $rs->GetAssoc($force_array,$first2cols); return $arr; } - + /** * Return first element of first row of sql statement. Recordset is disposed * for you. @@ -1264,29 +1264,29 @@ global $ADODB_COUNTRECS; $crecs = $ADODB_COUNTRECS; $ADODB_COUNTRECS = false; - + $ret = false; $rs = &$this->Execute($sql,$inputarr); - if ($rs) { + if ($rs) { if (!$rs->EOF) $ret = reset($rs->fields); $rs->Close(); } $ADODB_COUNTRECS = $crecs; return $ret; } - + function CacheGetOne($secs2cache,$sql=false,$inputarr=false) { $ret = false; $rs = &$this->CacheExecute($secs2cache,$sql,$inputarr); - if ($rs) { + if ($rs) { if (!$rs->EOF) $ret = reset($rs->fields); $rs->Close(); - } - + } + return $ret; } - + function GetCol($sql, $inputarr = false, $trim = false) { $rv = false; @@ -1308,7 +1308,7 @@ } return $rv; } - + function CacheGetCol($secs, $sql = false, $inputarr = false,$trim=false) { $rv = false; @@ -1329,21 +1329,21 @@ } return $rv; } - + /* Calculate the offset of a date for a particular database and generate appropriate SQL. Useful for calculating future/past dates and storing in a database. - + If dayFraction=1.5 means 1.5 days from now, 1.0/24 for 1 hour. */ function OffsetDate($dayFraction,$date=false) - { + { if (!$date) $date = $this->sysDate; return '('.$date.'+'.$dayFraction.')'; } - - + + /** * * @param sql SQL statement @@ -1352,12 +1352,12 @@ function &GetArray($sql,$inputarr=false) { global $ADODB_COUNTRECS; - + $savec = $ADODB_COUNTRECS; $ADODB_COUNTRECS = false; $rs =& $this->Execute($sql,$inputarr); $ADODB_COUNTRECS = $savec; - if (!$rs) + if (!$rs) if (defined('ADODB_PEAR')) return ADODB_PEAR_Error(); else { $false = false; @@ -1367,22 +1367,22 @@ $rs->Close(); return $arr; } - + function &CacheGetAll($secs2cache,$sql=false,$inputarr=false) { return $this->CacheGetArray($secs2cache,$sql,$inputarr); } - + function &CacheGetArray($secs2cache,$sql=false,$inputarr=false) { global $ADODB_COUNTRECS; - + $savec = $ADODB_COUNTRECS; $ADODB_COUNTRECS = false; $rs =& $this->CacheExecute($secs2cache,$sql,$inputarr); $ADODB_COUNTRECS = $savec; - - if (!$rs) + + if (!$rs) if (defined('ADODB_PEAR')) return ADODB_PEAR_Error(); else { $false = false; @@ -1392,9 +1392,9 @@ $rs->Close(); return $arr; } - - - + + + /** * Return one row of sql statement. Recordset is disposed for you. * @@ -1406,9 +1406,9 @@ global $ADODB_COUNTRECS; $crecs = $ADODB_COUNTRECS; $ADODB_COUNTRECS = false; - + $rs =& $this->Execute($sql,$inputarr); - + $ADODB_COUNTRECS = $crecs; if ($rs) { if (!$rs->EOF) $arr = $rs->fields; @@ -1416,11 +1416,11 @@ $rs->Close(); return $arr; } - + $false = false; return $false; } - + function &CacheGetRow($secs2cache,$sql=false,$inputarr=false) { $rs =& $this->CacheExecute($secs2cache,$sql,$inputarr); @@ -1433,9 +1433,9 @@ $false = false; return $false; } - + /** - * Insert or replace a single record. Note: this is not the same as MySQL's replace. + * Insert or replace a single record. Note: this is not the same as MySQL's replace. * ADOdb's Replace() uses update-insert semantics, not insert-delete-duplicates of MySQL. * Also note that no table locking is done currently, so it is possible that the * record be inserted twice by two programs... @@ -1451,24 +1451,24 @@ * * Currently blob replace not supported * - * returns 0 = fail, 1 = update, 2 = insert + * returns 0 = fail, 1 = update, 2 = insert */ - + function Replace($table, $fieldArray, $keyCol, $autoQuote=false, $has_autoinc=false) { global $ADODB_INCLUDED_LIB; if (empty($ADODB_INCLUDED_LIB)) include_once(ADODB_DIR.'/adodb-lib.inc.php'); - + return _adodb_replace($this, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc); } - - + + /** - * Will select, getting rows from $offset (1-based), for $nrows. + * Will select, getting rows from $offset (1-based), for $nrows. * This simulates the MySQL "select * from table limit $offset,$nrows" , and * the PostgreSQL "select * from table limit $nrows offset $offset". Note that * MySQL and PostgreSQL parameter ordering is the opposite of the other. - * eg. + * eg. * CacheSelectLimit(15,'select * from table',3); will return rows 1 to 3 (1-based) * CacheSelectLimit(15,'select * from table',3,2); will return rows 3 to 5 (1-based) * @@ -1482,7 +1482,7 @@ * @return the recordset ($rs->databaseType == 'array') */ function &CacheSelectLimit($secs2cache,$sql,$nrows=-1,$offset=-1,$inputarr=false) - { + { if (!is_numeric($secs2cache)) { if ($sql === false) $sql = -1; if ($offset == -1) $offset = false; @@ -1494,21 +1494,21 @@ } return $rs; } - + /** - * Flush cached recordsets that match a particular $sql statement. + * Flush cached recordsets that match a particular $sql statement. * If $sql == false, then we purge all files in the cache. */ function CacheFlush($sql=false,$inputarr=false) { global $ADODB_CACHE_DIR; - + if (strlen($ADODB_CACHE_DIR) > 1 && !$sql) { if (strncmp(PHP_OS,'WIN',3) === 0) { $cmd = 'del /s '.str_replace('/','\\',$ADODB_CACHE_DIR).'\adodb_*.cache'; } else { //$cmd = 'find "'.$ADODB_CACHE_DIR.'" -type f -maxdepth 1 -print0 | xargs -0 rm -f'; - $cmd = 'rm -rf '.$ADODB_CACHE_DIR.'/[0-9a-f][0-9a-f]/'; + $cmd = 'rm -rf '.$ADODB_CACHE_DIR.'/[0-9a-f][0-9a-f]/'; // old version 'rm -f `find '.$ADODB_CACHE_DIR.' -name adodb_*.cache`'; } if ($this->debug) { @@ -1517,18 +1517,18 @@ exec($cmd); } return; - } - + } + global $ADODB_INCLUDED_CSV; if (empty($ADODB_INCLUDED_CSV)) include_once(ADODB_DIR.'/adodb-csvlib.inc.php'); - + $f = $this->_gencachename($sql.serialize($inputarr),false); adodb_write_file($f,''); // is adodb_write_file needed? if (!@unlink($f)) { if ($this->debug) ADOConnection::outp( "CacheFlush: failed for $f"); } } - + /** * Private function to generate filename for caching. * Filename is generated based on: @@ -1539,40 +1539,40 @@ * - userid * - setFetchMode (adodb 4.23) * - * When not in safe mode, we create 256 sub-directories in the cache directory ($ADODB_CACHE_DIR). - * Assuming that we can have 50,000 files per directory with good performance, + * When not in safe mode, we create 256 sub-directories in the cache directory ($ADODB_CACHE_DIR). + * Assuming that we can have 50,000 files per directory with good performance, * then we can scale to 12.8 million unique cached recordsets. Wow! */ function _gencachename($sql,$createdir) { global $ADODB_CACHE_DIR; static $notSafeMode; - - if ($this->fetchMode === false) { + + if ($this->fetchMode === false) { global $ADODB_FETCH_MODE; $mode = $ADODB_FETCH_MODE; } else { $mode = $this->fetchMode; } $m = md5($sql.$this->databaseType.$this->database.$this->user.$mode); - + if (!isset($notSafeMode)) $notSafeMode = !ini_get('safe_mode'); $dir = ($notSafeMode) ? $ADODB_CACHE_DIR.'/'.substr($m,0,2) : $ADODB_CACHE_DIR; - + if ($createdir && $notSafeMode && !file_exists($dir)) { $oldu = umask(0); - if (!mkdir($dir,0771)) + if (!mkdir($dir,0771)) if ($this->debug) ADOConnection::outp( "Unable to mkdir $dir for $sql"); umask($oldu); } return $dir.'/adodb_'.$m.'.cache'; } - - + + /** * Execute SQL, caching recordsets. * - * @param [secs2cache] seconds to cache data, set to 0 to force query. + * @param [secs2cache] seconds to cache data, set to 0 to force query. * This is an optional parameter. * @param sql SQL statement to execute * @param [inputarr] holds the input data to bind to @@ -1581,25 +1581,25 @@ function &CacheExecute($secs2cache,$sql=false,$inputarr=false) { - + if (!is_numeric($secs2cache)) { $inputarr = $sql; $sql = $secs2cache; $secs2cache = $this->cacheSecs; } - + if (is_array($sql)) { $sqlparam = $sql; $sql = $sql[0]; } else $sqlparam = $sql; - + global $ADODB_INCLUDED_CSV; if (empty($ADODB_INCLUDED_CSV)) include_once(ADODB_DIR.'/adodb-csvlib.inc.php'); - + $md5file = $this->_gencachename($sql.serialize($inputarr),true); $err = ''; - + if ($secs2cache > 0){ $rs = &csv2rs($md5file,$err,$secs2cache,$this->arrayClass); $this->numCacheHits += 1; @@ -1616,14 +1616,14 @@ } if ($this->debug !== -1) ADOConnection::outp( " $md5file cache failure: $err (see sql below)"); } - + $rs = &$this->Execute($sqlparam,$inputarr); if ($rs) { $eof = $rs->EOF; $rs = &$this->_rs2rs($rs); // read entire recordset into memory immediately $txt = _rs2serialize($rs,false,$sql); // serialize - + if (!adodb_write_file($md5file,$txt,$this->debug)) { if ($fn = $this->raiseErrorFn) { $fn($this->databaseType,'CacheExecute',-32000,"Cache write error",$md5file,$sql,$this); @@ -1632,46 +1632,46 @@ } if ($rs->EOF && !$eof) { $rs->MoveFirst(); - //$rs = &csv2rs($md5file,$err); + //$rs = &csv2rs($md5file,$err); $rs->connection = &$this; // Pablo suggestion - } - + } + } else @unlink($md5file); } else { $this->_errorMsg = ''; $this->_errorCode = 0; - + if ($this->fnCacheExecute) { $fn = $this->fnCacheExecute; $fn($this, $secs2cache, $sql, $inputarr); } // ok, set cached object found $rs->connection = &$this; // Pablo suggestion - if ($this->debug){ - + if ($this->debug){ + $inBrowser = isset($_SERVER['HTTP_USER_AGENT']); $ttl = $rs->timeCreated + $secs2cache - time(); $s = is_array($sql) ? $sql[0] : $sql; if ($inBrowser) $s = ''.htmlspecialchars($s).''; - + ADOConnection::outp( " $md5file reloaded, ttl=$ttl [ $s ]"); } } return $rs; } - - - /* - Similar to PEAR DB's autoExecute(), except that + + + /* + Similar to PEAR DB's autoExecute(), except that $mode can be 'INSERT' or 'UPDATE' or DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE If $mode == 'UPDATE', then $where is compulsory as a safety measure. - + $forceUpdate means that even if the data has not changed, perform update. */ - function& AutoExecute($table, $fields_values, $mode = 'INSERT', $where = FALSE, $forceUpdate=true, $magicq=false) + function& AutoExecute($table, $fields_values, $mode = 'INSERT', $where = FALSE, $forceUpdate=true, $magicq=false) { - $sql = 'SELECT * FROM '.$table; + $sql = 'SELECT * FROM '.$table; if ($where!==FALSE) $sql .= ' WHERE '.$where; else if ($mode == 'UPDATE') { ADOConnection::outp('AutoExecute: Illegal mode=UPDATE with empty WHERE clause'); @@ -1681,7 +1681,7 @@ $rs =& $this->SelectLimit($sql,1); if (!$rs) return false; // table does not exist $rs->tableName = $table; - + switch((string) $mode) { case 'UPDATE': case '2': @@ -1700,15 +1700,15 @@ if ($ret) $ret = true; return $ret; } - - + + /** * Generates an Update Query based on an existing recordset. * $arrFields is an associative array of fields with the value * that should be assigned. * * Note: This function should only be used on a recordset - * that is run against a single table and sql should only + * that is run against a single table and sql should only * be a simple select stmt with no groupby/orderby/limit * * "Jonathan Younger" @@ -1730,8 +1730,8 @@ return _adodb_getupdatesql($this,$rs,$arrFields,$forceUpdate,$magicq,$force); } - - + + /** * Generates an Insert Query based on an existing recordset. @@ -1742,27 +1742,27 @@ * that is run against a single table. */ function GetInsertSQL(&$rs, $arrFields,$magicq=false,$force=null) - { + { global $ADODB_INCLUDED_LIB; if (!isset($force)) { global $ADODB_FORCE_TYPE; $force = $ADODB_FORCE_TYPE; - + } if (empty($ADODB_INCLUDED_LIB)) include_once(ADODB_DIR.'/adodb-lib.inc.php'); return _adodb_getinsertsql($this,$rs,$arrFields,$magicq,$force); } - + /** * Update a blob column, given a where clause. There are more sophisticated * blob handling functions that we could have implemented, but all require * a very complex API. Instead we have chosen something that is extremely - * simple to understand and use. + * simple to understand and use. * * Note: $blobtype supports 'BLOB' and 'CLOB', default is BLOB of course. * - * Usage to update a $blobvalue which has a primary key blob_id=1 into a + * Usage to update a $blobvalue which has a primary key blob_id=1 into a * field blobtable.blobcolumn: * * UpdateBlob('blobtable', 'blobcolumn', $blobvalue, 'blob_id=1'); @@ -1772,7 +1772,7 @@ * $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)'); * $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1'); */ - + function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB') { return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false; @@ -1781,7 +1781,7 @@ /** * Usage: * UpdateBlob('TABLE', 'COLUMN', '/path/to/file', 'ID=1'); - * + * * $blobtype supports 'BLOB' and 'CLOB' * * $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)'); @@ -1795,45 +1795,45 @@ fclose($fd); return $this->UpdateBlob($table,$column,$val,$where,$blobtype); } - + function BlobDecode($blob) { return $blob; } - + function BlobEncode($blob) { return $blob; } - + function SetCharSet($charset) { return false; } - - function IfNull( $field, $ifNull ) + + function IfNull( $field, $ifNull ) { return " CASE WHEN $field is null THEN $ifNull ELSE $field END "; } - + function LogSQL($enable=true) { include_once(ADODB_DIR.'/adodb-perf.inc.php'); - + if ($enable) $this->fnExecute = 'adodb_log_sql'; else $this->fnExecute = false; - - $old = $this->_logsql; + + $old = $this->_logsql; $this->_logsql = $enable; if ($enable && !$old) $this->_affected = false; return $old; } - + function GetCharSet() { return false; } - + /** * Usage: * UpdateClob('TABLE', 'COLUMN', $var, 'ID=1', 'CLOB'); @@ -1845,21 +1845,21 @@ { return $this->UpdateBlob($table,$column,$val,$where,'CLOB'); } - + // not the fastest implementation - quick and dirty - jlim // for best performance, use the actual $rs->MetaType(). function MetaType($t,$len=-1,$fieldobj=false) { - + if (empty($this->_metars)) { $rsclass = $this->rsPrefix.$this->databaseType; - $this->_metars =& new $rsclass(false,$this->fetchMode); + $this->_metars =& new $rsclass(false,$this->fetchMode); } - + return $this->_metars->MetaType($t,$len,$fieldobj); } - - + + /** * Change the SQL connection locale to a specified locale. * This is used to get the date formats written depending on the client locale. @@ -1873,12 +1873,12 @@ $this->fmtDate="'Y-m-d'"; $this->fmtTimeStamp = "'Y-m-d H:i:s'"; break; - + case 'US': $this->fmtDate = "'m-d-Y'"; $this->fmtTimeStamp = "'m-d-Y H:i:s'"; break; - + case 'NL': case 'FR': case 'RO': @@ -1886,12 +1886,12 @@ $this->fmtDate="'d-m-Y'"; $this->fmtTimeStamp = "'d-m-Y H:i:s'"; break; - + case 'GE': $this->fmtDate="'d.m.Y'"; $this->fmtTimeStamp = "'d.m.Y H:i:s'"; break; - + default: $this->fmtDate="'Y-m-d'"; $this->fmtTimeStamp = "'Y-m-d H:i:s'"; @@ -1899,7 +1899,7 @@ } } - + /** * Close Connection */ @@ -1909,15 +1909,15 @@ $this->_connectionID = false; return $rez; } - + /** * Begin a Transaction. Must be followed by CommitTrans() or RollbackTrans(). * * @return true if succeeded or false if database does not support transactions */ function BeginTrans() {return false;} - - + + /** * If database does not support transactions, always return true as data always commited * @@ -1925,47 +1925,47 @@ * * @return true/false. */ - function CommitTrans($ok=true) + function CommitTrans($ok=true) { return true;} - - + + /** * If database does not support transactions, rollbacks always fail, so return false * * @return true/false. */ - function RollbackTrans() + function RollbackTrans() { return false;} /** - * return the databases that the driver can connect to. + * return the databases that the driver can connect to. * Some databases will return an empty array. * * @return an array of database names. */ - function MetaDatabases() + function MetaDatabases() { global $ADODB_FETCH_MODE; - + if ($this->metaDatabasesSQL) { - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false); - + $arr = $this->GetCol($this->metaDatabasesSQL); if (isset($savem)) $this->SetFetchMode($savem); - $ADODB_FETCH_MODE = $save; - + $ADODB_FETCH_MODE = $save; + return $arr; } - + return false; } - + /** - * @param ttype can either be 'VIEW' or 'TABLE' or false. + * @param ttype can either be 'VIEW' or 'TABLE' or false. * If false, both views and tables are returned. * "VIEW" returns only views * "TABLE" returns only tables @@ -1973,34 +1973,34 @@ * @param mask is the input mask - only supported by oci8 and postgresql * * @return array of tables for current database. - */ - function &MetaTables($ttype=false,$showSchema=false,$mask=false) + */ + function &MetaTables($ttype=false,$showSchema=false,$mask=false) { global $ADODB_FETCH_MODE; - - + + $false = false; if ($mask) { return $false; } if ($this->metaTablesSQL) { - $save = $ADODB_FETCH_MODE; - $ADODB_FETCH_MODE = ADODB_FETCH_NUM; - + $save = $ADODB_FETCH_MODE; + $ADODB_FETCH_MODE = ADODB_FETCH_NUM; + if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false); - + $rs = $this->Execute($this->metaTablesSQL); if (isset($savem)) $this->SetFetchMode($savem); - $ADODB_FETCH_MODE = $save; - + $ADODB_FETCH_MODE = $save; + if ($rs === false) return $false; $arr =& $rs->GetArray(); $arr2 = array(); - - if ($hast = ($ttype && isset($arr[0][1]))) { + + if ($hast = ($ttype && isset($arr[0][1]))) { $showt = strncmp($ttype,'T',1); } - + for ($i=0; $i < sizeof($arr); $i++) { if ($hast) { if ($showt == 0) { @@ -2016,8 +2016,8 @@ } return $false; } - - + + function _findschema(&$table,&$schema) { if (!$schema && ($at = strpos($table,'.')) !== false) { @@ -2025,9 +2025,9 @@ $table = substr($table,$at+1); } } - + /** - * List columns in a database as an array of ADOFieldObjects. + * List columns in a database as an array of ADOFieldObjects. * See top of file for definition of object. * * @param table table name to query @@ -2036,17 +2036,17 @@ * * @return array of ADOFieldObjects for current table. */ - function &MetaColumns($table,$upper=true) + function &MetaColumns($table,$upper=true) { global $ADODB_FETCH_MODE; - + $false = false; - + if (!empty($this->metaColumnsSQL)) { - + $schema = false; $this->_findschema($table,$schema); - + $save = $ADODB_FETCH_MODE; $ADODB_FETCH_MODE = ADODB_FETCH_NUM; if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false); @@ -2066,24 +2066,24 @@ if ($fld->scale>0) $fld->max_length += 1; } else $fld->max_length = $rs->fields[2]; - - if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld; + + if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld; else $retarr[strtoupper($fld->name)] = $fld; $rs->MoveNext(); } $rs->Close(); - return $retarr; + return $retarr; } return $false; } - + /** * List indexes on a table as an array. * @param table table name to query * @param primary true to only show primary keys. Not actually used for most databases * * @return array of indexes on current table. Each element represents an index, and is itself an associative array. - + Array ( [name_of_index] => Array ( @@ -2093,7 +2093,7 @@ [0] => firstname [1] => lastname ) - ) + ) */ function &MetaIndexes($table, $primary = false, $owner = false) { @@ -2102,12 +2102,12 @@ } /** - * List columns names in a table as an array. + * List columns names in a table as an array. * @param table table name to query * * @return array of column names for current table. - */ - function &MetaColumnNames($table, $numIndexes=false) + */ + function &MetaColumnNames($table, $numIndexes=false) { $objarr =& $this->MetaColumns($table); if (!is_array($objarr)) { @@ -2120,27 +2120,27 @@ foreach($objarr as $v) $arr[$i++] = $v->name; } else foreach($objarr as $v) $arr[strtoupper($v->name)] = $v->name; - + return $arr; } - + /** * Different SQL databases used different methods to combine strings together. - * This function provides a wrapper. - * + * This function provides a wrapper. + * * param s variable number of string parameters * * Usage: $db->Concat($str1,$str2); - * + * * @return concatenated string - */ + */ function Concat() - { + { $arr = func_get_args(); return implode($this->concat_operator, $arr); } - - + + /** * Converts a date "d" to a string that the database can understand. * @@ -2160,8 +2160,8 @@ return adodb_date($this->fmtDate,$d); } - - + + /** * Converts a timestamp "ts" to a string that the database can understand. * @@ -2174,16 +2174,16 @@ if (empty($ts) && $ts !== 0) return 'null'; # strlen(14) allows YYYYMMDDHHMMSS format - if (!is_string($ts) || (is_numeric($ts) && strlen($ts)<14)) + if (!is_string($ts) || (is_numeric($ts) && strlen($ts)<14)) return adodb_date($this->fmtTimeStamp,$ts); - + if ($ts === 'null') return $ts; if ($this->isoDates && strlen($ts) !== 14) return "'$ts'"; - + $ts = ADOConnection::UnixTimeStamp($ts); return adodb_date($this->fmtTimeStamp,$ts); } - + /** * Also in ADORecordSet. * @param $v is a date string in YYYY-MM-DD format @@ -2197,16 +2197,16 @@ //( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 ) return adodb_mktime($v->hour,$v->minute,$v->second,$v->month,$v->day, $v->year); } - + if (is_numeric($v) && strlen($v) !== 8) return $v; - if (!preg_match( "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})|", + if (!preg_match( "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})|", ($v), $rr)) return false; if ($rr[1] <= TIMESTAMP_FIRST_YEAR) return 0; // h-m-s-MM-DD-YY return @adodb_mktime(0,0,0,$rr[2],$rr[3],$rr[1]); } - + /** * Also in ADORecordSet. @@ -2221,18 +2221,18 @@ //( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 ) return adodb_mktime($v->hour,$v->minute,$v->second,$v->month,$v->day, $v->year); } - - if (!preg_match( - "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ ,-]*(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", + + if (!preg_match( + "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ ,-]*(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|", ($v), $rr)) return false; - + if ($rr[1] <= TIMESTAMP_FIRST_YEAR && $rr[2]<= 1) return 0; - + // h-m-s-MM-DD-YY if (!isset($rr[5])) return adodb_mktime(0,0,0,$rr[2],$rr[3],$rr[1]); return @adodb_mktime($rr[5],$rr[6],$rr[7],$rr[2],$rr[3],$rr[1]); } - + /** * Also in ADORecordSet. * @@ -2243,7 +2243,7 @@ * * @return a date formated as user desires */ - + function UserDate($v,$fmt='Y-m-d',$gmt=false) { $tt = $this->UnixDate($v); @@ -2253,11 +2253,11 @@ else if ($tt == 0) return $this->emptyDate; else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR } - + return ($gmt) ? adodb_gmdate($fmt,$tt) : adodb_date($fmt,$tt); - + } - + /** * * @param v is the character timestamp in YYYY-MM-DD hh:mm:ss format @@ -2276,19 +2276,19 @@ if ($tt == 0) return $this->emptyTimeStamp; return ($gmt) ? adodb_gmdate($fmt,$tt) : adodb_date($fmt,$tt); } - + function escape($s,$magic_quotes=false) { return $this->addq($s,$magic_quotes); } - + /** - * Quotes a string, without prefixing nor appending quotes. + * Quotes a string, without prefixing nor appending quotes. */ function addq($s,$magic_quotes=false) { if (!$magic_quotes) { - + if ($this->replaceQuote[0] == '\\'){ // only since php 4.0.5 $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s); @@ -2296,10 +2296,10 @@ } return str_replace("'",$this->replaceQuote,$s); } - + // undo magic quotes for " $s = str_replace('\\"','"',$s); - + if ($this->replaceQuote == "\\'") // ' already quoted, no need to change anything return $s; else {// change \' to '' for sybase/mssql @@ -2307,12 +2307,12 @@ return str_replace("\\'",$this->replaceQuote,$s); } } - + /** * Correctly quotes a string so that all strings are escaped. We prefix and append * to the string single-quotes. * An example is $db->qstr("Don't bother",magic_quotes_runtime()); - * + * * @param s the string to quote * @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc(). * This undoes the stupidity of magic quotes for GPC. @@ -2320,9 +2320,9 @@ * @return quoted string to be sent back to database */ function qstr($s,$magic_quotes=false) - { + { if (!$magic_quotes) { - + if ($this->replaceQuote[0] == '\\'){ // only since php 4.0.5 $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s); @@ -2330,10 +2330,10 @@ } return "'".str_replace("'",$this->replaceQuote,$s)."'"; } - + // undo magic quotes for " $s = str_replace('\\"','"',$s); - + if ($this->replaceQuote == "\\'") // ' already quoted, no need to change anything return "'$s'"; else {// change \' to '' for sybase/mssql @@ -2341,11 +2341,11 @@ return "'".str_replace("\\'",$this->replaceQuote,$s)."'"; } } - - + + /** - * Will select the supplied $page number from a recordset, given that it is paginated in pages of - * $nrows rows per page. It also saves two boolean values saying if the given page is the first + * Will select the supplied $page number from a recordset, given that it is paginated in pages of + * $nrows rows per page. It also saves two boolean values saying if the given page is the first * and/or last one of the recordset. Added by Iv�n Oliva to provide recordset pagination. * * See readme.htm#ex8 for an example of usage. @@ -2360,7 +2360,7 @@ * NOTE: phpLens uses a different algorithm and does not use PageExecute(). * */ - function &PageExecute($sql, $nrows, $page, $inputarr=false, $secs2cache=0) + function &PageExecute($sql, $nrows, $page, $inputarr=false, $secs2cache=0) { global $ADODB_INCLUDED_LIB; if (empty($ADODB_INCLUDED_LIB)) include_once(ADODB_DIR.'/adodb-lib.inc.php'); @@ -2368,11 +2368,11 @@ else $rs =& _adodb_pageexecute_no_last_page($this, $sql, $nrows, $page, $inputarr, $secs2cache); return $rs; } - - + + /** - * Will select the supplied $page number from a recordset, given that it is paginated in pages of - * $nrows rows per page. It also saves two boolean values saying if the given page is the first + * Will select the supplied $page number from a recordset, given that it is paginated in pages of + * $nrows rows per page. It also saves two boolean values saying if the given page is the first * and/or last one of the recordset. Added by Iv�n Oliva to provide recordset pagination. * * @param secs2cache seconds to cache data, set to 0 to force query @@ -2382,11 +2382,11 @@ * @param [inputarr] array of bind variables * @return the recordset ($rs->databaseType == 'array') */ - function &CachePageExecute($secs2cache, $sql, $nrows, $page,$inputarr=false) + function &CachePageExecute($secs2cache, $sql, $nrows, $page,$inputarr=false) { /*switch($this->dataProvider) { case 'postgres': - case 'mysql': + case 'mysql': break; default: $secs2cache = 0; break; }*/ @@ -2395,23 +2395,23 @@ } } // end class ADOConnection - - - - //============================================================================================== + + + + //============================================================================================== // CLASS ADOFetchObj - //============================================================================================== - + //============================================================================================== + /** * Internal placeholder for record objects. Used by ADORecordSet->FetchObj(). */ class ADOFetchObj { }; - - //============================================================================================== + + //============================================================================================== // CLASS ADORecordSet_empty - //============================================================================================== - + //============================================================================================== + /** * Lightweight recordset when there are no records to be returned */ @@ -2431,15 +2431,15 @@ function FieldCount(){ return 0;} function Init() {} } - - //============================================================================================== + + //============================================================================================== // DATE AND TIME FUNCTIONS - //============================================================================================== + //============================================================================================== include_once(ADODB_DIR.'/adodb-time.inc.php'); - - //============================================================================================== + + //============================================================================================== // CLASS ADORecordSet - //============================================================================================== + //============================================================================================== if (PHP_VERSION < 5) include_once(ADODB_DIR.'/adodb-php4.inc.php'); else include_once(ADODB_DIR.'/adodb-iterator.inc.php'); @@ -2451,7 +2451,7 @@ */ class ADORecordSet extends ADODB_BASE_RS { /* - * public variables + * public variables */ var $dataProvider = "native"; var $fields = false; /// holds the current row data @@ -2459,8 +2459,8 @@ /// in other words, we use a text area for editing. var $canSeek = false; /// indicates that seek is supported var $sql; /// sql text - var $EOF = false; /// Indicates that the current record position is after the last record in a Recordset object. - + var $EOF = false; /// Indicates that the current record position is after the last record in a Recordset object. + var $emptyTimeStamp = ' '; /// what to display when $time==0 var $emptyDate = ' '; /// what to display when $time==0 var $debug = false; @@ -2470,7 +2470,7 @@ var $fetchMode; /// default fetch mode var $connection = false; /// the parent connection /* - * private variables + * private variables */ var $_numOfRows = -1; /** number of rows, or -1 */ var $_numOfFields = -1; /** number of fields in recordset */ @@ -2480,27 +2480,27 @@ var $_inited = false; /** Init() should only be called once */ var $_obj; /** Used by FetchObj */ var $_names; /** Used by FetchObj */ - + var $_currentPage = -1; /** Added by Iv�n Oliva to implement recordset pagination */ var $_atFirstPage = false; /** Added by Iv�n Oliva to implement recordset pagination */ var $_atLastPage = false; /** Added by Iv�n Oliva to implement recordset pagination */ - var $_lastPageNo = -1; + var $_lastPageNo = -1; var $_maxRecordCount = 0; var $datetime = false; - + /** * Constructor * * @param queryID this is the queryID returned by ADOConnection->_query() * */ - function ADORecordSet($queryID) + function ADORecordSet($queryID) { $this->_queryID = $queryID; } - - - + + + function Init() { if ($this->_inited) return; @@ -2511,7 +2511,7 @@ $this->_numOfFields = 0; } if ($this->_numOfRows != 0 && $this->_numOfFields && $this->_currentRow == -1) { - + $this->_currentRow = 0; if ($this->EOF = ($this->_fetch() === false)) { $this->_numOfRows = 0; // _numOfRows could be -1 @@ -2520,11 +2520,11 @@ $this->EOF = true; } } - - + + /** * Generate a SELECT tag string from a recordset, and return the string. - * If the recordset has 2 cols, we treat the 1st col as the containing + * If the recordset has 2 cols, we treat the 1st col as the containing * the text to display to the user, and 2nd col as the return value. Default * strings are compared with the FIRST column. * @@ -2535,7 +2535,7 @@ * @param [size] #rows to show for listbox. not used by popup * @param [selectAttr] additional attributes to defined for SELECT tag. * useful for holding javascript onChange='...' handlers. - & @param [compareFields0] when we have 2 cols in recordset, we compare the defstr with + & @param [compareFields0] when we have 2 cols in recordset, we compare the defstr with * column 0 (1st col) if this is true. This is not documented. * * @return HTML @@ -2550,22 +2550,22 @@ return _adodb_getmenu($this, $name,$defstr,$blank1stItem,$multiple, $size, $selectAttr,$compareFields0); } - - + + /** * Generate a SELECT tag string from a recordset, and return the string. - * If the recordset has 2 cols, we treat the 1st col as the containing + * If the recordset has 2 cols, we treat the 1st col as the containing * the text to display to the user, and 2nd col as the return value. Default * strings are compared with the SECOND column. * */ - function GetMenu2($name,$defstr='',$blank1stItem=true,$multiple=false,$size=0, $selectAttr='') + function GetMenu2($name,$defstr='',$blank1stItem=true,$multiple=false,$size=0, $selectAttr='') { return $this->GetMenu($name,$defstr,$blank1stItem,$multiple, $size, $selectAttr,false); } - + /* Grouped Menu */ @@ -2585,10 +2585,10 @@ * * @return an array indexed by the rows (0-based) from the recordset */ - function &GetArray($nRows = -1) + function &GetArray($nRows = -1) { global $ADODB_EXTENSION; if ($ADODB_EXTENSION) return adodb_getall($this,$nRows); - + $results = array(); $cnt = 0; while (!$this->EOF && $nRows != $cnt) { @@ -2598,13 +2598,13 @@ } return $results; } - + function &GetAll($nRows = -1) { $arr =& $this->GetArray($nRows); return $arr; } - + /* * Some databases allow multiple recordsets to be returned. This function * will return true if there is a next recordset, or false if no more. @@ -2613,9 +2613,9 @@ { return false; } - + /** - * return recordset as a 2-dimensional array. + * return recordset as a 2-dimensional array. * Helper function for ADOConnection->SelectLimit() * * @param offset is the row to start calculations from (1-based) @@ -2623,26 +2623,26 @@ * * @return an array indexed by the rows (0-based) from the recordset */ - function &GetArrayLimit($nrows,$offset=-1) - { + function &GetArrayLimit($nrows,$offset=-1) + { if ($offset <= 0) { $arr =& $this->GetArray($nrows); return $arr; - } - + } + $this->Move($offset); - + $results = array(); $cnt = 0; while (!$this->EOF && $nrows != $cnt) { $results[$cnt++] = $this->fields; $this->MoveNext(); } - + return $results; } - - + + /** * Synonym for GetArray() for compatibility with ADO. * @@ -2650,15 +2650,15 @@ * * @return an array indexed by the rows (0-based) from the recordset */ - function &GetRows($nRows = -1) + function &GetRows($nRows = -1) { $arr =& $this->GetArray($nRows); return $arr; } - + /** - * return whole recordset as a 2-dimensional associative array if there are more than 2 columns. - * The first column is treated as the key and is not included in the array. + * return whole recordset as a 2-dimensional associative array if there are more than 2 columns. + * The first column is treated as the key and is not included in the array. * If there is only 2 columns, it will return a 1 dimensional array of key-value pairs unless * $force_array == true. * @@ -2666,16 +2666,16 @@ * array is returned, otherwise a 2 dimensional array is returned. If this sounds confusing, * read the source. * - * @param [first2cols] means if there are more than 2 cols, ignore the remaining cols and + * @param [first2cols] means if there are more than 2 cols, ignore the remaining cols and * instead of returning array[col0] => array(remaining cols), return array[col0] => col1 * - * @return an associative array indexed by the first column of the array, + * @return an associative array indexed by the first column of the array, * or false if the data has less than 2 cols. */ - function &GetAssoc($force_array = false, $first2cols = false) + function &GetAssoc($force_array = false, $first2cols = false) { global $ADODB_EXTENSION; - + $cols = $this->_numOfFields; if ($cols < 2) { $false = false; @@ -2683,7 +2683,7 @@ } $numIndex = isset($this->fields[0]); $results = array(); - + if (!$first2cols && ($cols > 2 || $force_array)) { if ($ADODB_EXTENSION) { if ($numIndex) { @@ -2723,7 +2723,7 @@ while (!$this->EOF) { // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string $v1 = trim(reset($this->fields)); - $v2 = ''.next($this->fields); + $v2 = ''.next($this->fields); $results[$v1] = $v2; adodb_movenext($this); } @@ -2739,17 +2739,17 @@ while (!$this->EOF) { // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string $v1 = trim(reset($this->fields)); - $v2 = ''.next($this->fields); + $v2 = ''.next($this->fields); $results[$v1] = $v2; $this->MoveNext(); } } } } - return $results; + return $results; } - - + + /** * * @param v is the character timestamp in YYYY-MM-DD hh:mm:ss format @@ -2766,8 +2766,8 @@ if ($tt === 0) return $this->emptyTimeStamp; return adodb_date($fmt,$tt); } - - + + /** * @param v is the character date in YYYY-MM-DD format, returned by database * @param fmt is the format to apply to it, using date() @@ -2784,8 +2784,8 @@ } return adodb_date($fmt,$tt); } - - + + /** * @param $v is a date string in YYYY-MM-DD format * @@ -2795,7 +2795,7 @@ { return ADOConnection::UnixDate($v); } - + /** * @param $v is a timestamp string in YYYY-MM-DD HH-NN-SS format @@ -2806,8 +2806,8 @@ { return ADOConnection::UnixTimeStamp($v); } - - + + /** * PEAR DB Compat - do not use internally */ @@ -2815,8 +2815,8 @@ { return $this->Close(); } - - + + /** * PEAR DB compat, number of rows */ @@ -2824,8 +2824,8 @@ { return $this->_numOfRows; } - - + + /** * PEAR DB compat, number of cols */ @@ -2833,9 +2833,9 @@ { return $this->_numOfFields; } - + /** - * Fetch a row, returning false if no more rows. + * Fetch a row, returning false if no more rows. * This is PEAR DB compat mode. * * @return false or array containing the current record @@ -2851,10 +2851,10 @@ if (!$this->_fetch()) $this->EOF = true; return $arr; } - - + + /** - * Fetch a row, returning PEAR_Error if no more rows. + * Fetch a row, returning PEAR_Error if no more rows. * This is PEAR DB compat mode. * * @return DB_OK or error object @@ -2866,26 +2866,26 @@ $this->MoveNext(); return 1; // DB_OK } - - + + /** * Move to the first row in the recordset. Many databases do NOT support this. * * @return true or false */ - function MoveFirst() + function MoveFirst() { if ($this->_currentRow == 0) return true; - return $this->Move(0); - } + return $this->Move(0); + } + - /** - * Move to the last row in the recordset. + * Move to the last row in the recordset. * * @return true or false */ - function MoveLast() + function MoveLast() { if ($this->_numOfRows >= 0) return $this->Move($this->_numOfRows-1); if ($this->EOF) return false; @@ -2897,14 +2897,14 @@ $this->EOF = false; return true; } - - + + /** * Move to next record in the recordset. * * @return true if there still rows available, or false if there are no more rows (EOF). */ - function MoveNext() + function MoveNext() { if (!$this->EOF) { $this->_currentRow++; @@ -2920,8 +2920,8 @@ */ return false; } - - + + /** * Random access to a specific row in the recordset. Some databases do not support * access to previous rows in the databases (no scrolling backwards). @@ -2930,15 +2930,15 @@ * * @return true if there still rows available, or false if there are no more rows (EOF). */ - function Move($rowNumber = 0) + function Move($rowNumber = 0) { $this->EOF = false; if ($rowNumber == $this->_currentRow) return true; if ($rowNumber >= $this->_numOfRows) if ($this->_numOfRows != -1) $rowNumber = $this->_numOfRows-2; - - if ($this->canSeek) { - + + if ($this->canSeek) { + if ($this->_seek($rowNumber)) { $this->_currentRow = $rowNumber; if ($this->_fetch()) { @@ -2956,26 +2956,26 @@ adodb_movenext($this); } } else { - + while (! $this->EOF && $this->_currentRow < $rowNumber) { $this->_currentRow++; - + if (!$this->_fetch()) $this->EOF = true; } } return !($this->EOF); } - - $this->fields = false; + + $this->fields = false; $this->EOF = true; return false; } - - + + /** * Get the value of a field in the current row by column name. * Will not work if ADODB_FETCH_MODE is set to ADODB_FETCH_NUM. - * + * * @param colname is the field to access * * @return the value of $colname column @@ -2984,7 +2984,7 @@ { return $this->fields[$colname]; } - + function GetAssocKeys($upper=true) { $this->bind = array(); @@ -2994,7 +2994,7 @@ else $this->bind[($upper) ? strtoupper($o->name) : strtolower($o->name)] = $i; } } - + /** * Use associative array to get fields array for databases that do not support * associative arrays. Submitted by Paolo S. Asioli paolo.asioli#libero.it @@ -3008,44 +3008,44 @@ { $record = array(); // if (!$this->fields) return $record; - + if (!$this->bind) { $this->GetAssocKeys($upper); } - + foreach($this->bind as $k => $v) { $record[$k] = $this->fields[$v]; } return $record; } - - + + /** * Clean up recordset * * @return true or false */ - function Close() + function Close() { // free connection object - this seems to globally free the object // and not merely the reference, so don't do this... - // $this->connection = false; + // $this->connection = false; if (!$this->_closed) { $this->_closed = true; - return $this->_close(); + return $this->_close(); } else return true; } - + /** - * synonyms RecordCount and RowCount + * synonyms RecordCount and RowCount * * @return the number of rows or -1 if this is not supported */ function RecordCount() {return $this->_numOfRows;} - - + + /* * If we are using PageExecute(), this will return the maximum possible rows * that can be returned when paging a recordset. @@ -3054,14 +3054,14 @@ { return ($this->_maxRecordCount) ? $this->_maxRecordCount : $this->RecordCount(); } - + /** - * synonyms RecordCount and RowCount + * synonyms RecordCount and RowCount * * @return the number of rows or -1 if this is not supported */ - function RowCount() {return $this->_numOfRows;} - + function RowCount() {return $this->_numOfRows;} + /** * Portable RecordCount. Pablo Roca @@ -3070,38 +3070,38 @@ * * But aware possible problems in multiuser environments. For better speed the table * must be indexed by the condition. Heavy test this before deploying. - */ + */ function PO_RecordCount($table="", $condition="") { - + $lnumrows = $this->_numOfRows; // the database doesn't support native recordcount, so we do a workaround if ($lnumrows == -1 && $this->connection) { IF ($table) { - if ($condition) $condition = " WHERE " . $condition; + if ($condition) $condition = " WHERE " . $condition; $resultrows = &$this->connection->Execute("SELECT COUNT(*) FROM $table $condition"); if ($resultrows) $lnumrows = reset($resultrows->fields); } } return $lnumrows; } - + /** * @return the current row in the recordset. If at EOF, will return the last row. 0-based. */ function CurrentRow() {return $this->_currentRow;} - + /** * synonym for CurrentRow -- for ADO compat * * @return the current row in the recordset. If at EOF, will return the last row. 0-based. */ function AbsolutePosition() {return $this->_currentRow;} - + /** * @return the number of columns in the recordset. Some databases will set this to 0 * if no records are returned, others will return the number of columns in the query. */ - function FieldCount() {return $this->_numOfFields;} + function FieldCount() {return $this->_numOfFields;} /** @@ -3111,11 +3111,11 @@ * * @return the ADOFieldObject for that column, or false. */ - function &FetchField($fieldoffset) + function &FetchField($fieldoffset) { // must be defined by child class - } - + } + /** * Get the ADOFieldObjects of all columns in an array. * @@ -3123,11 +3123,11 @@ function& FieldTypesArray() { $arr = array(); - for ($i=0, $max=$this->_numOfFields; $i < $max; $i++) + for ($i=0, $max=$this->_numOfFields; $i < $max; $i++) $arr[] = $this->FetchField($i); return $arr; } - + /** * Return the fields array of the current row as an object for convenience. * The default case is lowercase field names. @@ -3139,11 +3139,11 @@ $o =& $this->FetchObject(false); return $o; } - + /** * Return the fields array of the current row as an object for convenience. * The default case is uppercase. - * + * * @param $isupper to set the object property names to uppercase * * @return the object with the properties set to the fields of the current row @@ -3161,21 +3161,21 @@ $i = 0; if (PHP_VERSION >= 5) $o = clone($this->_obj); else $o = $this->_obj; - + for ($i=0; $i <$this->_numOfFields; $i++) { $name = $this->_names[$i]; if ($isupper) $n = strtoupper($name); else $n = $name; - + $o->$n = $this->Fields($name); } return $o; } - + /** * Return the fields array of the current row as an object for convenience. * The default is lower-case field names. - * + * * @return the object with the properties set to the fields of the current row, * or false if EOF * @@ -3186,12 +3186,12 @@ $o =& $this->FetchNextObject(false); return $o; } - - + + /** - * Return the fields array of the current row as an object for convenience. + * Return the fields array of the current row as an object for convenience. * The default is upper case field names. - * + * * @param $isupper to set the object property names to uppercase * * @return the object with the properties set to the fields of the current row, @@ -3203,14 +3203,14 @@ { $o = false; if ($this->_numOfRows != 0 && !$this->EOF) { - $o = $this->FetchObject($isupper); + $o = $this->FetchObject($isupper); $this->_currentRow++; if ($this->_fetch()) return $o; } $this->EOF = true; return $o; } - + /** * Get the metatype of the column. This is used for formatting. This is because * many databases use different names for the same type, so we transform the original @@ -3221,8 +3221,8 @@ * fields bigger than a certain size as a 'B' (blob). * @param fieldobj is the field object returned by the database driver. Can hold * additional info (eg. primary_key for mysql). - * - * @return the general type of the data: + * + * @return the general type of the data: * C for character < 250 chars * X for teXt (>= 250 chars) * B for Binary @@ -3232,7 +3232,7 @@ * L for logical/Boolean * I for integer * R for autoincrement counter/integer - * + * * */ function MetaType($t,$len=-1,$fieldobj=false) @@ -3283,7 +3283,7 @@ 'T' => 'T', ## 'BOOL' => 'L', - 'BOOLEAN' => 'L', + 'BOOLEAN' => 'L', 'BIT' => 'L', 'L' => 'L', ## @@ -3316,62 +3316,62 @@ 'NUM' => 'N', 'NUMERIC' => 'N', 'MONEY' => 'N', - + ## informix 9.2 - 'SQLINT' => 'I', - 'SQLSERIAL' => 'I', - 'SQLSMINT' => 'I', - 'SQLSMFLOAT' => 'N', - 'SQLFLOAT' => 'N', - 'SQLMONEY' => 'N', - 'SQLDECIMAL' => 'N', - 'SQLDATE' => 'D', - 'SQLVCHAR' => 'C', - 'SQLCHAR' => 'C', - 'SQLDTIME' => 'T', - 'SQLINTERVAL' => 'N', - 'SQLBYTES' => 'B', - 'SQLTEXT' => 'X' + 'SQLINT' => 'I', + 'SQLSERIAL' => 'I', + 'SQLSMINT' => 'I', + 'SQLSMFLOAT' => 'N', + 'SQLFLOAT' => 'N', + 'SQLMONEY' => 'N', + 'SQLDECIMAL' => 'N', + 'SQLDATE' => 'D', + 'SQLVCHAR' => 'C', + 'SQLCHAR' => 'C', + 'SQLDTIME' => 'T', + 'SQLINTERVAL' => 'N', + 'SQLBYTES' => 'B', + 'SQLTEXT' => 'X' ); - + $tmap = false; $t = strtoupper($t); $tmap = (isset($typeMap[$t])) ? $typeMap[$t] : 'N'; switch ($tmap) { case 'C': - - // is the char field is too long, return as text field... + + // is the char field is too long, return as text field... if ($this->blobSize >= 0) { if ($len > $this->blobSize) return 'X'; } else if ($len > 250) { return 'X'; } return 'C'; - + case 'I': if (!empty($fieldobj->primary_key)) return 'R'; return 'I'; - + case false: return 'N'; - + case 'B': - if (isset($fieldobj->binary)) + if (isset($fieldobj->binary)) return ($fieldobj->binary) ? 'B' : 'X'; return 'B'; - + case 'D': if (!empty($this->datetime)) return 'T'; return 'D'; - - default: + + default: if ($t == 'LONG' && $this->dataProvider == 'oci8') return 'B'; return $tmap; } } - + function _close() {} - + /** * set/returns the current recordset page when paginating */ @@ -3380,7 +3380,7 @@ if ($page != -1) $this->_currentPage = $page; return $this->_currentPage; } - + /** * set/returns the status of the atFirstPage flag when paginating */ @@ -3389,13 +3389,13 @@ if ($status != false) $this->_atFirstPage = $status; return $this->_atFirstPage; } - + function LastPageNo($page = false) { if ($page != false) $this->_lastPageNo = $page; return $this->_lastPageNo; } - + /** * set/returns the status of the atLastPage flag when paginating */ @@ -3404,11 +3404,12 @@ if ($status != false) $this->_atLastPage = $status; return $this->_atLastPage; } - + /** * PDO compatibility function: fetch the next row * - * @return array/boolean false if there's nothing to fetch + * @param $fetchmode=null ADODB_FETCH_{DEFAULT|ASSOC|NUM|BOTH}, default is to use currently selected fetch-mode + * @return array|boolean false if there's nothing to fetch */ function &fetch($fetchmode=null) { @@ -3426,28 +3427,49 @@ } /** - * PDO compatibility function: fetch the first column of the next row + * PDO compatibility function: fetch the n-th column of the next row * - * @return string/boolean false if there's nothing to fetch + * @param int $column_number=0 + * @return string|boolean false if there's nothing to fetch + */ + function fetchColumn($column_number=0) + { + if(!($row = $this->FetchRow())) + { + return false; + } + while ($column_number-- >= 0) + { + $ret = array_shift($row); + } + return $ret; + } + + /** + * fetch the first column of the next row + * + * was introduced in eGroupware 1.6 as PDO compatibility function, but is renamed in PDO to fetchColumn() + * + * @deprecated use fetchColumn() + * @return string|boolean false if there's nothing to fetch */ function fetchSingle() { - $row = $this->FetchRow(); - return is_array($row) ? array_shift($row) : false; + return $this->fetchColumn(); } } // end class ADORecordSet - - //============================================================================================== + + //============================================================================================== // CLASS ADORecordSet_array - //============================================================================================== - + //============================================================================================== + /** * This class encapsulates the concept of a recordset created in memory * as an array. This is useful for the creation of cached recordsets. - * + * * Note that the constructor is different from the standard ADORecordSet */ - + class ADORecordSet_array extends ADORecordSet { var $databaseType = 'array'; @@ -3469,21 +3491,21 @@ function ADORecordSet_array($fakeid=1) { global $ADODB_FETCH_MODE,$ADODB_COMPAT_FETCH; - + // fetch() on EOF does not delete $this->fields $this->compat = !empty($ADODB_COMPAT_FETCH); - $this->ADORecordSet($fakeid); // fake queryID + $this->ADORecordSet($fakeid); // fake queryID $this->fetchMode = $ADODB_FETCH_MODE; } - - + + /** * Setup the array. * * @param array is a 2-dimensional array holding the data. - * The first row should hold the column names + * The first row should hold the column names * unless paramter $colnames is used. - * @param typearr holds an array of types. These are the same types + * @param typearr holds an array of types. These are the same types * used in MetaTypes (C,B,L,I,N). * @param [colnames] array of column names. If set, then the first row of * $array should not hold the column names. @@ -3491,7 +3513,7 @@ function InitArray($array,$typearr,$colnames=false) { $this->_array = $array; - $this->_types = $typearr; + $this->_types = $typearr; if ($colnames) { $this->_skiprow1 = false; $this->_colnames = $colnames; @@ -3505,7 +3527,7 @@ * Setup the Array and datatype file objects * * @param array is a 2-dimensional array holding the data. - * The first row should hold the column names + * The first row should hold the column names * unless paramter $colnames is used. * @param fieldarr holds an array of ADOFieldObject's. */ @@ -3515,10 +3537,10 @@ $this->_skiprow1= false; if ($fieldarr) { $this->_fieldobjects =& $fieldarr; - } + } $this->Init(); } - + function &GetArray($nRows=-1) { if ($nRows == -1 && $this->_currentRow <= 0 && !$this->_skiprow1) { @@ -3528,21 +3550,21 @@ return $arr; } } - + function _initrs() { $this->_numOfRows = sizeof($this->_array); if ($this->_skiprow1) $this->_numOfRows -= 1; - + $this->_numOfFields =(isset($this->_fieldobjects)) ? sizeof($this->_fieldobjects):sizeof($this->_types); } - + /* Use associative array to get fields array */ function Fields($colname) { $mode = isset($this->adodbFetchMode) ? $this->adodbFetchMode : $this->fetchMode; - + if ($mode & ADODB_FETCH_ASSOC) { if (!isset($this->fields[$colname])) $colname = strtolower($colname); return $this->fields[$colname]; @@ -3556,8 +3578,8 @@ } return $this->fields[$this->bind[strtoupper($colname)]]; } - - function &FetchField($fieldOffset = -1) + + function &FetchField($fieldOffset = -1) { if (isset($this->_fieldobjects)) { return $this->_fieldobjects[$fieldOffset]; @@ -3566,10 +3588,10 @@ $o->name = $this->_colnames[$fieldOffset]; $o->type = $this->_types[$fieldOffset]; $o->max_length = -1; // length not known - + return $o; } - + function _seek($row) { if (sizeof($this->_array) && 0 <= $row && $row < $this->_numOfRows) { @@ -3580,31 +3602,31 @@ } return false; } - - function MoveNext() + + function MoveNext() { - if (!$this->EOF) { + if (!$this->EOF) { $this->_currentRow++; - + $pos = $this->_currentRow; - + if ($this->_numOfRows <= $pos) { if (!$this->compat) $this->fields = false; } else { if ($this->_skiprow1) $pos += 1; $this->fields = $this->_array[$pos]; return true; - } + } $this->EOF = true; } - + return false; - } - + } + function _fetch() { $pos = $this->_currentRow; - + if ($this->_numOfRows <= $pos) { if (!$this->compat) $this->fields = false; return false; @@ -3613,41 +3635,41 @@ $this->fields = $this->_array[$pos]; return true; } - - function _close() + + function _close() { - return true; + return true; } - + } // ADORecordSet_array - //============================================================================================== + //============================================================================================== // HELPER FUNCTIONS - //============================================================================================== - + //============================================================================================== + /** * Synonym for ADOLoadCode. Private function. Do not use. * * @deprecated */ - function ADOLoadDB($dbType) - { + function ADOLoadDB($dbType) + { return ADOLoadCode($dbType); } - + /** * Load the code for a specific database driver. Private function. Do not use. */ - function ADOLoadCode($dbType) + function ADOLoadCode($dbType) { global $ADODB_LASTDB; - + if (!$dbType) return false; $db = strtolower($dbType); switch ($db) { - case 'ado': + case 'ado': if (PHP_VERSION >= 5) $db = 'ado5'; - $class = 'ado'; + $class = 'ado'; break; case 'ifx': case 'maxsql': $class = $db = 'mysqlt'; break; @@ -3657,12 +3679,12 @@ default: $class = $db; break; } - + $file = ADODB_DIR."/drivers/adodb-".$db.".inc.php"; @include_once($file); $ADODB_LASTDB = $class; if (class_exists("ADODB_" . $class)) return $class; - + //ADOConnection::outp(adodb_pr(get_declared_classes(),true)); if (!file_exists($file)) ADOConnection::outp("Missing file: $file"); else ADOConnection::outp("Syntax error in file: $file"); @@ -3677,7 +3699,7 @@ $tmp =& ADONewConnection($db); return $tmp; } - + /** * Instantiate a new Connection class for a specific database driver. * @@ -3689,14 +3711,14 @@ function &ADONewConnection($db='') { GLOBAL $ADODB_NEWCONNECTION, $ADODB_LASTDB; - + if (!defined('ADODB_ASSOC_CASE')) define('ADODB_ASSOC_CASE',2); $errorfn = (defined('ADODB_ERROR_HANDLER')) ? ADODB_ERROR_HANDLER : false; $false = false; if (strpos($db,'://')) { $origdsn = $db; $dsna = @parse_url($db); - + if (!$dsna) { // special handling of oracle, which might not have host $db = str_replace('@/','@adodb-fakehost/',$db); @@ -3710,7 +3732,7 @@ $dsna['user'] = isset($dsna['user']) ? rawurldecode($dsna['user']) : ''; $dsna['pass'] = isset($dsna['pass']) ? rawurldecode($dsna['pass']) : ''; $dsna['path'] = isset($dsna['path']) ? rawurldecode(substr($dsna['path'],1)) : ''; # strip off initial / - + if (isset($dsna['query'])) { $opt1 = explode('&',$dsna['query']); foreach($opt1 as $k => $v) { @@ -3719,7 +3741,7 @@ } } else $opt = array(); } - + /* * phptype: Database backend used in PHP (mysql, odbc etc.) * dbsyntax: Database used with regards to SQL syntax etc. @@ -3733,12 +3755,12 @@ $obj = $ADODB_NEWCONNECTION($db); } else { - + if (!isset($ADODB_LASTDB)) $ADODB_LASTDB = ''; if (empty($db)) $db = $ADODB_LASTDB; - + if ($db != $ADODB_LASTDB) $db = ADOLoadCode($db); - + if (!$db) { if (isset($origdsn)) $db = $origdsn; if ($errorfn) { @@ -3749,19 +3771,19 @@ $db,false,$ignore); } else ADOConnection::outp( "

ADONewConnection: Unable to load database driver '$db'

",false); - + return $false; } - + $cls = 'ADODB_'.$db; if (!class_exists($cls)) { adodb_backtrace(); return $false; } - + $obj = new $cls(); } - + # constructor should not fail if ($obj) { if ($errorfn) $obj->raiseErrorFn = $errorfn; @@ -3794,27 +3816,27 @@ $ok = $obj->Connect($dsna['host'], $dsna['user'], $dsna['pass'], $dsna['path']); else $ok = $obj->PConnect($dsna['host'], $dsna['user'], $dsna['pass'], $dsna['path']); - + if (!$ok) return $false; } } return $obj; } - - - + + + // $perf == true means called by NewPerfMonitor(), otherwise for data dictionary function _adodb_getdriver($provider,$drivername,$perf=false) { switch ($provider) { - case 'odbtp': if (strncmp('odbtp_',$drivername,6)==0) return substr($drivername,6); - case 'odbc' : if (strncmp('odbc_',$drivername,5)==0) return substr($drivername,5); + case 'odbtp': if (strncmp('odbtp_',$drivername,6)==0) return substr($drivername,6); + case 'odbc' : if (strncmp('odbc_',$drivername,5)==0) return substr($drivername,5); case 'ado' : if (strncmp('ado_',$drivername,4)==0) return substr($drivername,4); case 'native': break; default: return $provider; } - + switch($drivername) { case 'firebird15': $drivername = 'firebird'; break; case 'oracle': $drivername = 'oci8'; break; @@ -3828,7 +3850,7 @@ } return $drivername; } - + function &NewPerfMonitor(&$conn) { $false = false; @@ -3839,10 +3861,10 @@ $class = "Perf_$drivername"; if (!class_exists($class)) return $false; $perf = new $class($conn); - + return $perf; } - + function &NewDataDictionary(&$conn,$drivername=false) { $false = false; @@ -3865,34 +3887,34 @@ $dict->quote = $conn->nameQuote; if (!empty($conn->_connectionID)) $dict->serverInfo = $conn->ServerInfo(); - + return $dict; } - + /* Perform a print_r, with pre tags for better formatting. */ function adodb_pr($var,$as_string=false) { if ($as_string) ob_start(); - - if (isset($_SERVER['HTTP_USER_AGENT'])) { + + if (isset($_SERVER['HTTP_USER_AGENT'])) { echo "
\n";print_r($var);echo "
\n"; } else print_r($var); - + if ($as_string) { $s = ob_get_contents(); ob_end_clean(); return $s; } } - + /* Perform a stack-crawl and pretty print it. - + @param printOrArr Pass in a boolean to indicate print, or an $exception->trace array (assumes that print is true then). @param levels Number of levels to display */ @@ -3902,6 +3924,6 @@ if (empty($ADODB_INCLUDED_LIB)) include_once(ADODB_DIR.'/adodb-lib.inc.php'); return _adodb_backtrace($printOrArr,$levels); } - + } // defined ?> diff --git a/phpgwapi/inc/class.egw_db.inc.php b/phpgwapi/inc/class.egw_db.inc.php index d6f5905ac6..88a8f6adbb 100644 --- a/phpgwapi/inc/class.egw_db.inc.php +++ b/phpgwapi/inc/class.egw_db.inc.php @@ -30,8 +30,8 @@ * * c) foreach($db->select($table,'*',$where,__LINE__,__FILE__,false,'',$app) as $row) * - * To fetch only single column (of the next row): - * $cnt = $db->query("SELECT COUNT(*) FROM ...")->fetchSingle(); + * To fetch only a single column (of the next row): + * $cnt = $db->query("SELECT COUNT(*) FROM ...")->fetchColumn($column_num=0); * * To fetch a next (single) row, you can use: * $row = $db->query("SELECT COUNT(*) FROM ...")->fetch($fetchmod=null);