Unix Technical Forum

1064 error in mysql query

This is a discussion on 1064 error in mysql query within the MySQL forums, part of the Database Server Software category; --> Hello all, When I run this query in phpadmin, it runs fine and returns the expected result : ( ...


Go Back   Unix Technical Forum > Database Server Software > MySQL

Register FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 03-04-2008, 06:24 AM
J
 
Posts: n/a
Default 1064 error in mysql query

Hello all,
When I run this query in phpadmin, it runs fine and returns the
expected result :

( SELECT s1.GRADE, FIRSTNAME, s1.MILES FROM paws s1 JOIN ( SELECT
kmclaurin.paws.GRADE, MAX(kmclaurin.paws.MILES) AS MILES FROM
kmclaurin.paws GROUP BY kmclaurin.paws.GRADE ) AS s2 ON s1.GRADE =
s2.GRADE AND s1.MILES = s2.MILES; SELECT s1.GRADE, s1.FIRSTNAME,
s1.MILES FROM kmclaurin.paws s1 LEFT JOIN paws s2 ON s1.GRADE =
s2.GRADE AND s1.MILES < s2.MILES WHERE s2.GRADE IS NULL ORDER BY GRADE
LIMIT 0 , 30


When I run the query from my .php program, it returns the following
error :
1064: You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near '; SELECT s1.GRADE, s1.FIRSTNAME, s1.MILES FROM kmclaurin.paws s1
LEFT JOIN ' at line 8

adodb_mysql._execute(SELECT s1.GRADE, FIRSTNAME, s1.MILES
FROM paws s1
JOIN (
SELECT kmclaurin.paws.GRADE, MAX(kmclaurin.paws.MILES) AS MILES
FRO..., false) % line 848, file: adodb.inc.php
adodb_mysql.execute(SELECT s1.GRADE, FIRSTNAME, s1.MILES
FROM paws s1
JOIN (
SELECT kmclaurin.paws.GRADE, MAX(kmclaurin.paws.MILES) AS MILES
FRO...) % line 108, file: TopsByGrade.php

Sorry for the length of this post, but I'm a novice and don't know
what is relavent.
Here is the adodb.inc.php referenced :
<?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.61 24 Feb 2005 (c) 2000-2005 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://php.weblogs.com/adodb<br>
Manual is at http://php.weblogs.com/adodb_manual

*/

if (!defined('_ADODB_LAYER')) {
define('_ADODB_LAYER',1);

//
================================================== ============================================
// CONSTANT DEFINITIONS
//
================================================== ============================================


/**
* Set ADODB_DIR to the directory where this file resides...
* This constant was formerly called $ADODB_RootPath
*/
if (!defined('ADODB_DIR')) define('ADODB_DIR',dirname(__FILE__));

//
================================================== ============================================
// GLOBAL VARIABLES
//
================================================== ============================================

GLOBAL
$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.61 24 Feb 2005 (c) 2000-2005 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 {
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_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
//
var $dataProvider = 'native';
var $databaseType = ''; /// RDBMS currently in use, eg. odbc, mysql,
mssql
var $database = ''; /// Name of database to be used.
var $host = ''; /// The hostname of the database server
var $user = ''; /// The username which is used to connect to the
database server.
var $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 operator
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 = '&nbsp;';
var $emptyTimeStamp = '&nbsp;';
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
var $sysDate = false; /// name of function that returns the current
date
var $sysTimeStamp = false; /// name of function that returns the
current timestamp
var $arrayClass = 'ADORecordSet_array'; /// name of class used to
generate array recordsets, which are pre-downloaded recordsets

var $noNullStrings = false; /// oracle specific stuff - if true
ensures that '' is converted to ' '
var $numCacheHits = 0;
var $numCacheMisses = 0;
var $pageExecuteCountRows = true;
var $uniqueSort = false; /// indicates that all fields in order by
must be unique
var $leftOuter = true; /// operator to use for left outer join in
WHERE clause
var $rightOuter = true; /// operator to use for right outer join in
WHERE clause
var $ansiOuter = true; /// whether ansi outer join syntax supported
var $autoRollback = false; // autoRollback on PConnect().
var $poorAffectedRows = false; // affectedRows not working or
unreliable

var $fnExecute = false;
var $fnCacheExecute = false;
var $blobEncodeType = false; // false=not required, 'I'=encode to
integer, 'C'=encode to char
var $rsPrefix = "ADORecordSet_";

var $autoCommit = true; /// do not modify this yourself - actually
private
var $transOff = 0; /// temporarily disable transactions
var $transCnt = 0; /// count of nested transactions

var $fetchMode=false;
//
// PRIVATE VARS
//
var $_oldRaiseFn = false;
var $_transOK = null;
var $_connectionID = false; /// The returned link identifier whenever
a successful database connection is made.
var $_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;



/**
* 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 $HTTP_SERVER_VARS,$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($HTTP_SERVER_VARS['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:utp( $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:utp( $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)
{
$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:utp("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:utp("Smart Commit failed");
} else
if ($this->debug) ADOConnection:utp("Smart Commit occurred");
} else {
$this->RollbackTrans();
if ($this->debug) ADOCOnnection:utp("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:utp("FailTrans outside StartTrans/CompleteTrans");
} else {
ADOConnection:utp("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));

if (!is_array($sql) && !$this->_bindInputArray) {
$sqlarr = explode('?',$sql);

if (!$array_2d) $inputarr = array($inputarr);
foreach($inputarr as $arr) {
$sql = ''; $i = 0;
foreach($arr as $v) {
$sql .= $sqlarr[$i];
// from Ron Baldwin <ron.baldwin#sourceprose.com>
// Only quote string types
$typ = gettype($v);
if ($typ == 'string')
$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 ($v === null)
$sql .= 'NULL';
else
$sql .= $v;
$i += 1;
}
if (isset($sqlarr[$i])) {
$sql .= $sqlarr[$i];
if ($i+1 != sizeof($sqlarr)) ADOConnection:utp( "Input Array
does not match ?: ".htmlspecialchars($sql));
} else if ($i != sizeof($sqlarr))
ADOConnection:utp( "Input array does not match ?:
".htmlspecialchars($sql));

$ret =& $this->_Execute($sql);
if (!$ret) return $ret;
}
} else {
if ($array_2d) {
$stmt = $this->Prepare($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_once(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;
@($rs = $this->Execute($getnext));
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:utp( '<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:utp( '<p>Affected_Rows error</
p>',false);
return false;
}


/**
* @return the last error message
*/
function ErrorMsg()
{
return '!! '.strtoupper($this->dataProvider.' '.$this-
>databaseType).': '.$this->_errorMsg;

}


/**
* @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.' '.$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 ($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')) return ADODB_PEAR_Error();
else {
$false = false;
return $false;
}
$arr =& $rs->GetArray();
$rs->Close();
return $arr;
}

function &CacheGetAll($secs2cache,$sql=false,$inputarr=fals e)
{
return $this->CacheGetArray($secs2cache,$sql,$inputarr);
}

function &CacheGetArray($secs2cache,$sql=false,$inputarr=fa lse)
{
global $ADODB_COUNTRECS;

$savec = $ADODB_COUNTRECS;
$ADODB_COUNTRECS = false;
$rs =& $this->CacheExecute($secs2cache,$sql,$inputarr);
$ADODB_COUNTRECS = $savec;

if (!$rs)
if (defined('ADODB_PEAR')) return ADODB_PEAR_Error();
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=fals e)
{
$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_once(ADODB_DIR.'/adodb-
lib.inc.php');

return _adodb_replace($this, $table, $fieldArray, $keyCol,
$autoQuote, $has_autoinc);
}


/**
* Will select, getting rows from $offset (1-based), for $nrows.
* 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,$th is-
>cacheSecs);

} else {
if ($sql === false) ADOConnection:utp( "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.
*/
function CacheFlush($sql=false,$inputarr=false)
{
global $ADODB_CACHE_DIR;

if (strlen($ADODB_CACHE_DIR) > 1 && !$sql) {
if (strncmp(PHP_OS,'WIN',3) === 0) {
$cmd = 'del /s '.str_replace('/','\\',
$ADODB_CACHE_DIR).'\adodb_*.cache';
} else {
//$cmd = 'find "'.$ADODB_CACHE_DIR.'" -type f -maxdepth 1 -print0
| xargs -0 rm -f';
$cmd = 'rm -rf '.$ADODB_CACHE_DIR.'/[0-9a-f][0-9a-f]/';
// old version 'rm -f `find '.$ADODB_CACHE_DIR.' -name
adodb_*.cache`';
}
if ($this->debug) {
ADOConnection:utp( "CacheFlush: $cmd<br><pre>\n",
system($cmd),"</pre>");
} else {
exec($cmd);
}
return;
}

global $ADODB_INCLUDED_CSV;
if (empty($ADODB_INCLUDED_CSV)) include_once(ADODB_DIR.'/adodb-
csvlib.inc.php');

$f = $this->_gencachename($sql.serialize($inputarr),false);
adodb_write_file($f,''); // is adodb_write_file needed?
if (!@unlink($f)) {
if ($this->debug) ADOConnection:utp( "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:utp( "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=fal se)
{
if (!is_numeric($secs2cache)) {
$inputarr = $sql;
$sql = $secs2cache;
$secs2cache = $this->cacheSecs;
}
global $ADODB_INCLUDED_CSV;
if (empty($ADODB_INCLUDED_CSV)) include_once(ADODB_DIR.'/adodb-
csvlib.inc.php');

if (is_array($sql)) $sql = $sql[0];

$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:utp("Please disable magic_quotes_runtime - it
corrupts cache files ");
}
if ($this->debug !== -1) ADOConnection:utp( " $md5file cache
failure: $err (see sql below)");
}

$rs = &$this->Execute($sql,$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:utp( " 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){
global $HTTP_SERVER_VARS;

$inBrowser = isset($HTTP_SERVER_VARS['HTTP_USER_AGENT']);
$ttl = $rs->timeCreated + $secs2cache - time();
$s = is_array($sql) ? $sql[0] : $sql;
if ($inBrowser) $s = '<i>'.htmlspecialchars($s).'</i>';

ADOConnection:utp( " $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)
{
//$flds = array_keys($fields_values);
//$fldstr = implode(', ',$flds);
$sql = 'SELECT * FROM '.$table;
if ($where!==FALSE) $sql .= ' WHERE '.$where;
else if ($mode == 'UPDATE') {
ADOConnection:utp('AutoExecute: Illegal mode=UPDATE with empty
WHERE clause');
return false;
}

$rs =& $this->SelectLimit($sql,1);
if (!$rs) return false; // table does not exist

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:utp("AutoExecute: Unknown mode=$mode");
return false;
}
if ($sql) return $this->Execute($sql);
return false;
}


/**
* 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_once(ADODB_DIR.'/adodb-
lib.inc.php');
return _adodb_getupdatesql($this,$rs,$arrFields,$forceUpd ate,$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_once(ADODB_DIR.'/adodb-
lib.inc.php');
return _adodb_getinsertsql($this,$rs,$arrFields,$magicq,$ force);
}


/**
* Update a blob column, given a where clause. There are more
sophisticated
* blob handling functions that we could have implemented, but all
require
* a very complex API. Instead we have chosen something that is
extremely
* simple to understand and use.
*
* 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='B LOB')
{
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,$blobty pe='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');
}


/**
* 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 ($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;
}
}


/**
* 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=f alse)
{
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 upper uppercase table name (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,$upper=true)
{
global $ADODB_FETCH_MODE;

$false = false;

if (!empty($this->metaColumnsSQL)) {

$schema = false;
$this->_findschema($table,$schema);

$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this-
>SetFetchMode(false);

$rs = $this->Execute(sprintf($this->metaColumnsSQL,($upper)?
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)
{
# 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);
}

/**
* 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_once(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,$secs2cac he);
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
{
var $dataProvider = 'empty';
var $databaseType = false;
var $EOF = true;
var $_numOfRows = 0;
var $fields = false;
var $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
//
================================================== ============================================
include_once(ADODB_DIR.'/adodb-time.inc.php');

//
================================================== ============================================
// CLASS ADORecordSet
//
================================================== ============================================

if (PHP_VERSION < 5) include_once(ADODB_DIR.'/adodb-php4.inc.php');
else include_once(ADODB_DIR.'/adodb-iterator.inc.php');
/**
* 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
*/
var $dataProvider = "native";
var $fields = false; /// holds the current row data
var $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.
var $canSeek = false; /// indicates that seek is supported
var $sql; /// sql text
var $EOF = false; /// Indicates that the current record position is
after the last record in a Recordset object.

var $emptyTimeStamp = '&nbsp;'; /// what to display when $time==0
var $emptyDate = '&nbsp;'; /// what to display when $time==0
var $debug = false;
var $timeCreated=0; /// datetime in Unix format rs created -- for
cached recordsets

var $bind = false; /// used by Fields() to hold array - should be
private?
var $fetchMode; /// default fetch mode
var $connection = false; /// the parent connection
/*
* private variables
*/
var $_numOfRows = -1; /** number of rows, or -1 */
var $_numOfFields = -1; /** number of fields in recordset */
var $_queryID = -1; /** This variable keeps the result link
identifier. */
var $_currentRow = -1; /** This variable keeps the current row in the
Recordset. */
var $_closed = false; /** has recordset been closed */
var $_inited = false; /** Init() should only be called once */
var $_obj; /** Used by FetchObj */
var $_names; /** Used by FetchObj */

var $_currentPage = -1; /** Added by Iván Oliva toimplement
recordset pagination */
var $_atFirstPage = false; /** Added by Iván Olivato
implement recordset pagination */
var $_atLastPage = false; /** Added by Iván Oliva to implement
recordset pagination */
var $_lastPageNo = -1;
var $_maxRecordCount = 0;
var $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,$multi ple=false,
$size=0, $selectAttr='',$compareFields0=true)
{
global $ADODB_INCLUDED_LIB;
if (empty($ADODB_INCLUDED_LIB)) include_once(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,$mult iple=false,
$size=0, $selectAttr='')
{
global $ADODB_INCLUDED_LIB;
if (empty($ADODB_INCLUDED_LIB)) include_once(ADODB_DIR.'/adodb-
lib.inc.php');
return _adodb_getmenu($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) return
adodb_getall($this,$nRows);

$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();
}
}
}
}
return $results;
}


/**
*
* @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
*
* @ret