summaryrefslogtreecommitdiff
path: root/framework/3rdParty/adodb/adodb.inc.php
diff options
context:
space:
mode:
authorwei <>2006-12-16 03:56:03 +0000
committerwei <>2006-12-16 03:56:03 +0000
commitddc0de38f64e5834ce04f0407a8416172b596655 (patch)
treea94c75b6e7a4f443f748124b84e30d02826bb23a /framework/3rdParty/adodb/adodb.inc.php
parentc8689010d28a0fe2a734131a2964d7df394cdf6c (diff)
removed adodb and framework/DataAccess
Diffstat (limited to 'framework/3rdParty/adodb/adodb.inc.php')
-rw-r--r--framework/3rdParty/adodb/adodb.inc.php4009
1 files changed, 0 insertions, 4009 deletions
diff --git a/framework/3rdParty/adodb/adodb.inc.php b/framework/3rdParty/adodb/adodb.inc.php
deleted file mode 100644
index f363f7cc..00000000
--- a/framework/3rdParty/adodb/adodb.inc.php
+++ /dev/null
@@ -1,4009 +0,0 @@
-<?php
-/*
- * Set tabs to 4 for best viewing.
- *
- * Latest version is available at http://adodb.sourceforge.net
- *
- * This is the main include file for ADOdb.
- * Database specific drivers are stored in the adodb/drivers/adodb-*.inc.php
- *
- * The ADOdb files are formatted so that doxygen can be used to generate documentation.
- * Doxygen is a documentation generation tool and can be downloaded from http://doxygen.org/
- */
-
-/**
- \mainpage
-
- @version V4.81 3 May 2006 (c) 2000-2006 John Lim (jlim#natsoft.com.my). All rights reserved.
-
- Released under both BSD license and Lesser GPL library license. You can choose which license
- you prefer.
-
- PHP's database access functions are not standardised. This creates a need for a database
- class library to hide the differences between the different database API's (encapsulate
- the differences) so we can easily switch databases.
-
- We currently support MySQL, Oracle, Microsoft SQL Server, Sybase, Sybase SQL Anywhere, DB2,
- Informix, PostgreSQL, FrontBase, Interbase (Firebird and Borland variants), Foxpro, Access,
- ADO, SAP DB, SQLite and ODBC. We have had successful reports of connecting to Progress and
- other databases via ODBC.
-
- Latest Download at http://adodb.sourceforge.net/
-
- */
-
- if (!defined('_ADODB_LAYER')) {
- define('_ADODB_LAYER',1);
-
- //==============================================================================================
- // CONSTANT DEFINITIONS
- //==============================================================================================
-
-
- /**
- * Set ADODB_DIR to the directory where this file resides...
- * This constant was formerly called $ADODB_RootPath
- */
- if (!defined('ADODB_DIR')) define('ADODB_DIR',dirname(__FILE__));
-
- //==============================================================================================
- // GLOBAL VARIABLES
- //==============================================================================================
-
- GLOBAL
- $ADODB_vers, // database version
- $ADODB_COUNTRECS, // count number of records returned - slows down query
- $ADODB_CACHE_DIR, // directory to cache recordsets
- $ADODB_EXTENSION, // ADODB extension installed
- $ADODB_COMPAT_FETCH, // If $ADODB_COUNTRECS and this is true, $rs->fields is available on EOF
- $ADODB_FETCH_MODE; // DEFAULT, NUM, ASSOC or BOTH. Default follows native driver default...
-
- //==============================================================================================
- // GLOBAL SETUP
- //==============================================================================================
-
- $ADODB_EXTENSION = defined('ADODB_EXTENSION');
-
- //********************************************************//
- /*
- Controls $ADODB_FORCE_TYPE mode. Default is ADODB_FORCE_VALUE (3).
- Used in GetUpdateSql and GetInsertSql functions. Thx to Niko, nuko#mbnet.fi
-
- 0 = ignore empty fields. All empty fields in array are ignored.
- 1 = force null. All empty, php null and string 'null' fields are changed to sql NULL values.
- 2 = force empty. All empty, php null and string 'null' fields are changed to sql empty '' or 0 values.
- 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.
- */
- define('ADODB_FORCE_IGNORE',0);
- define('ADODB_FORCE_NULL',1);
- define('ADODB_FORCE_EMPTY',2);
- define('ADODB_FORCE_VALUE',3);
- //********************************************************//
-
-
- if (!$ADODB_EXTENSION || ADODB_EXTENSION < 4.0) {
-
- define('ADODB_BAD_RS','<p>Bad $rs in %s. Connection or SQL invalid. Try using $connection->debug=true;</p>');
-
- // allow [ ] @ ` " and . in table names
- define('ADODB_TABLE_REGEX','([]0-9a-z_\:\"\`\.\@\[-]*)');
-
- // prefetching used by oracle
- if (!defined('ADODB_PREFETCH_ROWS')) define('ADODB_PREFETCH_ROWS',10);
-
-
- /*
- Controls ADODB_FETCH_ASSOC field-name case. Default is 2, use native case-names.
- This currently works only with mssql, odbc, oci8po and ibase derived drivers.
-
- 0 = assoc lowercase field names. $rs->fields['orderid']
- 1 = assoc uppercase field names. $rs->fields['ORDERID']
- 2 = use native-case field names. $rs->fields['OrderID']
- */
-
- define('ADODB_FETCH_DEFAULT',0);
- define('ADODB_FETCH_NUM',1);
- define('ADODB_FETCH_ASSOC',2);
- define('ADODB_FETCH_BOTH',3);
-
- if (!defined('TIMESTAMP_FIRST_YEAR')) define('TIMESTAMP_FIRST_YEAR',100);
-
- // PHP's version scheme makes converting to numbers difficult - workaround
- $_adodb_ver = (float) PHP_VERSION;
- if ($_adodb_ver >= 5.0) {
- define('ADODB_PHPVER',0x5000);
- } else if ($_adodb_ver > 4.299999) { # 4.3
- define('ADODB_PHPVER',0x4300);
- } else if ($_adodb_ver > 4.199999) { # 4.2
- define('ADODB_PHPVER',0x4200);
- } else if (strnatcmp(PHP_VERSION,'4.0.5')>=0) {
- define('ADODB_PHPVER',0x4050);
- } else {
- define('ADODB_PHPVER',0x4000);
- }
- }
-
- //if (!defined('ADODB_ASSOC_CASE')) define('ADODB_ASSOC_CASE',2);
-
-
- /**
- Accepts $src and $dest arrays, replacing string $data
- */
- function ADODB_str_replace($src, $dest, $data)
- {
- if (ADODB_PHPVER >= 0x4050) return str_replace($src,$dest,$data);
-
- $s = reset($src);
- $d = reset($dest);
- while ($s !== false) {
- $data = str_replace($s,$d,$data);
- $s = next($src);
- $d = next($dest);
- }
- return $data;
- }
-
- function ADODB_Setup()
- {
- GLOBAL
- $ADODB_vers, // database version
- $ADODB_COUNTRECS, // count number of records returned - slows down query
- $ADODB_CACHE_DIR, // directory to cache recordsets
- $ADODB_FETCH_MODE,
- $ADODB_FORCE_TYPE;
-
- $ADODB_FETCH_MODE = ADODB_FETCH_DEFAULT;
- $ADODB_FORCE_TYPE = ADODB_FORCE_VALUE;
-
-
- if (!isset($ADODB_CACHE_DIR)) {
- $ADODB_CACHE_DIR = '/tmp'; //(isset($_ENV['TMP'])) ? $_ENV['TMP'] : '/tmp';
- } else {
- // do not accept url based paths, eg. http:/ or ftp:/
- if (strpos($ADODB_CACHE_DIR,'://') !== false)
- die("Illegal path http:// or ftp://");
- }
-
-
- // Initialize random number generator for randomizing cache flushes
- srand(((double)microtime())*1000000);
-
- /**
- * ADODB version as a string.
- */
- $ADODB_vers = 'V4.81 3 May 2006 (c) 2000-2006 John Lim (jlim#natsoft.com.my). All rights reserved. Released BSD & LGPL.';
-
- /**
- * Determines whether recordset->RecordCount() is used.
- * Set to false for highest performance -- RecordCount() will always return -1 then
- * for databases that provide "virtual" recordcounts...
- */
- if (!isset($ADODB_COUNTRECS)) $ADODB_COUNTRECS = true;
- }
-
-
- //==============================================================================================
- // CHANGE NOTHING BELOW UNLESS YOU ARE DESIGNING ADODB
- //==============================================================================================
-
- ADODB_Setup();
-
- //==============================================================================================
- // CLASS ADOFieldObject
- //==============================================================================================
- /**
- * Helper class for FetchFields -- holds info on a column
- */
- class ADOFieldObject {
- public $name = '';
- public $max_length=0;
- public $type="";
-/*
- // additional fields by dannym... (danny_milo@yahoo.com)
- public $not_null = false;
- // actually, this has already been built-in in the postgres, fbsql AND mysql module? ^-^
- // so we can as well make not_null standard (leaving it at "false" does not harm anyways)
-
- public $has_default = false; // this one I have done only in mysql and postgres for now ...
- // others to come (dannym)
- public $default_value; // default, if any, and supported. Check has_default first.
-*/
- }
-
-
-
- function ADODB_TransMonitor($dbms, $fn, $errno, $errmsg, $p1, $p2, &$thisConnection)
- {
- //print "Errorno ($fn errno=$errno m=$errmsg) ";
- $thisConnection->_transOK = false;
- if ($thisConnection->_oldRaiseFn) {
- $fn = $thisConnection->_oldRaiseFn;
- $fn($dbms, $fn, $errno, $errmsg, $p1, $p2,$thisConnection);
- }
- }
-
- //==============================================================================================
- // CLASS ADOConnection
- //==============================================================================================
-
- /**
- * Connection object. For connecting to databases, and executing queries.
- */
- class ADOConnection {
- //
- // PUBLIC VARS
- //
- public $dataProvider = 'native';
- public $databaseType = ''; /// RDBMS currently in use, eg. odbc, mysql, mssql
- public $database = ''; /// Name of database to be used.
- public $host = ''; /// The hostname of the database server
- public $user = ''; /// The username which is used to connect to the database server.
- public $password = ''; /// Password for the username. For security, we no longer store it.
- public $debug = false; /// if set to true will output sql statements
- public $maxblobsize = 262144; /// maximum size of blobs or large text fields (262144 = 256K)-- some db's die otherwise like foxpro
- public $concat_operator = '+'; /// default concat operator -- change to || for Oracle/Interbase
- public $substr = 'substr'; /// substring operator
- public $length = 'length'; /// string length ofperator
- public $random = 'rand()'; /// random function
- public $upperCase = 'upper'; /// uppercase function
- public $fmtDate = "'Y-m-d'"; /// used by DBDate() as the default date format used by the database
- public $fmtTimeStamp = "'Y-m-d, h:i:s A'"; /// used by DBTimeStamp as the default timestamp fmt.
- public $true = '1'; /// string that represents TRUE for a database
- public $false = '0'; /// string that represents FALSE for a database
- public $replaceQuote = "\\'"; /// string to use to replace quotes
- public $nameQuote = '"'; /// string to use to quote identifiers and names
- public $charSet=false; /// character set to use - only for interbase, postgres and oci8
- public $metaDatabasesSQL = '';
- public $metaTablesSQL = '';
- public $uniqueOrderBy = false; /// All order by columns have to be unique
- public $emptyDate = '&nbsp;';
- public $emptyTimeStamp = '&nbsp;';
- public $lastInsID = false;
- //--
- public $hasInsertID = false; /// supports autoincrement ID?
- public $hasAffectedRows = false; /// supports affected rows for update/delete?
- public $hasTop = false; /// support mssql/access SELECT TOP 10 * FROM TABLE
- public $hasLimit = false; /// support pgsql/mysql SELECT * FROM TABLE LIMIT 10
- public $readOnly = false; /// this is a readonly database - used by phpLens
- public $hasMoveFirst = false; /// has ability to run MoveFirst(), scrolling backwards
- public $hasGenID = false; /// can generate sequences using GenID();
- public $hasTransactions = true; /// has transactions
- //--
- public $genID = 0; /// sequence id used by GenID();
- public $raiseErrorFn = false; /// error function to call
- public $isoDates = false; /// accepts dates in ISO format
- public $cacheSecs = 3600; /// cache for 1 hour
- public $sysDate = false; /// name of function that returns the current date
- public $sysTimeStamp = false; /// name of function that returns the current timestamp
- public $arrayClass = 'ADORecordSet_array'; /// name of class used to generate array recordsets, which are pre-downloaded recordsets
-
- public $noNullStrings = false; /// oracle specific stuff - if true ensures that '' is converted to ' '
- public $numCacheHits = 0;
- public $numCacheMisses = 0;
- public $pageExecuteCountRows = true;
- public $uniqueSort = false; /// indicates that all fields in order by must be unique
- public $leftOuter = false; /// operator to use for left outer join in WHERE clause
- public $rightOuter = false; /// operator to use for right outer join in WHERE clause
- public $ansiOuter = false; /// whether ansi outer join syntax supported
- public $autoRollback = false; // autoRollback on PConnect().
- public $poorAffectedRows = false; // affectedRows not working or unreliable
-
- public $fnExecute = false;
- public $fnCacheExecute = false;
- public $blobEncodeType = false; // false=not required, 'I'=encode to integer, 'C'=encode to char
- public $rsPrefix = "ADORecordSet_";
-
- public $autoCommit = true; /// do not modify this yourself - actually private
- public $transOff = 0; /// temporarily disable transactions
- public $transCnt = 0; /// count of nested transactions
-
- public $fetchMode=false;
- //
- // PRIVATE VARS
- //
- public $_oldRaiseFn = false;
- public $_transOK = null;
- public $_connectionID = false; /// The returned link identifier whenever a successful database connection is made.
- public $_errorMsg = false; /// A variable which was used to keep the returned last error message. The value will
- /// then returned by the errorMsg() function
- public $_errorCode = false; /// Last error code, not guaranteed to be used - only by oci8
- public $_queryID = false; /// This variable keeps the last created result link identifier
-
- public $_isPersistentConnection = false; /// A boolean variable to state whether its a persistent connection or normal connection. */
- public $_bindInputArray = false; /// set to true if ADOConnection.Execute() permits binding of array parameters.
- public $_evalAll = false;
- public $_affected = false;
- public $_logsql = false;
-
- /**
- * Constructor
- */
- function ADOConnection()
- {
- die('Virtual Class -- cannot instantiate');
- }
-
- function Version()
- {
- global $ADODB_vers;
-
- return (float) substr($ADODB_vers,1);
- }
-
- /**
- Get server version info...
-
- @returns An array with 2 elements: $arr['string'] is the description string,
- and $arr[version] is the version (also a string).
- */
- function ServerInfo()
- {
- return array('description' => '', 'version' => '');
- }
-
- function IsConnected()
- {
- return !empty($this->_connectionID);
- }
-
- function _findvers($str)
- {
- if (preg_match('/([0-9]+\.([0-9\.])+)/',$str, $arr)) return $arr[1];
- else return '';
- }
-
- /**
- * All error messages go through this bottleneck function.
- * You can define your own handler by defining the function name in ADODB_OUTP.
- */
- function outp($msg,$newline=true)
- {
- global $ADODB_FLUSH,$ADODB_OUTP;
-
- if (defined('ADODB_OUTP')) {
- $fn = ADODB_OUTP;
- $fn($msg,$newline);
- return;
- } else if (isset($ADODB_OUTP)) {
- $fn = $ADODB_OUTP;
- $fn($msg,$newline);
- return;
- }
-
- if ($newline) $msg .= "<br>\n";
-
- if (isset($_SERVER['HTTP_USER_AGENT']) || !$newline) echo $msg;
- else echo strip_tags($msg);
-
-
- if (!empty($ADODB_FLUSH) && ob_get_length() !== false) flush(); // do not flush if output buffering enabled - useless - thx to Jesse Mullan
-
- }
-
- function Time()
- {
- $rs =& $this->_Execute("select $this->sysTimeStamp");
- if ($rs && !$rs->EOF) return $this->UnixTimeStamp(reset($rs->fields));
-
- return false;
- }
-
- /**
- * Connect to database
- *
- * @param [argHostname] Host to connect to
- * @param [argUsername] Userid to login
- * @param [argPassword] Associated password
- * @param [argDatabaseName] database
- * @param [forceNew] force new connection
- *
- * @return true or false
- */
- function Connect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "", $forceNew = false)
- {
- if ($argHostname != "") $this->host = $argHostname;
- if ($argUsername != "") $this->user = $argUsername;
- if ($argPassword != "") $this->password = $argPassword; // not stored for security reasons
- if ($argDatabaseName != "") $this->database = $argDatabaseName;
-
- $this->_isPersistentConnection = false;
- if ($forceNew) {
- if ($rez=$this->_nconnect($this->host, $this->user, $this->password, $this->database)) return true;
- } else {
- if ($rez=$this->_connect($this->host, $this->user, $this->password, $this->database)) return true;
- }
- if (isset($rez)) {
- $err = $this->ErrorMsg();
- if (empty($err)) $err = "Connection error to server '$argHostname' with user '$argUsername'";
- $ret = false;
- } else {
- $err = "Missing extension for ".$this->dataProvider;
- $ret = 0;
- }
- if ($fn = $this->raiseErrorFn)
- $fn($this->databaseType,'CONNECT',$this->ErrorNo(),$err,$this->host,$this->database,$this);
-
-
- $this->_connectionID = false;
- if ($this->debug) ADOConnection::outp( $this->host.': '.$err);
- return $ret;
- }
-
- function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName)
- {
- return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName);
- }
-
-
- /**
- * Always force a new connection to database - currently only works with oracle
- *
- * @param [argHostname] Host to connect to
- * @param [argUsername] Userid to login
- * @param [argPassword] Associated password
- * @param [argDatabaseName] database
- *
- * @return true or false
- */
- function NConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "")
- {
- return $this->Connect($argHostname, $argUsername, $argPassword, $argDatabaseName, true);
- }
-
- /**
- * Establish persistent connect to database
- *
- * @param [argHostname] Host to connect to
- * @param [argUsername] Userid to login
- * @param [argPassword] Associated password
- * @param [argDatabaseName] database
- *
- * @return return true or false
- */
- function PConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "")
- {
- if (defined('ADODB_NEVER_PERSIST'))
- return $this->Connect($argHostname,$argUsername,$argPassword,$argDatabaseName);
-
- if ($argHostname != "") $this->host = $argHostname;
- if ($argUsername != "") $this->user = $argUsername;
- if ($argPassword != "") $this->password = $argPassword;
- if ($argDatabaseName != "") $this->database = $argDatabaseName;
-
- $this->_isPersistentConnection = true;
- if ($rez = $this->_pconnect($this->host, $this->user, $this->password, $this->database)) return true;
- if (isset($rez)) {
- $err = $this->ErrorMsg();
- if (empty($err)) $err = "Connection error to server '$argHostname' with user '$argUsername'";
- $ret = false;
- } else {
- $err = "Missing extension for ".$this->dataProvider;
- $ret = 0;
- }
- if ($fn = $this->raiseErrorFn) {
- $fn($this->databaseType,'PCONNECT',$this->ErrorNo(),$err,$this->host,$this->database,$this);
- }
-
- $this->_connectionID = false;
- if ($this->debug) ADOConnection::outp( $this->host.': '.$err);
- return $ret;
- }
-
- // Format date column in sql string given an input format that understands Y M D
- function SQLDate($fmt, $col=false)
- {
- if (!$col) $col = $this->sysDate;
- return $col; // child class implement
- }
-
- /**
- * Should prepare the sql statement and return the stmt resource.
- * For databases that do not support this, we return the $sql. To ensure
- * compatibility with databases that do not support prepare:
- *
- * $stmt = $db->Prepare("insert into table (id, name) values (?,?)");
- * $db->Execute($stmt,array(1,'Jill')) or die('insert failed');
- * $db->Execute($stmt,array(2,'Joe')) or die('insert failed');
- *
- * @param sql SQL to send to database
- *
- * @return return FALSE, or the prepared statement, or the original sql if
- * if the database does not support prepare.
- *
- */
- function Prepare($sql)
- {
- return $sql;
- }
-
- /**
- * Some databases, eg. mssql require a different function for preparing
- * stored procedures. So we cannot use Prepare().
- *
- * Should prepare the stored procedure and return the stmt resource.
- * For databases that do not support this, we return the $sql. To ensure
- * compatibility with databases that do not support prepare:
- *
- * @param sql SQL to send to database
- *
- * @return return FALSE, or the prepared statement, or the original sql if
- * if the database does not support prepare.
- *
- */
- function PrepareSP($sql,$param=true)
- {
- return $this->Prepare($sql,$param);
- }
-
- /**
- * PEAR DB Compat
- */
- function Quote($s)
- {
- return $this->qstr($s,false);
- }
-
- /**
- Requested by "Karsten Dambekalns" <k.dambekalns@fishfarm.de>
- */
- function QMagic($s)
- {
- return $this->qstr($s,get_magic_quotes_gpc());
- }
-
- function q(&$s)
- {
- #if (!empty($this->qNull)) if ($s == 'null') return $s;
- $s = $this->qstr($s,false);
- }
-
- /**
- * PEAR DB Compat - do not use internally.
- */
- function ErrorNative()
- {
- return $this->ErrorNo();
- }
-
-
- /**
- * PEAR DB Compat - do not use internally.
- */
- function nextId($seq_name)
- {
- return $this->GenID($seq_name);
- }
-
- /**
- * Lock a row, will escalate and lock the table if row locking not supported
- * will normally free the lock at the end of the transaction
- *
- * @param $table name of table to lock
- * @param $where where clause to use, eg: "WHERE row=12". If left empty, will escalate to table lock
- */
- function RowLock($table,$where)
- {
- return false;
- }
-
- function CommitLock($table)
- {
- return $this->CommitTrans();
- }
-
- function RollbackLock($table)
- {
- return $this->RollbackTrans();
- }
-
- /**
- * PEAR DB Compat - do not use internally.
- *
- * The fetch modes for NUMERIC and ASSOC for PEAR DB and ADODB are identical
- * for easy porting :-)
- *
- * @param mode The fetchmode ADODB_FETCH_ASSOC or ADODB_FETCH_NUM
- * @returns The previous fetch mode
- */
- function SetFetchMode($mode)
- {
- $old = $this->fetchMode;
- $this->fetchMode = $mode;
-
- if ($old === false) {
- global $ADODB_FETCH_MODE;
- return $ADODB_FETCH_MODE;
- }
- return $old;
- }
-
-
- /**
- * PEAR DB Compat - do not use internally.
- */
- function &Query($sql, $inputarr=false)
- {
- $rs = &$this->Execute($sql, $inputarr);
- if (!$rs && defined('ADODB_PEAR')) return ADODB_PEAR_Error();
- return $rs;
- }
-
-
- /**
- * PEAR DB Compat - do not use internally
- */
- function &LimitQuery($sql, $offset, $count, $params=false)
- {
- $rs = &$this->SelectLimit($sql, $count, $offset, $params);
- if (!$rs && defined('ADODB_PEAR')) return ADODB_PEAR_Error();
- return $rs;
- }
-
-
- /**
- * PEAR DB Compat - do not use internally
- */
- function Disconnect()
- {
- return $this->Close();
- }
-
- /*
- Returns placeholder for parameter, eg.
- $DB->Param('a')
-
- will return ':a' for Oracle, and '?' for most other databases...
-
- For databases that require positioned params, eg $1, $2, $3 for postgresql,
- pass in Param(false) before setting the first parameter.
- */
- function Param($name,$type='C')
- {
- return '?';
- }
-
- /*
- InParameter and OutParameter are self-documenting versions of Parameter().
- */
- function InParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false)
- {
- return $this->Parameter($stmt,$var,$name,false,$maxLen,$type);
- }
-
- /*
- */
- function OutParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false)
- {
- return $this->Parameter($stmt,$var,$name,true,$maxLen,$type);
-
- }
-
- /*
- Usage in oracle
- $stmt = $db->Prepare('select * from table where id =:myid and group=:group');
- $db->Parameter($stmt,$id,'myid');
- $db->Parameter($stmt,$group,'group',64);
- $db->Execute();
-
- @param $stmt Statement returned by Prepare() or PrepareSP().
- @param $var PHP variable to bind to
- @param $name Name of stored procedure variable name to bind to.
- @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8.
- @param [$maxLen] Holds an maximum length of the variable.
- @param [$type] The data type of $var. Legal values depend on driver.
-
- */
- function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false)
- {
- return false;
- }
-
- /**
- Improved method of initiating a transaction. Used together with CompleteTrans().
- Advantages include:
-
- a. StartTrans/CompleteTrans is nestable, unlike BeginTrans/CommitTrans/RollbackTrans.
- Only the outermost block is treated as a transaction.<br>
- b. CompleteTrans auto-detects SQL errors, and will rollback on errors, commit otherwise.<br>
- c. All BeginTrans/CommitTrans/RollbackTrans inside a StartTrans/CompleteTrans block
- are disabled, making it backward compatible.
- */
- function StartTrans($errfn = 'ADODB_TransMonitor')
- {
- if ($this->transOff > 0) {
- $this->transOff += 1;
- return;
- }
-
- $this->_oldRaiseFn = $this->raiseErrorFn;
- $this->raiseErrorFn = $errfn;
- $this->_transOK = true;
-
- if ($this->debug && $this->transCnt > 0) ADOConnection::outp("Bad Transaction: StartTrans called within BeginTrans");
- $this->BeginTrans();
- $this->transOff = 1;
- }
-
-
- /**
- Used together with StartTrans() to end a transaction. Monitors connection
- for sql errors, and will commit or rollback as appropriate.
-
- @autoComplete if true, monitor sql errors and commit and rollback as appropriate,
- and if set to false force rollback even if no SQL error detected.
- @returns true on commit, false on rollback.
- */
- function CompleteTrans($autoComplete = true)
- {
- if ($this->transOff > 1) {
- $this->transOff -= 1;
- return true;
- }
- $this->raiseErrorFn = $this->_oldRaiseFn;
-
- $this->transOff = 0;
- if ($this->_transOK && $autoComplete) {
- if (!$this->CommitTrans()) {
- $this->_transOK = false;
- if ($this->debug) ADOConnection::outp("Smart Commit failed");
- } else
- if ($this->debug) ADOConnection::outp("Smart Commit occurred");
- } else {
- $this->_transOK = false;
- $this->RollbackTrans();
- if ($this->debug) ADOCOnnection::outp("Smart Rollback occurred");
- }
-
- return $this->_transOK;
- }
-
- /*
- At the end of a StartTrans/CompleteTrans block, perform a rollback.
- */
- function FailTrans()
- {
- if ($this->debug)
- if ($this->transOff == 0) {
- ADOConnection::outp("FailTrans outside StartTrans/CompleteTrans");
- } else {
- ADOConnection::outp("FailTrans was called");
- adodb_backtrace();
- }
- $this->_transOK = false;
- }
-
- /**
- Check if transaction has failed, only for Smart Transactions.
- */
- function HasFailedTrans()
- {
- if ($this->transOff > 0) return $this->_transOK == false;
- return false;
- }
-
- /**
- * Execute SQL
- *
- * @param sql SQL statement to execute, or possibly an array holding prepared statement ($sql[0] will hold sql text)
- * @param [inputarr] holds the input data to bind to. Null elements will be set to null.
- * @return RecordSet or false
- */
- function &Execute($sql,$inputarr=false)
- {
- if ($this->fnExecute) {
- $fn = $this->fnExecute;
- $ret =& $fn($this,$sql,$inputarr);
- if (isset($ret)) return $ret;
- }
- if ($inputarr) {
- if (!is_array($inputarr)) $inputarr = array($inputarr);
-
- $element0 = reset($inputarr);
- # is_object check because oci8 descriptors can be passed in
- $array_2d = is_array($element0) && !is_object(reset($element0));
- //remove extra memory copy of input -mikefedyk
- unset($element0);
-
- if (!is_array($sql) && !$this->_bindInputArray) {
- $sqlarr = explode('?',$sql);
-
- if (!$array_2d) $inputarr = array($inputarr);
- foreach($inputarr as $arr) {
- $sql = ''; $i = 0;
- //Use each() instead of foreach to reduce memory usage -mikefedyk
- while(list(, $v) = each($arr)) {
- $sql .= $sqlarr[$i];
- // from Ron Baldwin <ron.baldwin#sourceprose.com>
- // Only quote string types
- $typ = gettype($v);
- if ($typ == 'string')
- //New memory copy of input created here -mikefedyk
- $sql .= $this->qstr($v);
- else if ($typ == 'double')
- $sql .= str_replace(',','.',$v); // locales fix so 1.1 does not get converted to 1,1
- else if ($typ == 'boolean')
- $sql .= $v ? $this->true : $this->false;
- else if ($v === null)
- $sql .= 'NULL';
- else
- $sql .= $v;
- $i += 1;
- }
- if (isset($sqlarr[$i])) {
- $sql .= $sqlarr[$i];
- if ($i+1 != sizeof($sqlarr)) ADOConnection::outp( "Input Array does not match ?: ".htmlspecialchars($sql));
- } else if ($i != sizeof($sqlarr))
- ADOConnection::outp( "Input array does not match ?: ".htmlspecialchars($sql));
-
- $ret =& $this->_Execute($sql);
- if (!$ret) return $ret;
- }
- } else {
- if ($array_2d) {
- if (is_string($sql))
- $stmt = $this->Prepare($sql);
- else
- $stmt = $sql;
-
- foreach($inputarr as $arr) {
- $ret =& $this->_Execute($stmt,$arr);
- if (!$ret) return $ret;
- }
- } else {
- $ret =& $this->_Execute($sql,$inputarr);
- }
- }
- } else {
- $ret =& $this->_Execute($sql,false);
- }
-
- return $ret;
- }
-
-
- function &_Execute($sql,$inputarr=false)
- {
- if ($this->debug) {
- global $ADODB_INCLUDED_LIB;
- if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR.'/adodb-lib.inc.php');
- $this->_queryID = _adodb_debug_execute($this, $sql,$inputarr);
- } else {
- $this->_queryID = @$this->_query($sql,$inputarr);
- }
-
- /************************
- // OK, query executed
- *************************/
-
- if ($this->_queryID === false) { // error handling if query fails
- if ($this->debug == 99) adodb_backtrace(true,5);
- $fn = $this->raiseErrorFn;
- if ($fn) {
- $fn($this->databaseType,'EXECUTE',$this->ErrorNo(),$this->ErrorMsg(),$sql,$inputarr,$this);
- }
- $false = false;
- return $false;
- }
-
- if ($this->_queryID === true) { // return simplified recordset for inserts/updates/deletes with lower overhead
- $rs = new ADORecordSet_empty();
- return $rs;
- }
-
- // return real recordset from select statement
- $rsclass = $this->rsPrefix.$this->databaseType;
- $rs = new $rsclass($this->_queryID,$this->fetchMode);
- $rs->connection = &$this; // Pablo suggestion
- $rs->Init();
- if (is_array($sql)) $rs->sql = $sql[0];
- else $rs->sql = $sql;
- if ($rs->_numOfRows <= 0) {
- global $ADODB_COUNTRECS;
- if ($ADODB_COUNTRECS) {
- if (!$rs->EOF) {
- $rs = &$this->_rs2rs($rs,-1,-1,!is_array($sql));
- $rs->_queryID = $this->_queryID;
- } else
- $rs->_numOfRows = 0;
- }
- }
- return $rs;
- }
-
- function CreateSequence($seqname='adodbseq',$startID=1)
- {
- if (empty($this->_genSeqSQL)) return false;
- return $this->Execute(sprintf($this->_genSeqSQL,$seqname,$startID));
- }
-
- function DropSequence($seqname='adodbseq')
- {
- if (empty($this->_dropSeqSQL)) return false;
- return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
- }
-
- /**
- * Generates a sequence id and stores it in $this->genID;
- * GenID is only available if $this->hasGenID = true;
- *
- * @param seqname name of sequence to use
- * @param startID if sequence does not exist, start at this ID
- * @return 0 if not supported, otherwise a sequence id
- */
- function GenID($seqname='adodbseq',$startID=1)
- {
- if (!$this->hasGenID) {
- return 0; // formerly returns false pre 1.60
- }
-
- $getnext = sprintf($this->_genIDSQL,$seqname);
-
- $holdtransOK = $this->_transOK;
-
- $save_handler = $this->raiseErrorFn;
- $this->raiseErrorFn = '';
- @($rs = $this->Execute($getnext));
- $this->raiseErrorFn = $save_handler;
-
- if (!$rs) {
- $this->_transOK = $holdtransOK; //if the status was ok before reset
- $createseq = $this->Execute(sprintf($this->_genSeqSQL,$seqname,$startID));
- $rs = $this->Execute($getnext);
- }
- if ($rs && !$rs->EOF) $this->genID = reset($rs->fields);
- else $this->genID = 0; // false
-
- if ($rs) $rs->Close();
-
- return $this->genID;
- }
-
- /**
- * @param $table string name of the table, not needed by all databases (eg. mysql), default ''
- * @param $column string name of the column, not needed by all databases (eg. mysql), default ''
- * @return the last inserted ID. Not all databases support this.
- */
- function Insert_ID($table='',$column='')
- {
- if ($this->_logsql && $this->lastInsID) return $this->lastInsID;
- if ($this->hasInsertID) return $this->_insertid($table,$column);
- if ($this->debug) {
- ADOConnection::outp( '<p>Insert_ID error</p>');
- adodb_backtrace();
- }
- return false;
- }
-
-
- /**
- * Portable Insert ID. Pablo Roca <pabloroca#mvps.org>
- *
- * @return the last inserted ID. All databases support this. But aware possible
- * problems in multiuser environments. Heavy test this before deploying.
- */
- function PO_Insert_ID($table="", $id="")
- {
- if ($this->hasInsertID){
- return $this->Insert_ID($table,$id);
- } else {
- return $this->GetOne("SELECT MAX($id) FROM $table");
- }
- }
-
- /**
- * @return # rows affected by UPDATE/DELETE
- */
- function Affected_Rows()
- {
- if ($this->hasAffectedRows) {
- if ($this->fnExecute === 'adodb_log_sql') {
- if ($this->_logsql && $this->_affected !== false) return $this->_affected;
- }
- $val = $this->_affectedrows();
- return ($val < 0) ? false : $val;
- }
-
- if ($this->debug) ADOConnection::outp( '<p>Affected_Rows error</p>',false);
- return false;
- }
-
-
- /**
- * @return the last error message
- */
- function ErrorMsg()
- {
- if ($this->_errorMsg) return '!! '.strtoupper($this->dataProvider.' '.$this->databaseType).': '.$this->_errorMsg;
- else return '';
- }
-
-
- /**
- * @return the last error number. Normally 0 means no error.
- */
- function ErrorNo()
- {
- return ($this->_errorMsg) ? -1 : 0;
- }
-
- function MetaError($err=false)
- {
- include_once(ADODB_DIR."/adodb-error.inc.php");
- if ($err === false) $err = $this->ErrorNo();
- return adodb_error($this->dataProvider,$this->databaseType,$err);
- }
-
- function MetaErrorMsg($errno)
- {
- include_once(ADODB_DIR."/adodb-error.inc.php");
- return adodb_errormsg($errno);
- }
-
- /**
- * @returns an array with the primary key columns in it.
- */
- function MetaPrimaryKeys($table, $owner=false)
- {
- // owner not used in base class - see oci8
- $p = array();
- $objs =& $this->MetaColumns($table);
- if ($objs) {
- foreach($objs as $v) {
- if (!empty($v->primary_key))
- $p[] = $v->name;
- }
- }
- if (sizeof($p)) return $p;
- if (function_exists('ADODB_VIEW_PRIMARYKEYS'))
- return ADODB_VIEW_PRIMARYKEYS($this->databaseType, $this->database, $table, $owner);
- return false;
- }
-
- /**
- * @returns assoc array where keys are tables, and values are foreign keys
- */
- function MetaForeignKeys($table, $owner=false, $upper=false)
- {
- return false;
- }
- /**
- * Choose a database to connect to. Many databases do not support this.
- *
- * @param dbName is the name of the database to select
- * @return true or false
- */
- function SelectDB($dbName)
- {return false;}
-
-
- /**
- * Will select, getting rows from $offset (1-based), for $nrows.
- * This simulates the MySQL "select * from table limit $offset,$nrows" , and
- * the PostgreSQL "select * from table limit $nrows offset $offset". Note that
- * MySQL and PostgreSQL parameter ordering is the opposite of the other.
- * eg.
- * SelectLimit('select * from table',3); will return rows 1 to 3 (1-based)
- * SelectLimit('select * from table',3,2); will return rows 3 to 5 (1-based)
- *
- * Uses SELECT TOP for Microsoft databases (when $this->hasTop is set)
- * BUG: Currently SelectLimit fails with $sql with LIMIT or TOP clause already set
- *
- * @param sql
- * @param [offset] is the row to start calculations from (1-based)
- * @param [nrows] is the number of rows to get
- * @param [inputarr] array of bind variables
- * @param [secs2cache] is a private parameter only used by jlim
- * @return the recordset ($rs->databaseType == 'array')
- */
- function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
- {
- if ($this->hasTop && $nrows > 0) {
- // suggested by Reinhard Balling. Access requires top after distinct
- // Informix requires first before distinct - F Riosa
- $ismssql = (strpos($this->databaseType,'mssql') !== false);
- if ($ismssql) $isaccess = false;
- else $isaccess = (strpos($this->databaseType,'access') !== false);
-
- if ($offset <= 0) {
-
- // access includes ties in result
- if ($isaccess) {
- $sql = preg_replace(
- '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop.' '.((integer)$nrows).' ',$sql);
-
- if ($secs2cache>0) {
- $ret =& $this->CacheExecute($secs2cache, $sql,$inputarr);
- } else {
- $ret =& $this->Execute($sql,$inputarr);
- }
- return $ret; // PHP5 fix
- } else if ($ismssql){
- $sql = preg_replace(
- '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop.' '.((integer)$nrows).' ',$sql);
- } else {
- $sql = preg_replace(
- '/(^\s*select\s)/i','\\1 '.$this->hasTop.' '.((integer)$nrows).' ',$sql);
- }
- } else {
- $nn = $nrows + $offset;
- if ($isaccess || $ismssql) {
- $sql = preg_replace(
- '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop.' '.$nn.' ',$sql);
- } else {
- $sql = preg_replace(
- '/(^\s*select\s)/i','\\1 '.$this->hasTop.' '.$nn.' ',$sql);
- }
- }
- }
-
- // if $offset>0, we want to skip rows, and $ADODB_COUNTRECS is set, we buffer rows
- // 0 to offset-1 which will be discarded anyway. So we disable $ADODB_COUNTRECS.
- global $ADODB_COUNTRECS;
-
- $savec = $ADODB_COUNTRECS;
- $ADODB_COUNTRECS = false;
-
- if ($offset>0){
- if ($secs2cache>0) $rs = &$this->CacheExecute($secs2cache,$sql,$inputarr);
- else $rs = &$this->Execute($sql,$inputarr);
- } else {
- if ($secs2cache>0) $rs = &$this->CacheExecute($secs2cache,$sql,$inputarr);
- else $rs = &$this->Execute($sql,$inputarr);
- }
- $ADODB_COUNTRECS = $savec;
- if ($rs && !$rs->EOF) {
- $rs =& $this->_rs2rs($rs,$nrows,$offset);
- }
- //print_r($rs);
- return $rs;
- }
-
- /**
- * Create serializable recordset. Breaks rs link to connection.
- *
- * @param rs the recordset to serialize
- */
- function &SerializableRS(&$rs)
- {
- $rs2 =& $this->_rs2rs($rs);
- $ignore = false;
- $rs2->connection =& $ignore;
-
- return $rs2;
- }
-
- /**
- * Convert database recordset to an array recordset
- * input recordset's cursor should be at beginning, and
- * old $rs will be closed.
- *
- * @param rs the recordset to copy
- * @param [nrows] number of rows to retrieve (optional)
- * @param [offset] offset by number of rows (optional)
- * @return the new recordset
- */
- function &_rs2rs(&$rs,$nrows=-1,$offset=-1,$close=true)
- {
- if (! $rs) {
- $false = false;
- return $false;
- }
- $dbtype = $rs->databaseType;
- if (!$dbtype) {
- $rs = &$rs; // required to prevent crashing in 4.2.1, but does not happen in 4.3.1 -- why ?
- return $rs;
- }
- if (($dbtype == 'array' || $dbtype == 'csv') && $nrows == -1 && $offset == -1) {
- $rs->MoveFirst();
- $rs = &$rs; // required to prevent crashing in 4.2.1, but does not happen in 4.3.1-- why ?
- return $rs;
- }
- $flds = array();
- for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) {
- $flds[] = $rs->FetchField($i);
- }
-
- $arr =& $rs->GetArrayLimit($nrows,$offset);
- //print_r($arr);
- if ($close) $rs->Close();
-
- $arrayClass = $this->arrayClass;
-
- $rs2 = new $arrayClass();
- $rs2->connection = &$this;
- $rs2->sql = $rs->sql;
- $rs2->dataProvider = $this->dataProvider;
- $rs2->InitArrayFields($arr,$flds);
- $rs2->fetchMode = isset($rs->adodbFetchMode) ? $rs->adodbFetchMode : $rs->fetchMode;
- return $rs2;
- }
-
- /*
- * Return all rows. Compat with PEAR DB
- */
- function &GetAll($sql, $inputarr=false)
- {
- $arr =& $this->GetArray($sql,$inputarr);
- return $arr;
- }
-
- function &GetAssoc($sql, $inputarr=false,$force_array = false, $first2cols = false)
- {
- $rs =& $this->Execute($sql, $inputarr);
- if (!$rs) {
- $false = false;
- return $false;
- }
- $arr =& $rs->GetAssoc($force_array,$first2cols);
- return $arr;
- }
-
- function &CacheGetAssoc($secs2cache, $sql=false, $inputarr=false,$force_array = false, $first2cols = false)
- {
- if (!is_numeric($secs2cache)) {
- $first2cols = $force_array;
- $force_array = $inputarr;
- }
- $rs =& $this->CacheExecute($secs2cache, $sql, $inputarr);
- if (!$rs) {
- $false = false;
- return $false;
- }
- $arr =& $rs->GetAssoc($force_array,$first2cols);
- return $arr;
- }
-
- /**
- * Return first element of first row of sql statement. Recordset is disposed
- * for you.
- *
- * @param sql SQL statement
- * @param [inputarr] input bind array
- */
- function GetOne($sql,$inputarr=false)
- {
- global $ADODB_COUNTRECS;
- $crecs = $ADODB_COUNTRECS;
- $ADODB_COUNTRECS = false;
-
- $ret = false;
- $rs = &$this->Execute($sql,$inputarr);
- if ($rs) {
- if (!$rs->EOF) $ret = reset($rs->fields);
- $rs->Close();
- }
- $ADODB_COUNTRECS = $crecs;
- return $ret;
- }
-
- function CacheGetOne($secs2cache,$sql=false,$inputarr=false)
- {
- $ret = false;
- $rs = &$this->CacheExecute($secs2cache,$sql,$inputarr);
- if ($rs) {
- if (!$rs->EOF) $ret = reset($rs->fields);
- $rs->Close();
- }
-
- return $ret;
- }
-
- function GetCol($sql, $inputarr = false, $trim = false)
- {
- $rv = false;
- $rs = &$this->Execute($sql, $inputarr);
- if ($rs) {
- $rv = array();
- if ($trim) {
- while (!$rs->EOF) {
- $rv[] = trim(reset($rs->fields));
- $rs->MoveNext();
- }
- } else {
- while (!$rs->EOF) {
- $rv[] = reset($rs->fields);
- $rs->MoveNext();
- }
- }
- $rs->Close();
- }
- return $rv;
- }
-
- function CacheGetCol($secs, $sql = false, $inputarr = false,$trim=false)
- {
- $rv = false;
- $rs = &$this->CacheExecute($secs, $sql, $inputarr);
- if ($rs) {
- if ($trim) {
- while (!$rs->EOF) {
- $rv[] = trim(reset($rs->fields));
- $rs->MoveNext();
- }
- } else {
- while (!$rs->EOF) {
- $rv[] = reset($rs->fields);
- $rs->MoveNext();
- }
- }
- $rs->Close();
- }
- return $rv;
- }
-
- /*
- Calculate the offset of a date for a particular database and generate
- appropriate SQL. Useful for calculating future/past dates and storing
- in a database.
-
- If dayFraction=1.5 means 1.5 days from now, 1.0/24 for 1 hour.
- */
- function OffsetDate($dayFraction,$date=false)
- {
- if (!$date) $date = $this->sysDate;
- return '('.$date.'+'.$dayFraction.')';
- }
-
-
- /**
- *
- * @param sql SQL statement
- * @param [inputarr] input bind array
- */
- function &GetArray($sql,$inputarr=false)
- {
- global $ADODB_COUNTRECS;
-
- $savec = $ADODB_COUNTRECS;
- $ADODB_COUNTRECS = false;
- $rs =& $this->Execute($sql,$inputarr);
- $ADODB_COUNTRECS = $savec;
- if (!$rs)
- if (defined('ADODB_PEAR')) {
- $cls = ADODB_PEAR_Error();
- return $cls;
- } else {
- $false = false;
- return $false;
- }
- $arr =& $rs->GetArray();
- $rs->Close();
- return $arr;
- }
-
- function &CacheGetAll($secs2cache,$sql=false,$inputarr=false)
- {
- return $this->CacheGetArray($secs2cache,$sql,$inputarr);
- }
-
- function &CacheGetArray($secs2cache,$sql=false,$inputarr=false)
- {
- global $ADODB_COUNTRECS;
-
- $savec = $ADODB_COUNTRECS;
- $ADODB_COUNTRECS = false;
- $rs =& $this->CacheExecute($secs2cache,$sql,$inputarr);
- $ADODB_COUNTRECS = $savec;
-
- if (!$rs)
- if (defined('ADODB_PEAR')) {
- $cls = ADODB_PEAR_Error();
- return $cls;
- } else {
- $false = false;
- return $false;
- }
- $arr =& $rs->GetArray();
- $rs->Close();
- return $arr;
- }
-
-
-
- /**
- * Return one row of sql statement. Recordset is disposed for you.
- *
- * @param sql SQL statement
- * @param [inputarr] input bind array
- */
- function &GetRow($sql,$inputarr=false)
- {
- global $ADODB_COUNTRECS;
- $crecs = $ADODB_COUNTRECS;
- $ADODB_COUNTRECS = false;
-
- $rs =& $this->Execute($sql,$inputarr);
-
- $ADODB_COUNTRECS = $crecs;
- if ($rs) {
- if (!$rs->EOF) $arr = $rs->fields;
- else $arr = array();
- $rs->Close();
- return $arr;
- }
-
- $false = false;
- return $false;
- }
-
- function &CacheGetRow($secs2cache,$sql=false,$inputarr=false)
- {
- $rs =& $this->CacheExecute($secs2cache,$sql,$inputarr);
- if ($rs) {
- $arr = false;
- if (!$rs->EOF) $arr = $rs->fields;
- $rs->Close();
- return $arr;
- }
- $false = false;
- return $false;
- }
-
- /**
- * Insert or replace a single record. Note: this is not the same as MySQL's replace.
- * ADOdb's Replace() uses update-insert semantics, not insert-delete-duplicates of MySQL.
- * Also note that no table locking is done currently, so it is possible that the
- * record be inserted twice by two programs...
- *
- * $this->Replace('products', array('prodname' =>"'Nails'","price" => 3.99), 'prodname');
- *
- * $table table name
- * $fieldArray associative array of data (you must quote strings yourself).
- * $keyCol the primary key field name or if compound key, array of field names
- * autoQuote set to true to use a hueristic to quote strings. Works with nulls and numbers
- * but does not work with dates nor SQL functions.
- * has_autoinc the primary key is an auto-inc field, so skip in insert.
- *
- * Currently blob replace not supported
- *
- * returns 0 = fail, 1 = update, 2 = insert
- */
-
- function Replace($table, $fieldArray, $keyCol, $autoQuote=false, $has_autoinc=false)
- {
- global $ADODB_INCLUDED_LIB;
- if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR.'/adodb-lib.inc.php');
-
- return _adodb_replace($this, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc);
- }
-
-
- /**
- * Will select, getting rows from $offset (1-based), for $nrows.
- * This simulates the MySQL "select * from table limit $offset,$nrows" , and
- * the PostgreSQL "select * from table limit $nrows offset $offset". Note that
- * MySQL and PostgreSQL parameter ordering is the opposite of the other.
- * eg.
- * CacheSelectLimit(15,'select * from table',3); will return rows 1 to 3 (1-based)
- * CacheSelectLimit(15,'select * from table',3,2); will return rows 3 to 5 (1-based)
- *
- * BUG: Currently CacheSelectLimit fails with $sql with LIMIT or TOP clause already set
- *
- * @param [secs2cache] seconds to cache data, set to 0 to force query. This is optional
- * @param sql
- * @param [offset] is the row to start calculations from (1-based)
- * @param [nrows] is the number of rows to get
- * @param [inputarr] array of bind variables
- * @return the recordset ($rs->databaseType == 'array')
- */
- function &CacheSelectLimit($secs2cache,$sql,$nrows=-1,$offset=-1,$inputarr=false)
- {
- if (!is_numeric($secs2cache)) {
- if ($sql === false) $sql = -1;
- if ($offset == -1) $offset = false;
- // sql, nrows, offset,inputarr
- $rs =& $this->SelectLimit($secs2cache,$sql,$nrows,$offset,$this->cacheSecs);
- } else {
- if ($sql === false) ADOConnection::outp( "Warning: \$sql missing from CacheSelectLimit()");
- $rs =& $this->SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
- }
- return $rs;
- }
-
-
- /**
- * Flush cached recordsets that match a particular $sql statement.
- * If $sql == false, then we purge all files in the cache.
- */
-
- /**
- * Flush cached recordsets that match a particular $sql statement.
- * If $sql == false, then we purge all files in the cache.
- */
- function CacheFlush($sql=false,$inputarr=false)
- {
- global $ADODB_CACHE_DIR;
-
- if (strlen($ADODB_CACHE_DIR) > 1 && !$sql) {
- /*if (strncmp(PHP_OS,'WIN',3) === 0)
- $dir = str_replace('/', '\\', $ADODB_CACHE_DIR);
- else */
- $dir = $ADODB_CACHE_DIR;
-
- if ($this->debug) {
- ADOConnection::outp( "CacheFlush: $dir<br><pre>\n", $this->_dirFlush($dir),"</pre>");
- } else {
- $this->_dirFlush($dir);
- }
- return;
- }
-
- global $ADODB_INCLUDED_CSV;
- if (empty($ADODB_INCLUDED_CSV)) include(ADODB_DIR.'/adodb-csvlib.inc.php');
-
- $f = $this->_gencachename($sql.serialize($inputarr),false);
- adodb_write_file($f,''); // is adodb_write_file needed?
- if (!@unlink($f)) {
- if ($this->debug) ADOConnection::outp( "CacheFlush: failed for $f");
- }
- }
-
- /**
- * Private function to erase all of the files and subdirectories in a directory.
- *
- * Just specify the directory, and tell it if you want to delete the directory or just clear it out.
- * Note: $kill_top_level is used internally in the function to flush subdirectories.
- */
- function _dirFlush($dir, $kill_top_level = false) {
- if(!$dh = @opendir($dir)) return;
-
- while (($obj = readdir($dh))) {
- if($obj=='.' || $obj=='..')
- continue;
-
- if (!@unlink($dir.'/'.$obj))
- $this->_dirFlush($dir.'/'.$obj, true);
- }
- if ($kill_top_level === true)
- @rmdir($dir);
- return true;
- }
-
-
- function xCacheFlush($sql=false,$inputarr=false)
- {
- global $ADODB_CACHE_DIR;
-
- if (strlen($ADODB_CACHE_DIR) > 1 && !$sql) {
- if (strncmp(PHP_OS,'WIN',3) === 0) {
- $cmd = 'del /s '.str_replace('/','\\',$ADODB_CACHE_DIR).'\adodb_*.cache';
- } else {
- //$cmd = 'find "'.$ADODB_CACHE_DIR.'" -type f -maxdepth 1 -print0 | xargs -0 rm -f';
- $cmd = 'rm -rf '.$ADODB_CACHE_DIR.'/[0-9a-f][0-9a-f]/';
- // old version 'rm -f `find '.$ADODB_CACHE_DIR.' -name adodb_*.cache`';
- }
- if ($this->debug) {
- ADOConnection::outp( "CacheFlush: $cmd<br><pre>\n", system($cmd),"</pre>");
- } else {
- exec($cmd);
- }
- return;
- }
-
- global $ADODB_INCLUDED_CSV;
- if (empty($ADODB_INCLUDED_CSV)) include(ADODB_DIR.'/adodb-csvlib.inc.php');
-
- $f = $this->_gencachename($sql.serialize($inputarr),false);
- adodb_write_file($f,''); // is adodb_write_file needed?
- if (!@unlink($f)) {
- if ($this->debug) ADOConnection::outp( "CacheFlush: failed for $f");
- }
- }
-
- /**
- * Private function to generate filename for caching.
- * Filename is generated based on:
- *
- * - sql statement
- * - database type (oci8, ibase, ifx, etc)
- * - database name
- * - userid
- * - setFetchMode (adodb 4.23)
- *
- * When not in safe mode, we create 256 sub-directories in the cache directory ($ADODB_CACHE_DIR).
- * Assuming that we can have 50,000 files per directory with good performance,
- * then we can scale to 12.8 million unique cached recordsets. Wow!
- */
- function _gencachename($sql,$createdir)
- {
- global $ADODB_CACHE_DIR;
- static $notSafeMode;
-
- if ($this->fetchMode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- } else {
- $mode = $this->fetchMode;
- }
- $m = md5($sql.$this->databaseType.$this->database.$this->user.$mode);
-
- if (!isset($notSafeMode)) $notSafeMode = !ini_get('safe_mode');
- $dir = ($notSafeMode) ? $ADODB_CACHE_DIR.'/'.substr($m,0,2) : $ADODB_CACHE_DIR;
-
- if ($createdir && $notSafeMode && !file_exists($dir)) {
- $oldu = umask(0);
- if (!mkdir($dir,0771))
- if ($this->debug) ADOConnection::outp( "Unable to mkdir $dir for $sql");
- umask($oldu);
- }
- return $dir.'/adodb_'.$m.'.cache';
- }
-
-
- /**
- * Execute SQL, caching recordsets.
- *
- * @param [secs2cache] seconds to cache data, set to 0 to force query.
- * This is an optional parameter.
- * @param sql SQL statement to execute
- * @param [inputarr] holds the input data to bind to
- * @return RecordSet or false
- */
- function &CacheExecute($secs2cache,$sql=false,$inputarr=false)
- {
-
-
- if (!is_numeric($secs2cache)) {
- $inputarr = $sql;
- $sql = $secs2cache;
- $secs2cache = $this->cacheSecs;
- }
-
- if (is_array($sql)) {
- $sqlparam = $sql;
- $sql = $sql[0];
- } else
- $sqlparam = $sql;
-
- global $ADODB_INCLUDED_CSV;
- if (empty($ADODB_INCLUDED_CSV)) include(ADODB_DIR.'/adodb-csvlib.inc.php');
-
- $md5file = $this->_gencachename($sql.serialize($inputarr),true);
- $err = '';
-
- if ($secs2cache > 0){
- $rs = &csv2rs($md5file,$err,$secs2cache,$this->arrayClass);
- $this->numCacheHits += 1;
- } else {
- $err='Timeout 1';
- $rs = false;
- $this->numCacheMisses += 1;
- }
- if (!$rs) {
- // no cached rs found
- if ($this->debug) {
- if (get_magic_quotes_runtime()) {
- ADOConnection::outp("Please disable magic_quotes_runtime - it corrupts cache files :(");
- }
- if ($this->debug !== -1) ADOConnection::outp( " $md5file cache failure: $err (see sql below)");
- }
-
- $rs = &$this->Execute($sqlparam,$inputarr);
-
- if ($rs) {
- $eof = $rs->EOF;
- $rs = &$this->_rs2rs($rs); // read entire recordset into memory immediately
- $txt = _rs2serialize($rs,false,$sql); // serialize
-
- if (!adodb_write_file($md5file,$txt,$this->debug)) {
- if ($fn = $this->raiseErrorFn) {
- $fn($this->databaseType,'CacheExecute',-32000,"Cache write error",$md5file,$sql,$this);
- }
- if ($this->debug) ADOConnection::outp( " Cache write error");
- }
- if ($rs->EOF && !$eof) {
- $rs->MoveFirst();
- //$rs = &csv2rs($md5file,$err);
- $rs->connection = &$this; // Pablo suggestion
- }
-
- } else
- @unlink($md5file);
- } else {
- $this->_errorMsg = '';
- $this->_errorCode = 0;
-
- if ($this->fnCacheExecute) {
- $fn = $this->fnCacheExecute;
- $fn($this, $secs2cache, $sql, $inputarr);
- }
- // ok, set cached object found
- $rs->connection = &$this; // Pablo suggestion
- if ($this->debug){
-
- $inBrowser = isset($_SERVER['HTTP_USER_AGENT']);
- $ttl = $rs->timeCreated + $secs2cache - time();
- $s = is_array($sql) ? $sql[0] : $sql;
- if ($inBrowser) $s = '<i>'.htmlspecialchars($s).'</i>';
-
- ADOConnection::outp( " $md5file reloaded, ttl=$ttl [ $s ]");
- }
- }
- return $rs;
- }
-
-
- /*
- Similar to PEAR DB's autoExecute(), except that
- $mode can be 'INSERT' or 'UPDATE' or DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE
- If $mode == 'UPDATE', then $where is compulsory as a safety measure.
-
- $forceUpdate means that even if the data has not changed, perform update.
- */
- function& AutoExecute($table, $fields_values, $mode = 'INSERT', $where = FALSE, $forceUpdate=true, $magicq=false)
- {
- $sql = 'SELECT * FROM '.$table;
- if ($where!==FALSE) $sql .= ' WHERE '.$where;
- else if ($mode == 'UPDATE' || $mode == 2 /* DB_AUTOQUERY_UPDATE */) {
- ADOConnection::outp('AutoExecute: Illegal mode=UPDATE with empty WHERE clause');
- return false;
- }
-
- $rs =& $this->SelectLimit($sql,1);
- if (!$rs) return false; // table does not exist
- $rs->tableName = $table;
-
- switch((string) $mode) {
- case 'UPDATE':
- case '2':
- $sql = $this->GetUpdateSQL($rs, $fields_values, $forceUpdate, $magicq);
- break;
- case 'INSERT':
- case '1':
- $sql = $this->GetInsertSQL($rs, $fields_values, $magicq);
- break;
- default:
- ADOConnection::outp("AutoExecute: Unknown mode=$mode");
- return false;
- }
- $ret = false;
- if ($sql) $ret = $this->Execute($sql);
- if ($ret) $ret = true;
- return $ret;
- }
-
-
- /**
- * Generates an Update Query based on an existing recordset.
- * $arrFields is an associative array of fields with the value
- * that should be assigned.
- *
- * Note: This function should only be used on a recordset
- * that is run against a single table and sql should only
- * be a simple select stmt with no groupby/orderby/limit
- *
- * "Jonathan Younger" <jyounger@unilab.com>
- */
- function GetUpdateSQL(&$rs, $arrFields,$forceUpdate=false,$magicq=false,$force=null)
- {
- global $ADODB_INCLUDED_LIB;
-
- //********************************************************//
- //This is here to maintain compatibility
- //with older adodb versions. Sets force type to force nulls if $forcenulls is set.
- if (!isset($force)) {
- global $ADODB_FORCE_TYPE;
- $force = $ADODB_FORCE_TYPE;
- }
- //********************************************************//
-
- if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR.'/adodb-lib.inc.php');
- return _adodb_getupdatesql($this,$rs,$arrFields,$forceUpdate,$magicq,$force);
- }
-
- /**
- * Generates an Insert Query based on an existing recordset.
- * $arrFields is an associative array of fields with the value
- * that should be assigned.
- *
- * Note: This function should only be used on a recordset
- * that is run against a single table.
- */
- function GetInsertSQL(&$rs, $arrFields,$magicq=false,$force=null)
- {
- global $ADODB_INCLUDED_LIB;
- if (!isset($force)) {
- global $ADODB_FORCE_TYPE;
- $force = $ADODB_FORCE_TYPE;
-
- }
- if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR.'/adodb-lib.inc.php');
- return _adodb_getinsertsql($this,$rs,$arrFields,$magicq,$force);
- }
-
-
- /**
- * Update a blob column, given a where clause. There are more sophisticated
- * blob handling functions that we could have implemented, but all require
- * a very complex API. Instead we have chosen something that is extremely
- * simple to understand and use.
- *
- * Note: $blobtype supports 'BLOB' and 'CLOB', default is BLOB of course.
- *
- * Usage to update a $blobvalue which has a primary key blob_id=1 into a
- * field blobtable.blobcolumn:
- *
- * UpdateBlob('blobtable', 'blobcolumn', $blobvalue, 'blob_id=1');
- *
- * Insert example:
- *
- * $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
- * $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
- */
-
- function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
- {
- return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false;
- }
-
- /**
- * Usage:
- * UpdateBlob('TABLE', 'COLUMN', '/path/to/file', 'ID=1');
- *
- * $blobtype supports 'BLOB' and 'CLOB'
- *
- * $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
- * $conn->UpdateBlob('blobtable','blobcol',$blobpath,'id=1');
- */
- function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
- {
- $fd = fopen($path,'rb');
- if ($fd === false) return false;
- $val = fread($fd,filesize($path));
- fclose($fd);
- return $this->UpdateBlob($table,$column,$val,$where,$blobtype);
- }
-
- function BlobDecode($blob)
- {
- return $blob;
- }
-
- function BlobEncode($blob)
- {
- return $blob;
- }
-
- function SetCharSet($charset)
- {
- return false;
- }
-
- function IfNull( $field, $ifNull )
- {
- return " CASE WHEN $field is null THEN $ifNull ELSE $field END ";
- }
-
- function LogSQL($enable=true)
- {
- include_once(ADODB_DIR.'/adodb-perf.inc.php');
-
- if ($enable) $this->fnExecute = 'adodb_log_sql';
- else $this->fnExecute = false;
-
- $old = $this->_logsql;
- $this->_logsql = $enable;
- if ($enable && !$old) $this->_affected = false;
- return $old;
- }
-
- function GetCharSet()
- {
- return false;
- }
-
- /**
- * Usage:
- * UpdateClob('TABLE', 'COLUMN', $var, 'ID=1', 'CLOB');
- *
- * $conn->Execute('INSERT INTO clobtable (id, clobcol) VALUES (1, null)');
- * $conn->UpdateClob('clobtable','clobcol',$clob,'id=1');
- */
- function UpdateClob($table,$column,$val,$where)
- {
- return $this->UpdateBlob($table,$column,$val,$where,'CLOB');
- }
-
- // not the fastest implementation - quick and dirty - jlim
- // for best performance, use the actual $rs->MetaType().
- function MetaType($t,$len=-1,$fieldobj=false)
- {
-
- if (empty($this->_metars)) {
- $rsclass = $this->rsPrefix.$this->databaseType;
- $this->_metars = new $rsclass(false,$this->fetchMode);
- $this->_metars->connection =& $this;
- }
- return $this->_metars->MetaType($t,$len,$fieldobj);
- }
-
-
- /**
- * Change the SQL connection locale to a specified locale.
- * This is used to get the date formats written depending on the client locale.
- */
- function SetDateLocale($locale = 'En')
- {
- $this->locale = $locale;
- switch (strtoupper($locale))
- {
- case 'EN':
- $this->fmtDate="'Y-m-d'";
- $this->fmtTimeStamp = "'Y-m-d H:i:s'";
- break;
-
- case 'US':
- $this->fmtDate = "'m-d-Y'";
- $this->fmtTimeStamp = "'m-d-Y H:i:s'";
- break;
-
- case 'NL':
- case 'FR':
- case 'RO':
- case 'IT':
- $this->fmtDate="'d-m-Y'";
- $this->fmtTimeStamp = "'d-m-Y H:i:s'";
- break;
-
- case 'GE':
- $this->fmtDate="'d.m.Y'";
- $this->fmtTimeStamp = "'d.m.Y H:i:s'";
- break;
-
- default:
- $this->fmtDate="'Y-m-d'";
- $this->fmtTimeStamp = "'Y-m-d H:i:s'";
- break;
- }
- }
-
- function &GetActiveRecordsClass($class, $table,$whereOrderBy=false,$bindarr=false, $primkeyArr=false)
- {
- global $_ADODB_ACTIVE_DBS;
-
- $save = $this->SetFetchMode(ADODB_FETCH_NUM);
- if (empty($whereOrderBy)) $whereOrderBy = '1=1';
- $rows = $this->GetAll("select * from ".$table.' WHERE '.$whereOrderBy,$bindarr);
- $this->SetFetchMode($save);
-
- $false = false;
-
- if ($rows === false) {
- return $false;
- }
-
-
- if (!isset($_ADODB_ACTIVE_DBS)) {
- include(ADODB_DIR.'/adodb-active-record.inc.php');
- }
- if (!class_exists($class)) {
- ADOConnection::outp("Unknown class $class in GetActiveRcordsClass()");
- return $false;
- }
- $arr = array();
- foreach($rows as $row) {
-
- $obj = new $class($table,$primkeyArr,$this);
- if ($obj->ErrorMsg()){
- $this->_errorMsg = $obj->ErrorMsg();
- return $false;
- }
- $obj->Set($row);
- $arr[] = $obj;
- }
- return $arr;
- }
-
- function &GetActiveRecords($class,$where=false,$bindarr=false,$primkeyArr=false)
- {
- $table = ADODB_Active_Record::_pluralize($class);
- $arr =& $this->GetActiveRecordsClass($class, $table, $where, $bindarr, $primkeyArr);
- return $arr;
- }
-
- /**
- * Close Connection
- */
- function Close()
- {
- $rez = $this->_close();
- $this->_connectionID = false;
- return $rez;
- }
-
- /**
- * Begin a Transaction. Must be followed by CommitTrans() or RollbackTrans().
- *
- * @return true if succeeded or false if database does not support transactions
- */
- function BeginTrans() {return false;}
-
-
- /**
- * If database does not support transactions, always return true as data always commited
- *
- * @param $ok set to false to rollback transaction, true to commit
- *
- * @return true/false.
- */
- function CommitTrans($ok=true)
- { return true;}
-
-
- /**
- * If database does not support transactions, rollbacks always fail, so return false
- *
- * @return true/false.
- */
- function RollbackTrans()
- { return false;}
-
-
- /**
- * return the databases that the driver can connect to.
- * Some databases will return an empty array.
- *
- * @return an array of database names.
- */
- function MetaDatabases()
- {
- global $ADODB_FETCH_MODE;
-
- if ($this->metaDatabasesSQL) {
- $save = $ADODB_FETCH_MODE;
- $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
-
- if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
-
- $arr = $this->GetCol($this->metaDatabasesSQL);
- if (isset($savem)) $this->SetFetchMode($savem);
- $ADODB_FETCH_MODE = $save;
-
- return $arr;
- }
-
- return false;
- }
-
-
- /**
- * @param ttype can either be 'VIEW' or 'TABLE' or false.
- * If false, both views and tables are returned.
- * "VIEW" returns only views
- * "TABLE" returns only tables
- * @param showSchema returns the schema/user with the table name, eg. USER.TABLE
- * @param mask is the input mask - only supported by oci8 and postgresql
- *
- * @return array of tables for current database.
- */
- function &MetaTables($ttype=false,$showSchema=false,$mask=false)
- {
- global $ADODB_FETCH_MODE;
-
-
- $false = false;
- if ($mask) {
- return $false;
- }
- if ($this->metaTablesSQL) {
- $save = $ADODB_FETCH_MODE;
- $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
-
- if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
-
- $rs = $this->Execute($this->metaTablesSQL);
- if (isset($savem)) $this->SetFetchMode($savem);
- $ADODB_FETCH_MODE = $save;
-
- if ($rs === false) return $false;
- $arr =& $rs->GetArray();
- $arr2 = array();
-
- if ($hast = ($ttype && isset($arr[0][1]))) {
- $showt = strncmp($ttype,'T',1);
- }
-
- for ($i=0; $i < sizeof($arr); $i++) {
- if ($hast) {
- if ($showt == 0) {
- if (strncmp($arr[$i][1],'T',1) == 0) $arr2[] = trim($arr[$i][0]);
- } else {
- if (strncmp($arr[$i][1],'V',1) == 0) $arr2[] = trim($arr[$i][0]);
- }
- } else
- $arr2[] = trim($arr[$i][0]);
- }
- $rs->Close();
- return $arr2;
- }
- return $false;
- }
-
-
- function _findschema(&$table,&$schema)
- {
- if (!$schema && ($at = strpos($table,'.')) !== false) {
- $schema = substr($table,0,$at);
- $table = substr($table,$at+1);
- }
- }
-
- /**
- * List columns in a database as an array of ADOFieldObjects.
- * See top of file for definition of object.
- *
- * @param $table table name to query
- * @param $normalize makes table name case-insensitive (required by some databases)
- * @schema is optional database schema to use - not supported by all databases.
- *
- * @return array of ADOFieldObjects for current table.
- */
- function &MetaColumns($table,$normalize=true)
- {
- global $ADODB_FETCH_MODE;
-
- $false = false;
-
- if (!empty($this->metaColumnsSQL)) {
-
- $schema = false;
- $this->_findschema($table,$schema);
-
- $save = $ADODB_FETCH_MODE;
- $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
- if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
- $rs = $this->Execute(sprintf($this->metaColumnsSQL,($normalize)?strtoupper($table):$table));
- if (isset($savem)) $this->SetFetchMode($savem);
- $ADODB_FETCH_MODE = $save;
- if ($rs === false || $rs->EOF) return $false;
-
- $retarr = array();
- while (!$rs->EOF) { //print_r($rs->fields);
- $fld = new ADOFieldObject();
- $fld->name = $rs->fields[0];
- $fld->type = $rs->fields[1];
- if (isset($rs->fields[3]) && $rs->fields[3]) {
- if ($rs->fields[3]>0) $fld->max_length = $rs->fields[3];
- $fld->scale = $rs->fields[4];
- if ($fld->scale>0) $fld->max_length += 1;
- } else
- $fld->max_length = $rs->fields[2];
-
- if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
- else $retarr[strtoupper($fld->name)] = $fld;
- $rs->MoveNext();
- }
- $rs->Close();
- return $retarr;
- }
- return $false;
- }
-
- /**
- * List indexes on a table as an array.
- * @param table table name to query
- * @param primary true to only show primary keys. Not actually used for most databases
- *
- * @return array of indexes on current table. Each element represents an index, and is itself an associative array.
-
- Array (
- [name_of_index] => Array
- (
- [unique] => true or false
- [columns] => Array
- (
- [0] => firstname
- [1] => lastname
- )
- )
- */
- function &MetaIndexes($table, $primary = false, $owner = false)
- {
- $false = false;
- return $false;
- }
-
- /**
- * List columns names in a table as an array.
- * @param table table name to query
- *
- * @return array of column names for current table.
- */
- function &MetaColumnNames($table, $numIndexes=false)
- {
- $objarr =& $this->MetaColumns($table);
- if (!is_array($objarr)) {
- $false = false;
- return $false;
- }
- $arr = array();
- if ($numIndexes) {
- $i = 0;
- foreach($objarr as $v) $arr[$i++] = $v->name;
- } else
- foreach($objarr as $v) $arr[strtoupper($v->name)] = $v->name;
-
- return $arr;
- }
-
- /**
- * Different SQL databases used different methods to combine strings together.
- * This function provides a wrapper.
- *
- * param s variable number of string parameters
- *
- * Usage: $db->Concat($str1,$str2);
- *
- * @return concatenated string
- */
- function Concat()
- {
- $arr = func_get_args();
- return implode($this->concat_operator, $arr);
- }
-
-
- /**
- * Converts a date "d" to a string that the database can understand.
- *
- * @param d a date in Unix date time format.
- *
- * @return date string in database date format
- */
- function DBDate($d)
- {
- if (empty($d) && $d !== 0) return 'null';
-
- if (is_string($d) && !is_numeric($d)) {
- if ($d === 'null' || strncmp($d,"'",1) === 0) return $d;
- if ($this->isoDates) return "'$d'";
- $d = ADOConnection::UnixDate($d);
- }
-
- return adodb_date($this->fmtDate,$d);
- }
-
-
- /**
- * Converts a timestamp "ts" to a string that the database can understand.
- *
- * @param ts a timestamp in Unix date time format.
- *
- * @return timestamp string in database timestamp format
- */
- function DBTimeStamp($ts)
- {
- if (empty($ts) && $ts !== 0) return 'null';
-
- # strlen(14) allows YYYYMMDDHHMMSS format
- if (!is_string($ts) || (is_numeric($ts) && strlen($ts)<14))
- return adodb_date($this->fmtTimeStamp,$ts);
-
- if ($ts === 'null') return $ts;
- if ($this->isoDates && strlen($ts) !== 14) return "'$ts'";
-
- $ts = ADOConnection::UnixTimeStamp($ts);
- return adodb_date($this->fmtTimeStamp,$ts);
- }
-
- /**
- * Also in ADORecordSet.
- * @param $v is a date string in YYYY-MM-DD format
- *
- * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
- */
- function UnixDate($v)
- {
- if (is_object($v)) {
- // odbtp support
- //( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
- return adodb_mktime($v->hour,$v->minute,$v->second,$v->month,$v->day, $v->year);
- }
-
- if (is_numeric($v) && strlen($v) !== 8) return $v;
- if (!preg_match( "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})|",
- ($v), $rr)) return false;
-
- if ($rr[1] <= TIMESTAMP_FIRST_YEAR) return 0;
- // h-m-s-MM-DD-YY
- return @adodb_mktime(0,0,0,$rr[2],$rr[3],$rr[1]);
- }
-
-
- /**
- * Also in ADORecordSet.
- * @param $v is a timestamp string in YYYY-MM-DD HH-NN-SS format
- *
- * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
- */
- function UnixTimeStamp($v)
- {
- if (is_object($v)) {
- // odbtp support
- //( [year] => 2004 [month] => 9 [day] => 4 [hour] => 12 [minute] => 44 [second] => 8 [fraction] => 0 )
- return adodb_mktime($v->hour,$v->minute,$v->second,$v->month,$v->day, $v->year);
- }
-
- if (!preg_match(
- "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ ,-]*(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|",
- ($v), $rr)) return false;
-
- if ($rr[1] <= TIMESTAMP_FIRST_YEAR && $rr[2]<= 1) return 0;
-
- // h-m-s-MM-DD-YY
- if (!isset($rr[5])) return adodb_mktime(0,0,0,$rr[2],$rr[3],$rr[1]);
- return @adodb_mktime($rr[5],$rr[6],$rr[7],$rr[2],$rr[3],$rr[1]);
- }
-
- /**
- * Also in ADORecordSet.
- *
- * Format database date based on user defined format.
- *
- * @param v is the character date in YYYY-MM-DD format, returned by database
- * @param fmt is the format to apply to it, using date()
- *
- * @return a date formated as user desires
- */
-
- function UserDate($v,$fmt='Y-m-d',$gmt=false)
- {
- $tt = $this->UnixDate($v);
-
- // $tt == -1 if pre TIMESTAMP_FIRST_YEAR
- if (($tt === false || $tt == -1) && $v != false) return $v;
- else if ($tt == 0) return $this->emptyDate;
- else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
- }
-
- return ($gmt) ? adodb_gmdate($fmt,$tt) : adodb_date($fmt,$tt);
-
- }
-
- /**
- *
- * @param v is the character timestamp in YYYY-MM-DD hh:mm:ss format
- * @param fmt is the format to apply to it, using date()
- *
- * @return a timestamp formated as user desires
- */
- function UserTimeStamp($v,$fmt='Y-m-d H:i:s',$gmt=false)
- {
- if (!isset($v)) return $this->emptyTimeStamp;
- # strlen(14) allows YYYYMMDDHHMMSS format
- if (is_numeric($v) && strlen($v)<14) return ($gmt) ? adodb_gmdate($fmt,$v) : adodb_date($fmt,$v);
- $tt = $this->UnixTimeStamp($v);
- // $tt == -1 if pre TIMESTAMP_FIRST_YEAR
- if (($tt === false || $tt == -1) && $v != false) return $v;
- if ($tt == 0) return $this->emptyTimeStamp;
- return ($gmt) ? adodb_gmdate($fmt,$tt) : adodb_date($fmt,$tt);
- }
-
- function escape($s,$magic_quotes=false)
- {
- return $this->addq($s,$magic_quotes);
- }
-
- /**
- * Quotes a string, without prefixing nor appending quotes.
- */
- function addq($s,$magic_quotes=false)
- {
- if (!$magic_quotes) {
-
- if ($this->replaceQuote[0] == '\\'){
- // only since php 4.0.5
- $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
- //$s = str_replace("\0","\\\0", str_replace('\\','\\\\',$s));
- }
- return str_replace("'",$this->replaceQuote,$s);
- }
-
- // undo magic quotes for "
- $s = str_replace('\\"','"',$s);
-
- if ($this->replaceQuote == "\\'") // ' already quoted, no need to change anything
- return $s;
- else {// change \' to '' for sybase/mssql
- $s = str_replace('\\\\','\\',$s);
- return str_replace("\\'",$this->replaceQuote,$s);
- }
- }
-
- /**
- * Correctly quotes a string so that all strings are escaped. We prefix and append
- * to the string single-quotes.
- * An example is $db->qstr("Don't bother",magic_quotes_runtime());
- *
- * @param s the string to quote
- * @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc().
- * This undoes the stupidity of magic quotes for GPC.
- *
- * @return quoted string to be sent back to database
- */
- function qstr($s,$magic_quotes=false)
- {
- if (!$magic_quotes) {
-
- if ($this->replaceQuote[0] == '\\'){
- // only since php 4.0.5
- $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
- //$s = str_replace("\0","\\\0", str_replace('\\','\\\\',$s));
- }
- return "'".str_replace("'",$this->replaceQuote,$s)."'";
- }
-
- // undo magic quotes for "
- $s = str_replace('\\"','"',$s);
-
- if ($this->replaceQuote == "\\'") // ' already quoted, no need to change anything
- return "'$s'";
- else {// change \' to '' for sybase/mssql
- $s = str_replace('\\\\','\\',$s);
- return "'".str_replace("\\'",$this->replaceQuote,$s)."'";
- }
- }
-
-
- /**
- * Will select the supplied $page number from a recordset, given that it is paginated in pages of
- * $nrows rows per page. It also saves two boolean values saying if the given page is the first
- * and/or last one of the recordset. Added by Iván Oliva to provide recordset pagination.
- *
- * See readme.htm#ex8 for an example of usage.
- *
- * @param sql
- * @param nrows is the number of rows per page to get
- * @param page is the page number to get (1-based)
- * @param [inputarr] array of bind variables
- * @param [secs2cache] is a private parameter only used by jlim
- * @return the recordset ($rs->databaseType == 'array')
- *
- * NOTE: phpLens uses a different algorithm and does not use PageExecute().
- *
- */
- function &PageExecute($sql, $nrows, $page, $inputarr=false, $secs2cache=0)
- {
- global $ADODB_INCLUDED_LIB;
- if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR.'/adodb-lib.inc.php');
- if ($this->pageExecuteCountRows) $rs =& _adodb_pageexecute_all_rows($this, $sql, $nrows, $page, $inputarr, $secs2cache);
- else $rs =& _adodb_pageexecute_no_last_page($this, $sql, $nrows, $page, $inputarr, $secs2cache);
- return $rs;
- }
-
-
- /**
- * Will select the supplied $page number from a recordset, given that it is paginated in pages of
- * $nrows rows per page. It also saves two boolean values saying if the given page is the first
- * and/or last one of the recordset. Added by Iván Oliva to provide recordset pagination.
- *
- * @param secs2cache seconds to cache data, set to 0 to force query
- * @param sql
- * @param nrows is the number of rows per page to get
- * @param page is the page number to get (1-based)
- * @param [inputarr] array of bind variables
- * @return the recordset ($rs->databaseType == 'array')
- */
- function &CachePageExecute($secs2cache, $sql, $nrows, $page,$inputarr=false)
- {
- /*switch($this->dataProvider) {
- case 'postgres':
- case 'mysql':
- break;
- default: $secs2cache = 0; break;
- }*/
- $rs =& $this->PageExecute($sql,$nrows,$page,$inputarr,$secs2cache);
- return $rs;
- }
-
-} // end class ADOConnection
-
-
-
- //==============================================================================================
- // CLASS ADOFetchObj
- //==============================================================================================
-
- /**
- * Internal placeholder for record objects. Used by ADORecordSet->FetchObj().
- */
- class ADOFetchObj {
- };
-
- //==============================================================================================
- // CLASS ADORecordSet_empty
- //==============================================================================================
-
- /**
- * Lightweight recordset when there are no records to be returned
- */
- class ADORecordSet_empty
- {
- public $dataProvider = 'empty';
- public $databaseType = false;
- public $EOF = true;
- public $_numOfRows = 0;
- public $fields = false;
- public $connection = false;
- function RowCount() {return 0;}
- function RecordCount() {return 0;}
- function PO_RecordCount(){return 0;}
- function Close(){return true;}
- function FetchRow() {return false;}
- function FieldCount(){ return 0;}
- function Init() {}
- }
-
- //==============================================================================================
- // DATE AND TIME FUNCTIONS
- //==============================================================================================
- if (!defined('ADODB_DATE_VERSION')) include(ADODB_DIR.'/adodb-time.inc.php');
-
- //==============================================================================================
- // CLASS ADORecordSet
- //==============================================================================================
-
- if (PHP_VERSION < 5) include_once(ADODB_DIR.'/adodb-php4.inc.php');
- else include_once(ADODB_DIR.'/adodb-iterator.inc.php');
- /**
- * RecordSet class that represents the dataset returned by the database.
- * To keep memory overhead low, this class holds only the current row in memory.
- * No prefetching of data is done, so the RecordCount() can return -1 ( which
- * means recordcount not known).
- */
- class ADORecordSet extends ADODB_BASE_RS {
- /*
- * public variables
- */
- public $dataProvider = "native";
- public $fields = false; /// holds the current row data
- public $blobSize = 100; /// any varchar/char field this size or greater is treated as a blob
- /// in other words, we use a text area for editing.
- public $canSeek = false; /// indicates that seek is supported
- public $sql; /// sql text
- public $EOF = false; /// Indicates that the current record position is after the last record in a Recordset object.
-
- public $emptyTimeStamp = '&nbsp;'; /// what to display when $time==0
- public $emptyDate = '&nbsp;'; /// what to display when $time==0
- public $debug = false;
- public $timeCreated=0; /// datetime in Unix format rs created -- for cached recordsets
-
- public $bind = false; /// used by Fields() to hold array - should be private?
- public $fetchMode; /// default fetch mode
- public $connection = false; /// the parent connection
- /*
- * private variables
- */
- public $_numOfRows = -1; /** number of rows, or -1 */
- public $_numOfFields = -1; /** number of fields in recordset */
- public $_queryID = -1; /** This variable keeps the result link identifier. */
- public $_currentRow = -1; /** This variable keeps the current row in the Recordset. */
- public $_closed = false; /** has recordset been closed */
- public $_inited = false; /** Init() should only be called once */
- public $_obj; /** Used by FetchObj */
- public $_names; /** Used by FetchObj */
-
- public $_currentPage = -1; /** Added by Iván Oliva to implement recordset pagination */
- public $_atFirstPage = false; /** Added by Iván Oliva to implement recordset pagination */
- public $_atLastPage = false; /** Added by Iván Oliva to implement recordset pagination */
- public $_lastPageNo = -1;
- public $_maxRecordCount = 0;
- public $datetime = false;
-
- /**
- * Constructor
- *
- * @param queryID this is the queryID returned by ADOConnection->_query()
- *
- */
- function ADORecordSet($queryID)
- {
- $this->_queryID = $queryID;
- }
-
-
-
- function Init()
- {
- if ($this->_inited) return;
- $this->_inited = true;
- if ($this->_queryID) @$this->_initrs();
- else {
- $this->_numOfRows = 0;
- $this->_numOfFields = 0;
- }
- if ($this->_numOfRows != 0 && $this->_numOfFields && $this->_currentRow == -1) {
-
- $this->_currentRow = 0;
- if ($this->EOF = ($this->_fetch() === false)) {
- $this->_numOfRows = 0; // _numOfRows could be -1
- }
- } else {
- $this->EOF = true;
- }
- }
-
-
- /**
- * Generate a SELECT tag string from a recordset, and return the string.
- * If the recordset has 2 cols, we treat the 1st col as the containing
- * the text to display to the user, and 2nd col as the return value. Default
- * strings are compared with the FIRST column.
- *
- * @param name name of SELECT tag
- * @param [defstr] the value to hilite. Use an array for multiple hilites for listbox.
- * @param [blank1stItem] true to leave the 1st item in list empty
- * @param [multiple] true for listbox, false for popup
- * @param [size] #rows to show for listbox. not used by popup
- * @param [selectAttr] additional attributes to defined for SELECT tag.
- * useful for holding javascript onChange='...' handlers.
- & @param [compareFields0] when we have 2 cols in recordset, we compare the defstr with
- * column 0 (1st col) if this is true. This is not documented.
- *
- * @return HTML
- *
- * changes by glen.davies@cce.ac.nz to support multiple hilited items
- */
- function GetMenu($name,$defstr='',$blank1stItem=true,$multiple=false,
- $size=0, $selectAttr='',$compareFields0=true)
- {
- global $ADODB_INCLUDED_LIB;
- if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR.'/adodb-lib.inc.php');
- return _adodb_getmenu($this, $name,$defstr,$blank1stItem,$multiple,
- $size, $selectAttr,$compareFields0);
- }
-
-
-
- /**
- * Generate a SELECT tag string from a recordset, and return the string.
- * If the recordset has 2 cols, we treat the 1st col as the containing
- * the text to display to the user, and 2nd col as the return value. Default
- * strings are compared with the SECOND column.
- *
- */
- function GetMenu2($name,$defstr='',$blank1stItem=true,$multiple=false,$size=0, $selectAttr='')
- {
- return $this->GetMenu($name,$defstr,$blank1stItem,$multiple,
- $size, $selectAttr,false);
- }
-
- /*
- Grouped Menu
- */
- function GetMenu3($name,$defstr='',$blank1stItem=true,$multiple=false,
- $size=0, $selectAttr='')
- {
- global $ADODB_INCLUDED_LIB;
- if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR.'/adodb-lib.inc.php');
- return _adodb_getmenu_gp($this, $name,$defstr,$blank1stItem,$multiple,
- $size, $selectAttr,false);
- }
-
- /**
- * return recordset as a 2-dimensional array.
- *
- * @param [nRows] is the number of rows to return. -1 means every row.
- *
- * @return an array indexed by the rows (0-based) from the recordset
- */
- function &GetArray($nRows = -1)
- {
- global $ADODB_EXTENSION; if ($ADODB_EXTENSION) {
- $results = adodb_getall($this,$nRows);
- return $results;
- }
- $results = array();
- $cnt = 0;
- while (!$this->EOF && $nRows != $cnt) {
- $results[] = $this->fields;
- $this->MoveNext();
- $cnt++;
- }
- return $results;
- }
-
- function &GetAll($nRows = -1)
- {
- $arr =& $this->GetArray($nRows);
- return $arr;
- }
-
- /*
- * Some databases allow multiple recordsets to be returned. This function
- * will return true if there is a next recordset, or false if no more.
- */
- function NextRecordSet()
- {
- return false;
- }
-
- /**
- * return recordset as a 2-dimensional array.
- * Helper function for ADOConnection->SelectLimit()
- *
- * @param offset is the row to start calculations from (1-based)
- * @param [nrows] is the number of rows to return
- *
- * @return an array indexed by the rows (0-based) from the recordset
- */
- function &GetArrayLimit($nrows,$offset=-1)
- {
- if ($offset <= 0) {
- $arr =& $this->GetArray($nrows);
- return $arr;
- }
-
- $this->Move($offset);
-
- $results = array();
- $cnt = 0;
- while (!$this->EOF && $nrows != $cnt) {
- $results[$cnt++] = $this->fields;
- $this->MoveNext();
- }
-
- return $results;
- }
-
-
- /**
- * Synonym for GetArray() for compatibility with ADO.
- *
- * @param [nRows] is the number of rows to return. -1 means every row.
- *
- * @return an array indexed by the rows (0-based) from the recordset
- */
- function &GetRows($nRows = -1)
- {
- $arr =& $this->GetArray($nRows);
- return $arr;
- }
-
- /**
- * return whole recordset as a 2-dimensional associative array if there are more than 2 columns.
- * The first column is treated as the key and is not included in the array.
- * If there is only 2 columns, it will return a 1 dimensional array of key-value pairs unless
- * $force_array == true.
- *
- * @param [force_array] has only meaning if we have 2 data columns. If false, a 1 dimensional
- * array is returned, otherwise a 2 dimensional array is returned. If this sounds confusing,
- * read the source.
- *
- * @param [first2cols] means if there are more than 2 cols, ignore the remaining cols and
- * instead of returning array[col0] => array(remaining cols), return array[col0] => col1
- *
- * @return an associative array indexed by the first column of the array,
- * or false if the data has less than 2 cols.
- */
- function &GetAssoc($force_array = false, $first2cols = false)
- {
- global $ADODB_EXTENSION;
-
- $cols = $this->_numOfFields;
- if ($cols < 2) {
- $false = false;
- return $false;
- }
- $numIndex = isset($this->fields[0]);
- $results = array();
-
- if (!$first2cols && ($cols > 2 || $force_array)) {
- if ($ADODB_EXTENSION) {
- if ($numIndex) {
- while (!$this->EOF) {
- $results[trim($this->fields[0])] = array_slice($this->fields, 1);
- adodb_movenext($this);
- }
- } else {
- while (!$this->EOF) {
- $results[trim(reset($this->fields))] = array_slice($this->fields, 1);
- adodb_movenext($this);
- }
- }
- } else {
- if ($numIndex) {
- while (!$this->EOF) {
- $results[trim($this->fields[0])] = array_slice($this->fields, 1);
- $this->MoveNext();
- }
- } else {
- while (!$this->EOF) {
- $results[trim(reset($this->fields))] = array_slice($this->fields, 1);
- $this->MoveNext();
- }
- }
- }
- } else {
- if ($ADODB_EXTENSION) {
- // return scalar values
- if ($numIndex) {
- while (!$this->EOF) {
- // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string
- $results[trim(($this->fields[0]))] = $this->fields[1];
- adodb_movenext($this);
- }
- } else {
- while (!$this->EOF) {
- // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string
- $v1 = trim(reset($this->fields));
- $v2 = ''.next($this->fields);
- $results[$v1] = $v2;
- adodb_movenext($this);
- }
- }
- } else {
- if ($numIndex) {
- while (!$this->EOF) {
- // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string
- $results[trim(($this->fields[0]))] = $this->fields[1];
- $this->MoveNext();
- }
- } else {
- while (!$this->EOF) {
- // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string
- $v1 = trim(reset($this->fields));
- $v2 = ''.next($this->fields);
- $results[$v1] = $v2;
- $this->MoveNext();
- }
- }
- }
- }
-
- $ref =& $results; # workaround accelerator incompat with PHP 4.4 :(
- return $ref;
- }
-
-
- /**
- *
- * @param v is the character timestamp in YYYY-MM-DD hh:mm:ss format
- * @param fmt is the format to apply to it, using date()
- *
- * @return a timestamp formated as user desires
- */
- function UserTimeStamp($v,$fmt='Y-m-d H:i:s')
- {
- if (is_numeric($v) && strlen($v)<14) return adodb_date($fmt,$v);
- $tt = $this->UnixTimeStamp($v);
- // $tt == -1 if pre TIMESTAMP_FIRST_YEAR
- if (($tt === false || $tt == -1) && $v != false) return $v;
- if ($tt === 0) return $this->emptyTimeStamp;
- return adodb_date($fmt,$tt);
- }
-
-
- /**
- * @param v is the character date in YYYY-MM-DD format, returned by database
- * @param fmt is the format to apply to it, using date()
- *
- * @return a date formated as user desires
- */
- function UserDate($v,$fmt='Y-m-d')
- {
- $tt = $this->UnixDate($v);
- // $tt == -1 if pre TIMESTAMP_FIRST_YEAR
- if (($tt === false || $tt == -1) && $v != false) return $v;
- else if ($tt == 0) return $this->emptyDate;
- else if ($tt == -1) { // pre-TIMESTAMP_FIRST_YEAR
- }
- return adodb_date($fmt,$tt);
- }
-
-
- /**
- * @param $v is a date string in YYYY-MM-DD format
- *
- * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
- */
- function UnixDate($v)
- {
- return ADOConnection::UnixDate($v);
- }
-
-
- /**
- * @param $v is a timestamp string in YYYY-MM-DD HH-NN-SS format
- *
- * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
- */
- function UnixTimeStamp($v)
- {
- return ADOConnection::UnixTimeStamp($v);
- }
-
-
- /**
- * PEAR DB Compat - do not use internally
- */
- function Free()
- {
- return $this->Close();
- }
-
-
- /**
- * PEAR DB compat, number of rows
- */
- function NumRows()
- {
- return $this->_numOfRows;
- }
-
-
- /**
- * PEAR DB compat, number of cols
- */
- function NumCols()
- {
- return $this->_numOfFields;
- }
-
- /**
- * Fetch a row, returning false if no more rows.
- * This is PEAR DB compat mode.
- *
- * @return false or array containing the current record
- */
- function &FetchRow()
- {
- if ($this->EOF) {
- $false = false;
- return $false;
- }
- $arr = $this->fields;
- $this->_currentRow++;
- if (!$this->_fetch()) $this->EOF = true;
- return $arr;
- }
-
-
- /**
- * Fetch a row, returning PEAR_Error if no more rows.
- * This is PEAR DB compat mode.
- *
- * @return DB_OK or error object
- */
- function FetchInto(&$arr)
- {
- if ($this->EOF) return (defined('PEAR_ERROR_RETURN')) ? new PEAR_Error('EOF',-1): false;
- $arr = $this->fields;
- $this->MoveNext();
- return 1; // DB_OK
- }
-
-
- /**
- * Move to the first row in the recordset. Many databases do NOT support this.
- *
- * @return true or false
- */
- function MoveFirst()
- {
- if ($this->_currentRow == 0) return true;
- return $this->Move(0);
- }
-
-
- /**
- * Move to the last row in the recordset.
- *
- * @return true or false
- */
- function MoveLast()
- {
- if ($this->_numOfRows >= 0) return $this->Move($this->_numOfRows-1);
- if ($this->EOF) return false;
- while (!$this->EOF) {
- $f = $this->fields;
- $this->MoveNext();
- }
- $this->fields = $f;
- $this->EOF = false;
- return true;
- }
-
-
- /**
- * Move to next record in the recordset.
- *
- * @return true if there still rows available, or false if there are no more rows (EOF).
- */
- function MoveNext()
- {
- if (!$this->EOF) {
- $this->_currentRow++;
- if ($this->_fetch()) return true;
- }
- $this->EOF = true;
- /* -- tested error handling when scrolling cursor -- seems useless.
- $conn = $this->connection;
- if ($conn && $conn->raiseErrorFn && ($errno = $conn->ErrorNo())) {
- $fn = $conn->raiseErrorFn;
- $fn($conn->databaseType,'MOVENEXT',$errno,$conn->ErrorMsg().' ('.$this->sql.')',$conn->host,$conn->database);
- }
- */
- return false;
- }
-
-
- /**
- * Random access to a specific row in the recordset. Some databases do not support
- * access to previous rows in the databases (no scrolling backwards).
- *
- * @param rowNumber is the row to move to (0-based)
- *
- * @return true if there still rows available, or false if there are no more rows (EOF).
- */
- function Move($rowNumber = 0)
- {
- $this->EOF = false;
- if ($rowNumber == $this->_currentRow) return true;
- if ($rowNumber >= $this->_numOfRows)
- if ($this->_numOfRows != -1) $rowNumber = $this->_numOfRows-2;
-
- if ($this->canSeek) {
-
- if ($this->_seek($rowNumber)) {
- $this->_currentRow = $rowNumber;
- if ($this->_fetch()) {
- return true;
- }
- } else {
- $this->EOF = true;
- return false;
- }
- } else {
- if ($rowNumber < $this->_currentRow) return false;
- global $ADODB_EXTENSION;
- if ($ADODB_EXTENSION) {
- while (!$this->EOF && $this->_currentRow < $rowNumber) {
- adodb_movenext($this);
- }
- } else {
-
- while (! $this->EOF && $this->_currentRow < $rowNumber) {
- $this->_currentRow++;
-
- if (!$this->_fetch()) $this->EOF = true;
- }
- }
- return !($this->EOF);
- }
-
- $this->fields = false;
- $this->EOF = true;
- return false;
- }
-
-
- /**
- * Get the value of a field in the current row by column name.
- * Will not work if ADODB_FETCH_MODE is set to ADODB_FETCH_NUM.
- *
- * @param colname is the field to access
- *
- * @return the value of $colname column
- */
- function Fields($colname)
- {
- return $this->fields[$colname];
- }
-
- function GetAssocKeys($upper=true)
- {
- $this->bind = array();
- for ($i=0; $i < $this->_numOfFields; $i++) {
- $o = $this->FetchField($i);
- if ($upper === 2) $this->bind[$o->name] = $i;
- else $this->bind[($upper) ? strtoupper($o->name) : strtolower($o->name)] = $i;
- }
- }
-
- /**
- * Use associative array to get fields array for databases that do not support
- * associative arrays. Submitted by Paolo S. Asioli paolo.asioli#libero.it
- *
- * If you don't want uppercase cols, set $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC
- * before you execute your SQL statement, and access $rs->fields['col'] directly.
- *
- * $upper 0 = lowercase, 1 = uppercase, 2 = whatever is returned by FetchField
- */
- function &GetRowAssoc($upper=1)
- {
- $record = array();
- // if (!$this->fields) return $record;
-
- if (!$this->bind) {
- $this->GetAssocKeys($upper);
- }
-
- foreach($this->bind as $k => $v) {
- $record[$k] = $this->fields[$v];
- }
-
- return $record;
- }
-
-
- /**
- * Clean up recordset
- *
- * @return true or false
- */
- function Close()
- {
- // free connection object - this seems to globally free the object
- // and not merely the reference, so don't do this...
- // $this->connection = false;
- if (!$this->_closed) {
- $this->_closed = true;
- return $this->_close();
- } else
- return true;
- }
-
- /**
- * synonyms RecordCount and RowCount
- *
- * @return the number of rows or -1 if this is not supported
- */
- function RecordCount() {return $this->_numOfRows;}
-
-
- /*
- * If we are using PageExecute(), this will return the maximum possible rows
- * that can be returned when paging a recordset.
- */
- function MaxRecordCount()
- {
- return ($this->_maxRecordCount) ? $this->_maxRecordCount : $this->RecordCount();
- }
-
- /**
- * synonyms RecordCount and RowCount
- *
- * @return the number of rows or -1 if this is not supported
- */
- function RowCount() {return $this->_numOfRows;}
-
-
- /**
- * Portable RecordCount. Pablo Roca <pabloroca@mvps.org>
- *
- * @return the number of records from a previous SELECT. All databases support this.
- *
- * But aware possible problems in multiuser environments. For better speed the table
- * must be indexed by the condition. Heavy test this before deploying.
- */
- function PO_RecordCount($table="", $condition="") {
-
- $lnumrows = $this->_numOfRows;
- // the database doesn't support native recordcount, so we do a workaround
- if ($lnumrows == -1 && $this->connection) {
- IF ($table) {
- if ($condition) $condition = " WHERE " . $condition;
- $resultrows = &$this->connection->Execute("SELECT COUNT(*) FROM $table $condition");
- if ($resultrows) $lnumrows = reset($resultrows->fields);
- }
- }
- return $lnumrows;
- }
-
-
- /**
- * @return the current row in the recordset. If at EOF, will return the last row. 0-based.
- */
- function CurrentRow() {return $this->_currentRow;}
-
- /**
- * synonym for CurrentRow -- for ADO compat
- *
- * @return the current row in the recordset. If at EOF, will return the last row. 0-based.
- */
- function AbsolutePosition() {return $this->_currentRow;}
-
- /**
- * @return the number of columns in the recordset. Some databases will set this to 0
- * if no records are returned, others will return the number of columns in the query.
- */
- function FieldCount() {return $this->_numOfFields;}
-
-
- /**
- * Get the ADOFieldObject of a specific column.
- *
- * @param fieldoffset is the column position to access(0-based).
- *
- * @return the ADOFieldObject for that column, or false.
- */
- function &FetchField($fieldoffset=-1)
- {
- // must be defined by child class
- }
-
- /**
- * Get the ADOFieldObjects of all columns in an array.
- *
- */
- function& FieldTypesArray()
- {
- $arr = array();
- for ($i=0, $max=$this->_numOfFields; $i < $max; $i++)
- $arr[] = $this->FetchField($i);
- return $arr;
- }
-
- /**
- * Return the fields array of the current row as an object for convenience.
- * The default case is lowercase field names.
- *
- * @return the object with the properties set to the fields of the current row
- */
- function &FetchObj()
- {
- $o =& $this->FetchObject(false);
- return $o;
- }
-
- /**
- * Return the fields array of the current row as an object for convenience.
- * The default case is uppercase.
- *
- * @param $isupper to set the object property names to uppercase
- *
- * @return the object with the properties set to the fields of the current row
- */
- function &FetchObject($isupper=true)
- {
- if (empty($this->_obj)) {
- $this->_obj = new ADOFetchObj();
- $this->_names = array();
- for ($i=0; $i <$this->_numOfFields; $i++) {
- $f = $this->FetchField($i);
- $this->_names[] = $f->name;
- }
- }
- $i = 0;
- if (PHP_VERSION >= 5) $o = clone($this->_obj);
- else $o = $this->_obj;
-
- for ($i=0; $i <$this->_numOfFields; $i++) {
- $name = $this->_names[$i];
- if ($isupper) $n = strtoupper($name);
- else $n = $name;
-
- $o->$n = $this->Fields($name);
- }
- return $o;
- }
-
- /**
- * Return the fields array of the current row as an object for convenience.
- * The default is lower-case field names.
- *
- * @return the object with the properties set to the fields of the current row,
- * or false if EOF
- *
- * Fixed bug reported by tim@orotech.net
- */
- function &FetchNextObj()
- {
- $o =& $this->FetchNextObject(false);
- return $o;
- }
-
-
- /**
- * Return the fields array of the current row as an object for convenience.
- * The default is upper case field names.
- *
- * @param $isupper to set the object property names to uppercase
- *
- * @return the object with the properties set to the fields of the current row,
- * or false if EOF
- *
- * Fixed bug reported by tim@orotech.net
- */
- function &FetchNextObject($isupper=true)
- {
- $o = false;
- if ($this->_numOfRows != 0 && !$this->EOF) {
- $o = $this->FetchObject($isupper);
- $this->_currentRow++;
- if ($this->_fetch()) return $o;
- }
- $this->EOF = true;
- return $o;
- }
-
- /**
- * Get the metatype of the column. This is used for formatting. This is because
- * many databases use different names for the same type, so we transform the original
- * type to our standardised version which uses 1 character codes:
- *
- * @param t is the type passed in. Normally is ADOFieldObject->type.
- * @param len is the maximum length of that field. This is because we treat character
- * fields bigger than a certain size as a 'B' (blob).
- * @param fieldobj is the field object returned by the database driver. Can hold
- * additional info (eg. primary_key for mysql).
- *
- * @return the general type of the data:
- * C for character < 250 chars
- * X for teXt (>= 250 chars)
- * B for Binary
- * N for numeric or floating point
- * D for date
- * T for timestamp
- * L for logical/Boolean
- * I for integer
- * R for autoincrement counter/integer
- *
- *
- */
- function MetaType($t,$len=-1,$fieldobj=false)
- {
- if (is_object($t)) {
- $fieldobj = $t;
- $t = $fieldobj->type;
- $len = $fieldobj->max_length;
- }
- // changed in 2.32 to hashing instead of switch stmt for speed...
- static $typeMap = array(
- 'VARCHAR' => 'C',
- 'VARCHAR2' => 'C',
- 'CHAR' => 'C',
- 'C' => 'C',
- 'STRING' => 'C',
- 'NCHAR' => 'C',
- 'NVARCHAR' => 'C',
- 'VARYING' => 'C',
- 'BPCHAR' => 'C',
- 'CHARACTER' => 'C',
- 'INTERVAL' => 'C', # Postgres
- ##
- 'LONGCHAR' => 'X',
- 'TEXT' => 'X',
- 'NTEXT' => 'X',
- 'M' => 'X',
- 'X' => 'X',
- 'CLOB' => 'X',
- 'NCLOB' => 'X',
- 'LVARCHAR' => 'X',
- ##
- 'BLOB' => 'B',
- 'IMAGE' => 'B',
- 'BINARY' => 'B',
- 'VARBINARY' => 'B',
- 'LONGBINARY' => 'B',
- 'B' => 'B',
- ##
- 'YEAR' => 'D', // mysql
- 'DATE' => 'D',
- 'D' => 'D',
- ##
- 'TIME' => 'T',
- 'TIMESTAMP' => 'T',
- 'DATETIME' => 'T',
- 'TIMESTAMPTZ' => 'T',
- 'T' => 'T',
- ##
- 'BOOL' => 'L',
- 'BOOLEAN' => 'L',
- 'BIT' => 'L',
- 'L' => 'L',
- ##
- 'COUNTER' => 'R',
- 'R' => 'R',
- 'SERIAL' => 'R', // ifx
- 'INT IDENTITY' => 'R',
- ##
- 'INT' => 'I',
- 'INT2' => 'I',
- 'INT4' => 'I',
- 'INT8' => 'I',
- 'INTEGER' => 'I',
- 'INTEGER UNSIGNED' => 'I',
- 'SHORT' => 'I',
- 'TINYINT' => 'I',
- 'SMALLINT' => 'I',
- 'I' => 'I',
- ##
- 'LONG' => 'N', // interbase is numeric, oci8 is blob
- 'BIGINT' => 'N', // this is bigger than PHP 32-bit integers
- 'DECIMAL' => 'N',
- 'DEC' => 'N',
- 'REAL' => 'N',
- 'DOUBLE' => 'N',
- 'DOUBLE PRECISION' => 'N',
- 'SMALLFLOAT' => 'N',
- 'FLOAT' => 'N',
- 'NUMBER' => 'N',
- 'NUM' => 'N',
- 'NUMERIC' => 'N',
- 'MONEY' => 'N',
-
- ## informix 9.2
- 'SQLINT' => 'I',
- 'SQLSERIAL' => 'I',
- 'SQLSMINT' => 'I',
- 'SQLSMFLOAT' => 'N',
- 'SQLFLOAT' => 'N',
- 'SQLMONEY' => 'N',
- 'SQLDECIMAL' => 'N',
- 'SQLDATE' => 'D',
- 'SQLVCHAR' => 'C',
- 'SQLCHAR' => 'C',
- 'SQLDTIME' => 'T',
- 'SQLINTERVAL' => 'N',
- 'SQLBYTES' => 'B',
- 'SQLTEXT' => 'X'
- );
-
- $tmap = false;
- $t = strtoupper($t);
- $tmap = (isset($typeMap[$t])) ? $typeMap[$t] : 'N';
- switch ($tmap) {
- case 'C':
-
- // is the char field is too long, return as text field...
- if ($this->blobSize >= 0) {
- if ($len > $this->blobSize) return 'X';
- } else if ($len > 250) {
- return 'X';
- }
- return 'C';
-
- case 'I':
- if (!empty($fieldobj->primary_key)) return 'R';
- return 'I';
-
- case false:
- return 'N';
-
- case 'B':
- if (isset($fieldobj->binary))
- return ($fieldobj->binary) ? 'B' : 'X';
- return 'B';
-
- case 'D':
- if (!empty($this->connection) && !empty($this->connection->datetime)) return 'T';
- return 'D';
-
- default:
- if ($t == 'LONG' && $this->dataProvider == 'oci8') return 'B';
- return $tmap;
- }
- }
-
- function _close() {}
-
- /**
- * set/returns the current recordset page when paginating
- */
- function AbsolutePage($page=-1)
- {
- if ($page != -1) $this->_currentPage = $page;
- return $this->_currentPage;
- }
-
- /**
- * set/returns the status of the atFirstPage flag when paginating
- */
- function AtFirstPage($status=false)
- {
- if ($status != false) $this->_atFirstPage = $status;
- return $this->_atFirstPage;
- }
-
- function LastPageNo($page = false)
- {
- if ($page != false) $this->_lastPageNo = $page;
- return $this->_lastPageNo;
- }
-
- /**
- * set/returns the status of the atLastPage flag when paginating
- */
- function AtLastPage($status=false)
- {
- if ($status != false) $this->_atLastPage = $status;
- return $this->_atLastPage;
- }
-
-} // end class ADORecordSet
-
- //==============================================================================================
- // CLASS ADORecordSet_array
- //==============================================================================================
-
- /**
- * This class encapsulates the concept of a recordset created in memory
- * as an array. This is useful for the creation of cached recordsets.
- *
- * Note that the constructor is different from the standard ADORecordSet
- */
-
- class ADORecordSet_array extends ADORecordSet
- {
- public $databaseType = 'array';
-
- public $_array; // holds the 2-dimensional data array
- public $_types; // the array of types of each column (C B I L M)
- public $_colnames; // names of each column in array
- public $_skiprow1; // skip 1st row because it holds column names
- public $_fieldarr; // holds array of field objects
- public $canSeek = true;
- public $affectedrows = false;
- public $insertid = false;
- public $sql = '';
- public $compat = false;
- /**
- * Constructor
- *
- */
- function ADORecordSet_array($fakeid=1)
- {
- global $ADODB_FETCH_MODE,$ADODB_COMPAT_FETCH;
-
- // fetch() on EOF does not delete $this->fields
- $this->compat = !empty($ADODB_COMPAT_FETCH);
- $this->ADORecordSet($fakeid); // fake queryID
- $this->fetchMode = $ADODB_FETCH_MODE;
- }
-
-
- /**
- * Setup the array.
- *
- * @param array is a 2-dimensional array holding the data.
- * The first row should hold the column names
- * unless paramter $colnames is used.
- * @param typearr holds an array of types. These are the same types
- * used in MetaTypes (C,B,L,I,N).
- * @param [colnames] array of column names. If set, then the first row of
- * $array should not hold the column names.
- */
- function InitArray($array,$typearr,$colnames=false)
- {
- $this->_array = $array;
- $this->_types = $typearr;
- if ($colnames) {
- $this->_skiprow1 = false;
- $this->_colnames = $colnames;
- } else {
- $this->_skiprow1 = true;
- $this->_colnames = $array[0];
- }
- $this->Init();
- }
- /**
- * Setup the Array and datatype file objects
- *
- * @param array is a 2-dimensional array holding the data.
- * The first row should hold the column names
- * unless paramter $colnames is used.
- * @param fieldarr holds an array of ADOFieldObject's.
- */
- function InitArrayFields(&$array,&$fieldarr)
- {
- $this->_array =& $array;
- $this->_skiprow1= false;
- if ($fieldarr) {
- $this->_fieldobjects =& $fieldarr;
- }
- $this->Init();
- }
-
- function &GetArray($nRows=-1)
- {
- if ($nRows == -1 && $this->_currentRow <= 0 && !$this->_skiprow1) {
- return $this->_array;
- } else {
- $arr =& ADORecordSet::GetArray($nRows);
- return $arr;
- }
- }
-
- function _initrs()
- {
- $this->_numOfRows = sizeof($this->_array);
- if ($this->_skiprow1) $this->_numOfRows -= 1;
-
- $this->_numOfFields =(isset($this->_fieldobjects)) ?
- sizeof($this->_fieldobjects):sizeof($this->_types);
- }
-
- /* Use associative array to get fields array */
- function Fields($colname)
- {
- $mode = isset($this->adodbFetchMode) ? $this->adodbFetchMode : $this->fetchMode;
-
- if ($mode & ADODB_FETCH_ASSOC) {
- if (!isset($this->fields[$colname])) $colname = strtolower($colname);
- return $this->fields[$colname];
- }
- if (!$this->bind) {
- $this->bind = array();
- for ($i=0; $i < $this->_numOfFields; $i++) {
- $o = $this->FetchField($i);
- $this->bind[strtoupper($o->name)] = $i;
- }
- }
- return $this->fields[$this->bind[strtoupper($colname)]];
- }
-
- function &FetchField($fieldOffset = -1)
- {
- if (isset($this->_fieldobjects)) {
- return $this->_fieldobjects[$fieldOffset];
- }
- $o = new ADOFieldObject();
- $o->name = $this->_colnames[$fieldOffset];
- $o->type = $this->_types[$fieldOffset];
- $o->max_length = -1; // length not known
-
- return $o;
- }
-
- function _seek($row)
- {
- if (sizeof($this->_array) && 0 <= $row && $row < $this->_numOfRows) {
- $this->_currentRow = $row;
- if ($this->_skiprow1) $row += 1;
- $this->fields = $this->_array[$row];
- return true;
- }
- return false;
- }
-
- function MoveNext()
- {
- if (!$this->EOF) {
- $this->_currentRow++;
-
- $pos = $this->_currentRow;
-
- if ($this->_numOfRows <= $pos) {
- if (!$this->compat) $this->fields = false;
- } else {
- if ($this->_skiprow1) $pos += 1;
- $this->fields = $this->_array[$pos];
- return true;
- }
- $this->EOF = true;
- }
-
- return false;
- }
-
- function _fetch()
- {
- $pos = $this->_currentRow;
-
- if ($this->_numOfRows <= $pos) {
- if (!$this->compat) $this->fields = false;
- return false;
- }
- if ($this->_skiprow1) $pos += 1;
- $this->fields = $this->_array[$pos];
- return true;
- }
-
- function _close()
- {
- return true;
- }
-
- } // ADORecordSet_array
-
- //==============================================================================================
- // HELPER FUNCTIONS
- //==============================================================================================
-
- /**
- * Synonym for ADOLoadCode. Private function. Do not use.
- *
- * @deprecated
- */
- function ADOLoadDB($dbType)
- {
- return ADOLoadCode($dbType);
- }
-
- /**
- * Load the code for a specific database driver. Private function. Do not use.
- */
- function ADOLoadCode($dbType)
- {
- global $ADODB_LASTDB;
-
- if (!$dbType) return false;
- $db = strtolower($dbType);
- switch ($db) {
- case 'ado':
- if (PHP_VERSION >= 5) $db = 'ado5';
- $class = 'ado';
- break;
- case 'ifx':
- case 'maxsql': $class = $db = 'mysqlt'; break;
- case 'postgres':
- case 'postgres8':
- case 'pgsql': $class = $db = 'postgres7'; break;
- default:
- $class = $db; break;
- }
-
- $file = ADODB_DIR."/drivers/adodb-".$db.".inc.php";
- @include_once($file);
- $ADODB_LASTDB = $class;
- if (class_exists("ADODB_" . $class)) return $class;
-
- //ADOConnection::outp(adodb_pr(get_declared_classes(),true));
- if (!file_exists($file)) ADOConnection::outp("Missing file: $file");
- else ADOConnection::outp("Syntax error in file: $file");
- return false;
- }
-
- /**
- * synonym for ADONewConnection for people like me who cannot remember the correct name
- */
- function &NewADOConnection($db='')
- {
- $tmp =& ADONewConnection($db);
- return $tmp;
- }
-
- /**
- * Instantiate a new Connection class for a specific database driver.
- *
- * @param [db] is the database Connection object to create. If undefined,
- * use the last database driver that was loaded by ADOLoadCode().
- *
- * @return the freshly created instance of the Connection class.
- */
- function &ADONewConnection($db='')
- {
- GLOBAL $ADODB_NEWCONNECTION, $ADODB_LASTDB;
-
- if (!defined('ADODB_ASSOC_CASE')) define('ADODB_ASSOC_CASE',2);
- $errorfn = (defined('ADODB_ERROR_HANDLER')) ? ADODB_ERROR_HANDLER : false;
- $false = false;
- if ($at = strpos($db,'://')) {
- $origdsn = $db;
- if (PHP_VERSION < 5) $dsna = @parse_url($db);
- else {
- $fakedsn = 'fake'.substr($db,$at);
- $dsna = @parse_url($fakedsn);
- $dsna['scheme'] = substr($db,0,$at);
-
- if (strncmp($db,'pdo',3) == 0) {
- $sch = explode('_',$dsna['scheme']);
- if (sizeof($sch)>1) {
- $dsna['host'] = isset($dsna['host']) ? rawurldecode($dsna['host']) : '';
- $dsna['host'] = rawurlencode($sch[1].':host='.rawurldecode($dsna['host']));
- $dsna['scheme'] = 'pdo';
- }
- }
- }
-
- if (!$dsna) {
- // special handling of oracle, which might not have host
- $db = str_replace('@/','@adodb-fakehost/',$db);
- $dsna = parse_url($db);
- if (!$dsna) return $false;
- $dsna['host'] = '';
- }
- $db = @$dsna['scheme'];
- if (!$db) return $false;
- $dsna['host'] = isset($dsna['host']) ? rawurldecode($dsna['host']) : '';
- $dsna['user'] = isset($dsna['user']) ? rawurldecode($dsna['user']) : '';
- $dsna['pass'] = isset($dsna['pass']) ? rawurldecode($dsna['pass']) : '';
- $dsna['path'] = isset($dsna['path']) ? rawurldecode(substr($dsna['path'],1)) : ''; # strip off initial /
-
- if (isset($dsna['query'])) {
- $opt1 = explode('&',$dsna['query']);
- foreach($opt1 as $k => $v) {
- $arr = explode('=',$v);
- $opt[$arr[0]] = isset($arr[1]) ? rawurldecode($arr[1]) : 1;
- }
- } else $opt = array();
- }
- /*
- * phptype: Database backend used in PHP (mysql, odbc etc.)
- * dbsyntax: Database used with regards to SQL syntax etc.
- * protocol: Communication protocol to use (tcp, unix etc.)
- * hostspec: Host specification (hostname[:port])
- * database: Database to use on the DBMS server
- * username: User name for login
- * password: Password for login
- */
- if (!empty($ADODB_NEWCONNECTION)) {
- $obj = $ADODB_NEWCONNECTION($db);
-
- } else {
-
- if (!isset($ADODB_LASTDB)) $ADODB_LASTDB = '';
- if (empty($db)) $db = $ADODB_LASTDB;
-
- if ($db != $ADODB_LASTDB) $db = ADOLoadCode($db);
-
- if (!$db) {
- if (isset($origdsn)) $db = $origdsn;
- if ($errorfn) {
- // raise an error
- $ignore = false;
- $errorfn('ADONewConnection', 'ADONewConnection', -998,
- "could not load the database driver for '$db'",
- $db,false,$ignore);
- } else
- ADOConnection::outp( "<p>ADONewConnection: Unable to load database driver '$db'</p>",false);
-
- return $false;
- }
-
- $cls = 'ADODB_'.$db;
- if (!class_exists($cls)) {
- adodb_backtrace();
- return $false;
- }
-
- $obj = new $cls();
- }
-
- # constructor should not fail
- if ($obj) {
- if ($errorfn) $obj->raiseErrorFn = $errorfn;
- if (isset($dsna)) {
- if (isset($dsna['port'])) $obj->port = $dsna['port'];
- foreach($opt as $k => $v) {
- switch(strtolower($k)) {
- case 'new':
- $nconnect = true; $persist = true; break;
- case 'persist':
- case 'persistent': $persist = $v; break;
- case 'debug': $obj->debug = (integer) $v; break;
- #ibase
- case 'role': $obj->role = $v; break;
- case 'dialect': $obj->dialect = (integer) $v; break;
- case 'charset': $obj->charset = $v; $obj->charSet=$v; break;
- case 'buffers': $obj->buffers = $v; break;
- case 'fetchmode': $obj->SetFetchMode($v); break;
- #ado
- case 'charpage': $obj->charPage = $v; break;
- #mysql, mysqli
- case 'clientflags': $obj->clientFlags = $v; break;
- #mysql, mysqli, postgres
- case 'port': $obj->port = $v; break;
- #mysqli
- case 'socket': $obj->socket = $v; break;
- #oci8
- case 'nls_date_format': $obj->NLS_DATE_FORMAT = $v; break;
- }
- }
- if (empty($persist))
- $ok = $obj->Connect($dsna['host'], $dsna['user'], $dsna['pass'], $dsna['path']);
- else if (empty($nconnect))
- $ok = $obj->PConnect($dsna['host'], $dsna['user'], $dsna['pass'], $dsna['path']);
- else
- $ok = $obj->NConnect($dsna['host'], $dsna['user'], $dsna['pass'], $dsna['path']);
-
- if (!$ok) return $false;
- }
- }
- return $obj;
- }
-
-
-
- // $perf == true means called by NewPerfMonitor(), otherwise for data dictionary
- function _adodb_getdriver($provider,$drivername,$perf=false)
- {
- switch ($provider) {
- case 'odbtp': if (strncmp('odbtp_',$drivername,6)==0) return substr($drivername,6);
- case 'odbc' : if (strncmp('odbc_',$drivername,5)==0) return substr($drivername,5);
- case 'ado' : if (strncmp('ado_',$drivername,4)==0) return substr($drivername,4);
- case 'native': break;
- default:
- return $provider;
- }
-
- switch($drivername) {
- case 'mysqlt':
- case 'mysqli':
- $drivername='mysql';
- break;
- case 'postgres7':
- case 'postgres8':
- $drivername = 'postgres';
- break;
- case 'firebird15': $drivername = 'firebird'; break;
- case 'oracle': $drivername = 'oci8'; break;
- case 'access': if ($perf) $drivername = ''; break;
- case 'db2' : break;
- case 'sapdb' : break;
- default:
- $drivername = 'generic';
- break;
- }
- return $drivername;
- }
-
- function &NewPerfMonitor(&$conn)
- {
- $false = false;
- $drivername = _adodb_getdriver($conn->dataProvider,$conn->databaseType,true);
- if (!$drivername || $drivername == 'generic') return $false;
- include_once(ADODB_DIR.'/adodb-perf.inc.php');
- @include_once(ADODB_DIR."/perf/perf-$drivername.inc.php");
- $class = "Perf_$drivername";
- if (!class_exists($class)) return $false;
- $perf = new $class($conn);
-
- return $perf;
- }
-
- function &NewDataDictionary(&$conn,$drivername=false)
- {
- $false = false;
- if (!$drivername) $drivername = _adodb_getdriver($conn->dataProvider,$conn->databaseType);
-
- include_once(ADODB_DIR.'/adodb-lib.inc.php');
- include_once(ADODB_DIR.'/adodb-datadict.inc.php');
- $path = ADODB_DIR."/datadict/datadict-$drivername.inc.php";
-
- if (!file_exists($path)) {
- ADOConnection::outp("Dictionary driver '$path' not available");
- return $false;
- }
- include_once($path);
- $class = "ADODB2_$drivername";
- $dict = new $class();
- $dict->dataProvider = $conn->dataProvider;
- $dict->connection = &$conn;
- $dict->upperName = strtoupper($drivername);
- $dict->quote = $conn->nameQuote;
- if (!empty($conn->_connectionID))
- $dict->serverInfo = $conn->ServerInfo();
-
- return $dict;
- }
-
-
-
- /*
- Perform a print_r, with pre tags for better formatting.
- */
- function adodb_pr($var,$as_string=false)
- {
- if ($as_string) ob_start();
-
- if (isset($_SERVER['HTTP_USER_AGENT'])) {
- echo " <pre>\n";print_r($var);echo "</pre>\n";
- } else
- print_r($var);
-
- if ($as_string) {
- $s = ob_get_contents();
- ob_end_clean();
- return $s;
- }
- }
-
- /*
- Perform a stack-crawl and pretty print it.
-
- @param printOrArr Pass in a boolean to indicate print, or an $exception->trace array (assumes that print is true then).
- @param levels Number of levels to display
- */
- function adodb_backtrace($printOrArr=true,$levels=9999)
- {
- global $ADODB_INCLUDED_LIB;
- if (empty($ADODB_INCLUDED_LIB)) include(ADODB_DIR.'/adodb-lib.inc.php');
- return _adodb_backtrace($printOrArr,$levels);
- }
-
-
-}
-?>