/lib/adodb/adodb.inc.php
PHP | 5102 lines | 3164 code | 602 blank | 1336 comment | 650 complexity | f6d0e8c5618f82ebfb398a1ff2d9394d MD5 | raw file
Possible License(s): MIT, AGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, Apache-2.0, LGPL-2.1, BSD-3-Clause
Large files files are truncated, but you can click here to view the full file
- <?php
- /*
- * Set tabs to 4 for best viewing.
- *
- * Latest version is available at http://adodb.org/
- *
- * 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 v5.20.16 12-Jan-2020
- @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
- @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
- 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.
- */
- if (!defined('_ADODB_LAYER')) {
- define('_ADODB_LAYER',1);
- // The ADOdb extension is no longer maintained and effectively unsupported
- // since v5.04. The library will not function properly if it is present.
- if(defined('ADODB_EXTENSION')) {
- $msg = "Unsupported ADOdb Extension (v" . ADODB_EXTENSION . ") detected! "
- . "Disable it to use ADOdb";
- $errorfn = defined('ADODB_ERROR_HANDLER') ? ADODB_ERROR_HANDLER : false;
- if ($errorfn) {
- $conn = false;
- $errorfn('ADOdb', basename(__FILE__), -9999, $msg, null, null, $conn);
- } else {
- die($msg . PHP_EOL);
- }
- }
- //==============================================================================================
- // 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_CACHE,
- $ADODB_CACHE_CLASS,
- $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...
- $ADODB_GETONE_EOF,
- $ADODB_QUOTE_FIELDNAMES; // Allows you to force quotes (backticks) around field names in queries generated by getinsertsql and getupdatesql.
- //==============================================================================================
- // 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);
- }
- /**
- * Fetch mode
- *
- * Set global variable $ADODB_FETCH_MODE to one of these constants or use
- * the SetFetchMode() method to control how recordset fields are returned
- * when fetching data.
- *
- * - NUM: array()
- * - ASSOC: array('id' => 456, 'name' => 'john')
- * - BOTH: array(0 => 456, 'id' => 456, 1 => 'john', 'name' => 'john')
- * - DEFAULT: driver-dependent
- */
- define('ADODB_FETCH_DEFAULT', 0);
- define('ADODB_FETCH_NUM', 1);
- define('ADODB_FETCH_ASSOC', 2);
- define('ADODB_FETCH_BOTH', 3);
- /**
- * Associative array case constants
- *
- * By defining the ADODB_ASSOC_CASE constant to one of these values, it is
- * possible to control the case of field names (associative array's keys)
- * when operating in ADODB_FETCH_ASSOC fetch mode.
- * - LOWER: $rs->fields['orderid']
- * - UPPER: $rs->fields['ORDERID']
- * - NATIVE: $rs->fields['OrderID'] (or whatever the RDBMS will return)
- *
- * The default is to use native case-names.
- *
- * NOTE: This functionality is not implemented everywhere, it currently
- * works only with: mssql, odbc, oci8 and ibase derived drivers
- */
- define('ADODB_ASSOC_CASE_LOWER', 0);
- define('ADODB_ASSOC_CASE_UPPER', 1);
- define('ADODB_ASSOC_CASE_NATIVE', 2);
- if (!defined('TIMESTAMP_FIRST_YEAR')) {
- define('TIMESTAMP_FIRST_YEAR',100);
- }
- /**
- * AutoExecute constants
- * (moved from adodb-pear.inc.php since they are only used in here)
- */
- define('DB_AUTOQUERY_INSERT', 1);
- define('DB_AUTOQUERY_UPDATE', 2);
- // PHP's version scheme makes converting to numbers difficult - workaround
- $_adodb_ver = (float) PHP_VERSION;
- if ($_adodb_ver >= 5.2) {
- define('ADODB_PHPVER',0x5200);
- } else if ($_adodb_ver >= 5.0) {
- define('ADODB_PHPVER',0x5000);
- } else {
- die("PHP5 or later required. You are running ".PHP_VERSION);
- }
- unset($_adodb_ver);
- }
- /**
- 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_CACHE,
- $ADODB_CACHE_CLASS,
- $ADODB_FORCE_TYPE,
- $ADODB_GETONE_EOF,
- $ADODB_QUOTE_FIELDNAMES;
- if (empty($ADODB_CACHE_CLASS)) {
- $ADODB_CACHE_CLASS = 'ADODB_Cache_File' ;
- }
- $ADODB_FETCH_MODE = ADODB_FETCH_DEFAULT;
- $ADODB_FORCE_TYPE = ADODB_FORCE_VALUE;
- $ADODB_GETONE_EOF = null;
- 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://");
- }
- }
- /**
- * ADODB version as a string.
- */
- $ADODB_vers = 'v5.20.16 12-Jan-2020';
- /**
- * 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 {
- var $name = '';
- var $max_length=0;
- var $type="";
- /*
- // additional fields by dannym... (danny_milo@yahoo.com)
- var $not_null = false;
- // actually, this has already been built-in in the postgres, fbsql AND mysql module? ^-^
- // so we can as well make not_null standard (leaving it at "false" does not harm anyways)
- var $has_default = false; // this one I have done only in mysql and postgres for now ...
- // others to come (dannym)
- var $default_value; // default, if any, and supported. Check has_default first.
- */
- }
- function _adodb_safedate($s) {
- return str_replace(array("'", '\\'), '', $s);
- }
- // parse date string to prevent injection attack
- // date string will have one quote at beginning e.g. '3434343'
- function _adodb_safedateq($s) {
- $len = strlen($s);
- if ($s[0] !== "'") {
- $s2 = "'".$s[0];
- } else {
- $s2 = "'";
- }
- for($i=1; $i<$len; $i++) {
- $ch = $s[$i];
- if ($ch === '\\') {
- $s2 .= "'";
- break;
- } elseif ($ch === "'") {
- $s2 .= $ch;
- break;
- }
- $s2 .= $ch;
- }
- return strlen($s2) == 0 ? 'null' : $s2;
- }
- // for transaction handling
- 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 for caching
- class ADODB_Cache_File {
- var $createdir = true; // requires creation of temp dirs
- function __construct() {
- global $ADODB_INCLUDED_CSV;
- if (empty($ADODB_INCLUDED_CSV)) {
- include_once(ADODB_DIR.'/adodb-csvlib.inc.php');
- }
- }
- // write serialised recordset to cache item/file
- function writecache($filename, $contents, $debug, $secs2cache) {
- return adodb_write_file($filename, $contents,$debug);
- }
- // load serialised recordset and unserialise it
- function &readcache($filename, &$err, $secs2cache, $rsClass) {
- $rs = csv2rs($filename,$err,$secs2cache,$rsClass);
- return $rs;
- }
- // flush all items in cache
- function flushall($debug=false) {
- global $ADODB_CACHE_DIR;
- $rez = false;
- if (strlen($ADODB_CACHE_DIR) > 1) {
- $rez = $this->_dirFlush($ADODB_CACHE_DIR);
- if ($debug) {
- ADOConnection::outp( "flushall: $ADODB_CACHE_DIR<br><pre>\n". $rez."</pre>");
- }
- }
- return $rez;
- }
- // flush one file in cache
- function flushcache($f, $debug=false) {
- if (!@unlink($f)) {
- if ($debug) {
- ADOConnection::outp( "flushcache: failed for $f");
- }
- }
- }
- function getdirname($hash) {
- global $ADODB_CACHE_DIR;
- if (!isset($this->notSafeMode)) {
- $this->notSafeMode = !ini_get('safe_mode');
- }
- return ($this->notSafeMode) ? $ADODB_CACHE_DIR.'/'.substr($hash,0,2) : $ADODB_CACHE_DIR;
- }
- // create temp directories
- function createdir($hash, $debug) {
- global $ADODB_CACHE_PERMS;
- $dir = $this->getdirname($hash);
- if ($this->notSafeMode && !file_exists($dir)) {
- $oldu = umask(0);
- if (!@mkdir($dir, empty($ADODB_CACHE_PERMS) ? 0771 : $ADODB_CACHE_PERMS)) {
- if(!is_dir($dir) && $debug) {
- ADOConnection::outp("Cannot create $dir");
- }
- }
- umask($oldu);
- }
- return $dir;
- }
- /**
- * 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;
- $f = $dir.'/'.$obj;
- if (strpos($obj,'.cache')) {
- @unlink($f);
- }
- if (is_dir($f)) {
- $this->_dirFlush($f, true);
- }
- }
- if ($kill_top_level === true) {
- @rmdir($dir);
- }
- return true;
- }
- }
- //==============================================================================================
- // CLASS ADOConnection
- //==============================================================================================
- /**
- * Connection object. For connecting to databases, and executing queries.
- */
- abstract class ADOConnection {
- //
- // PUBLIC VARS
- //
- var $dataProvider = 'native';
- var $databaseType = ''; /// RDBMS currently in use, eg. odbc, mysql, mssql
- var $database = ''; /// Name of database to be used.
- var $host = ''; /// The hostname of the database server
- var $port = ''; /// The port of the database server
- var $user = ''; /// The username which is used to connect to the database server.
- var $password = ''; /// Password for the username. For security, we no longer store it.
- var $debug = false; /// if set to true will output sql statements
- var $maxblobsize = 262144; /// maximum size of blobs or large text fields (262144 = 256K)-- some db's die otherwise like foxpro
- var $concat_operator = '+'; /// default concat operator -- change to || for Oracle/Interbase
- var $substr = 'substr'; /// substring operator
- var $length = 'length'; /// string length ofperator
- var $random = 'rand()'; /// random function
- var $upperCase = 'upper'; /// uppercase function
- var $fmtDate = "'Y-m-d'"; /// used by DBDate() as the default date format used by the database
- var $fmtTimeStamp = "'Y-m-d, h:i:s A'"; /// used by DBTimeStamp as the default timestamp fmt.
- var $true = '1'; /// string that represents TRUE for a database
- var $false = '0'; /// string that represents FALSE for a database
- var $replaceQuote = "\\'"; /// string to use to replace quotes
- var $nameQuote = '"'; /// string to use to quote identifiers and names
- var $charSet=false; /// character set to use - only for interbase, postgres and oci8
- var $metaDatabasesSQL = '';
- var $metaTablesSQL = '';
- var $uniqueOrderBy = false; /// All order by columns have to be unique
- var $emptyDate = ' ';
- var $emptyTimeStamp = ' ';
- var $lastInsID = false;
- //--
- var $hasInsertID = false; /// supports autoincrement ID?
- var $hasAffectedRows = false; /// supports affected rows for update/delete?
- var $hasTop = false; /// support mssql/access SELECT TOP 10 * FROM TABLE
- var $hasLimit = false; /// support pgsql/mysql SELECT * FROM TABLE LIMIT 10
- var $readOnly = false; /// this is a readonly database - used by phpLens
- var $hasMoveFirst = false; /// has ability to run MoveFirst(), scrolling backwards
- var $hasGenID = false; /// can generate sequences using GenID();
- var $hasTransactions = true; /// has transactions
- //--
- var $genID = 0; /// sequence id used by GenID();
- var $raiseErrorFn = false; /// error function to call
- var $isoDates = false; /// accepts dates in ISO format
- var $cacheSecs = 3600; /// cache for 1 hour
- // memcache
- var $memCache = false; /// should we use memCache instead of caching in files
- var $memCacheHost; /// memCache host
- var $memCachePort = 11211; /// memCache port
- var $memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib)
- var $sysDate = false; /// name of function that returns the current date
- var $sysTimeStamp = false; /// name of function that returns the current timestamp
- var $sysUTimeStamp = false; // name of function that returns the current timestamp accurate to the microsecond or nearest fraction
- var $arrayClass = 'ADORecordSet_array'; /// name of class used to generate array recordsets, which are pre-downloaded recordsets
- var $noNullStrings = false; /// oracle specific stuff - if true ensures that '' is converted to ' '
- var $numCacheHits = 0;
- var $numCacheMisses = 0;
- var $pageExecuteCountRows = true;
- var $uniqueSort = false; /// indicates that all fields in order by must be unique
- var $leftOuter = false; /// operator to use for left outer join in WHERE clause
- var $rightOuter = false; /// operator to use for right outer join in WHERE clause
- var $ansiOuter = false; /// whether ansi outer join syntax supported
- var $autoRollback = false; // autoRollback on PConnect().
- var $poorAffectedRows = false; // affectedRows not working or unreliable
- var $fnExecute = false;
- var $fnCacheExecute = false;
- var $blobEncodeType = false; // false=not required, 'I'=encode to integer, 'C'=encode to char
- var $rsPrefix = "ADORecordSet_";
- var $autoCommit = true; /// do not modify this yourself - actually private
- var $transOff = 0; /// temporarily disable transactions
- var $transCnt = 0; /// count of nested transactions
- var $fetchMode=false;
- var $null2null = 'null'; // in autoexecute/getinsertsql/getupdatesql, this value will be converted to a null
- var $bulkBind = false; // enable 2D Execute array
- //
- // PRIVATE VARS
- //
- var $_oldRaiseFn = false;
- var $_transOK = null;
- var $_connectionID = false; /// The returned link identifier whenever a successful database connection is made.
- var $_errorMsg = false; /// A variable which was used to keep the returned last error message. The value will
- /// then returned by the errorMsg() function
- var $_errorCode = false; /// Last error code, not guaranteed to be used - only by oci8
- var $_queryID = false; /// This variable keeps the last created result link identifier
- var $_isPersistentConnection = false; /// A boolean variable to state whether its a persistent connection or normal connection. */
- var $_bindInputArray = false; /// set to true if ADOConnection.Execute() permits binding of array parameters.
- var $_evalAll = false;
- var $_affected = false;
- var $_logsql = false;
- var $_transmode = ''; // transaction mode
- /*
- * Additional parameters that may be passed to drivers in the connect string
- * Driver must be coded to accept the parameters
- */
- protected $connectionParameters = array();
- /**
- * Adds a parameter to the connection string.
- *
- * These parameters are added to the connection string when connecting,
- * if the driver is coded to use it.
- *
- * @param string $parameter The name of the parameter to set
- * @param string $value The value of the parameter
- *
- * @return null
- *
- * @example, for mssqlnative driver ('CharacterSet','UTF-8')
- */
- final public function setConnectionParameter($parameter,$value)
- {
- $this->connectionParameters[$parameter] = $value;
- }
- static function Version() {
- global $ADODB_vers;
- // Semantic Version number matching regex
- $regex = '^[vV]?(\d+\.\d+\.\d+' // Version number (X.Y.Z) with optional 'V'
- . '(?:-(?:' // Optional preprod version: a '-'
- . 'dev|' // followed by 'dev'
- . '(?:(?:alpha|beta|rc)(?:\.\d+))' // or a preprod suffix and version number
- . '))?)(?:\s|$)'; // Whitespace or end of string
- if (!preg_match("/$regex/", $ADODB_vers, $matches)) {
- // This should normally not happen... Return whatever is between the start
- // of the string and the first whitespace (or the end of the string).
- self::outp("Invalid version number: '$ADODB_vers'", 'Version');
- $regex = '^[vV]?(.*?)(?:\s|$)';
- preg_match("/$regex/", $ADODB_vers, $matches);
- }
- return $matches[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.
- */
- static 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;
- }
- /**
- * Parses the hostname to extract the port.
- * Overwrites $this->host and $this->port, only if a port is specified.
- * The Hostname can be fully or partially qualified,
- * ie: "db.mydomain.com:5432" or "ldaps://ldap.mydomain.com:636"
- * Any specified scheme such as ldap:// or ldaps:// is maintained.
- */
- protected function parseHostNameAndPort() {
- $parsed_url = parse_url($this->host);
- if (is_array($parsed_url) && isset($parsed_url['host']) && isset($parsed_url['port'])) {
- if ( isset($parsed_url['scheme']) ) {
- // If scheme is specified (ie: ldap:// or ldaps://, make sure we retain that.
- $this->host = $parsed_url['scheme'] . "://" . $parsed_url['host'];
- } else {
- $this->host = $parsed_url['host'];
- }
- $this->port = $parsed_url['port'];
- }
- }
- /**
- * 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;
- }
- // Overwrites $this->host and $this->port if a port is specified.
- $this->parseHostNameAndPort();
- if ($argUsername != "") {
- $this->user = $argUsername;
- }
- if ($argPassword != "") {
- $this->password = 'not stored'; // not stored for security reasons
- }
- if ($argDatabaseName != "") {
- $this->database = $argDatabaseName;
- }
- $this->_isPersistentConnection = false;
- if ($forceNew) {
- if ($rez=$this->_nconnect($this->host, $this->user, $argPassword, $this->database)) {
- return true;
- }
- } else {
- if ($rez=$this->_connect($this->host, $this->user, $argPassword, $this->database)) {
- return true;
- }
- }
- if (isset($rez)) {
- $err = $this->ErrorMsg();
- $errno = $this->ErrorNo();
- if (empty($err)) {
- $err = "Connection error to server '$argHostname' with user '$argUsername'";
- }
- } else {
- $err = "Missing extension for ".$this->dataProvider;
- $errno = 0;
- }
- if ($fn = $this->raiseErrorFn) {
- $fn($this->databaseType, 'CONNECT', $errno, $err, $this->host, $this->database, $this);
- }
- $this->_connectionID = false;
- if ($this->debug) {
- ADOConnection::outp( $this->host.': '.$err);
- }
- return false;
- }
- 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;
- }
- // Overwrites $this->host and $this->port if a port is specified.
- $this->parseHostNameAndPort();
- if ($argUsername != "") {
- $this->user = $argUsername;
- }
- if ($argPassword != "") {
- $this->password = 'not stored';
- }
- if ($argDatabaseName != "") {
- $this->database = $argDatabaseName;
- }
- $this->_isPersistentConnection = true;
- if ($rez = $this->_pconnect($this->host, $this->user, $argPassword, $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;
- }
- function outp_throw($msg,$src='WARN',$sql='') {
- if (defined('ADODB_ERROR_HANDLER') && ADODB_ERROR_HANDLER == 'adodb_throw') {
- adodb_throw($this->databaseType,$src,-9999,$msg,$sql,false,$this);
- return;
- }
- ADOConnection::outp($msg);
- }
- // create cache class. Code is backward compat with old memcache implementation
- function _CreateCache() {
- global $ADODB_CACHE, $ADODB_CACHE_CLASS;
- if ($this->memCache) {
- global $ADODB_INCLUDED_MEMCACHE;
- if (empty($ADODB_INCLUDED_MEMCACHE)) {
- include_once(ADODB_DIR.'/adodb-memcache.lib.inc.php');
- }
- $ADODB_CACHE = new ADODB_Cache_MemCache($this);
- } else {
- $ADODB_CACHE = new $ADODB_CACHE_CLASS($this);
- }
- }
- // 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 && $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,$col='1 as adodbignore') {
- 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 a placeholder for query parameters
- * e.g. $DB->Param('a') will return
- * - '?' for most databases
- * - ':a' for Oracle
- * - '$1', '$2', etc. for PostgreSQL
- * @param string $name parameter's name, false to force a reset of the
- * number to 1 (for databases that require positioned
- * params such as PostgreSQL; note that ADOdb will
- * automatically reset this when executing a query )
- * @param string $type (unused)
- * @return string query parameter placeholder
- */
- 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;
- }
- function IgnoreErrors($saveErrs=false) {
- if (!$saveErrs) {
- $saveErrs = array($this->raiseErrorFn,$this->_transOK);
- $this->raiseErrorFn = false;
- return $saveErrs;
- } else {
- $this->raiseErrorFn = $saveErrs[0];
- $this->_transOK = $saveErrs[1];
- }
- }
- /**
- * 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 true;
- }
- $this->_oldRaiseFn = $this->raiseErrorFn;
- $this->raiseErrorFn = $errfn;
- $this->_transOK = true;
- if ($this->debug && $this->transCnt > 0) {
- ADOConnection::outp("Bad Transaction: StartTrans called within BeginTrans");
- }
- $ok = $this->BeginTrans();
- $this->transOff = 1;
- return $ok;
- }
- /**
- 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 !== false) {
- if (!is_array($inputarr)) {
- $inputarr = array($inputarr);
- }
- $element0 = reset($inputarr);
- # is_object check because oci8 descriptors can be passed in
- $array_2d = $this->bulkBind && is_array($element0) && !is_object(reset($element0));
- //remove extra memory copy of input -mikefedyk
- unset($element0);
- if (!is_array($sql) && !$this->_bindInputArray) {
- // @TODO this would consider a '?' within a string as a parameter...
- $sqlarr = explode('?',$sql);
- $nparams = sizeof($sqlarr)-1;
- if (!$array_2d) {
- // When not Bind Bulk - convert to array of arguments list
- $inputarr = array($inputarr);
- } else {
- // Bulk bind - Make sure all list of params have the same number of elements
- $countElements = array_map('count', $inputarr);
- if (1 != count(array_unique($countElements))) {
- $this->outp_throw(
- "[bulk execute] Input array has different number of params [" . print_r($countElements, true) . "].",
- 'Execute'
- );
- return false;
- }
- unset($countElements);
- }
- // Make sure the number of parameters provided in the input
- // array matches what the query expects
- $element0 = reset($inputarr);
- if ($nparams != count($element0)) {
- $this->outp_throw(
- "Input array has " . count($element0) .
- " params, does not match query: '" . htmlspecialchars($sql) . "'",
- 'Execute'
- );
- return false;
- }
- // clean memory
- unset($element0);
- foreach($inputarr as $arr) {
- $sql = ''; $i = 0;
- foreach ($arr as $v) {
- $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 ($typ == 'object') {
- if (method_exists($v, '__toString')) {
- $sql .= $this->qstr($v->__toString());
- } else {
- $sql .= $this->qstr((string) $v);
- }
- } else if ($v === null) {
- $sql .= 'NULL';
- } else {
- $sql .= $v;
- }
- $i += 1;
- if ($i == $nparams) {
- break;
- }
- } // while
- if (isset($sqlarr[$i])) {
- $sql .= $sqlarr[$i];
- if ($i+1 != sizeof($sqlarr)) {
- $this->outp_throw( "Input Array does not match ?: ".htmlspecialchars($sql),'Execute');
- }
- } else if ($i != sizeof($sqlarr)) {
- $this->outp_throw( "Input array does not match ?: ".htmlspecialchars($sql),'Execute');
- }
- $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) {
- // ExecuteCursor() may send non-string queries (such as arrays),
- // so we need to ignore those.
- if( is_string($sql) ) {
- // Strips keyword used to help generate SELECT COUNT(*) queries
- // from SQL if it exists.
- $sql = ADODB_str_replace( '_ADODB_COUNT', '', $sql );
- }
- 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
- // ************************
- // error handling if query fails
- if ($this->_queryID === false) {
- if ($this->debug == 99) {
- adodb_backtrace(true,5);
- }
- $fn = $this->raiseErrorFn;
- if ($fn) {
- $fn($this->databaseType,'EXECUTE',$this->ErrorNo(),$this->ErrorMsg(),$sql,$inputarr,$this);
- }
- return false;
- }
- // return simplified recordset for inserts/updates/deletes with lower overhead
- if ($this->_queryID === true) {
- $rsclass = $this->rsPrefix.'empty';
- $rs = (class_exists($rsclass)) ? new $rsclass(): 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) {
- $nrows = (int)$nrows;
- $offset = (int)$offset;
- 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.' '.$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.' '.$nrows.' ',$sql);
- } else {
- $sql = preg_replace(
- '/(^\s*select\s)/i','\\1 '.$this->hasTop.' '.$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 ($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) {
- 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) {
- 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) {
- 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,$ADODB_GETONE_EOF;
- $crecs = $ADODB_COUNTRECS;
- $ADODB_COU…
Large files files are truncated, but you can click here to view the full file