3 * Set tabs to 4 for best viewing.
5 * Latest version is available at http://adodb.sourceforge.net
7 * This is the main include file for ADOdb.
8 * Database specific drivers are stored in the adodb/drivers/adodb-*.inc.php
10 * The ADOdb files are formatted so that doxygen can be used to generate documentation.
11 * Doxygen is a documentation generation tool and can be downloaded from http://doxygen.org/
17 @version V5.19 23-Apr-2014 (c) 2000-2014 John Lim (jlim#natsoft.com). All rights reserved.
19 Released under both BSD license and Lesser GPL library license. You can choose which license
22 PHP's database access functions are not standardised. This creates a need for a database
23 class library to hide the differences between the different database API's (encapsulate
24 the differences) so we can easily switch databases.
26 We currently support MySQL, Oracle, Microsoft SQL Server, Sybase, Sybase SQL Anywhere, DB2,
27 Informix, PostgreSQL, FrontBase, Interbase (Firebird and Borland variants), Foxpro, Access,
28 ADO, SAP DB, SQLite and ODBC. We have had successful reports of connecting to Progress and
29 other databases via ODBC.
31 Latest Download at http://adodb.sourceforge.net/
35 if (!defined('_ADODB_LAYER')) {
36 define('_ADODB_LAYER',1);
38 //==============================================================================================
39 // CONSTANT DEFINITIONS
40 //==============================================================================================
44 * Set ADODB_DIR to the directory where this file resides...
45 * This constant was formerly called $ADODB_RootPath
47 if (!defined('ADODB_DIR')) define('ADODB_DIR',dirname(__FILE__
));
49 //==============================================================================================
51 //==============================================================================================
54 $ADODB_vers, // database version
55 $ADODB_COUNTRECS, // count number of records returned - slows down query
56 $ADODB_CACHE_DIR, // directory to cache recordsets
59 $ADODB_EXTENSION, // ADODB extension installed
60 $ADODB_COMPAT_FETCH, // If $ADODB_COUNTRECS and this is true, $rs->fields is available on EOF
61 $ADODB_FETCH_MODE, // DEFAULT, NUM, ASSOC or BOTH. Default follows native driver default...
63 $ADODB_QUOTE_FIELDNAMES; // Allows you to force quotes (backticks) around field names in queries generated by getinsertsql and getupdatesql.
65 //==============================================================================================
67 //==============================================================================================
69 $ADODB_EXTENSION = defined('ADODB_EXTENSION');
71 // ********************************************************
72 // Controls $ADODB_FORCE_TYPE mode. Default is ADODB_FORCE_VALUE (3).
73 // Used in GetUpdateSql and GetInsertSql functions. Thx to Niko, nuko#mbnet.fi
75 // 0 = ignore empty fields. All empty fields in array are ignored.
76 // 1 = force null. All empty, php null and string 'null' fields are changed to sql NULL values.
77 // 2 = force empty. All empty, php null and string 'null' fields are changed to sql empty '' or 0 values.
78 // 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.
80 define('ADODB_FORCE_IGNORE',0);
81 define('ADODB_FORCE_NULL',1);
82 define('ADODB_FORCE_EMPTY',2);
83 define('ADODB_FORCE_VALUE',3);
84 // ********************************************************
87 if (!$ADODB_EXTENSION || ADODB_EXTENSION
< 4.0) {
89 define('ADODB_BAD_RS','<p>Bad $rs in %s. Connection or SQL invalid. Try using $connection->debug=true;</p>');
91 // allow [ ] @ ` " and . in table names
92 define('ADODB_TABLE_REGEX','([]0-9a-z_\:\"\`\.\@\[-]*)');
94 // prefetching used by oracle
95 if (!defined('ADODB_PREFETCH_ROWS')) define('ADODB_PREFETCH_ROWS',10);
99 Controls ADODB_FETCH_ASSOC field-name case. Default is 2, use native case-names.
100 This currently works only with mssql, odbc, oci8po and ibase derived drivers.
102 0 = assoc lowercase field names. $rs->fields['orderid']
103 1 = assoc uppercase field names. $rs->fields['ORDERID']
104 2 = use native-case field names. $rs->fields['OrderID']
106 define('ADODB_ASSOC_CASE_LOWER', 0);
107 define('ADODB_ASSOC_CASE_UPPER', 1);
108 define('ADODB_ASSOC_CASE_NATIVE', 2);
110 define('ADODB_FETCH_DEFAULT',0);
111 define('ADODB_FETCH_NUM',1);
112 define('ADODB_FETCH_ASSOC',2);
113 define('ADODB_FETCH_BOTH',3);
115 if (!defined('TIMESTAMP_FIRST_YEAR')) define('TIMESTAMP_FIRST_YEAR',100);
117 // PHP's version scheme makes converting to numbers difficult - workaround
118 $_adodb_ver = (float) PHP_VERSION
;
119 if ($_adodb_ver >= 5.2) {
120 define('ADODB_PHPVER',0x5200);
121 } else if ($_adodb_ver >= 5.0) {
122 define('ADODB_PHPVER',0x5000);
124 die("PHP5 or later required. You are running ".PHP_VERSION
);
128 //if (!defined('ADODB_ASSOC_CASE')) define('ADODB_ASSOC_CASE',2);
132 Accepts $src and $dest arrays, replacing string $data
134 function ADODB_str_replace($src, $dest, $data)
136 if (ADODB_PHPVER
>= 0x4050) return str_replace($src,$dest,$data);
140 while ($s !== false) {
141 $data = str_replace($s,$d,$data);
148 function ADODB_Setup()
151 $ADODB_vers, // database version
152 $ADODB_COUNTRECS, // count number of records returned - slows down query
153 $ADODB_CACHE_DIR, // directory to cache recordsets
159 $ADODB_QUOTE_FIELDNAMES;
161 if (empty($ADODB_CACHE_CLASS)) $ADODB_CACHE_CLASS = 'ADODB_Cache_File' ;
162 $ADODB_FETCH_MODE = ADODB_FETCH_DEFAULT
;
163 $ADODB_FORCE_TYPE = ADODB_FORCE_VALUE
;
164 $ADODB_GETONE_EOF = null;
166 if (!isset($ADODB_CACHE_DIR)) {
167 $ADODB_CACHE_DIR = '/tmp'; //(isset($_ENV['TMP'])) ? $_ENV['TMP'] : '/tmp';
169 // do not accept url based paths, eg. http:/ or ftp:/
170 if (strpos($ADODB_CACHE_DIR,'://') !== false)
171 die("Illegal path http:// or ftp://");
175 // Initialize random number generator for randomizing cache flushes
176 // -- note Since PHP 4.2.0, the seed becomes optional and defaults to a random value if omitted.
177 // MDL-41198 Removed random seed initialization.
178 // srand(((double)microtime())*1000000);
181 * ADODB version as a string.
183 $ADODB_vers = 'V5.19 23-Apr-2014 (c) 2000-2014 John Lim (jlim#natsoft.com). All rights reserved. Released BSD & LGPL.';
186 * Determines whether recordset->RecordCount() is used.
187 * Set to false for highest performance -- RecordCount() will always return -1 then
188 * for databases that provide "virtual" recordcounts...
190 if (!isset($ADODB_COUNTRECS)) $ADODB_COUNTRECS = true;
194 //==============================================================================================
195 // CHANGE NOTHING BELOW UNLESS YOU ARE DESIGNING ADODB
196 //==============================================================================================
200 //==============================================================================================
201 // CLASS ADOFieldObject
202 //==============================================================================================
204 * Helper class for FetchFields -- holds info on a column
206 class ADOFieldObject
{
211 // additional fields by dannym... (danny_milo@yahoo.com)
212 var $not_null = false;
213 // actually, this has already been built-in in the postgres, fbsql AND mysql module? ^-^
214 // so we can as well make not_null standard (leaving it at "false" does not harm anyways)
216 var $has_default = false; // this one I have done only in mysql and postgres for now ...
217 // others to come (dannym)
218 var $default_value; // default, if any, and supported. Check has_default first.
223 function _adodb_safedate($s)
225 return str_replace(array("'", '\\'), '', $s);
228 // parse date string to prevent injection attack
229 // date string will have one quote at beginning e.g. '3434343'
230 function _adodb_safedateq($s)
233 if ($s[0] !== "'") $s2 = "'".$s[0];
235 for($i=1; $i<$len; $i++
) {
240 } elseif ($ch === "'") {
248 return strlen($s2) == 0 ?
'null' : $s2;
252 // for transaction handling
254 function ADODB_TransMonitor($dbms, $fn, $errno, $errmsg, $p1, $p2, &$thisConnection)
256 //print "Errorno ($fn errno=$errno m=$errmsg) ";
257 $thisConnection->_transOK
= false;
258 if ($thisConnection->_oldRaiseFn
) {
259 $fn = $thisConnection->_oldRaiseFn
;
260 $fn($dbms, $fn, $errno, $errmsg, $p1, $p2,$thisConnection);
266 class ADODB_Cache_File
{
268 var $createdir = true; // requires creation of temp dirs
270 function ADODB_Cache_File()
272 global $ADODB_INCLUDED_CSV;
273 if (empty($ADODB_INCLUDED_CSV)) include_once(ADODB_DIR
.'/adodb-csvlib.inc.php');
276 // write serialised recordset to cache item/file
277 function writecache($filename, $contents, $debug, $secs2cache)
279 return adodb_write_file($filename, $contents,$debug);
282 // load serialised recordset and unserialise it
283 function &readcache($filename, &$err, $secs2cache, $rsClass)
285 $rs = csv2rs($filename,$err,$secs2cache,$rsClass);
289 // flush all items in cache
290 function flushall($debug=false)
292 global $ADODB_CACHE_DIR;
296 if (strlen($ADODB_CACHE_DIR) > 1) {
297 $rez = $this->_dirFlush($ADODB_CACHE_DIR);
298 if ($debug) ADOConnection
::outp( "flushall: $dir<br><pre>\n". $rez."</pre>");
303 // flush one file in cache
304 function flushcache($f, $debug=false)
307 if ($debug) ADOConnection
::outp( "flushcache: failed for $f");
311 function getdirname($hash)
313 global $ADODB_CACHE_DIR;
314 if (!isset($this->notSafeMode
)) $this->notSafeMode
= !ini_get('safe_mode');
315 return ($this->notSafeMode
) ?
$ADODB_CACHE_DIR.'/'.substr($hash,0,2) : $ADODB_CACHE_DIR;
318 // create temp directories
319 function createdir($hash, $debug)
321 global $ADODB_CACHE_PERMS;
323 $dir = $this->getdirname($hash);
324 if ($this->notSafeMode
&& !file_exists($dir)) {
326 if (!@mkdir
($dir, empty($ADODB_CACHE_PERMS) ?
0771 : $ADODB_CACHE_PERMS)) if(!is_dir($dir) && $debug) ADOConnection
::outp("Cannot create $dir");
334 * Private function to erase all of the files and subdirectories in a directory.
336 * Just specify the directory, and tell it if you want to delete the directory or just clear it out.
337 * Note: $kill_top_level is used internally in the function to flush subdirectories.
339 function _dirFlush($dir, $kill_top_level = false)
341 if(!$dh = @opendir
($dir)) return;
343 while (($obj = readdir($dh))) {
344 if($obj=='.' ||
$obj=='..') continue;
347 if (strpos($obj,'.cache')) @unlink
($f);
348 if (is_dir($f)) $this->_dirFlush($f, true);
350 if ($kill_top_level === true) @rmdir
($dir);
355 //==============================================================================================
356 // CLASS ADOConnection
357 //==============================================================================================
360 * Connection object. For connecting to databases, and executing queries.
362 abstract class ADOConnection
{
366 var $dataProvider = 'native';
367 var $databaseType = ''; /// RDBMS currently in use, eg. odbc, mysql, mssql
368 var $database = ''; /// Name of database to be used.
369 var $host = ''; /// The hostname of the database server
370 var $user = ''; /// The username which is used to connect to the database server.
371 var $password = ''; /// Password for the username. For security, we no longer store it.
372 var $debug = false; /// if set to true will output sql statements
373 var $maxblobsize = 262144; /// maximum size of blobs or large text fields (262144 = 256K)-- some db's die otherwise like foxpro
374 var $concat_operator = '+'; /// default concat operator -- change to || for Oracle/Interbase
375 var $substr = 'substr'; /// substring operator
376 var $length = 'length'; /// string length ofperator
377 var $random = 'rand()'; /// random function
378 var $upperCase = 'upper'; /// uppercase function
379 var $fmtDate = "'Y-m-d'"; /// used by DBDate() as the default date format used by the database
380 var $fmtTimeStamp = "'Y-m-d, h:i:s A'"; /// used by DBTimeStamp as the default timestamp fmt.
381 var $true = '1'; /// string that represents TRUE for a database
382 var $false = '0'; /// string that represents FALSE for a database
383 var $replaceQuote = "\\'"; /// string to use to replace quotes
384 var $nameQuote = '"'; /// string to use to quote identifiers and names
385 var $charSet=false; /// character set to use - only for interbase, postgres and oci8
386 var $metaDatabasesSQL = '';
387 var $metaTablesSQL = '';
388 var $uniqueOrderBy = false; /// All order by columns have to be unique
389 var $emptyDate = ' ';
390 var $emptyTimeStamp = ' ';
391 var $lastInsID = false;
393 var $hasInsertID = false; /// supports autoincrement ID?
394 var $hasAffectedRows = false; /// supports affected rows for update/delete?
395 var $hasTop = false; /// support mssql/access SELECT TOP 10 * FROM TABLE
396 var $hasLimit = false; /// support pgsql/mysql SELECT * FROM TABLE LIMIT 10
397 var $readOnly = false; /// this is a readonly database - used by phpLens
398 var $hasMoveFirst = false; /// has ability to run MoveFirst(), scrolling backwards
399 var $hasGenID = false; /// can generate sequences using GenID();
400 var $hasTransactions = true; /// has transactions
402 var $genID = 0; /// sequence id used by GenID();
403 var $raiseErrorFn = false; /// error function to call
404 var $isoDates = false; /// accepts dates in ISO format
405 var $cacheSecs = 3600; /// cache for 1 hour
408 var $memCache = false; /// should we use memCache instead of caching in files
409 var $memCacheHost; /// memCache host
410 var $memCachePort = 11211; /// memCache port
411 var $memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib)
413 var $sysDate = false; /// name of function that returns the current date
414 var $sysTimeStamp = false; /// name of function that returns the current timestamp
415 var $sysUTimeStamp = false; // name of function that returns the current timestamp accurate to the microsecond or nearest fraction
416 var $arrayClass = 'ADORecordSet_array'; /// name of class used to generate array recordsets, which are pre-downloaded recordsets
418 var $noNullStrings = false; /// oracle specific stuff - if true ensures that '' is converted to ' '
419 var $numCacheHits = 0;
420 var $numCacheMisses = 0;
421 var $pageExecuteCountRows = true;
422 var $uniqueSort = false; /// indicates that all fields in order by must be unique
423 var $leftOuter = false; /// operator to use for left outer join in WHERE clause
424 var $rightOuter = false; /// operator to use for right outer join in WHERE clause
425 var $ansiOuter = false; /// whether ansi outer join syntax supported
426 var $autoRollback = false; // autoRollback on PConnect().
427 var $poorAffectedRows = false; // affectedRows not working or unreliable
429 var $fnExecute = false;
430 var $fnCacheExecute = false;
431 var $blobEncodeType = false; // false=not required, 'I'=encode to integer, 'C'=encode to char
432 var $rsPrefix = "ADORecordSet_";
434 var $autoCommit = true; /// do not modify this yourself - actually private
435 var $transOff = 0; /// temporarily disable transactions
436 var $transCnt = 0; /// count of nested transactions
438 var $fetchMode=false;
440 var $null2null = 'null'; // in autoexecute/getinsertsql/getupdatesql, this value will be converted to a null
441 var $bulkBind = false; // enable 2D Execute array
445 var $_oldRaiseFn = false;
446 var $_transOK = null;
447 var $_connectionID = false; /// The returned link identifier whenever a successful database connection is made.
448 var $_errorMsg = false; /// A variable which was used to keep the returned last error message. The value will
449 /// then returned by the errorMsg() function
450 var $_errorCode = false; /// Last error code, not guaranteed to be used - only by oci8
451 var $_queryID = false; /// This variable keeps the last created result link identifier
453 var $_isPersistentConnection = false; /// A boolean variable to state whether its a persistent connection or normal connection. */
454 var $_bindInputArray = false; /// set to true if ADOConnection.Execute() permits binding of array parameters.
455 var $_evalAll = false;
456 var $_affected = false;
457 var $_logsql = false;
458 var $_transmode = ''; // transaction mode
461 static function Version()
465 $ok = preg_match( '/^[Vv]?([0-9]\.[0-9]+(dev|[a-z]))?/', $ADODB_vers, $matches );
466 if (!$ok) return (float) substr($ADODB_vers,1);
467 else return $matches[1];
471 Get server version info...
473 @returns An array with 2 elements: $arr['string'] is the description string,
474 and $arr[version] is the version (also a string).
476 function ServerInfo()
478 return array('description' => '', 'version' => '');
481 function IsConnected()
483 return !empty($this->_connectionID
);
486 function _findvers($str)
488 if (preg_match('/([0-9]+\.([0-9\.])+)/',$str, $arr)) return $arr[1];
493 * All error messages go through this bottleneck function.
494 * You can define your own handler by defining the function name in ADODB_OUTP.
496 static function outp($msg,$newline=true)
498 global $ADODB_FLUSH,$ADODB_OUTP;
500 if (defined('ADODB_OUTP')) {
504 } else if (isset($ADODB_OUTP)) {
510 if ($newline) $msg .= "<br>\n";
512 if (isset($_SERVER['HTTP_USER_AGENT']) ||
!$newline) echo $msg;
513 else echo strip_tags($msg);
516 if (!empty($ADODB_FLUSH) && ob_get_length() !== false) flush(); // do not flush if output buffering enabled - useless - thx to Jesse Mullan
522 $rs = $this->_Execute("select $this->sysTimeStamp");
523 if ($rs && !$rs->EOF
) return $this->UnixTimeStamp(reset($rs->fields
));
529 * Connect to database
531 * @param [argHostname] Host to connect to
532 * @param [argUsername] Userid to login
533 * @param [argPassword] Associated password
534 * @param [argDatabaseName] database
535 * @param [forceNew] force new connection
537 * @return true or false
539 function Connect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "", $forceNew = false)
541 if ($argHostname != "") $this->host
= $argHostname;
542 if ($argUsername != "") $this->user
= $argUsername;
543 if ($argPassword != "") $this->password
= 'not stored'; // not stored for security reasons
544 if ($argDatabaseName != "") $this->database
= $argDatabaseName;
546 $this->_isPersistentConnection
= false;
549 if ($rez=$this->_nconnect($this->host
, $this->user
, $argPassword, $this->database
)) return true;
551 if ($rez=$this->_connect($this->host
, $this->user
, $argPassword, $this->database
)) return true;
554 $err = $this->ErrorMsg();
555 if (empty($err)) $err = "Connection error to server '$argHostname' with user '$argUsername'";
558 $err = "Missing extension for ".$this->dataProvider
;
561 if ($fn = $this->raiseErrorFn
)
562 $fn($this->databaseType
,'CONNECT',$this->ErrorNo(),$err,$this->host
,$this->database
,$this);
565 $this->_connectionID
= false;
566 if ($this->debug
) ADOConnection
::outp( $this->host
.': '.$err);
570 function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName)
572 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName);
577 * Always force a new connection to database - currently only works with oracle
579 * @param [argHostname] Host to connect to
580 * @param [argUsername] Userid to login
581 * @param [argPassword] Associated password
582 * @param [argDatabaseName] database
584 * @return true or false
586 function NConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "")
588 return $this->Connect($argHostname, $argUsername, $argPassword, $argDatabaseName, true);
592 * Establish persistent connect to database
594 * @param [argHostname] Host to connect to
595 * @param [argUsername] Userid to login
596 * @param [argPassword] Associated password
597 * @param [argDatabaseName] database
599 * @return return true or false
601 function PConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "")
604 if (defined('ADODB_NEVER_PERSIST'))
605 return $this->Connect($argHostname,$argUsername,$argPassword,$argDatabaseName);
607 if ($argHostname != "") $this->host
= $argHostname;
608 if ($argUsername != "") $this->user
= $argUsername;
609 if ($argPassword != "") $this->password
= 'not stored';
610 if ($argDatabaseName != "") $this->database
= $argDatabaseName;
612 $this->_isPersistentConnection
= true;
614 if ($rez = $this->_pconnect($this->host
, $this->user
, $argPassword, $this->database
)) return true;
616 $err = $this->ErrorMsg();
617 if (empty($err)) $err = "Connection error to server '$argHostname' with user '$argUsername'";
620 $err = "Missing extension for ".$this->dataProvider
;
623 if ($fn = $this->raiseErrorFn
) {
624 $fn($this->databaseType
,'PCONNECT',$this->ErrorNo(),$err,$this->host
,$this->database
,$this);
627 $this->_connectionID
= false;
628 if ($this->debug
) ADOConnection
::outp( $this->host
.': '.$err);
632 function outp_throw($msg,$src='WARN',$sql='')
634 if (defined('ADODB_ERROR_HANDLER') && ADODB_ERROR_HANDLER
== 'adodb_throw') {
635 adodb_throw($this->databaseType
,$src,-9999,$msg,$sql,false,$this);
638 ADOConnection
::outp($msg);
641 // create cache class. Code is backward compat with old memcache implementation
642 function _CreateCache()
644 global $ADODB_CACHE, $ADODB_CACHE_CLASS;
646 if ($this->memCache
) {
647 global $ADODB_INCLUDED_MEMCACHE;
649 if (empty($ADODB_INCLUDED_MEMCACHE)) include(ADODB_DIR
.'/adodb-memcache.lib.inc.php');
650 $ADODB_CACHE = new ADODB_Cache_MemCache($this);
652 $ADODB_CACHE = new $ADODB_CACHE_CLASS($this);
656 // Format date column in sql string given an input format that understands Y M D
657 function SQLDate($fmt, $col=false)
659 if (!$col) $col = $this->sysDate
;
660 return $col; // child class implement
664 * Should prepare the sql statement and return the stmt resource.
665 * For databases that do not support this, we return the $sql. To ensure
666 * compatibility with databases that do not support prepare:
668 * $stmt = $db->Prepare("insert into table (id, name) values (?,?)");
669 * $db->Execute($stmt,array(1,'Jill')) or die('insert failed');
670 * $db->Execute($stmt,array(2,'Joe')) or die('insert failed');
672 * @param sql SQL to send to database
674 * @return return FALSE, or the prepared statement, or the original sql if
675 * if the database does not support prepare.
678 function Prepare($sql)
684 * Some databases, eg. mssql require a different function for preparing
685 * stored procedures. So we cannot use Prepare().
687 * Should prepare the stored procedure and return the stmt resource.
688 * For databases that do not support this, we return the $sql. To ensure
689 * compatibility with databases that do not support prepare:
691 * @param sql SQL to send to database
693 * @return return FALSE, or the prepared statement, or the original sql if
694 * if the database does not support prepare.
697 function PrepareSP($sql,$param=true)
699 return $this->Prepare($sql,$param);
707 return $this->qstr($s,false);
711 Requested by "Karsten Dambekalns" <k.dambekalns@fishfarm.de>
715 return $this->qstr($s,get_magic_quotes_gpc());
720 #if (!empty($this->qNull)) if ($s == 'null') return $s;
721 $s = $this->qstr($s,false);
725 * PEAR DB Compat - do not use internally.
727 function ErrorNative()
729 return $this->ErrorNo();
734 * PEAR DB Compat - do not use internally.
736 function nextId($seq_name)
738 return $this->GenID($seq_name);
742 * Lock a row, will escalate and lock the table if row locking not supported
743 * will normally free the lock at the end of the transaction
745 * @param $table name of table to lock
746 * @param $where where clause to use, eg: "WHERE row=12". If left empty, will escalate to table lock
748 function RowLock($table,$where,$col='1 as adodbignore')
753 function CommitLock($table)
755 return $this->CommitTrans();
758 function RollbackLock($table)
760 return $this->RollbackTrans();
764 * PEAR DB Compat - do not use internally.
766 * The fetch modes for NUMERIC and ASSOC for PEAR DB and ADODB are identical
767 * for easy porting :-)
769 * @param mode The fetchmode ADODB_FETCH_ASSOC or ADODB_FETCH_NUM
770 * @returns The previous fetch mode
772 function SetFetchMode($mode)
774 $old = $this->fetchMode
;
775 $this->fetchMode
= $mode;
777 if ($old === false) {
778 global $ADODB_FETCH_MODE;
779 return $ADODB_FETCH_MODE;
786 * PEAR DB Compat - do not use internally.
788 function Query($sql, $inputarr=false)
790 $rs = $this->Execute($sql, $inputarr);
791 if (!$rs && defined('ADODB_PEAR')) return ADODB_PEAR_Error();
797 * PEAR DB Compat - do not use internally
799 function LimitQuery($sql, $offset, $count, $params=false)
801 $rs = $this->SelectLimit($sql, $count, $offset, $params);
802 if (!$rs && defined('ADODB_PEAR')) return ADODB_PEAR_Error();
808 * PEAR DB Compat - do not use internally
810 function Disconnect()
812 return $this->Close();
816 * Returns a placeholder for query parameters
817 * e.g. $DB->Param('a') will return
818 * - '?' for most databases
820 * - '$1', '$2', etc. for PostgreSQL
821 * @param string $name parameter's name, false to force a reset of the
822 * number to 1 (for databases that require positioned
823 * params such as PostgreSQL; note that ADOdb will
824 * automatically reset this when executing a query )
825 * @param string $type (unused)
826 * @return string query parameter placeholder
828 function Param($name,$type='C')
834 InParameter and OutParameter are self-documenting versions of Parameter().
836 function InParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false)
838 return $this->Parameter($stmt,$var,$name,false,$maxLen,$type);
843 function OutParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false)
845 return $this->Parameter($stmt,$var,$name,true,$maxLen,$type);
852 $stmt = $db->Prepare('select * from table where id =:myid and group=:group');
853 $db->Parameter($stmt,$id,'myid');
854 $db->Parameter($stmt,$group,'group',64);
857 @param $stmt Statement returned by Prepare() or PrepareSP().
858 @param $var PHP variable to bind to
859 @param $name Name of stored procedure variable name to bind to.
860 @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8.
861 @param [$maxLen] Holds an maximum length of the variable.
862 @param [$type] The data type of $var. Legal values depend on driver.
865 function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false)
871 function IgnoreErrors($saveErrs=false)
874 $saveErrs = array($this->raiseErrorFn
,$this->_transOK
);
875 $this->raiseErrorFn
= false;
878 $this->raiseErrorFn
= $saveErrs[0];
879 $this->_transOK
= $saveErrs[1];
884 Improved method of initiating a transaction. Used together with CompleteTrans().
887 a. StartTrans/CompleteTrans is nestable, unlike BeginTrans/CommitTrans/RollbackTrans.
888 Only the outermost block is treated as a transaction.<br>
889 b. CompleteTrans auto-detects SQL errors, and will rollback on errors, commit otherwise.<br>
890 c. All BeginTrans/CommitTrans/RollbackTrans inside a StartTrans/CompleteTrans block
891 are disabled, making it backward compatible.
893 function StartTrans($errfn = 'ADODB_TransMonitor')
895 if ($this->transOff
> 0) {
896 $this->transOff +
= 1;
900 $this->_oldRaiseFn
= $this->raiseErrorFn
;
901 $this->raiseErrorFn
= $errfn;
902 $this->_transOK
= true;
904 if ($this->debug
&& $this->transCnt
> 0) ADOConnection
::outp("Bad Transaction: StartTrans called within BeginTrans");
905 $ok = $this->BeginTrans();
912 Used together with StartTrans() to end a transaction. Monitors connection
913 for sql errors, and will commit or rollback as appropriate.
915 @autoComplete if true, monitor sql errors and commit and rollback as appropriate,
916 and if set to false force rollback even if no SQL error detected.
917 @returns true on commit, false on rollback.
919 function CompleteTrans($autoComplete = true)
921 if ($this->transOff
> 1) {
922 $this->transOff
-= 1;
925 $this->raiseErrorFn
= $this->_oldRaiseFn
;
928 if ($this->_transOK
&& $autoComplete) {
929 if (!$this->CommitTrans()) {
930 $this->_transOK
= false;
931 if ($this->debug
) ADOConnection
::outp("Smart Commit failed");
933 if ($this->debug
) ADOConnection
::outp("Smart Commit occurred");
935 $this->_transOK
= false;
936 $this->RollbackTrans();
937 if ($this->debug
) ADOCOnnection
::outp("Smart Rollback occurred");
940 return $this->_transOK
;
944 At the end of a StartTrans/CompleteTrans block, perform a rollback.
949 if ($this->transOff
== 0) {
950 ADOConnection
::outp("FailTrans outside StartTrans/CompleteTrans");
952 ADOConnection
::outp("FailTrans was called");
955 $this->_transOK
= false;
959 Check if transaction has failed, only for Smart Transactions.
961 function HasFailedTrans()
963 if ($this->transOff
> 0) return $this->_transOK
== false;
970 * @param sql SQL statement to execute, or possibly an array holding prepared statement ($sql[0] will hold sql text)
971 * @param [inputarr] holds the input data to bind to. Null elements will be set to null.
972 * @return RecordSet or false
974 function Execute($sql,$inputarr=false)
976 if ($this->fnExecute
) {
977 $fn = $this->fnExecute
;
978 $ret = $fn($this,$sql,$inputarr);
979 if (isset($ret)) return $ret;
981 if ($inputarr !== false) {
982 if (!is_array($inputarr)) $inputarr = array($inputarr);
984 $element0 = reset($inputarr);
985 # is_object check because oci8 descriptors can be passed in
986 $array_2d = $this->bulkBind
&& is_array($element0) && !is_object(reset($element0));
988 //remove extra memory copy of input -mikefedyk
991 if (!is_array($sql) && !$this->_bindInputArray
) {
992 $sqlarr = explode('?',$sql);
993 $nparams = sizeof($sqlarr)-1;
994 if (!$array_2d) $inputarr = array($inputarr);
996 foreach($inputarr as $arr) {
998 //Use each() instead of foreach to reduce memory usage -mikefedyk
999 while(list(, $v) = each($arr)) {
1000 $sql .= $sqlarr[$i];
1001 // from Ron Baldwin <ron.baldwin#sourceprose.com>
1002 // Only quote string types
1004 if ($typ == 'string')
1005 //New memory copy of input created here -mikefedyk
1006 $sql .= $this->qstr($v);
1007 else if ($typ == 'double')
1008 $sql .= str_replace(',','.',$v); // locales fix so 1.1 does not get converted to 1,1
1009 else if ($typ == 'boolean')
1010 $sql .= $v ?
$this->true : $this->false;
1011 else if ($typ == 'object') {
1012 if (method_exists($v, '__toString')) $sql .= $this->qstr($v->__toString());
1013 else $sql .= $this->qstr((string) $v);
1014 } else if ($v === null)
1020 if ($i == $nparams) break;
1022 if (isset($sqlarr[$i])) {
1023 $sql .= $sqlarr[$i];
1024 if ($i+
1 != sizeof($sqlarr)) $this->outp_throw( "Input Array does not match ?: ".htmlspecialchars($sql),'Execute');
1025 } else if ($i != sizeof($sqlarr))
1026 $this->outp_throw( "Input array does not match ?: ".htmlspecialchars($sql),'Execute');
1028 $ret = $this->_Execute($sql);
1029 if (!$ret) return $ret;
1033 if (is_string($sql))
1034 $stmt = $this->Prepare($sql);
1038 foreach($inputarr as $arr) {
1039 $ret = $this->_Execute($stmt,$arr);
1040 if (!$ret) return $ret;
1043 $ret = $this->_Execute($sql,$inputarr);
1047 $ret = $this->_Execute($sql,false);
1054 function _Execute($sql,$inputarr=false)
1057 global $ADODB_INCLUDED_LIB;
1058 if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR
.'/adodb-lib.inc.php');
1059 $this->_queryID
= _adodb_debug_execute($this, $sql,$inputarr);
1061 $this->_queryID
= @$this->_query($sql,$inputarr);
1064 // ************************
1065 // OK, query executed
1066 // ************************
1068 if ($this->_queryID
=== false) { // error handling if query fails
1069 if ($this->debug
== 99) adodb_backtrace(true,5);
1070 $fn = $this->raiseErrorFn
;
1072 $fn($this->databaseType
,'EXECUTE',$this->ErrorNo(),$this->ErrorMsg(),$sql,$inputarr,$this);
1078 if ($this->_queryID
=== true) { // return simplified recordset for inserts/updates/deletes with lower overhead
1079 $rsclass = $this->rsPrefix
.'empty';
1080 $rs = (class_exists($rsclass)) ?
new $rsclass(): new ADORecordSet_empty();
1085 // return real recordset from select statement
1086 $rsclass = $this->rsPrefix
.$this->databaseType
;
1087 $rs = new $rsclass($this->_queryID
,$this->fetchMode
);
1088 $rs->connection
= $this; // Pablo suggestion
1090 if (is_array($sql)) $rs->sql
= $sql[0];
1091 else $rs->sql
= $sql;
1092 if ($rs->_numOfRows
<= 0) {
1093 global $ADODB_COUNTRECS;
1094 if ($ADODB_COUNTRECS) {
1096 $rs = $this->_rs2rs($rs,-1,-1,!is_array($sql));
1097 $rs->_queryID
= $this->_queryID
;
1099 $rs->_numOfRows
= 0;
1105 function CreateSequence($seqname='adodbseq',$startID=1)
1107 if (empty($this->_genSeqSQL
)) return false;
1108 return $this->Execute(sprintf($this->_genSeqSQL
,$seqname,$startID));
1111 function DropSequence($seqname='adodbseq')
1113 if (empty($this->_dropSeqSQL
)) return false;
1114 return $this->Execute(sprintf($this->_dropSeqSQL
,$seqname));
1118 * Generates a sequence id and stores it in $this->genID;
1119 * GenID is only available if $this->hasGenID = true;
1121 * @param seqname name of sequence to use
1122 * @param startID if sequence does not exist, start at this ID
1123 * @return 0 if not supported, otherwise a sequence id
1125 function GenID($seqname='adodbseq',$startID=1)
1127 if (!$this->hasGenID
) {
1128 return 0; // formerly returns false pre 1.60
1131 $getnext = sprintf($this->_genIDSQL
,$seqname);
1133 $holdtransOK = $this->_transOK
;
1135 $save_handler = $this->raiseErrorFn
;
1136 $this->raiseErrorFn
= '';
1137 @($rs = $this->Execute($getnext));
1138 $this->raiseErrorFn
= $save_handler;
1141 $this->_transOK
= $holdtransOK; //if the status was ok before reset
1142 $createseq = $this->Execute(sprintf($this->_genSeqSQL
,$seqname,$startID));
1143 $rs = $this->Execute($getnext);
1145 if ($rs && !$rs->EOF
) $this->genID
= reset($rs->fields
);
1146 else $this->genID
= 0; // false
1148 if ($rs) $rs->Close();
1150 return $this->genID
;
1154 * @param $table string name of the table, not needed by all databases (eg. mysql), default ''
1155 * @param $column string name of the column, not needed by all databases (eg. mysql), default ''
1156 * @return the last inserted ID. Not all databases support this.
1158 function Insert_ID($table='',$column='')
1160 if ($this->_logsql
&& $this->lastInsID
) return $this->lastInsID
;
1161 if ($this->hasInsertID
) return $this->_insertid($table,$column);
1163 ADOConnection
::outp( '<p>Insert_ID error</p>');
1171 * Portable Insert ID. Pablo Roca <pabloroca#mvps.org>
1173 * @return the last inserted ID. All databases support this. But aware possible
1174 * problems in multiuser environments. Heavy test this before deploying.
1176 function PO_Insert_ID($table="", $id="")
1178 if ($this->hasInsertID
){
1179 return $this->Insert_ID($table,$id);
1181 return $this->GetOne("SELECT MAX($id) FROM $table");
1186 * @return # rows affected by UPDATE/DELETE
1188 function Affected_Rows()
1190 if ($this->hasAffectedRows
) {
1191 if ($this->fnExecute
=== 'adodb_log_sql') {
1192 if ($this->_logsql
&& $this->_affected
!== false) return $this->_affected
;
1194 $val = $this->_affectedrows();
1195 return ($val < 0) ?
false : $val;
1198 if ($this->debug
) ADOConnection
::outp( '<p>Affected_Rows error</p>',false);
1204 * @return the last error message
1208 if ($this->_errorMsg
) return '!! '.strtoupper($this->dataProvider
.' '.$this->databaseType
).': '.$this->_errorMsg
;
1214 * @return the last error number. Normally 0 means no error.
1218 return ($this->_errorMsg
) ?
-1 : 0;
1221 function MetaError($err=false)
1223 include_once(ADODB_DIR
."/adodb-error.inc.php");
1224 if ($err === false) $err = $this->ErrorNo();
1225 return adodb_error($this->dataProvider
,$this->databaseType
,$err);
1228 function MetaErrorMsg($errno)
1230 include_once(ADODB_DIR
."/adodb-error.inc.php");
1231 return adodb_errormsg($errno);
1235 * @returns an array with the primary key columns in it.
1237 function MetaPrimaryKeys($table, $owner=false)
1239 // owner not used in base class - see oci8
1241 $objs = $this->MetaColumns($table);
1243 foreach($objs as $v) {
1244 if (!empty($v->primary_key
))
1248 if (sizeof($p)) return $p;
1249 if (function_exists('ADODB_VIEW_PRIMARYKEYS'))
1250 return ADODB_VIEW_PRIMARYKEYS($this->databaseType
, $this->database
, $table, $owner);
1255 * @returns assoc array where keys are tables, and values are foreign keys
1257 function MetaForeignKeys($table, $owner=false, $upper=false)
1262 * Choose a database to connect to. Many databases do not support this.
1264 * @param dbName is the name of the database to select
1265 * @return true or false
1267 function SelectDB($dbName)
1272 * Will select, getting rows from $offset (1-based), for $nrows.
1273 * This simulates the MySQL "select * from table limit $offset,$nrows" , and
1274 * the PostgreSQL "select * from table limit $nrows offset $offset". Note that
1275 * MySQL and PostgreSQL parameter ordering is the opposite of the other.
1277 * SelectLimit('select * from table',3); will return rows 1 to 3 (1-based)
1278 * SelectLimit('select * from table',3,2); will return rows 3 to 5 (1-based)
1280 * Uses SELECT TOP for Microsoft databases (when $this->hasTop is set)
1281 * BUG: Currently SelectLimit fails with $sql with LIMIT or TOP clause already set
1284 * @param [offset] is the row to start calculations from (1-based)
1285 * @param [nrows] is the number of rows to get
1286 * @param [inputarr] array of bind variables
1287 * @param [secs2cache] is a private parameter only used by jlim
1288 * @return the recordset ($rs->databaseType == 'array')
1290 function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
1292 if ($this->hasTop
&& $nrows > 0) {
1293 // suggested by Reinhard Balling. Access requires top after distinct
1294 // Informix requires first before distinct - F Riosa
1295 $ismssql = (strpos($this->databaseType
,'mssql') !== false);
1296 if ($ismssql) $isaccess = false;
1297 else $isaccess = (strpos($this->databaseType
,'access') !== false);
1301 // access includes ties in result
1303 $sql = preg_replace(
1304 '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop
.' '.((integer)$nrows).' ',$sql);
1306 if ($secs2cache != 0) {
1307 $ret = $this->CacheExecute($secs2cache, $sql,$inputarr);
1309 $ret = $this->Execute($sql,$inputarr);
1311 return $ret; // PHP5 fix
1312 } else if ($ismssql){
1313 $sql = preg_replace(
1314 '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop
.' '.((integer)$nrows).' ',$sql);
1316 $sql = preg_replace(
1317 '/(^\s*select\s)/i','\\1 '.$this->hasTop
.' '.((integer)$nrows).' ',$sql);
1320 $nn = $nrows +
$offset;
1321 if ($isaccess ||
$ismssql) {
1322 $sql = preg_replace(
1323 '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop
.' '.$nn.' ',$sql);
1325 $sql = preg_replace(
1326 '/(^\s*select\s)/i','\\1 '.$this->hasTop
.' '.$nn.' ',$sql);
1331 // if $offset>0, we want to skip rows, and $ADODB_COUNTRECS is set, we buffer rows
1332 // 0 to offset-1 which will be discarded anyway. So we disable $ADODB_COUNTRECS.
1333 global $ADODB_COUNTRECS;
1335 $savec = $ADODB_COUNTRECS;
1336 $ADODB_COUNTRECS = false;
1339 if ($secs2cache != 0) $rs = $this->CacheExecute($secs2cache,$sql,$inputarr);
1340 else $rs = $this->Execute($sql,$inputarr);
1342 $ADODB_COUNTRECS = $savec;
1343 if ($rs && !$rs->EOF
) {
1344 $rs = $this->_rs2rs($rs,$nrows,$offset);
1351 * Create serializable recordset. Breaks rs link to connection.
1353 * @param rs the recordset to serialize
1355 function SerializableRS(&$rs)
1357 $rs2 = $this->_rs2rs($rs);
1359 $rs2->connection
= $ignore;
1365 * Convert database recordset to an array recordset
1366 * input recordset's cursor should be at beginning, and
1367 * old $rs will be closed.
1369 * @param rs the recordset to copy
1370 * @param [nrows] number of rows to retrieve (optional)
1371 * @param [offset] offset by number of rows (optional)
1372 * @return the new recordset
1374 function &_rs2rs(&$rs,$nrows=-1,$offset=-1,$close=true)
1380 $dbtype = $rs->databaseType
;
1382 $rs = $rs; // required to prevent crashing in 4.2.1, but does not happen in 4.3.1 -- why ?
1385 if (($dbtype == 'array' ||
$dbtype == 'csv') && $nrows == -1 && $offset == -1) {
1387 $rs = $rs; // required to prevent crashing in 4.2.1, but does not happen in 4.3.1-- why ?
1391 for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++
) {
1392 $flds[] = $rs->FetchField($i);
1395 $arr = $rs->GetArrayLimit($nrows,$offset);
1397 if ($close) $rs->Close();
1399 $arrayClass = $this->arrayClass
;
1401 $rs2 = new $arrayClass();
1402 $rs2->connection
= $this;
1403 $rs2->sql
= $rs->sql
;
1404 $rs2->dataProvider
= $this->dataProvider
;
1405 $rs2->InitArrayFields($arr,$flds);
1406 $rs2->fetchMode
= isset($rs->adodbFetchMode
) ?
$rs->adodbFetchMode
: $rs->fetchMode
;
1411 * Return all rows. Compat with PEAR DB
1413 function GetAll($sql, $inputarr=false)
1415 $arr = $this->GetArray($sql,$inputarr);
1419 function GetAssoc($sql, $inputarr=false,$force_array = false, $first2cols = false)
1421 $rs = $this->Execute($sql, $inputarr);
1426 $arr = $rs->GetAssoc($force_array,$first2cols);
1430 function CacheGetAssoc($secs2cache, $sql=false, $inputarr=false,$force_array = false, $first2cols = false)
1432 if (!is_numeric($secs2cache)) {
1433 $first2cols = $force_array;
1434 $force_array = $inputarr;
1436 $rs = $this->CacheExecute($secs2cache, $sql, $inputarr);
1441 $arr = $rs->GetAssoc($force_array,$first2cols);
1446 * Return first element of first row of sql statement. Recordset is disposed
1449 * @param sql SQL statement
1450 * @param [inputarr] input bind array
1452 function GetOne($sql,$inputarr=false)
1454 global $ADODB_COUNTRECS,$ADODB_GETONE_EOF;
1455 $crecs = $ADODB_COUNTRECS;
1456 $ADODB_COUNTRECS = false;
1459 $rs = $this->Execute($sql,$inputarr);
1461 if ($rs->EOF
) $ret = $ADODB_GETONE_EOF;
1462 else $ret = reset($rs->fields
);
1466 $ADODB_COUNTRECS = $crecs;
1470 // $where should include 'WHERE fld=value'
1471 function GetMedian($table, $field,$where = '')
1473 $total = $this->GetOne("select count(*) from $table $where");
1474 if (!$total) return false;
1476 $midrow = (integer) ($total/2);
1477 $rs = $this->SelectLimit("select $field from $table $where order by 1",1,$midrow);
1478 if ($rs && !$rs->EOF
) return reset($rs->fields
);
1483 function CacheGetOne($secs2cache,$sql=false,$inputarr=false)
1485 global $ADODB_GETONE_EOF;
1487 $rs = $this->CacheExecute($secs2cache,$sql,$inputarr);
1489 if ($rs->EOF
) $ret = $ADODB_GETONE_EOF;
1490 else $ret = reset($rs->fields
);
1497 function GetCol($sql, $inputarr = false, $trim = false)
1500 $rs = $this->Execute($sql, $inputarr);
1505 $rv[] = trim(reset($rs->fields
));
1510 $rv[] = reset($rs->fields
);
1520 function CacheGetCol($secs, $sql = false, $inputarr = false,$trim=false)
1522 $rs = $this->CacheExecute($secs, $sql, $inputarr);
1527 $rv[] = trim(reset($rs->fields
));
1532 $rv[] = reset($rs->fields
);
1543 function Transpose(&$rs,$addfieldnames=true)
1545 $rs2 = $this->_rs2rs($rs);
1547 if (!$rs2) return $false;
1549 $rs2->_transpose($addfieldnames);
1554 Calculate the offset of a date for a particular database and generate
1555 appropriate SQL. Useful for calculating future/past dates and storing
1558 If dayFraction=1.5 means 1.5 days from now, 1.0/24 for 1 hour.
1560 function OffsetDate($dayFraction,$date=false)
1562 if (!$date) $date = $this->sysDate
;
1563 return '('.$date.'+'.$dayFraction.')';
1569 * @param sql SQL statement
1570 * @param [inputarr] input bind array
1572 function GetArray($sql,$inputarr=false)
1574 global $ADODB_COUNTRECS;
1576 $savec = $ADODB_COUNTRECS;
1577 $ADODB_COUNTRECS = false;
1578 $rs = $this->Execute($sql,$inputarr);
1579 $ADODB_COUNTRECS = $savec;
1581 if (defined('ADODB_PEAR')) {
1582 $cls = ADODB_PEAR_Error();
1588 $arr = $rs->GetArray();
1593 function CacheGetAll($secs2cache,$sql=false,$inputarr=false)
1595 $arr = $this->CacheGetArray($secs2cache,$sql,$inputarr);
1599 function CacheGetArray($secs2cache,$sql=false,$inputarr=false)
1601 global $ADODB_COUNTRECS;
1603 $savec = $ADODB_COUNTRECS;
1604 $ADODB_COUNTRECS = false;
1605 $rs = $this->CacheExecute($secs2cache,$sql,$inputarr);
1606 $ADODB_COUNTRECS = $savec;
1609 if (defined('ADODB_PEAR')) {
1610 $cls = ADODB_PEAR_Error();
1616 $arr = $rs->GetArray();
1621 function GetRandRow($sql, $arr= false)
1623 $rezarr = $this->GetAll($sql, $arr);
1624 $sz = sizeof($rezarr);
1625 return $rezarr[abs(rand()) %
$sz];
1629 * Return one row of sql statement. Recordset is disposed for you.
1630 * Note that SelectLimit should not be called.
1632 * @param sql SQL statement
1633 * @param [inputarr] input bind array
1635 function GetRow($sql,$inputarr=false)
1637 global $ADODB_COUNTRECS;
1638 $crecs = $ADODB_COUNTRECS;
1639 $ADODB_COUNTRECS = false;
1641 $rs = $this->Execute($sql,$inputarr);
1643 $ADODB_COUNTRECS = $crecs;
1645 if (!$rs->EOF
) $arr = $rs->fields
;
1646 else $arr = array();
1655 function CacheGetRow($secs2cache,$sql=false,$inputarr=false)
1657 $rs = $this->CacheExecute($secs2cache,$sql,$inputarr);
1659 if (!$rs->EOF
) $arr = $rs->fields
;
1660 else $arr = array();
1670 * Insert or replace a single record. Note: this is not the same as MySQL's replace.
1671 * ADOdb's Replace() uses update-insert semantics, not insert-delete-duplicates of MySQL.
1672 * Also note that no table locking is done currently, so it is possible that the
1673 * record be inserted twice by two programs...
1675 * $this->Replace('products', array('prodname' =>"'Nails'","price" => 3.99), 'prodname');
1678 * $fieldArray associative array of data (you must quote strings yourself).
1679 * $keyCol the primary key field name or if compound key, array of field names
1680 * autoQuote set to true to use a hueristic to quote strings. Works with nulls and numbers
1681 * but does not work with dates nor SQL functions.
1682 * has_autoinc the primary key is an auto-inc field, so skip in insert.
1684 * Currently blob replace not supported
1686 * returns 0 = fail, 1 = update, 2 = insert
1689 function Replace($table, $fieldArray, $keyCol, $autoQuote=false, $has_autoinc=false)
1691 global $ADODB_INCLUDED_LIB;
1692 if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR
.'/adodb-lib.inc.php');
1694 return _adodb_replace($this, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc);
1699 * Will select, getting rows from $offset (1-based), for $nrows.
1700 * This simulates the MySQL "select * from table limit $offset,$nrows" , and
1701 * the PostgreSQL "select * from table limit $nrows offset $offset". Note that
1702 * MySQL and PostgreSQL parameter ordering is the opposite of the other.
1704 * CacheSelectLimit(15,'select * from table',3); will return rows 1 to 3 (1-based)
1705 * CacheSelectLimit(15,'select * from table',3,2); will return rows 3 to 5 (1-based)
1707 * BUG: Currently CacheSelectLimit fails with $sql with LIMIT or TOP clause already set
1709 * @param [secs2cache] seconds to cache data, set to 0 to force query. This is optional
1711 * @param [offset] is the row to start calculations from (1-based)
1712 * @param [nrows] is the number of rows to get
1713 * @param [inputarr] array of bind variables
1714 * @return the recordset ($rs->databaseType == 'array')
1716 function CacheSelectLimit($secs2cache,$sql,$nrows=-1,$offset=-1,$inputarr=false)
1718 if (!is_numeric($secs2cache)) {
1719 if ($sql === false) $sql = -1;
1720 if ($offset == -1) $offset = false;
1721 // sql, nrows, offset,inputarr
1722 $rs = $this->SelectLimit($secs2cache,$sql,$nrows,$offset,$this->cacheSecs
);
1724 if ($sql === false) $this->outp_throw("Warning: \$sql missing from CacheSelectLimit()",'CacheSelectLimit');
1725 $rs = $this->SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
1732 * Flush cached recordsets that match a particular $sql statement.
1733 * If $sql == false, then we purge all files in the cache.
1737 * Flush cached recordsets that match a particular $sql statement.
1738 * If $sql == false, then we purge all files in the cache.
1740 function CacheFlush($sql=false,$inputarr=false)
1742 global $ADODB_CACHE_DIR, $ADODB_CACHE;
1744 if (empty($ADODB_CACHE)) return false;
1747 $ADODB_CACHE->flushall($this->debug
);
1751 $f = $this->_gencachename($sql.serialize($inputarr),false);
1752 return $ADODB_CACHE->flushcache($f, $this->debug
);
1757 * Private function to generate filename for caching.
1758 * Filename is generated based on:
1761 * - database type (oci8, ibase, ifx, etc)
1764 * - setFetchMode (adodb 4.23)
1766 * When not in safe mode, we create 256 sub-directories in the cache directory ($ADODB_CACHE_DIR).
1767 * Assuming that we can have 50,000 files per directory with good performance,
1768 * then we can scale to 12.8 million unique cached recordsets. Wow!
1770 function _gencachename($sql,$createdir)
1772 global $ADODB_CACHE, $ADODB_CACHE_DIR;
1774 if ($this->fetchMode
=== false) {
1775 global $ADODB_FETCH_MODE;
1776 $mode = $ADODB_FETCH_MODE;
1778 $mode = $this->fetchMode
;
1780 $m = md5($sql.$this->databaseType
.$this->database
.$this->user
.$mode);
1781 if (!$ADODB_CACHE->createdir
) return $m;
1782 if (!$createdir) $dir = $ADODB_CACHE->getdirname($m);
1783 else $dir = $ADODB_CACHE->createdir($m, $this->debug
);
1785 return $dir.'/adodb_'.$m.'.cache';
1790 * Execute SQL, caching recordsets.
1792 * @param [secs2cache] seconds to cache data, set to 0 to force query.
1793 * This is an optional parameter.
1794 * @param sql SQL statement to execute
1795 * @param [inputarr] holds the input data to bind to
1796 * @return RecordSet or false
1798 function CacheExecute($secs2cache,$sql=false,$inputarr=false)
1800 global $ADODB_CACHE;
1802 if (empty($ADODB_CACHE)) $this->_CreateCache();
1804 if (!is_numeric($secs2cache)) {
1807 $secs2cache = $this->cacheSecs
;
1810 if (is_array($sql)) {
1817 $md5file = $this->_gencachename($sql.serialize($inputarr),true);
1820 if ($secs2cache > 0){
1821 $rs = $ADODB_CACHE->readcache($md5file,$err,$secs2cache,$this->arrayClass
);
1822 $this->numCacheHits +
= 1;
1826 $this->numCacheMisses +
= 1;
1830 // no cached rs found
1832 if (get_magic_quotes_runtime() && !$this->memCache
) {
1833 ADOConnection
::outp("Please disable magic_quotes_runtime - it corrupts cache files :(");
1835 if ($this->debug
!== -1) ADOConnection
::outp( " $md5file cache failure: $err (this is a notice and not an error)");
1838 $rs = $this->Execute($sqlparam,$inputarr);
1843 $rs = $this->_rs2rs($rs); // read entire recordset into memory immediately
1844 $rs->timeCreated
= time(); // used by caching
1845 $txt = _rs2serialize($rs,false,$sql); // serialize
1847 $ok = $ADODB_CACHE->writecache($md5file,$txt,$this->debug
, $secs2cache);
1849 if ($ok === false) {
1850 $em = 'Cache write error';
1853 if ($fn = $this->raiseErrorFn
) {
1854 $fn($this->databaseType
,'CacheExecute', $en, $em, $md5file,$sql,$this);
1857 $em = 'Cache file locked warning';
1859 // do not call error handling for just a warning
1862 if ($this->debug
) ADOConnection
::outp( " ".$em);
1864 if ($rs->EOF
&& !$eof) {
1866 //$rs = csv2rs($md5file,$err);
1867 $rs->connection
= $this; // Pablo suggestion
1870 } else if (!$this->memCache
)
1871 $ADODB_CACHE->flushcache($md5file);
1873 $this->_errorMsg
= '';
1874 $this->_errorCode
= 0;
1876 if ($this->fnCacheExecute
) {
1877 $fn = $this->fnCacheExecute
;
1878 $fn($this, $secs2cache, $sql, $inputarr);
1880 // ok, set cached object found
1881 $rs->connection
= $this; // Pablo suggestion
1883 if ($this->debug
== 99) adodb_backtrace();
1884 $inBrowser = isset($_SERVER['HTTP_USER_AGENT']);
1885 $ttl = $rs->timeCreated +
$secs2cache - time();
1886 $s = is_array($sql) ?
$sql[0] : $sql;
1887 if ($inBrowser) $s = '<i>'.htmlspecialchars($s).'</i>';
1889 ADOConnection
::outp( " $md5file reloaded, ttl=$ttl [ $s ]");
1897 Similar to PEAR DB's autoExecute(), except that
1898 $mode can be 'INSERT' or 'UPDATE' or DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE
1899 If $mode == 'UPDATE', then $where is compulsory as a safety measure.
1901 $forceUpdate means that even if the data has not changed, perform update.
1903 function AutoExecute($table, $fields_values, $mode = 'INSERT', $where = FALSE, $forceUpdate=true, $magicq=false)
1906 $sql = 'SELECT * FROM '.$table;
1907 if ($where!==FALSE) $sql .= ' WHERE '.$where;
1908 else if ($mode == 'UPDATE' ||
$mode == 2 /* DB_AUTOQUERY_UPDATE */) {
1909 $this->outp_throw('AutoExecute: Illegal mode=UPDATE with empty WHERE clause','AutoExecute');
1913 $rs = $this->SelectLimit($sql,1);
1914 if (!$rs) return $false; // table does not exist
1915 $rs->tableName
= $table;
1918 switch((string) $mode) {
1921 $sql = $this->GetUpdateSQL($rs, $fields_values, $forceUpdate, $magicq);
1925 $sql = $this->GetInsertSQL($rs, $fields_values, $magicq);
1928 $this->outp_throw("AutoExecute: Unknown mode=$mode",'AutoExecute');
1932 if ($sql) $ret = $this->Execute($sql);
1933 if ($ret) $ret = true;
1939 * Generates an Update Query based on an existing recordset.
1940 * $arrFields is an associative array of fields with the value
1941 * that should be assigned.
1943 * Note: This function should only be used on a recordset
1944 * that is run against a single table and sql should only
1945 * be a simple select stmt with no groupby/orderby/limit
1947 * "Jonathan Younger" <jyounger@unilab.com>
1949 function GetUpdateSQL(&$rs, $arrFields,$forceUpdate=false,$magicq=false,$force=null)
1951 global $ADODB_INCLUDED_LIB;
1953 // ********************************************************
1954 // This is here to maintain compatibility
1955 // with older adodb versions. Sets force type to force nulls if $forcenulls is set.
1956 if (!isset($force)) {
1957 global $ADODB_FORCE_TYPE;
1958 $force = $ADODB_FORCE_TYPE;
1960 // ********************************************************
1962 if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR
.'/adodb-lib.inc.php');
1963 return _adodb_getupdatesql($this,$rs,$arrFields,$forceUpdate,$magicq,$force);
1967 * Generates an Insert Query based on an existing recordset.
1968 * $arrFields is an associative array of fields with the value
1969 * that should be assigned.
1971 * Note: This function should only be used on a recordset
1972 * that is run against a single table.
1974 function GetInsertSQL(&$rs, $arrFields,$magicq=false,$force=null)
1976 global $ADODB_INCLUDED_LIB;
1977 if (!isset($force)) {
1978 global $ADODB_FORCE_TYPE;
1979 $force = $ADODB_FORCE_TYPE;
1982 if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR
.'/adodb-lib.inc.php');
1983 return _adodb_getinsertsql($this,$rs,$arrFields,$magicq,$force);
1988 * Update a blob column, given a where clause. There are more sophisticated
1989 * blob handling functions that we could have implemented, but all require
1990 * a very complex API. Instead we have chosen something that is extremely
1991 * simple to understand and use.
1993 * Note: $blobtype supports 'BLOB' and 'CLOB', default is BLOB of course.
1995 * Usage to update a $blobvalue which has a primary key blob_id=1 into a
1996 * field blobtable.blobcolumn:
1998 * UpdateBlob('blobtable', 'blobcolumn', $blobvalue, 'blob_id=1');
2002 * $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
2003 * $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
2006 function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
2008 return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false;
2013 * UpdateBlob('TABLE', 'COLUMN', '/path/to/file', 'ID=1');
2015 * $blobtype supports 'BLOB' and 'CLOB'
2017 * $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
2018 * $conn->UpdateBlob('blobtable','blobcol',$blobpath,'id=1');
2020 function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
2022 $fd = fopen($path,'rb');
2023 if ($fd === false) return false;
2024 $val = fread($fd,filesize($path));
2026 return $this->UpdateBlob($table,$column,$val,$where,$blobtype);
2029 function BlobDecode($blob)
2034 function BlobEncode($blob)
2039 function SetCharSet($charset)
2044 function IfNull( $field, $ifNull )
2046 return " CASE WHEN $field is null THEN $ifNull ELSE $field END ";
2049 function LogSQL($enable=true)
2051 include_once(ADODB_DIR
.'/adodb-perf.inc.php');
2053 if ($enable) $this->fnExecute
= 'adodb_log_sql';
2054 else $this->fnExecute
= false;
2056 $old = $this->_logsql
;
2057 $this->_logsql
= $enable;
2058 if ($enable && !$old) $this->_affected
= false;
2062 function GetCharSet()
2069 * UpdateClob('TABLE', 'COLUMN', $var, 'ID=1', 'CLOB');
2071 * $conn->Execute('INSERT INTO clobtable (id, clobcol) VALUES (1, null)');
2072 * $conn->UpdateClob('clobtable','clobcol',$clob,'id=1');
2074 function UpdateClob($table,$column,$val,$where)
2076 return $this->UpdateBlob($table,$column,$val,$where,'CLOB');
2079 // not the fastest implementation - quick and dirty - jlim
2080 // for best performance, use the actual $rs->MetaType().
2081 function MetaType($t,$len=-1,$fieldobj=false)
2084 if (empty($this->_metars
)) {
2085 $rsclass = $this->rsPrefix
.$this->databaseType
;
2086 $this->_metars
= new $rsclass(false,$this->fetchMode
);
2087 $this->_metars
->connection
= $this;
2089 return $this->_metars
->MetaType($t,$len,$fieldobj);
2094 * Change the SQL connection locale to a specified locale.
2095 * This is used to get the date formats written depending on the client locale.
2097 function SetDateLocale($locale = 'En')
2099 $this->locale
= $locale;
2100 switch (strtoupper($locale))
2103 $this->fmtDate
="'Y-m-d'";
2104 $this->fmtTimeStamp
= "'Y-m-d H:i:s'";
2108 $this->fmtDate
= "'m-d-Y'";
2109 $this->fmtTimeStamp
= "'m-d-Y H:i:s'";
2117 $this->fmtDate
="'d-m-Y'";
2118 $this->fmtTimeStamp
= "'d-m-Y H:i:s'";
2122 $this->fmtDate
="'d.m.Y'";
2123 $this->fmtTimeStamp
= "'d.m.Y H:i:s'";
2127 $this->fmtDate
="'Y-m-d'";
2128 $this->fmtTimeStamp
= "'Y-m-d H:i:s'";
2134 * GetActiveRecordsClass Performs an 'ALL' query
2136 * @param mixed $class This string represents the class of the current active record
2137 * @param mixed $table Table used by the active record object
2138 * @param mixed $whereOrderBy Where, order, by clauses
2139 * @param mixed $bindarr
2140 * @param mixed $primkeyArr
2141 * @param array $extra Query extras: limit, offset...
2142 * @param mixed $relations Associative array: table's foreign name, "hasMany", "belongsTo"
2146 function GetActiveRecordsClass(
2147 $class, $table,$whereOrderBy=false,$bindarr=false, $primkeyArr=false,
2151 global $_ADODB_ACTIVE_DBS;
2152 ## reduce overhead of adodb.inc.php -- moved to adodb-active-record.inc.php
2153 ## if adodb-active-recordx is loaded -- should be no issue as they will probably use Find()
2154 if (!isset($_ADODB_ACTIVE_DBS))include_once(ADODB_DIR
.'/adodb-active-record.inc.php');
2155 return adodb_GetActiveRecordsClass($this, $class, $table, $whereOrderBy, $bindarr, $primkeyArr, $extra, $relations);
2158 function GetActiveRecords($table,$where=false,$bindarr=false,$primkeyArr=false)
2160 $arr = $this->GetActiveRecordsClass('ADODB_Active_Record', $table, $where, $bindarr, $primkeyArr);
2169 $rez = $this->_close();
2170 $this->_connectionID
= false;
2175 * Begin a Transaction. Must be followed by CommitTrans() or RollbackTrans().
2177 * @return true if succeeded or false if database does not support transactions
2179 function BeginTrans()
2181 if ($this->debug
) ADOConnection
::outp("BeginTrans: Transactions not supported for this driver");
2185 /* set transaction mode */
2186 function SetTransactionMode( $transaction_mode )
2188 $transaction_mode = $this->MetaTransaction($transaction_mode, $this->dataProvider
);
2189 $this->_transmode
= $transaction_mode;
2192 http://msdn2.microsoft.com/en-US/ms173763.aspx
2193 http://dev.mysql.com/doc/refman/5.0/en/innodb-transaction-isolation.html
2194 http://www.postgresql.org/docs/8.1/interactive/sql-set-transaction.html
2195 http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_10005.htm
2197 function MetaTransaction($mode,$db)
2199 $mode = strtoupper($mode);
2200 $mode = str_replace('ISOLATION LEVEL ','',$mode);
2204 case 'READ UNCOMMITTED':
2208 return 'ISOLATION LEVEL READ COMMITTED';
2210 return 'ISOLATION LEVEL READ UNCOMMITTED';
2214 case 'READ COMMITTED':
2215 return 'ISOLATION LEVEL READ COMMITTED';
2218 case 'REPEATABLE READ':
2222 return 'ISOLATION LEVEL SERIALIZABLE';
2224 return 'ISOLATION LEVEL REPEATABLE READ';
2228 case 'SERIALIZABLE':
2229 return 'ISOLATION LEVEL SERIALIZABLE';
2238 * If database does not support transactions, always return true as data always commited
2240 * @param $ok set to false to rollback transaction, true to commit
2242 * @return true/false.
2244 function CommitTrans($ok=true)
2249 * If database does not support transactions, rollbacks always fail, so return false
2251 * @return true/false.
2253 function RollbackTrans()
2258 * return the databases that the driver can connect to.
2259 * Some databases will return an empty array.
2261 * @return an array of database names.
2263 function MetaDatabases()
2265 global $ADODB_FETCH_MODE;
2267 if ($this->metaDatabasesSQL
) {
2268 $save = $ADODB_FETCH_MODE;
2269 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
2271 if ($this->fetchMode
!== false) $savem = $this->SetFetchMode(false);
2273 $arr = $this->GetCol($this->metaDatabasesSQL
);
2274 if (isset($savem)) $this->SetFetchMode($savem);
2275 $ADODB_FETCH_MODE = $save;
2284 * List procedures or functions in an array.
2285 * @param procedureNamePattern a procedure name pattern; must match the procedure name as it is stored in the database
2286 * @param catalog a catalog name; must match the catalog name as it is stored in the database;
2287 * @param schemaPattern a schema name pattern;
2289 * @return array of procedures on current database.
2292 * [name_of_procedure] => Array(
2293 * [type] => PROCEDURE or FUNCTION
2294 * [catalog] => Catalog_name
2295 * [schema] => Schema_name
2296 * [remarks] => explanatory comment on the procedure
2300 function MetaProcedures($procedureNamePattern = null, $catalog = null, $schemaPattern = null)
2307 * @param ttype can either be 'VIEW' or 'TABLE' or false.
2308 * If false, both views and tables are returned.
2309 * "VIEW" returns only views
2310 * "TABLE" returns only tables
2311 * @param showSchema returns the schema/user with the table name, eg. USER.TABLE
2312 * @param mask is the input mask - only supported by oci8 and postgresql
2314 * @return array of tables for current database.
2316 function MetaTables($ttype=false,$showSchema=false,$mask=false)
2318 global $ADODB_FETCH_MODE;
2325 if ($this->metaTablesSQL
) {
2326 $save = $ADODB_FETCH_MODE;
2327 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
2329 if ($this->fetchMode
!== false) $savem = $this->SetFetchMode(false);
2331 $rs = $this->Execute($this->metaTablesSQL
);
2332 if (isset($savem)) $this->SetFetchMode($savem);
2333 $ADODB_FETCH_MODE = $save;
2335 if ($rs === false) return $false;
2336 $arr = $rs->GetArray();
2339 if ($hast = ($ttype && isset($arr[0][1]))) {
2340 $showt = strncmp($ttype,'T',1);
2343 for ($i=0; $i < sizeof($arr); $i++
) {
2346 if (strncmp($arr[$i][1],'T',1) == 0) $arr2[] = trim($arr[$i][0]);
2348 if (strncmp($arr[$i][1],'V',1) == 0) $arr2[] = trim($arr[$i][0]);
2351 $arr2[] = trim($arr[$i][0]);
2360 function _findschema(&$table,&$schema)
2362 if (!$schema && ($at = strpos($table,'.')) !== false) {
2363 $schema = substr($table,0,$at);
2364 $table = substr($table,$at+
1);
2369 * List columns in a database as an array of ADOFieldObjects.
2370 * See top of file for definition of object.
2372 * @param $table table name to query
2373 * @param $normalize makes table name case-insensitive (required by some databases)
2374 * @schema is optional database schema to use - not supported by all databases.
2376 * @return array of ADOFieldObjects for current table.
2378 function MetaColumns($table,$normalize=true)
2380 global $ADODB_FETCH_MODE;
2384 if (!empty($this->metaColumnsSQL
)) {
2387 $this->_findschema($table,$schema);
2389 $save = $ADODB_FETCH_MODE;
2390 $ADODB_FETCH_MODE = ADODB_FETCH_NUM
;
2391 if ($this->fetchMode
!== false) $savem = $this->SetFetchMode(false);
2392 $rs = $this->Execute(sprintf($this->metaColumnsSQL
,($normalize)?
strtoupper($table):$table));
2393 if (isset($savem)) $this->SetFetchMode($savem);
2394 $ADODB_FETCH_MODE = $save;
2395 if ($rs === false ||
$rs->EOF
) return $false;
2398 while (!$rs->EOF
) { //print_r($rs->fields);
2399 $fld = new ADOFieldObject();
2400 $fld->name
= $rs->fields
[0];
2401 $fld->type
= $rs->fields
[1];
2402 if (isset($rs->fields
[3]) && $rs->fields
[3]) {
2403 if ($rs->fields
[3]>0) $fld->max_length
= $rs->fields
[3];
2404 $fld->scale
= $rs->fields
[4];
2405 if ($fld->scale
>0) $fld->max_length +
= 1;
2407 $fld->max_length
= $rs->fields
[2];
2409 if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM
) $retarr[] = $fld;
2410 else $retarr[strtoupper($fld->name
)] = $fld;
2420 * List indexes on a table as an array.
2421 * @param table table name to query
2422 * @param primary true to only show primary keys. Not actually used for most databases
2424 * @return array of indexes on current table. Each element represents an index, and is itself an associative array.
2427 * [name_of_index] => Array(
2428 * [unique] => true or false
2429 * [columns] => Array(
2436 function MetaIndexes($table, $primary = false, $owner = false)
2443 * List columns names in a table as an array.
2444 * @param table table name to query
2446 * @return array of column names for current table.
2448 function MetaColumnNames($table, $numIndexes=false,$useattnum=false /* only for postgres */)
2450 $objarr = $this->MetaColumns($table);
2451 if (!is_array($objarr)) {
2459 foreach($objarr as $v)
2460 $arr[$v->attnum
] = $v->name
;
2463 foreach($objarr as $v) $arr[$i++
] = $v->name
;
2465 foreach($objarr as $v) $arr[strtoupper($v->name
)] = $v->name
;
2471 * Different SQL databases used different methods to combine strings together.
2472 * This function provides a wrapper.
2474 * param s variable number of string parameters
2476 * Usage: $db->Concat($str1,$str2);
2478 * @return concatenated string
2482 $arr = func_get_args();
2483 return implode($this->concat_operator
, $arr);
2488 * Converts a date "d" to a string that the database can understand.
2490 * @param d a date in Unix date time format.
2492 * @return date string in database date format
2494 function DBDate($d, $isfld=false)
2496 if (empty($d) && $d !== 0) return 'null';
2497 if ($isfld) return $d;
2499 if (is_object($d)) return $d->format($this->fmtDate
);
2502 if (is_string($d) && !is_numeric($d)) {
2503 if ($d === 'null') return $d;
2504 if (strncmp($d,"'",1) === 0) {
2505 $d = _adodb_safedateq($d);
2508 if ($this->isoDates
) return "'$d'";
2509 $d = ADOConnection
::UnixDate($d);
2512 return adodb_date($this->fmtDate
,$d);
2515 function BindDate($d)
2517 $d = $this->DBDate($d);
2518 if (strncmp($d,"'",1)) return $d;
2520 return substr($d,1,strlen($d)-2);
2523 function BindTimeStamp($d)
2525 $d = $this->DBTimeStamp($d);
2526 if (strncmp($d,"'",1)) return $d;
2528 return substr($d,1,strlen($d)-2);
2533 * Converts a timestamp "ts" to a string that the database can understand.
2535 * @param ts a timestamp in Unix date time format.
2537 * @return timestamp string in database timestamp format
2539 function DBTimeStamp($ts,$isfld=false)
2541 if (empty($ts) && $ts !== 0) return 'null';
2542 if ($isfld) return $ts;
2543 if (is_object($ts)) return $ts->format($this->fmtTimeStamp
);
2545 # strlen(14) allows YYYYMMDDHHMMSS format
2546 if (!is_string($ts) ||
(is_numeric($ts) && strlen($ts)<14))
2547 return adodb_date($this->fmtTimeStamp
,$ts);
2549 if ($ts === 'null') return $ts;
2550 if ($this->isoDates
&& strlen($ts) !== 14) {
2551 $ts = _adodb_safedate($ts);
2554 $ts = ADOConnection
::UnixTimeStamp($ts);
2555 return adodb_date($this->fmtTimeStamp
,$ts);
2559 * Also in ADORecordSet.
2560 * @param $v is a date string in YYYY-MM-DD format
2562 * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
2564 static function UnixDate($v)
2566 if (is_object($v)) {
2568 //( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
2569 return adodb_mktime($v->hour
,$v->minute
,$v->second
,$v->month
,$v->day
, $v->year
);
2572 if (is_numeric($v) && strlen($v) !== 8) return $v;
2573 if (!preg_match( "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})|",
2574 ($v), $rr)) return false;
2576 if ($rr[1] <= TIMESTAMP_FIRST_YEAR
) return 0;
2578 return @adodb_mktime
(0,0,0,$rr[2],$rr[3],$rr[1]);
2583 * Also in ADORecordSet.
2584 * @param $v is a timestamp string in YYYY-MM-DD HH-NN-SS format
2586 * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
2588 static function UnixTimeStamp($v)
2590 if (is_object($v)) {
2592 //( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
2593 return adodb_mktime($v->hour
,$v->minute
,$v->second
,$v->month
,$v->day
, $v->year
);
2597 "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ ,-]*(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|",
2598 ($v), $rr)) return false;
2600 if ($rr[1] <= TIMESTAMP_FIRST_YEAR
&& $rr[2]<= 1) return 0;
2603 if (!isset($rr[5])) return adodb_mktime(0,0,0,$rr[2],$rr[3],$rr[1]);
2604 return @adodb_mktime
($rr[5],$rr[6],$rr[7],$rr[2],$rr[3],$rr[1]);
2608 * Also in ADORecordSet.
2610 * Format database date based on user defined format.
2612 * @param v is the character date in YYYY-MM-DD format, returned by database
2613 * @param fmt is the format to apply to it, using date()
2615 * @return a date formated as user desires
2618 function UserDate($v,$fmt='Y-m-d',$gmt=false)
2620 $tt = $this->UnixDate($v);
2622 // $tt == -1 if pre TIMESTAMP_FIRST_YEAR
2623 if (($tt === false ||
$tt == -1) && $v != false) return $v;
2624 else if ($tt == 0) return $this->emptyDate
;
2625 else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
2628 return ($gmt) ?
adodb_gmdate($fmt,$tt) : adodb_date($fmt,$tt);
2634 * @param v is the character timestamp in YYYY-MM-DD hh:mm:ss format
2635 * @param fmt is the format to apply to it, using date()
2637 * @return a timestamp formated as user desires
2639 function UserTimeStamp($v,$fmt='Y-m-d H:i:s',$gmt=false)
2641 if (!isset($v)) return $this->emptyTimeStamp
;
2642 # strlen(14) allows YYYYMMDDHHMMSS format
2643 if (is_numeric($v) && strlen($v)<14) return ($gmt) ?
adodb_gmdate($fmt,$v) : adodb_date($fmt,$v);
2644 $tt = $this->UnixTimeStamp($v);
2645 // $tt == -1 if pre TIMESTAMP_FIRST_YEAR
2646 if (($tt === false ||
$tt == -1) && $v != false) return $v;
2647 if ($tt == 0) return $this->emptyTimeStamp
;
2648 return ($gmt) ?
adodb_gmdate($fmt,$tt) : adodb_date($fmt,$tt);
2651 function escape($s,$magic_quotes=false)
2653 return $this->addq($s,$magic_quotes);
2657 * Quotes a string, without prefixing nor appending quotes.
2659 function addq($s,$magic_quotes=false)
2661 if (!$magic_quotes) {
2663 if ($this->replaceQuote
[0] == '\\'){
2664 // only since php 4.0.5
2665 $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
2666 //$s = str_replace("\0","\\\0", str_replace('\\','\\\\',$s));
2668 return str_replace("'",$this->replaceQuote
,$s);
2671 // undo magic quotes for "
2672 $s = str_replace('\\"','"',$s);
2674 if ($this->replaceQuote
== "\\'" ||
ini_get('magic_quotes_sybase')) // ' already quoted, no need to change anything
2676 else {// change \' to '' for sybase/mssql
2677 $s = str_replace('\\\\','\\',$s);
2678 return str_replace("\\'",$this->replaceQuote
,$s);
2683 * Correctly quotes a string so that all strings are escaped. We prefix and append
2684 * to the string single-quotes.
2685 * An example is $db->qstr("Don't bother",magic_quotes_runtime());
2687 * @param s the string to quote
2688 * @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc().
2689 * This undoes the stupidity of magic quotes for GPC.
2691 * @return quoted string to be sent back to database
2693 function qstr($s,$magic_quotes=false)
2695 if (!$magic_quotes) {
2697 if ($this->replaceQuote
[0] == '\\'){
2698 // only since php 4.0.5
2699 $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
2700 //$s = str_replace("\0","\\\0", str_replace('\\','\\\\',$s));
2702 return "'".str_replace("'",$this->replaceQuote
,$s)."'";
2705 // undo magic quotes for "
2706 $s = str_replace('\\"','"',$s);
2708 if ($this->replaceQuote
== "\\'" ||
ini_get('magic_quotes_sybase')) // ' already quoted, no need to change anything
2710 else {// change \' to '' for sybase/mssql
2711 $s = str_replace('\\\\','\\',$s);
2712 return "'".str_replace("\\'",$this->replaceQuote
,$s)."'";
2718 * Will select the supplied $page number from a recordset, given that it is paginated in pages of
2719 * $nrows rows per page. It also saves two boolean values saying if the given page is the first
2720 * and/or last one of the recordset. Added by Iván Oliva to provide recordset pagination.
2722 * See docs-adodb.htm#ex8 for an example of usage.
2725 * @param nrows is the number of rows per page to get
2726 * @param page is the page number to get (1-based)
2727 * @param [inputarr] array of bind variables
2728 * @param [secs2cache] is a private parameter only used by jlim
2729 * @return the recordset ($rs->databaseType == 'array')
2731 * NOTE: phpLens uses a different algorithm and does not use PageExecute().
2734 function PageExecute($sql, $nrows, $page, $inputarr=false, $secs2cache=0)
2736 global $ADODB_INCLUDED_LIB;
2737 if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR
.'/adodb-lib.inc.php');
2738 if ($this->pageExecuteCountRows
) $rs = _adodb_pageexecute_all_rows($this, $sql, $nrows, $page, $inputarr, $secs2cache);
2739 else $rs = _adodb_pageexecute_no_last_page($this, $sql, $nrows, $page, $inputarr, $secs2cache);
2745 * Will select the supplied $page number from a recordset, given that it is paginated in pages of
2746 * $nrows rows per page. It also saves two boolean values saying if the given page is the first
2747 * and/or last one of the recordset. Added by Iván Oliva to provide recordset pagination.
2749 * @param secs2cache seconds to cache data, set to 0 to force query
2751 * @param nrows is the number of rows per page to get
2752 * @param page is the page number to get (1-based)
2753 * @param [inputarr] array of bind variables
2754 * @return the recordset ($rs->databaseType == 'array')
2756 function CachePageExecute($secs2cache, $sql, $nrows, $page,$inputarr=false)
2758 /*switch($this->dataProvider) {
2762 default: $secs2cache = 0; break;
2764 $rs = $this->PageExecute($sql,$nrows,$page,$inputarr,$secs2cache);
2768 } // end class ADOConnection
2772 //==============================================================================================
2773 // CLASS ADOFetchObj
2774 //==============================================================================================
2777 * Internal placeholder for record objects. Used by ADORecordSet->FetchObj().
2782 //==============================================================================================
2783 // CLASS ADORecordSet_empty
2784 //==============================================================================================
2786 class ADODB_Iterator_empty
implements Iterator
{
2790 function __construct($rs)
2800 return !$this->rs
->EOF
;
2817 function __call($func, $params)
2819 return call_user_func_array(array($this->rs
, $func), $params);
2831 * Lightweight recordset when there are no records to be returned
2833 class ADORecordSet_empty
implements IteratorAggregate
2835 var $dataProvider = 'empty';
2836 var $databaseType = false;
2838 var $_numOfRows = 0;
2839 var $fields = false;
2840 var $connection = false;
2841 function RowCount() {return 0;}
2842 function RecordCount() {return 0;}
2843 function PO_RecordCount(){return 0;}
2844 function Close(){return true;}
2845 function FetchRow() {return false;}
2846 function FieldCount(){ return 0;}
2848 function getIterator() {return new ADODB_Iterator_empty($this);}
2849 function GetAssoc() {return array();}
2852 //==============================================================================================
2853 // DATE AND TIME FUNCTIONS
2854 //==============================================================================================
2855 if (!defined('ADODB_DATE_VERSION')) include(ADODB_DIR
.'/adodb-time.inc.php');
2857 //==============================================================================================
2858 // CLASS ADORecordSet
2859 //==============================================================================================
2861 class ADODB_Iterator
implements Iterator
{
2865 function __construct($rs)
2871 $this->rs
->MoveFirst();
2876 return !$this->rs
->EOF
;
2881 return $this->rs
->_currentRow
;
2886 return $this->rs
->fields
;
2891 $this->rs
->MoveNext();
2894 function __call($func, $params)
2896 return call_user_func_array(array($this->rs
, $func), $params);
2902 return !$this->rs
->EOF
;
2910 * RecordSet class that represents the dataset returned by the database.
2911 * To keep memory overhead low, this class holds only the current row in memory.
2912 * No prefetching of data is done, so the RecordCount() can return -1 ( which
2913 * means recordcount not known).
2915 class ADORecordSet
implements IteratorAggregate
{
2919 var $dataProvider = "native";
2920 var $fields = false; /// holds the current row data
2921 var $blobSize = 100; /// any varchar/char field this size or greater is treated as a blob
2922 /// in other words, we use a text area for editing.
2923 var $canSeek = false; /// indicates that seek is supported
2924 var $sql; /// sql text
2925 var $EOF = false; /// Indicates that the current record position is after the last record in a Recordset object.
2927 var $emptyTimeStamp = ' '; /// what to display when $time==0
2928 var $emptyDate = ' '; /// what to display when $time==0
2930 var $timeCreated=0; /// datetime in Unix format rs created -- for cached recordsets
2932 var $bind = false; /// used by Fields() to hold array - should be private?
2933 var $fetchMode; /// default fetch mode
2934 var $connection = false; /// the parent connection
2938 var $_numOfRows = -1; /** number of rows, or -1 */
2939 var $_numOfFields = -1; /** number of fields in recordset */
2940 var $_queryID = -1; /** This variable keeps the result link identifier. */
2941 var $_currentRow = -1; /** This variable keeps the current row in the Recordset. */
2942 var $_closed = false; /** has recordset been closed */
2943 var $_inited = false; /** Init() should only be called once */
2944 var $_obj; /** Used by FetchObj */
2945 var $_names; /** Used by FetchObj */
2947 var $_currentPage = -1; /** Added by Iván Oliva to implement recordset pagination */
2948 var $_atFirstPage = false; /** Added by Iván Oliva to implement recordset pagination */
2949 var $_atLastPage = false; /** Added by Iván Oliva to implement recordset pagination */
2950 var $_lastPageNo = -1;
2951 var $_maxRecordCount = 0;
2952 var $datetime = false;
2957 * @param queryID this is the queryID returned by ADOConnection->_query()
2960 function ADORecordSet($queryID)
2962 $this->_queryID
= $queryID;
2965 function getIterator()
2967 return new ADODB_Iterator($this);
2970 /* this is experimental - i don't really know what to return... */
2971 function __toString()
2973 include_once(ADODB_DIR
.'/toexport.inc.php');
2974 return _adodb_export($this,',',',',false,true);
2980 if ($this->_inited
) return;
2981 $this->_inited
= true;
2982 if ($this->_queryID
) @$this->_initrs();
2984 $this->_numOfRows
= 0;
2985 $this->_numOfFields
= 0;
2987 if ($this->_numOfRows
!= 0 && $this->_numOfFields
&& $this->_currentRow
== -1) {
2989 $this->_currentRow
= 0;
2990 if ($this->EOF
= ($this->_fetch() === false)) {
2991 $this->_numOfRows
= 0; // _numOfRows could be -1
3000 * Generate a SELECT tag string from a recordset, and return the string.
3001 * If the recordset has 2 cols, we treat the 1st col as the containing
3002 * the text to display to the user, and 2nd col as the return value. Default
3003 * strings are compared with the FIRST column.
3005 * @param name name of SELECT tag
3006 * @param [defstr] the value to hilite. Use an array for multiple hilites for listbox.
3007 * @param [blank1stItem] true to leave the 1st item in list empty
3008 * @param [multiple] true for listbox, false for popup
3009 * @param [size] #rows to show for listbox. not used by popup
3010 * @param [selectAttr] additional attributes to defined for SELECT tag.
3011 * useful for holding javascript onChange='...' handlers.
3012 & @param [compareFields0] when we have 2 cols in recordset, we compare the defstr with
3013 * column 0 (1st col) if this is true. This is not documented.
3017 * changes by glen.davies@cce.ac.nz to support multiple hilited items
3019 function GetMenu($name,$defstr='',$blank1stItem=true,$multiple=false,
3020 $size=0, $selectAttr='',$compareFields0=true)
3022 global $ADODB_INCLUDED_LIB;
3023 if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR
.'/adodb-lib.inc.php');
3024 return _adodb_getmenu($this, $name,$defstr,$blank1stItem,$multiple,
3025 $size, $selectAttr,$compareFields0);
3031 * Generate a SELECT tag string from a recordset, and return the string.
3032 * If the recordset has 2 cols, we treat the 1st col as the containing
3033 * the text to display to the user, and 2nd col as the return value. Default
3034 * strings are compared with the SECOND column.
3037 function GetMenu2($name,$defstr='',$blank1stItem=true,$multiple=false,$size=0, $selectAttr='')
3039 return $this->GetMenu($name,$defstr,$blank1stItem,$multiple,
3040 $size, $selectAttr,false);
3046 function GetMenu3($name,$defstr='',$blank1stItem=true,$multiple=false,
3047 $size=0, $selectAttr='')
3049 global $ADODB_INCLUDED_LIB;
3050 if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR
.'/adodb-lib.inc.php');
3051 return _adodb_getmenu_gp($this, $name,$defstr,$blank1stItem,$multiple,
3052 $size, $selectAttr,false);
3056 * return recordset as a 2-dimensional array.
3058 * @param [nRows] is the number of rows to return. -1 means every row.
3060 * @return an array indexed by the rows (0-based) from the recordset
3062 function GetArray($nRows = -1)
3064 global $ADODB_EXTENSION; if ($ADODB_EXTENSION) {
3065 $results = adodb_getall($this,$nRows);
3070 while (!$this->EOF
&& $nRows != $cnt) {
3071 $results[] = $this->fields
;
3078 function GetAll($nRows = -1)
3080 $arr = $this->GetArray($nRows);
3085 * Some databases allow multiple recordsets to be returned. This function
3086 * will return true if there is a next recordset, or false if no more.
3088 function NextRecordSet()
3094 * return recordset as a 2-dimensional array.
3095 * Helper function for ADOConnection->SelectLimit()
3097 * @param offset is the row to start calculations from (1-based)
3098 * @param [nrows] is the number of rows to return
3100 * @return an array indexed by the rows (0-based) from the recordset
3102 function GetArrayLimit($nrows,$offset=-1)
3105 $arr = $this->GetArray($nrows);
3109 $this->Move($offset);
3113 while (!$this->EOF
&& $nrows != $cnt) {
3114 $results[$cnt++
] = $this->fields
;
3123 * Synonym for GetArray() for compatibility with ADO.
3125 * @param [nRows] is the number of rows to return. -1 means every row.
3127 * @return an array indexed by the rows (0-based) from the recordset
3129 function GetRows($nRows = -1)
3131 $arr = $this->GetArray($nRows);
3136 * return whole recordset as a 2-dimensional associative array if there are more than 2 columns.
3137 * The first column is treated as the key and is not included in the array.
3138 * If there is only 2 columns, it will return a 1 dimensional array of key-value pairs unless
3139 * $force_array == true.
3141 * @param [force_array] has only meaning if we have 2 data columns. If false, a 1 dimensional
3142 * array is returned, otherwise a 2 dimensional array is returned. If this sounds confusing,
3145 * @param [first2cols] means if there are more than 2 cols, ignore the remaining cols and
3146 * instead of returning array[col0] => array(remaining cols), return array[col0] => col1
3148 * @return an associative array indexed by the first column of the array,
3149 * or false if the data has less than 2 cols.
3151 function GetAssoc($force_array = false, $first2cols = false)
3153 global $ADODB_EXTENSION;
3155 $cols = $this->_numOfFields
;
3160 $numIndex = is_array($this->fields
) && array_key_exists(0, $this->fields
);
3163 if (!$first2cols && ($cols > 2 ||
$force_array)) {
3164 if ($ADODB_EXTENSION) {
3166 while (!$this->EOF
) {
3167 $results[trim($this->fields
[0])] = array_slice($this->fields
, 1);
3168 adodb_movenext($this);
3171 while (!$this->EOF
) {
3172 // Fix for array_slice re-numbering numeric associative keys
3173 $keys = array_slice(array_keys($this->fields
), 1);
3174 $sliced_array = array();
3176 foreach($keys as $key) {
3177 $sliced_array[$key] = $this->fields
[$key];
3180 $results[trim(reset($this->fields
))] = $sliced_array;
3181 adodb_movenext($this);
3186 while (!$this->EOF
) {
3187 $results[trim($this->fields
[0])] = array_slice($this->fields
, 1);
3191 while (!$this->EOF
) {
3192 // Fix for array_slice re-numbering numeric associative keys
3193 $keys = array_slice(array_keys($this->fields
), 1);
3194 $sliced_array = array();
3196 foreach($keys as $key) {
3197 $sliced_array[$key] = $this->fields
[$key];
3200 $results[trim(reset($this->fields
))] = $sliced_array;
3206 if ($ADODB_EXTENSION) {
3207 // return scalar values
3209 while (!$this->EOF
) {
3210 // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string
3211 $results[trim(($this->fields
[0]))] = $this->fields
[1];
3212 adodb_movenext($this);
3215 while (!$this->EOF
) {
3216 // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string
3217 $v1 = trim(reset($this->fields
));
3218 $v2 = ''.next($this->fields
);
3219 $results[$v1] = $v2;
3220 adodb_movenext($this);
3225 while (!$this->EOF
) {
3226 // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string
3227 $results[trim(($this->fields
[0]))] = $this->fields
[1];
3231 while (!$this->EOF
) {
3232 // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string
3233 $v1 = trim(reset($this->fields
));
3234 $v2 = ''.next($this->fields
);
3235 $results[$v1] = $v2;
3242 $ref = $results; # workaround accelerator incompat with PHP 4.4 :(
3249 * @param v is the character timestamp in YYYY-MM-DD hh:mm:ss format
3250 * @param fmt is the format to apply to it, using date()
3252 * @return a timestamp formated as user desires
3254 function UserTimeStamp($v,$fmt='Y-m-d H:i:s')
3256 if (is_numeric($v) && strlen($v)<14) return adodb_date($fmt,$v);
3257 $tt = $this->UnixTimeStamp($v);
3258 // $tt == -1 if pre TIMESTAMP_FIRST_YEAR
3259 if (($tt === false ||
$tt == -1) && $v != false) return $v;
3260 if ($tt === 0) return $this->emptyTimeStamp
;
3261 return adodb_date($fmt,$tt);
3266 * @param v is the character date in YYYY-MM-DD format, returned by database
3267 * @param fmt is the format to apply to it, using date()
3269 * @return a date formated as user desires
3271 function UserDate($v,$fmt='Y-m-d')
3273 $tt = $this->UnixDate($v);
3274 // $tt == -1 if pre TIMESTAMP_FIRST_YEAR
3275 if (($tt === false ||
$tt == -1) && $v != false) return $v;
3276 else if ($tt == 0) return $this->emptyDate
;
3277 else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
3279 return adodb_date($fmt,$tt);
3284 * @param $v is a date string in YYYY-MM-DD format
3286 * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
3288 static function UnixDate($v)
3290 return ADOConnection
::UnixDate($v);
3295 * @param $v is a timestamp string in YYYY-MM-DD HH-NN-SS format
3297 * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
3299 static function UnixTimeStamp($v)
3301 return ADOConnection
::UnixTimeStamp($v);
3306 * PEAR DB Compat - do not use internally
3310 return $this->Close();
3315 * PEAR DB compat, number of rows
3319 return $this->_numOfRows
;
3324 * PEAR DB compat, number of cols
3328 return $this->_numOfFields
;
3332 * Fetch a row, returning false if no more rows.
3333 * This is PEAR DB compat mode.
3335 * @return false or array containing the current record
3343 $arr = $this->fields
;
3344 $this->_currentRow++
;
3345 if (!$this->_fetch()) $this->EOF
= true;
3351 * Fetch a row, returning PEAR_Error if no more rows.
3352 * This is PEAR DB compat mode.
3354 * @return DB_OK or error object
3356 function FetchInto(&$arr)
3358 if ($this->EOF
) return (defined('PEAR_ERROR_RETURN')) ?
new PEAR_Error('EOF',-1): false;
3359 $arr = $this->fields
;
3366 * Move to the first row in the recordset. Many databases do NOT support this.
3368 * @return true or false
3370 function MoveFirst()
3372 if ($this->_currentRow
== 0) return true;
3373 return $this->Move(0);
3378 * Move to the last row in the recordset.
3380 * @return true or false
3384 if ($this->_numOfRows
>= 0) return $this->Move($this->_numOfRows
-1);
3385 if ($this->EOF
) return false;
3386 while (!$this->EOF
) {
3397 * Move to next record in the recordset.
3399 * @return true if there still rows available, or false if there are no more rows (EOF).
3404 $this->_currentRow++
;
3405 if ($this->_fetch()) return true;
3408 /* -- tested error handling when scrolling cursor -- seems useless.
3409 $conn = $this->connection;
3410 if ($conn && $conn->raiseErrorFn && ($errno = $conn->ErrorNo())) {
3411 $fn = $conn->raiseErrorFn;
3412 $fn($conn->databaseType,'MOVENEXT',$errno,$conn->ErrorMsg().' ('.$this->sql.')',$conn->host,$conn->database);
3420 * Random access to a specific row in the recordset. Some databases do not support
3421 * access to previous rows in the databases (no scrolling backwards).
3423 * @param rowNumber is the row to move to (0-based)
3425 * @return true if there still rows available, or false if there are no more rows (EOF).
3427 function Move($rowNumber = 0)
3430 if ($rowNumber == $this->_currentRow
) return true;
3431 if ($rowNumber >= $this->_numOfRows
)
3432 if ($this->_numOfRows
!= -1) $rowNumber = $this->_numOfRows
-2;
3434 if ($this->canSeek
) {
3436 if ($this->_seek($rowNumber)) {
3437 $this->_currentRow
= $rowNumber;
3438 if ($this->_fetch()) {
3446 if ($rowNumber < $this->_currentRow
) return false;
3447 global $ADODB_EXTENSION;
3448 if ($ADODB_EXTENSION) {
3449 while (!$this->EOF
&& $this->_currentRow
< $rowNumber) {
3450 adodb_movenext($this);
3454 while (! $this->EOF
&& $this->_currentRow
< $rowNumber) {
3455 $this->_currentRow++
;
3457 if (!$this->_fetch()) $this->EOF
= true;
3460 return !($this->EOF
);
3463 $this->fields
= false;
3470 * Get the value of a field in the current row by column name.
3471 * Will not work if ADODB_FETCH_MODE is set to ADODB_FETCH_NUM.
3473 * @param colname is the field to access
3475 * @return the value of $colname column
3477 function Fields($colname)
3479 return $this->fields
[$colname];
3483 * Builds the bind array associating keys to recordset fields
3485 * @param int $upper Case for the array keys, defaults to uppercase
3486 * (see ADODB_ASSOC_CASE_xxx constants)
3488 function GetAssocKeys($upper=ADODB_ASSOC_CASE_UPPER
)
3490 $this->bind
= array();
3491 for ($i=0; $i < $this->_numOfFields
; $i++
) {
3492 $o = $this->FetchField($i);
3494 case ADODB_ASSOC_CASE_LOWER
:
3495 $key = strtolower($o->name
);
3497 case ADODB_ASSOC_CASE_UPPER
:
3498 $key = strtoupper($o->name
);
3500 case ADODB_ASSOC_CASE_NATIVE
:
3505 $val = $this->fetchMode
== ADODB_FETCH_ASSOC ?
$o->name
: $i;
3506 $this->bind
[$key] = $val;
3511 * Use associative array to get fields array for databases that do not support
3512 * associative arrays. Submitted by Paolo S. Asioli paolo.asioli#libero.it
3514 * @param int $upper Case for the array keys, defaults to uppercase
3515 * (see ADODB_ASSOC_CASE_xxx constants)
3517 function GetRowAssoc($upper=ADODB_ASSOC_CASE_UPPER
)
3521 $this->GetAssocKeys($upper);
3523 foreach($this->bind
as $k => $v) {
3524 if( array_key_exists( $v, $this->fields
) ) {
3525 $record[$k] = $this->fields
[$v];
3526 } elseif( array_key_exists( $k, $this->fields
) ) {
3527 $record[$k] = $this->fields
[$k];
3529 # This should not happen... trigger error ?
3537 * Clean up recordset
3539 * @return true or false
3543 // free connection object - this seems to globally free the object
3544 // and not merely the reference, so don't do this...
3545 // $this->connection = false;
3546 if (!$this->_closed
) {
3547 $this->_closed
= true;
3548 return $this->_close();
3554 * synonyms RecordCount and RowCount
3556 * @return the number of rows or -1 if this is not supported
3558 function RecordCount() {return $this->_numOfRows
;}
3562 * If we are using PageExecute(), this will return the maximum possible rows
3563 * that can be returned when paging a recordset.
3565 function MaxRecordCount()
3567 return ($this->_maxRecordCount
) ?
$this->_maxRecordCount
: $this->RecordCount();
3571 * synonyms RecordCount and RowCount
3573 * @return the number of rows or -1 if this is not supported
3575 function RowCount() {return $this->_numOfRows
;}
3579 * Portable RecordCount. Pablo Roca <pabloroca@mvps.org>
3581 * @return the number of records from a previous SELECT. All databases support this.
3583 * But aware possible problems in multiuser environments. For better speed the table
3584 * must be indexed by the condition. Heavy test this before deploying.
3586 function PO_RecordCount($table="", $condition="") {
3588 $lnumrows = $this->_numOfRows
;
3589 // the database doesn't support native recordcount, so we do a workaround
3590 if ($lnumrows == -1 && $this->connection
) {
3592 if ($condition) $condition = " WHERE " . $condition;
3593 $resultrows = $this->connection
->Execute("SELECT COUNT(*) FROM $table $condition");
3594 if ($resultrows) $lnumrows = reset($resultrows->fields
);
3602 * @return the current row in the recordset. If at EOF, will return the last row. 0-based.
3604 function CurrentRow() {return $this->_currentRow
;}
3607 * synonym for CurrentRow -- for ADO compat
3609 * @return the current row in the recordset. If at EOF, will return the last row. 0-based.
3611 function AbsolutePosition() {return $this->_currentRow
;}
3614 * @return the number of columns in the recordset. Some databases will set this to 0
3615 * if no records are returned, others will return the number of columns in the query.
3617 function FieldCount() {return $this->_numOfFields
;}
3621 * Get the ADOFieldObject of a specific column.
3623 * @param fieldoffset is the column position to access(0-based).
3625 * @return the ADOFieldObject for that column, or false.
3627 function FetchField($fieldoffset = -1)
3629 // must be defined by child class
3636 * Get the ADOFieldObjects of all columns in an array.
3639 function FieldTypesArray()
3642 for ($i=0, $max=$this->_numOfFields
; $i < $max; $i++
)
3643 $arr[] = $this->FetchField($i);
3648 * Return the fields array of the current row as an object for convenience.
3649 * The default case is lowercase field names.
3651 * @return the object with the properties set to the fields of the current row
3655 $o = $this->FetchObject(false);
3660 * Return the fields array of the current row as an object for convenience.
3661 * The default case is uppercase.
3663 * @param $isupper to set the object property names to uppercase
3665 * @return the object with the properties set to the fields of the current row
3667 function FetchObject($isupper=true)
3669 if (empty($this->_obj
)) {
3670 $this->_obj
= new ADOFetchObj();
3671 $this->_names
= array();
3672 for ($i=0; $i <$this->_numOfFields
; $i++
) {
3673 $f = $this->FetchField($i);
3674 $this->_names
[] = $f->name
;
3678 if (PHP_VERSION
>= 5) $o = clone($this->_obj
);
3679 else $o = $this->_obj
;
3681 for ($i=0; $i <$this->_numOfFields
; $i++
) {
3682 $name = $this->_names
[$i];
3683 if ($isupper) $n = strtoupper($name);
3686 $o->$n = $this->Fields($name);
3692 * Return the fields array of the current row as an object for convenience.
3693 * The default is lower-case field names.
3695 * @return the object with the properties set to the fields of the current row,
3698 * Fixed bug reported by tim@orotech.net
3700 function FetchNextObj()
3702 $o = $this->FetchNextObject(false);
3708 * Return the fields array of the current row as an object for convenience.
3709 * The default is upper case field names.
3711 * @param $isupper to set the object property names to uppercase
3713 * @return the object with the properties set to the fields of the current row,
3716 * Fixed bug reported by tim@orotech.net
3718 function FetchNextObject($isupper=true)
3721 if ($this->_numOfRows
!= 0 && !$this->EOF
) {
3722 $o = $this->FetchObject($isupper);
3723 $this->_currentRow++
;
3724 if ($this->_fetch()) return $o;
3731 * Get the metatype of the column. This is used for formatting. This is because
3732 * many databases use different names for the same type, so we transform the original
3733 * type to our standardised version which uses 1 character codes:
3735 * @param t is the type passed in. Normally is ADOFieldObject->type.
3736 * @param len is the maximum length of that field. This is because we treat character
3737 * fields bigger than a certain size as a 'B' (blob).
3738 * @param fieldobj is the field object returned by the database driver. Can hold
3739 * additional info (eg. primary_key for mysql).
3741 * @return the general type of the data:
3742 * C for character < 250 chars
3743 * X for teXt (>= 250 chars)
3745 * N for numeric or floating point
3748 * L for logical/Boolean
3750 * R for autoincrement counter/integer
3754 function MetaType($t,$len=-1,$fieldobj=false)
3756 if (is_object($t)) {
3758 $t = $fieldobj->type
;
3759 $len = $fieldobj->max_length
;
3761 // changed in 2.32 to hashing instead of switch stmt for speed...
3762 static $typeMap = array(
3773 'INTERVAL' => 'C', # Postgres
3774 'MACADDR' => 'C', # postgres
3775 'VAR_STRING' => 'C', # mysql
3790 'LONGBINARY' => 'B',
3793 'YEAR' => 'D', // mysql
3797 'UNIQUEIDENTIFIER' => 'C', # MS SQL Server
3799 'SMALLDATETIME' => 'T',
3803 'TIMESTAMPTZ' => 'T',
3805 'TIMESTAMP WITHOUT TIME ZONE' => 'T', // postgresql
3814 'SERIAL' => 'R', // ifx
3815 'INT IDENTITY' => 'R',
3822 'INTEGER UNSIGNED' => 'I',
3828 'LONG' => 'N', // interbase is numeric, oci8 is blob
3829 'BIGINT' => 'N', // this is bigger than PHP 32-bit integers
3834 'DOUBLE PRECISION' => 'N',
3835 'SMALLFLOAT' => 'N',
3846 'SQLSMFLOAT' => 'N',
3849 'SQLDECIMAL' => 'N',
3854 'SQLINTERVAL' => 'N',
3859 "SQLSERIAL8" => 'I8',
3862 "SQLLVARCHAR" => 'X',
3867 $t = strtoupper($t);
3868 $tmap = (isset($typeMap[$t])) ?
$typeMap[$t] : 'N';
3872 // is the char field is too long, return as text field...
3873 if ($this->blobSize
>= 0) {
3874 if ($len > $this->blobSize
) return 'X';
3875 } else if ($len > 250) {
3881 if (!empty($fieldobj->primary_key
)) return 'R';
3888 if (isset($fieldobj->binary
))
3889 return ($fieldobj->binary
) ?
'B' : 'X';
3893 if (!empty($this->connection
) && !empty($this->connection
->datetime
)) return 'T';
3897 if ($t == 'LONG' && $this->dataProvider
== 'oci8') return 'B';
3903 function _close() {}
3906 * set/returns the current recordset page when paginating
3908 function AbsolutePage($page=-1)
3910 if ($page != -1) $this->_currentPage
= $page;
3911 return $this->_currentPage
;
3915 * set/returns the status of the atFirstPage flag when paginating
3917 function AtFirstPage($status=false)
3919 if ($status != false) $this->_atFirstPage
= $status;
3920 return $this->_atFirstPage
;
3923 function LastPageNo($page = false)
3925 if ($page != false) $this->_lastPageNo
= $page;
3926 return $this->_lastPageNo
;
3930 * set/returns the status of the atLastPage flag when paginating
3932 function AtLastPage($status=false)
3934 if ($status != false) $this->_atLastPage
= $status;
3935 return $this->_atLastPage
;
3938 } // end class ADORecordSet
3940 //==============================================================================================
3941 // CLASS ADORecordSet_array
3942 //==============================================================================================
3945 * This class encapsulates the concept of a recordset created in memory
3946 * as an array. This is useful for the creation of cached recordsets.
3948 * Note that the constructor is different from the standard ADORecordSet
3951 class ADORecordSet_array
extends ADORecordSet
3953 var $databaseType = 'array';
3955 var $_array; // holds the 2-dimensional data array
3956 var $_types; // the array of types of each column (C B I L M)
3957 var $_colnames; // names of each column in array
3958 var $_skiprow1; // skip 1st row because it holds column names
3959 var $_fieldobjects; // holds array of field objects
3960 var $canSeek = true;
3961 var $affectedrows = false;
3962 var $insertid = false;
3964 var $compat = false;
3969 function ADORecordSet_array($fakeid=1)
3971 global $ADODB_FETCH_MODE,$ADODB_COMPAT_FETCH;
3973 // fetch() on EOF does not delete $this->fields
3974 $this->compat
= !empty($ADODB_COMPAT_FETCH);
3975 $this->ADORecordSet($fakeid); // fake queryID
3976 $this->fetchMode
= $ADODB_FETCH_MODE;
3979 function _transpose($addfieldnames=true)
3981 global $ADODB_INCLUDED_LIB;
3983 if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR
.'/adodb-lib.inc.php');
3986 $fobjs = $addfieldnames ?
$this->_fieldobjects
: false;
3987 adodb_transpose($this->_array
, $newarr, $hdr, $fobjs);
3988 //adodb_pr($newarr);
3990 $this->_skiprow1
= false;
3991 $this->_array
= $newarr;
3992 $this->_colnames
= $hdr;
3994 adodb_probetypes($newarr,$this->_types
);
3996 $this->_fieldobjects
= array();
3998 foreach($hdr as $k => $name) {
3999 $f = new ADOFieldObject();
4001 $f->type
= $this->_types
[$k];
4002 $f->max_length
= -1;
4003 $this->_fieldobjects
[] = $f;
4005 $this->fields
= reset($this->_array
);
4014 * @param array is a 2-dimensional array holding the data.
4015 * The first row should hold the column names
4016 * unless paramter $colnames is used.
4017 * @param typearr holds an array of types. These are the same types
4018 * used in MetaTypes (C,B,L,I,N).
4019 * @param [colnames] array of column names. If set, then the first row of
4020 * $array should not hold the column names.
4022 function InitArray($array,$typearr,$colnames=false)
4024 $this->_array
= $array;
4025 $this->_types
= $typearr;
4027 $this->_skiprow1
= false;
4028 $this->_colnames
= $colnames;
4030 $this->_skiprow1
= true;
4031 $this->_colnames
= $array[0];
4036 * Setup the Array and datatype file objects
4038 * @param array is a 2-dimensional array holding the data.
4039 * The first row should hold the column names
4040 * unless paramter $colnames is used.
4041 * @param fieldarr holds an array of ADOFieldObject's.
4043 function InitArrayFields(&$array,&$fieldarr)
4045 $this->_array
= $array;
4046 $this->_skiprow1
= false;
4048 $this->_fieldobjects
= $fieldarr;
4053 function GetArray($nRows=-1)
4055 if ($nRows == -1 && $this->_currentRow
<= 0 && !$this->_skiprow1
) {
4056 return $this->_array
;
4058 $arr = ADORecordSet
::GetArray($nRows);
4065 $this->_numOfRows
= sizeof($this->_array
);
4066 if ($this->_skiprow1
) $this->_numOfRows
-= 1;
4068 $this->_numOfFields
=(isset($this->_fieldobjects
)) ?
4069 sizeof($this->_fieldobjects
):sizeof($this->_types
);
4072 /* Use associative array to get fields array */
4073 function Fields($colname)
4075 $mode = isset($this->adodbFetchMode
) ?
$this->adodbFetchMode
: $this->fetchMode
;
4077 if ($mode & ADODB_FETCH_ASSOC
) {
4078 if (!isset($this->fields
[$colname]) && !is_null($this->fields
[$colname])) $colname = strtolower($colname);
4079 return $this->fields
[$colname];
4082 $this->bind
= array();
4083 for ($i=0; $i < $this->_numOfFields
; $i++
) {
4084 $o = $this->FetchField($i);
4085 $this->bind
[strtoupper($o->name
)] = $i;
4088 return $this->fields
[$this->bind
[strtoupper($colname)]];
4091 function FetchField($fieldOffset = -1)
4093 if (isset($this->_fieldobjects
)) {
4094 return $this->_fieldobjects
[$fieldOffset];
4096 $o = new ADOFieldObject();
4097 $o->name
= $this->_colnames
[$fieldOffset];
4098 $o->type
= $this->_types
[$fieldOffset];
4099 $o->max_length
= -1; // length not known
4104 function _seek($row)
4106 if (sizeof($this->_array
) && 0 <= $row && $row < $this->_numOfRows
) {
4107 $this->_currentRow
= $row;
4108 if ($this->_skiprow1
) $row +
= 1;
4109 $this->fields
= $this->_array
[$row];
4118 $this->_currentRow++
;
4120 $pos = $this->_currentRow
;
4122 if ($this->_numOfRows
<= $pos) {
4123 if (!$this->compat
) $this->fields
= false;
4125 if ($this->_skiprow1
) $pos +
= 1;
4126 $this->fields
= $this->_array
[$pos];
4137 $pos = $this->_currentRow
;
4139 if ($this->_numOfRows
<= $pos) {
4140 if (!$this->compat
) $this->fields
= false;
4143 if ($this->_skiprow1
) $pos +
= 1;
4144 $this->fields
= $this->_array
[$pos];
4153 } // ADORecordSet_array
4155 //==============================================================================================
4157 //==============================================================================================
4160 * Synonym for ADOLoadCode. Private function. Do not use.
4164 function ADOLoadDB($dbType)
4166 return ADOLoadCode($dbType);
4170 * Load the code for a specific database driver. Private function. Do not use.
4172 function ADOLoadCode($dbType)
4174 global $ADODB_LASTDB;
4176 if (!$dbType) return false;
4177 $db = strtolower($dbType);
4180 if (PHP_VERSION
>= 5) $db = 'ado5';
4186 $class = $db = 'mysqlt';
4191 $class = $db = 'postgres8';
4195 $class = $db; break;
4198 $file = ADODB_DIR
."/drivers/adodb-".$db.".inc.php";
4199 @include_once
($file);
4200 $ADODB_LASTDB = $class;
4201 if (class_exists("ADODB_" . $class)) return $class;
4203 //ADOConnection::outp(adodb_pr(get_declared_classes(),true));
4204 if (!file_exists($file)) ADOConnection
::outp("Missing file: $file");
4205 else ADOConnection
::outp("Syntax error in file: $file");
4210 * synonym for ADONewConnection for people like me who cannot remember the correct name
4212 function NewADOConnection($db='')
4214 $tmp = ADONewConnection($db);
4219 * Instantiate a new Connection class for a specific database driver.
4221 * @param [db] is the database Connection object to create. If undefined,
4222 * use the last database driver that was loaded by ADOLoadCode().
4224 * @return the freshly created instance of the Connection class.
4226 function ADONewConnection($db='')
4228 GLOBAL $ADODB_NEWCONNECTION, $ADODB_LASTDB;
4230 if (!defined('ADODB_ASSOC_CASE')) define('ADODB_ASSOC_CASE',2);
4231 $errorfn = (defined('ADODB_ERROR_HANDLER')) ? ADODB_ERROR_HANDLER
: false;
4233 if (($at = strpos($db,'://')) !== FALSE) {
4235 $fakedsn = 'fake'.substr($origdsn,$at);
4236 if (($at2 = strpos($origdsn,'@/')) !== FALSE) {
4237 // special handling of oracle, which might not have host
4238 $fakedsn = str_replace('@/','@adodb-fakehost/',$fakedsn);
4241 if ((strpos($origdsn, 'sqlite')) !== FALSE && stripos($origdsn, '%2F') === FALSE) {
4242 // special handling for SQLite, it only might have the path to the database file.
4243 // If you try to connect to a SQLite database using a dsn
4244 // like 'sqlite:///path/to/database', the 'parse_url' php function
4245 // will throw you an exception with a message such as "unable to parse url"
4246 list($scheme, $path) = explode('://', $origdsn);
4247 $dsna['scheme'] = $scheme;
4248 if ($qmark = strpos($path,'?')) {
4249 $dsn['query'] = substr($path,$qmark+
1);
4250 $path = substr($path,0,$qmark);
4252 $dsna['path'] = '/' . urlencode($path);
4254 $dsna = @parse_url
($fakedsn);
4259 $dsna['scheme'] = substr($origdsn,0,$at);
4260 if ($at2 !== FALSE) {
4264 if (strncmp($origdsn,'pdo',3) == 0) {
4265 $sch = explode('_',$dsna['scheme']);
4266 if (sizeof($sch)>1) {
4268 $dsna['host'] = isset($dsna['host']) ?
rawurldecode($dsna['host']) : '';
4269 if ($sch[1] == 'sqlite')
4270 $dsna['host'] = rawurlencode($sch[1].':'.rawurldecode($dsna['host']));
4272 $dsna['host'] = rawurlencode($sch[1].':host='.rawurldecode($dsna['host']));
4273 $dsna['scheme'] = 'pdo';
4277 $db = @$dsna['scheme'];
4278 if (!$db) return $false;
4279 $dsna['host'] = isset($dsna['host']) ?
rawurldecode($dsna['host']) : '';
4280 $dsna['user'] = isset($dsna['user']) ?
rawurldecode($dsna['user']) : '';
4281 $dsna['pass'] = isset($dsna['pass']) ?
rawurldecode($dsna['pass']) : '';
4282 $dsna['path'] = isset($dsna['path']) ?
rawurldecode(substr($dsna['path'],1)) : ''; # strip off initial /
4284 if (isset($dsna['query'])) {
4285 $opt1 = explode('&',$dsna['query']);
4286 foreach($opt1 as $k => $v) {
4287 $arr = explode('=',$v);
4288 $opt[$arr[0]] = isset($arr[1]) ?
rawurldecode($arr[1]) : 1;
4290 } else $opt = array();
4293 * phptype: Database backend used in PHP (mysql, odbc etc.)
4294 * dbsyntax: Database used with regards to SQL syntax etc.
4295 * protocol: Communication protocol to use (tcp, unix etc.)
4296 * hostspec: Host specification (hostname[:port])
4297 * database: Database to use on the DBMS server
4298 * username: User name for login
4299 * password: Password for login
4301 if (!empty($ADODB_NEWCONNECTION)) {
4302 $obj = $ADODB_NEWCONNECTION($db);
4308 if (!isset($ADODB_LASTDB)) $ADODB_LASTDB = '';
4309 if (empty($db)) $db = $ADODB_LASTDB;
4311 if ($db != $ADODB_LASTDB) $db = ADOLoadCode($db);
4314 if (isset($origdsn)) $db = $origdsn;
4318 $errorfn('ADONewConnection', 'ADONewConnection', -998,
4319 "could not load the database driver for '$db'",
4322 ADOConnection
::outp( "<p>ADONewConnection: Unable to load database driver '$db'</p>",false);
4327 $cls = 'ADODB_'.$db;
4328 if (!class_exists($cls)) {
4336 # constructor should not fail
4338 if ($errorfn) $obj->raiseErrorFn
= $errorfn;
4340 if (isset($dsna['port'])) $obj->port
= $dsna['port'];
4341 foreach($opt as $k => $v) {
4342 switch(strtolower($k)) {
4344 $nconnect = true; $persist = true; break;
4346 case 'persistent': $persist = $v; break;
4347 case 'debug': $obj->debug
= (integer) $v; break;
4349 case 'role': $obj->role
= $v; break;
4350 case 'dialect': $obj->dialect
= (integer) $v; break;
4351 case 'charset': $obj->charset
= $v; $obj->charSet
=$v; break;
4352 case 'buffers': $obj->buffers
= $v; break;
4353 case 'fetchmode': $obj->SetFetchMode($v); break;
4355 case 'charpage': $obj->charPage
= $v; break;
4357 case 'clientflags': $obj->clientFlags
= $v; break;
4358 #mysql, mysqli, postgres
4359 case 'port': $obj->port
= $v; break;
4361 case 'socket': $obj->socket
= $v; break;
4363 case 'nls_date_format': $obj->NLS_DATE_FORMAT
= $v; break;
4364 case 'cachesecs': $obj->cacheSecs
= $v; break;
4366 $varr = explode(':',$v);
4367 $vlen = sizeof($varr);
4368 if ($vlen == 0) break;
4369 $obj->memCache
= true;
4370 $obj->memCacheHost
= explode(',',$varr[0]);
4371 if ($vlen == 1) break;
4372 $obj->memCachePort
= $varr[1];
4373 if ($vlen == 2) break;
4374 $obj->memCacheCompress
= $varr[2] ?
true : false;
4378 if (empty($persist))
4379 $ok = $obj->Connect($dsna['host'], $dsna['user'], $dsna['pass'], $dsna['path']);
4380 else if (empty($nconnect))
4381 $ok = $obj->PConnect($dsna['host'], $dsna['user'], $dsna['pass'], $dsna['path']);
4383 $ok = $obj->NConnect($dsna['host'], $dsna['user'], $dsna['pass'], $dsna['path']);
4385 if (!$ok) return $false;
4393 // $perf == true means called by NewPerfMonitor(), otherwise for data dictionary
4394 function _adodb_getdriver($provider,$drivername,$perf=false)
4396 switch ($provider) {
4397 case 'odbtp': if (strncmp('odbtp_',$drivername,6)==0) return substr($drivername,6);
4398 case 'odbc' : if (strncmp('odbc_',$drivername,5)==0) return substr($drivername,5);
4399 case 'ado' : if (strncmp('ado_',$drivername,4)==0) return substr($drivername,4);
4400 case 'native': break;
4405 switch($drivername) {
4408 $drivername='mysql';
4412 $drivername = 'postgres';
4414 case 'firebird15': $drivername = 'firebird'; break;
4415 case 'oracle': $drivername = 'oci8'; break;
4416 case 'access': if ($perf) $drivername = ''; break;
4418 case 'sapdb' : break;
4420 $drivername = 'generic';
4426 function NewPerfMonitor(&$conn)
4429 $drivername = _adodb_getdriver($conn->dataProvider
,$conn->databaseType
,true);
4430 if (!$drivername ||
$drivername == 'generic') return $false;
4431 include_once(ADODB_DIR
.'/adodb-perf.inc.php');
4432 @include_once
(ADODB_DIR
."/perf/perf-$drivername.inc.php");
4433 $class = "Perf_$drivername";
4434 if (!class_exists($class)) return $false;
4435 $perf = new $class($conn);
4440 function NewDataDictionary(&$conn,$drivername=false)
4443 if (!$drivername) $drivername = _adodb_getdriver($conn->dataProvider
,$conn->databaseType
);
4445 include_once(ADODB_DIR
.'/adodb-lib.inc.php');
4446 include_once(ADODB_DIR
.'/adodb-datadict.inc.php');
4447 $path = ADODB_DIR
."/datadict/datadict-$drivername.inc.php";
4449 if (!file_exists($path)) {
4450 ADOConnection
::outp("Dictionary driver '$path' not available");
4453 include_once($path);
4454 $class = "ADODB2_$drivername";
4455 $dict = new $class();
4456 $dict->dataProvider
= $conn->dataProvider
;
4457 $dict->connection
= $conn;
4458 $dict->upperName
= strtoupper($drivername);
4459 $dict->quote
= $conn->nameQuote
;
4460 if (!empty($conn->_connectionID
))
4461 $dict->serverInfo
= $conn->ServerInfo();
4469 Perform a print_r, with pre tags for better formatting.
4471 function adodb_pr($var,$as_string=false)
4473 if ($as_string) ob_start();
4475 if (isset($_SERVER['HTTP_USER_AGENT'])) {
4476 echo " <pre>\n";print_r($var);echo "</pre>\n";
4481 $s = ob_get_contents();
4488 Perform a stack-crawl and pretty print it.
4490 @param printOrArr Pass in a boolean to indicate print, or an $exception->trace array (assumes that print is true then).
4491 @param levels Number of levels to display
4493 function adodb_backtrace($printOrArr=true,$levels=9999,$ishtml=null)
4495 global $ADODB_INCLUDED_LIB;
4496 if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR
.'/adodb-lib.inc.php');
4497 return _adodb_backtrace($printOrArr,$levels,0,$ishtml);