imported version 4.51 of ADOdb

This commit is contained in:
Ralf Becker 2004-07-31 13:09:39 +00:00
parent 3e3075e913
commit 0d70830fc3
98 changed files with 36159 additions and 0 deletions

View File

@ -0,0 +1,304 @@
<?php
// security - hide paths
if (!defined('ADODB_DIR')) die();
global $ADODB_INCLUDED_CSV;
$ADODB_INCLUDED_CSV = 1;
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Library for CSV serialization. This is used by the csv/proxy driver and is the
CacheExecute() serialization format.
==== NOTE ====
Format documented at http://php.weblogs.com/ADODB_CSV
==============
*/
/**
* convert a recordset into special format
*
* @param rs the recordset
*
* @return the CSV formated data
*/
function _rs2serialize(&$rs,$conn=false,$sql='')
{
$max = ($rs) ? $rs->FieldCount() : 0;
if ($sql) $sql = urlencode($sql);
// metadata setup
if ($max <= 0 || $rs->dataProvider == 'empty') { // is insert/update/delete
if (is_object($conn)) {
$sql .= ','.$conn->Affected_Rows();
$sql .= ','.$conn->Insert_ID();
} else
$sql .= ',,';
$text = "====-1,0,$sql\n";
return $text;
}
$tt = ($rs->timeCreated) ? $rs->timeCreated : time();
## changed format from ====0 to ====1
$line = "====1,$tt,$sql\n";
if ($rs->databaseType == 'array') {
$rows =& $rs->_array;
} else {
$rows = array();
while (!$rs->EOF) {
$rows[] = $rs->fields;
$rs->MoveNext();
}
}
for($i=0; $i < $max; $i++) {
$o =& $rs->FetchField($i);
$flds[] = $o;
}
$rs =& new ADORecordSet_array();
$rs->InitArrayFields($rows,$flds);
return $line.serialize($rs);
}
/**
* Open CSV file and convert it into Data.
*
* @param url file/ftp/http url
* @param err returns the error message
* @param timeout dispose if recordset has been alive for $timeout secs
*
* @return recordset, or false if error occured. If no
* error occurred in sql INSERT/UPDATE/DELETE,
* empty recordset is returned
*/
function &csv2rs($url,&$err,$timeout=0)
{
$err = false;
$fp = @fopen($url,'rb');
if (!$fp) {
$err = $url.' file/URL not found';
return false;
}
flock($fp, LOCK_SH);
$arr = array();
$ttl = 0;
if ($meta = fgetcsv($fp, 32000, ",")) {
// check if error message
if (strncmp($meta[0],'****',4) === 0) {
$err = trim(substr($meta[0],4,1024));
fclose($fp);
return false;
}
// check for meta data
// $meta[0] is -1 means return an empty recordset
// $meta[1] contains a time
if (strncmp($meta[0], '====',4) === 0) {
if ($meta[0] == "====-1") {
if (sizeof($meta) < 5) {
$err = "Corrupt first line for format -1";
fclose($fp);
return false;
}
fclose($fp);
if ($timeout > 0) {
$err = " Illegal Timeout $timeout ";
return false;
}
$rs->fields = array();
$rs->timeCreated = $meta[1];
$rs =& new ADORecordSet($val=true);
$rs->EOF = true;
$rs->_numOfFields=0;
$rs->sql = urldecode($meta[2]);
$rs->affectedrows = (integer)$meta[3];
$rs->insertid = $meta[4];
return $rs;
}
# Under high volume loads, we want only 1 thread/process to _write_file
# so that we don't have 50 processes queueing to write the same data.
# We use probabilistic timeout, ahead of time.
#
# -4 sec before timeout, give processes 1/32 chance of timing out
# -2 sec before timeout, give processes 1/16 chance of timing out
# -1 sec after timeout give processes 1/4 chance of timing out
# +0 sec after timeout, give processes 100% chance of timing out
if (sizeof($meta) > 1) {
if($timeout >0){
$tdiff = (integer)( $meta[1]+$timeout - time());
if ($tdiff <= 2) {
switch($tdiff) {
case 4:
case 3:
if ((rand() & 31) == 0) {
fclose($fp);
$err = "Timeout 3";
return false;
}
break;
case 2:
if ((rand() & 15) == 0) {
fclose($fp);
$err = "Timeout 2";
return false;
}
break;
case 1:
if ((rand() & 3) == 0) {
fclose($fp);
$err = "Timeout 1";
return false;
}
break;
default:
fclose($fp);
$err = "Timeout 0";
return false;
} // switch
} // if check flush cache
}// (timeout>0)
$ttl = $meta[1];
}
//================================================
// new cache format - use serialize extensively...
if ($meta[0] === '====1') {
// slurp in the data
$MAXSIZE = 128000;
$text = fread($fp,$MAXSIZE);
if (strlen($text)) {
while ($txt = fread($fp,$MAXSIZE)) {
$text .= $txt;
}
}
fclose($fp);
$rs = unserialize($text);
if (is_object($rs)) $rs->timeCreated = $ttl;
else {
$err = "Unable to unserialize recordset";
//echo htmlspecialchars($text),' !--END--!<p>';
}
return $rs;
}
$meta = false;
$meta = fgetcsv($fp, 32000, ",");
if (!$meta) {
fclose($fp);
$err = "Unexpected EOF 1";
return false;
}
}
// Get Column definitions
$flds = array();
foreach($meta as $o) {
$o2 = explode(':',$o);
if (sizeof($o2)!=3) {
$arr[] = $meta;
$flds = false;
break;
}
$fld =& new ADOFieldObject();
$fld->name = urldecode($o2[0]);
$fld->type = $o2[1];
$fld->max_length = $o2[2];
$flds[] = $fld;
}
} else {
fclose($fp);
$err = "Recordset had unexpected EOF 2";
return false;
}
// slurp in the data
$MAXSIZE = 128000;
$text = '';
while ($txt = fread($fp,$MAXSIZE)) {
$text .= $txt;
}
fclose($fp);
@$arr = unserialize($text);
//var_dump($arr);
if (!is_array($arr)) {
$err = "Recordset had unexpected EOF (in serialized recordset)";
if (get_magic_quotes_runtime()) $err .= ". Magic Quotes Runtime should be disabled!";
return false;
}
$rs =& new ADORecordSet_array();
$rs->timeCreated = $ttl;
$rs->InitArrayFields($arr,$flds);
return $rs;
}
/**
* Save a file $filename and its $contents (normally for caching) with file locking
*/
function adodb_write_file($filename, $contents,$debug=false)
{
# http://www.php.net/bugs.php?id=9203 Bug that flock fails on Windows
# So to simulate locking, we assume that rename is an atomic operation.
# First we delete $filename, then we create a $tempfile write to it and
# rename to the desired $filename. If the rename works, then we successfully
# modified the file exclusively.
# What a stupid need - having to simulate locking.
# Risks:
# 1. $tempfile name is not unique -- very very low
# 2. unlink($filename) fails -- ok, rename will fail
# 3. adodb reads stale file because unlink fails -- ok, $rs timeout occurs
# 4. another process creates $filename between unlink() and rename() -- ok, rename() fails and cache updated
if (strncmp(PHP_OS,'WIN',3) === 0) {
// skip the decimal place
$mtime = substr(str_replace(' ','_',microtime()),2);
// getmypid() actually returns 0 on Win98 - never mind!
$tmpname = $filename.uniqid($mtime).getmypid();
if (!($fd = fopen($tmpname,'a'))) return false;
$ok = ftruncate($fd,0);
if (!fwrite($fd,$contents)) $ok = false;
fclose($fd);
chmod($tmpname,0644);
// the tricky moment
@unlink($filename);
if (!@rename($tmpname,$filename)) {
unlink($tmpname);
$ok = false;
}
if (!$ok) {
if ($debug) ADOConnection::outp( " Rename $tmpname ".($ok? 'ok' : 'failed'));
}
return $ok;
}
if (!($fd = fopen($filename, 'a'))) return false;
if (flock($fd, LOCK_EX) && ftruncate($fd, 0)) {
$ok = fwrite( $fd, $contents );
fclose($fd);
chmod($filename,0644);
}else {
fclose($fd);
if ($debug)ADOConnection::outp( " Failed acquiring lock for $filename<br>\n");
$ok = false;
}
return $ok;
}
?>

View File

@ -0,0 +1,674 @@
<?php
/**
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
DOCUMENTATION:
See adodb/tests/test-datadict.php for docs and examples.
*/
/*
Test script for parser
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
function Lens_ParseTest()
{
$str = "`zcol ACOL` NUMBER(32,2) DEFAULT 'The \"cow\" (and Jim''s dog) jumps over the moon' PRIMARY, INTI INT AUTO DEFAULT 0";
print "<p>$str</p>";
$a= Lens_ParseArgs($str);
print "<pre>";
print_r($a);
print "</pre>";
}
if (!function_exists('ctype_alnum')) {
function ctype_alnum($text) {
return preg_match('/^[a-z0-9]*$/i', $text);
}
}
//Lens_ParseTest();
/**
Parse arguments, treat "text" (text) and 'text' as quotation marks.
To escape, use "" or '' or ))
Will read in "abc def" sans quotes, as: abc def
Same with 'abc def'.
However if `abc def`, then will read in as `abc def`
@param endstmtchar Character that indicates end of statement
@param tokenchars Include the following characters in tokens apart from A-Z and 0-9
@returns 2 dimensional array containing parsed tokens.
*/
function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-')
{
$pos = 0;
$intoken = false;
$stmtno = 0;
$endquote = false;
$tokens = array();
$tokens[$stmtno] = array();
$max = strlen($args);
$quoted = false;
while ($pos < $max) {
$ch = substr($args,$pos,1);
switch($ch) {
case ' ':
case "\t":
case "\n":
case "\r":
if (!$quoted) {
if ($intoken) {
$intoken = false;
$tokens[$stmtno][] = implode('',$tokarr);
}
break;
}
$tokarr[] = $ch;
break;
case '`':
if ($intoken) $tokarr[] = $ch;
case '(':
case ')':
case '"':
case "'":
if ($intoken) {
if (empty($endquote)) {
$tokens[$stmtno][] = implode('',$tokarr);
if ($ch == '(') $endquote = ')';
else $endquote = $ch;
$quoted = true;
$intoken = true;
$tokarr = array();
} else if ($endquote == $ch) {
$ch2 = substr($args,$pos+1,1);
if ($ch2 == $endquote) {
$pos += 1;
$tokarr[] = $ch2;
} else {
$quoted = false;
$intoken = false;
$tokens[$stmtno][] = implode('',$tokarr);
$endquote = '';
}
} else
$tokarr[] = $ch;
}else {
if ($ch == '(') $endquote = ')';
else $endquote = $ch;
$quoted = true;
$intoken = true;
$tokarr = array();
if ($ch == '`') $tokarr[] = '`';
}
break;
default:
if (!$intoken) {
if ($ch == $endstmtchar) {
$stmtno += 1;
$tokens[$stmtno] = array();
break;
}
$intoken = true;
$quoted = false;
$endquote = false;
$tokarr = array();
}
if ($quoted) $tokarr[] = $ch;
else if (ctype_alnum($ch) || strpos($tokenchars,$ch) !== false) $tokarr[] = $ch;
else {
if ($ch == $endstmtchar) {
$tokens[$stmtno][] = implode('',$tokarr);
$stmtno += 1;
$tokens[$stmtno] = array();
$intoken = false;
$tokarr = array();
break;
}
$tokens[$stmtno][] = implode('',$tokarr);
$tokens[$stmtno][] = $ch;
$intoken = false;
}
}
$pos += 1;
}
return $tokens;
}
class ADODB_DataDict {
var $connection;
var $debug = false;
var $dropTable = 'DROP TABLE %s';
var $dropIndex = 'DROP INDEX %s';
var $addCol = ' ADD';
var $alterCol = ' ALTER COLUMN';
var $dropCol = ' DROP COLUMN';
var $nameRegex = '\w';
var $schema = false;
var $serverInfo = array();
var $autoIncrement = false;
var $dataProvider;
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 editting.
function GetCommentSQL($table,$col)
{
return false;
}
function SetCommentSQL($table,$col,$cmt)
{
return false;
}
function &MetaTables()
{
return $this->connection->MetaTables();
}
function &MetaColumns($tab, $upper=true, $schema=false)
{
return $this->connection->MetaColumns($this->TableName($tab), $upper, $schema);
}
function &MetaPrimaryKeys($tab,$owner=false,$intkey=false)
{
return $this->connection->MetaPrimaryKeys($this->TableName($tab), $owner, $intkey);
}
function &MetaIndexes($table, $primary = false, $owner = false)
{
return $this->connection->MetaIndexes($this->TableName($table), $primary, $owner);
}
function MetaType($t,$len=-1,$fieldobj=false)
{
return ADORecordSet::MetaType($t,$len,$fieldobj);
}
function NameQuote($name = NULL)
{
if (!is_string($name)) {
return FALSE;
}
$name = trim($name);
if ( !is_object($this->connection) ) {
return $name;
}
$quote = $this->connection->nameQuote;
// if name is of the form `name`, quote it
if ( preg_match('/^`(.+)`$/', $name, $matches) ) {
return $quote . $matches[1] . $quote;
}
// if name contains special characters, quote it
if ( !preg_match('/^[' . $this->nameRegex . ']+$/', $name) ) {
return $quote . $name . $quote;
}
return $name;
}
function TableName($name)
{
if ( $this->schema ) {
return $this->NameQuote($this->schema) .'.'. $this->NameQuote($name);
}
return $this->NameQuote($name);
}
// Executes the sql array returned by GetTableSQL and GetIndexSQL
function ExecuteSQLArray($sql, $continueOnError = true)
{
$rez = 2;
$conn = &$this->connection;
$saved = $conn->debug;
foreach($sql as $line) {
if ($this->debug) $conn->debug = true;
$ok = $conn->Execute($line);
$conn->debug = $saved;
if (!$ok) {
if ($this->debug) ADOConnection::outp($conn->ErrorMsg());
if (!$continueOnError) return 0;
$rez = 1;
}
}
return $rez;
}
/*
Returns the actual type given a character code.
C: varchar
X: CLOB (character large object) or largest varchar size if CLOB is not supported
C2: Multibyte varchar
X2: Multibyte CLOB
B: BLOB (binary large object)
D: Date
T: Date-time
L: Integer field suitable for storing booleans (0 or 1)
I: Integer
F: Floating point number
N: Numeric or decimal number
*/
function ActualType($meta)
{
return $meta;
}
function CreateDatabase($dbname,$options=false)
{
$options = $this->_Options($options);
$sql = array();
$s = 'CREATE DATABASE ' . $this->NameQuote($dbname);
if (isset($options[$this->upperName]))
$s .= ' '.$options[$this->upperName];
$sql[] = $s;
return $sql;
}
/*
Generates the SQL to create index. Returns an array of sql strings.
*/
function CreateIndexSQL($idxname, $tabname, $flds, $idxoptions = false)
{
if (!is_array($flds)) {
$flds = explode(',',$flds);
}
foreach($flds as $key => $fld) {
$flds[$key] = $this->NameQuote($fld);
}
return $this->_IndexSQL($this->NameQuote($idxname), $this->TableName($tabname), $flds, $this->_Options($idxoptions));
}
function DropIndexSQL ($idxname, $tabname = NULL)
{
return array(sprintf($this->dropIndex, $this->NameQuote($idxname), $this->TableName($tabname)));
}
function SetSchema($schema)
{
$this->schema = $schema;
}
function AddColumnSQL($tabname, $flds)
{
$tabname = $this->TableName ($tabname);
$sql = array();
list($lines,$pkey) = $this->_GenFields($flds);
$alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' ';
foreach($lines as $v) {
$sql[] = $alter . $v;
}
return $sql;
}
function AlterColumnSQL($tabname, $flds)
{
$tabname = $this->TableName ($tabname);
$sql = array();
list($lines,$pkey) = $this->_GenFields($flds);
$alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' ';
foreach($lines as $v) {
$sql[] = $alter . $v;
}
return $sql;
}
function DropColumnSQL($tabname, $flds)
{
$tabname = $this->TableName ($tabname);
if (!is_array($flds)) $flds = explode(',',$flds);
$sql = array();
$alter = 'ALTER TABLE ' . $tabname . $this->dropCol . ' ';
foreach($flds as $v) {
$sql[] = $alter . $this->NameQuote($v);
}
return $sql;
}
function DropTableSQL($tabname)
{
return array (sprintf($this->dropTable, $this->TableName($tabname)));
}
/*
Generate the SQL to create table. Returns an array of sql strings.
*/
function CreateTableSQL($tabname, $flds, $tableoptions=false)
{
if (!$tableoptions) $tableoptions = array();
list($lines,$pkey) = $this->_GenFields($flds);
$taboptions = $this->_Options($tableoptions);
$tabname = $this->TableName ($tabname);
$sql = $this->_TableSQL($tabname,$lines,$pkey,$taboptions);
$tsql = $this->_Triggers($tabname,$taboptions);
foreach($tsql as $s) $sql[] = $s;
return $sql;
}
function _GenFields($flds)
{
if (is_string($flds)) {
$padding = ' ';
$txt = $flds.$padding;
$flds = array();
$flds0 = Lens_ParseArgs($txt,',');
$hasparam = false;
foreach($flds0 as $f0) {
$f1 = array();
foreach($f0 as $token) {
switch (strtoupper($token)) {
case 'CONSTRAINT':
case 'DEFAULT':
$hasparam = $token;
break;
default:
if ($hasparam) $f1[$hasparam] = $token;
else $f1[] = $token;
$hasparam = false;
break;
}
}
$flds[] = $f1;
}
}
$this->autoIncrement = false;
$lines = array();
$pkey = array();
foreach($flds as $fld) {
$fld = _array_change_key_case($fld);
$fname = false;
$fdefault = false;
$fautoinc = false;
$ftype = false;
$fsize = false;
$fprec = false;
$fprimary = false;
$fnoquote = false;
$fdefts = false;
$fdefdate = false;
$fconstraint = false;
$fnotnull = false;
$funsigned = false;
//-----------------
// Parse attributes
foreach($fld as $attr => $v) {
if ($attr == 2 && is_numeric($v)) $attr = 'SIZE';
else if (is_numeric($attr) && $attr > 1 && !is_numeric($v)) $attr = strtoupper($v);
switch($attr) {
case '0':
case 'NAME': $fname = $v; break;
case '1':
case 'TYPE': $ty = $v; $ftype = $this->ActualType(strtoupper($v)); break;
case 'SIZE':
$dotat = strpos($v,'.'); if ($dotat === false) $dotat = strpos($v,',');
if ($dotat === false) $fsize = $v;
else {
$fsize = substr($v,0,$dotat);
$fprec = substr($v,$dotat+1);
}
break;
case 'UNSIGNED': $funsigned = true; break;
case 'AUTOINCREMENT':
case 'AUTO': $fautoinc = true; $fnotnull = true; break;
case 'KEY':
case 'PRIMARY': $fprimary = $v; $fnotnull = true; break;
case 'DEF':
case 'DEFAULT': $fdefault = $v; break;
case 'NOTNULL': $fnotnull = $v; break;
case 'NOQUOTE': $fnoquote = $v; break;
case 'DEFDATE': $fdefdate = $v; break;
case 'DEFTIMESTAMP': $fdefts = $v; break;
case 'CONSTRAINT': $fconstraint = $v; break;
} //switch
} // foreach $fld
//--------------------
// VALIDATE FIELD INFO
if (!strlen($fname)) {
if ($this->debug) ADOConnection::outp("Undefined NAME");
return false;
}
$fid = strtoupper(preg_replace('/^`(.+)`$/', '$1', $fname));
$fname = $this->NameQuote($fname);
if (!strlen($ftype)) {
if ($this->debug) ADOConnection::outp("Undefined TYPE for field '$fname'");
return false;
} else {
$ftype = strtoupper($ftype);
}
$ftype = $this->_GetSize($ftype, $ty, $fsize, $fprec);
if ($ty == 'X' || $ty == 'X2' || $ty == 'B') $fnotnull = false; // some blob types do not accept nulls
if ($fprimary) $pkey[] = $fname;
// some databases do not allow blobs to have defaults
if ($ty == 'X') $fdefault = false;
//--------------------
// CONSTRUCT FIELD SQL
if ($fdefts) {
if (substr($this->connection->databaseType,0,5) == 'mysql') {
$ftype = 'TIMESTAMP';
} else {
$fdefault = $this->connection->sysTimeStamp;
}
} else if ($fdefdate) {
if (substr($this->connection->databaseType,0,5) == 'mysql') {
$ftype = 'TIMESTAMP';
} else {
$fdefault = $this->connection->sysDate;
}
} else if (strlen($fdefault) && !$fnoquote)
if ($ty == 'C' or $ty == 'X' or
( substr($fdefault,0,1) != "'" && !is_numeric($fdefault)))
if (strlen($fdefault) != 1 && substr($fdefault,0,1) == ' ' && substr($fdefault,strlen($fdefault)-1) == ' ')
$fdefault = trim($fdefault);
else if (strtolower($fdefault) != 'null')
$fdefault = $this->connection->qstr($fdefault);
$suffix = $this->_CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned);
$fname = str_pad($fname,16);
$lines[$fid] = $fname.' '.$ftype.$suffix;
if ($fautoinc) $this->autoIncrement = true;
} // foreach $flds
return array($lines,$pkey);
}
/*
GENERATE THE SIZE PART OF THE DATATYPE
$ftype is the actual type
$ty is the type defined originally in the DDL
*/
function _GetSize($ftype, $ty, $fsize, $fprec)
{
if (strlen($fsize) && $ty != 'X' && $ty != 'B' && strpos($ftype,'(') === false) {
$ftype .= "(".$fsize;
if (strlen($fprec)) $ftype .= ",".$fprec;
$ftype .= ')';
}
return $ftype;
}
// return string must begin with space
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint)
{
$suffix = '';
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fnotnull) $suffix .= ' NOT NULL';
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
{
$sql = array();
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
$sql[] = sprintf ($this->dropIndex, $idxname);
if ( isset($idxoptions['DROP']) )
return $sql;
}
if ( empty ($flds) ) {
return $sql;
}
$unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
$s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' ';
if ( isset($idxoptions[$this->upperName]) )
$s .= $idxoptions[$this->upperName];
if ( is_array($flds) )
$flds = implode(', ',$flds);
$s .= '(' . $flds . ')';
$sql[] = $s;
return $sql;
}
function _DropAutoIncrement($tabname)
{
return false;
}
function _TableSQL($tabname,$lines,$pkey,$tableoptions)
{
$sql = array();
if (isset($tableoptions['REPLACE']) || isset ($tableoptions['DROP'])) {
$sql[] = sprintf($this->dropTable,$tabname);
if ($this->autoIncrement) {
$sInc = $this->_DropAutoIncrement($tabname);
if ($sInc) $sql[] = $sInc;
}
if ( isset ($tableoptions['DROP']) ) {
return $sql;
}
}
$s = "CREATE TABLE $tabname (\n";
$s .= implode(",\n", $lines);
if (sizeof($pkey)>0) {
$s .= ",\n PRIMARY KEY (";
$s .= implode(", ",$pkey).")";
}
if (isset($tableoptions['CONSTRAINTS']))
$s .= "\n".$tableoptions['CONSTRAINTS'];
if (isset($tableoptions[$this->upperName.'_CONSTRAINTS']))
$s .= "\n".$tableoptions[$this->upperName.'_CONSTRAINTS'];
$s .= "\n)";
if (isset($tableoptions[$this->upperName])) $s .= $tableoptions[$this->upperName];
$sql[] = $s;
return $sql;
}
/*
GENERATE TRIGGERS IF NEEDED
used when table has auto-incrementing field that is emulated using triggers
*/
function _Triggers($tabname,$taboptions)
{
return array();
}
/*
Sanitize options, so that array elements with no keys are promoted to keys
*/
function _Options($opts)
{
if (!is_array($opts)) return array();
$newopts = array();
foreach($opts as $k => $v) {
if (is_numeric($k)) $newopts[strtoupper($v)] = $v;
else $newopts[strtoupper($k)] = $v;
}
return $newopts;
}
/*
"Florian Buzin [ easywe ]" <florian.buzin@easywe.de>
This function changes/adds new fields to your table. You don't
have to know if the col is new or not. It will check on its own.
*/
function ChangeTableSQL($tablename, $flds, $tableoptions = false)
{
// check table exists
$cols = &$this->MetaColumns($tablename);
if ( empty($cols)) {
return $this->CreateTableSQL($tablename, $flds, $tableoptions);
}
// already exists, alter table instead
list($lines,$pkey) = $this->_GenFields($flds);
$alter = 'ALTER TABLE ' . $this->TableName($tablename);
$sql = array();
foreach ( $lines as $id => $v ) {
if ( isset($cols[$id]) && is_object($cols[$id]) ) {
$sql[] = $alter . $this->alterCol . ' ' . $v;
} else {
$sql[] = $alter . $this->addCol . ' ' . $v;
}
}
return $sql;
}
} // class
?>

View File

@ -0,0 +1,79 @@
<?php
/**
* @version V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
* Released under both BSD license and Lesser GPL library license.
* Whenever there is any discrepancy between the two licenses,
* the BSD license will take precedence.
*
* Set tabs to 4 for best viewing.
*
* Latest version is available at http://php.weblogs.com
*
*/
// added Claudio Bustos clbustos#entelchile.net
if (!defined('ADODB_ERROR_HANDLER_TYPE')) define('ADODB_ERROR_HANDLER_TYPE',E_USER_ERROR);
define('ADODB_ERROR_HANDLER','ADODB_Error_Handler');
/**
* Default Error Handler. This will be called with the following params
*
* @param $dbms the RDBMS you are connecting to
* @param $fn the name of the calling function (in uppercase)
* @param $errno the native error number from the database
* @param $errmsg the native error msg from the database
* @param $p1 $fn specific parameter - see below
* @param $p2 $fn specific parameter - see below
* @param $thisConn $current connection object - can be false if no connection object created
*/
function ADODB_Error_Handler($dbms, $fn, $errno, $errmsg, $p1, $p2, &$thisConnection)
{
if (error_reporting() == 0) return; // obey @ protocol
switch($fn) {
case 'EXECUTE':
$sql = $p1;
$inputparams = $p2;
$s = "$dbms error: [$errno: $errmsg] in $fn(\"$sql\")\n";
break;
case 'PCONNECT':
case 'CONNECT':
$host = $p1;
$database = $p2;
$s = "$dbms error: [$errno: $errmsg] in $fn($host, '****', '****', $database)\n";
break;
default:
$s = "$dbms error: [$errno: $errmsg] in $fn($p1, $p2)\n";
break;
}
/*
* Log connection error somewhere
* 0 message is sent to PHP's system logger, using the Operating System's system
* logging mechanism or a file, depending on what the error_log configuration
* directive is set to.
* 1 message is sent by email to the address in the destination parameter.
* This is the only message type where the fourth parameter, extra_headers is used.
* This message type uses the same internal function as mail() does.
* 2 message is sent through the PHP debugging connection.
* This option is only available if remote debugging has been enabled.
* In this case, the destination parameter specifies the host name or IP address
* and optionally, port number, of the socket receiving the debug information.
* 3 message is appended to the file destination
*/
if (defined('ADODB_ERROR_LOG_TYPE')) {
$t = date('Y-m-d H:i:s');
if (defined('ADODB_ERROR_LOG_DEST'))
error_log("($t) $s", ADODB_ERROR_LOG_TYPE, ADODB_ERROR_LOG_DEST);
else
error_log("($t) $s", ADODB_ERROR_LOG_TYPE);
}
//print "<p>$s</p>";
trigger_error($s,ADODB_ERROR_HANDLER_TYPE);
}
?>

View File

@ -0,0 +1,79 @@
<?php
/**
* @version V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
* Released under both BSD license and Lesser GPL library license.
* Whenever there is any discrepancy between the two licenses,
* the BSD license will take precedence.
*
* Set tabs to 4 for best viewing.
*
* Latest version is available at http://php.weblogs.com
*
* Exception-handling code using PHP5 exceptions (try-catch-throw).
*/
if (!defined('ADODB_ERROR_HANDLER_TYPE')) define('ADODB_ERROR_HANDLER_TYPE',E_USER_ERROR);
define('ADODB_ERROR_HANDLER','adodb_throw');
class ADODB_Exception extends Exception {
var $dbms;
var $fn;
var $sql = '';
var $params = '';
var $host = '';
var $database = '';
function __construct($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection)
{
switch($fn) {
case 'EXECUTE':
$this->sql = $p1;
$this->params = $p2;
$s = "$dbms error: [$errno: $errmsg] in $fn(\"$p1\")\n";
break;
case 'PCONNECT':
case 'CONNECT':
$user = $thisConnection->user;
$s = "$dbms error: [$errno: $errmsg] in $fn($p1, '$user', '****', $p2)\n";
break;
default:
$s = "$dbms error: [$errno: $errmsg] in $fn($p1, $p2)\n";
break;
}
$this->dbms = $dbms;
$this->host = $thisConnection->host;
$this->database = $thisConnection->database;
$this->fn = $fn;
$this->msg = $errmsg;
if (!is_numeric($errno)) $errno = -1;
parent::__construct($s,$errno);
}
}
/**
* Default Error Handler. This will be called with the following params
*
* @param $dbms the RDBMS you are connecting to
* @param $fn the name of the calling function (in uppercase)
* @param $errno the native error number from the database
* @param $errmsg the native error msg from the database
* @param $p1 $fn specific parameter - see below
* @param $P2 $fn specific parameter - see below
*/
function adodb_throw($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection)
{
global $ADODB_EXCEPTION;
if (is_string($ADODB_EXCEPTION)) $errfn = $ADODB_EXCEPTION;
else $errfn = 'ADODB_EXCEPTION';
throw new $errfn($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection);
}
?>

View File

@ -0,0 +1,83 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4.
Declares the ADODB Base Class for PHP5 "ADODB_BASE_RS", and supports iteration with
the ADODB_Iterator class.
$rs = $db->Execute("select * from adoxyz");
foreach($rs as $k => $v) {
echo $k; print_r($v); echo "<br>";
}
Iterator code based on http://cvs.php.net/cvs.php/php-src/ext/spl/examples/cachingiterator.inc?login=2
*/
class ADODB_Iterator implements Iterator {
private $rs;
function __construct($rs)
{
$this->rs = $rs;
}
function rewind()
{
$this->rs->MoveFirst();
}
function valid()
{
return !$this->rs->EOF;
}
function key()
{
return $this->rs->_currentRow;
}
function current()
{
return $this->rs->fields;
}
function next()
{
$this->rs->MoveNext();
}
function __call($func, $params)
{
return call_user_func_array(array($this->rs, $func), $params);
}
function hasMore()
{
return !$this->rs->EOF;
}
}
class ADODB_BASE_RS implements IteratorAggregate {
function getIterator() {
return new ADODB_Iterator($this);
}
function __toString()
{
include_once(ADODB_DIR.'/toexport.inc.php');
return _adodb_export($this,',',',',false,true);
}
}
?>

View File

@ -0,0 +1,805 @@
<?php
// security - hide paths
if (!defined('ADODB_DIR')) die();
global $ADODB_INCLUDED_LIB;
$ADODB_INCLUDED_LIB = 1;
/*
@version V4.50 6 July 2004 (c) 2000-2004 John Lim (jlim\@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Less commonly used functions are placed here to reduce size of adodb.inc.php.
*/
// Force key to upper.
// See also http://www.php.net/manual/en/function.array-change-key-case.php
function _array_change_key_case($an_array)
{
if (is_array($an_array)) {
foreach($an_array as $key=>$value)
$new_array[strtoupper($key)] = $value;
return $new_array;
}
return $an_array;
}
function _adodb_replace(&$zthis, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc)
{
if (count($fieldArray) == 0) return 0;
$first = true;
$uSet = '';
if (!is_array($keyCol)) {
$keyCol = array($keyCol);
}
foreach($fieldArray as $k => $v) {
if ($autoQuote && !is_numeric($v) and strncmp($v,"'",1) !== 0 and strcasecmp($v,'null')!=0) {
$v = $zthis->qstr($v);
$fieldArray[$k] = $v;
}
if (in_array($k,$keyCol)) continue; // skip UPDATE if is key
if ($first) {
$first = false;
$uSet = "$k=$v";
} else
$uSet .= ",$k=$v";
}
$where = false;
foreach ($keyCol as $v) {
if ($where) $where .= " and $v=$fieldArray[$v]";
else $where = "$v=$fieldArray[$v]";
}
if ($uSet && $where) {
$update = "UPDATE $table SET $uSet WHERE $where";
$rs = $zthis->_Execute($update);
if ($rs) {
if ($zthis->poorAffectedRows) {
/*
The Select count(*) wipes out any errors that the update would have returned.
http://phplens.com/lens/lensforum/msgs.php?id=5696
*/
if ($zthis->ErrorNo()<>0) return 0;
# affected_rows == 0 if update field values identical to old values
# for mysql - which is silly.
$cnt = $zthis->GetOne("select count(*) from $table where $where");
if ($cnt > 0) return 1; // record already exists
} else {
if (($zthis->Affected_Rows()>0)) return 1;
}
}
}
// print "<p>Error=".$this->ErrorNo().'<p>';
$first = true;
foreach($fieldArray as $k => $v) {
if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col
if ($first) {
$first = false;
$iCols = "$k";
$iVals = "$v";
} else {
$iCols .= ",$k";
$iVals .= ",$v";
}
}
$insert = "INSERT INTO $table ($iCols) VALUES ($iVals)";
$rs = $zthis->_Execute($insert);
return ($rs) ? 2 : 0;
}
// Requires $ADODB_FETCH_MODE = ADODB_FETCH_NUM
function _adodb_getmenu(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
$size=0, $selectAttr='',$compareFields0=true)
{
$hasvalue = false;
if ($multiple or is_array($defstr)) {
if ($size==0) $size=5;
$attr = " multiple size=$size";
if (!strpos($name,'[]')) $name .= '[]';
} else if ($size) $attr = " size=$size";
else $attr ='';
$s = "<select name=\"$name\"$attr $selectAttr>";
if ($blank1stItem)
if (is_string($blank1stItem)) {
$barr = explode(':',$blank1stItem);
if (sizeof($barr) == 1) $barr[] = '';
$s .= "\n<option value=\"".$barr[0]."\">".$barr[1]."</option>";
} else $s .= "\n<option></option>";
if ($zthis->FieldCount() > 1) $hasvalue=true;
else $compareFields0 = true;
$value = '';
while(!$zthis->EOF) {
$zval = rtrim(reset($zthis->fields));
if (sizeof($zthis->fields) > 1) {
if (isset($zthis->fields[1]))
$zval2 = rtrim($zthis->fields[1]);
else
$zval2 = rtrim(next($zthis->fields));
}
$selected = ($compareFields0) ? $zval : $zval2;
if ($blank1stItem && $zval=="") {
$zthis->MoveNext();
continue;
}
if ($hasvalue)
$value = " value='".htmlspecialchars($zval2)."'";
if (is_array($defstr)) {
if (in_array($selected,$defstr))
$s .= "<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
else
$s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
}
else {
if (strcasecmp($selected,$defstr)==0)
$s .= "<option selected='selected'$value>".htmlspecialchars($zval).'</option>';
else
$s .= "\n<option".$value.'>'.htmlspecialchars($zval).'</option>';
}
$zthis->MoveNext();
} // while
return $s ."\n</select>\n";
}
/*
Count the number of records this sql statement will return by using
query rewriting techniques...
Does not work with UNIONs.
*/
function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0)
{
$qryRecs = 0;
if (preg_match("/^\s*SELECT\s+DISTINCT/is", $sql) || preg_match('/\s+GROUP\s+BY\s+/is',$sql)) {
// ok, has SELECT DISTINCT or GROUP BY so see if we can use a table alias
// but this is only supported by oracle and postgresql...
if ($zthis->dataProvider == 'oci8') {
$rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$sql);
$rewritesql = "SELECT COUNT(*) FROM ($rewritesql)";
} else if ( $zthis->databaseType == 'postgres' || $zthis->databaseType == 'postgres7') {
$info = $zthis->ServerInfo();
if (substr($info['version'],0,3) >= 7.1) { // good till version 999
$rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$sql);
$rewritesql = "SELECT COUNT(*) FROM ($rewritesql) _ADODB_ALIAS_";
}
}
} else {
// now replace SELECT ... FROM with SELECT COUNT(*) FROM
$rewritesql = preg_replace(
'/^\s*SELECT\s.*\s+FROM\s/Uis','SELECT COUNT(*) FROM ',$sql);
// fix by alexander zhukov, alex#unipack.ru, because count(*) and 'order by' fails
// with mssql, access and postgresql. Also a good speedup optimization - skips sorting!
$rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$rewritesql);
}
if (isset($rewritesql) && $rewritesql != $sql) {
if ($secs2cache) {
// we only use half the time of secs2cache because the count can quickly
// become inaccurate if new records are added
$qryRecs = $zthis->CacheGetOne($secs2cache/2,$rewritesql,$inputarr);
} else {
$qryRecs = $zthis->GetOne($rewritesql,$inputarr);
}
if ($qryRecs !== false) return $qryRecs;
}
//--------------------------------------------
// query rewrite failed - so try slower way...
// strip off unneeded ORDER BY if no UNION
if (preg_match('/\s*UNION\s*/is', $sql)) $rewritesql = $sql;
else $rewritesql = preg_replace('/(\sORDER\s+BY\s.*)/is','',$sql);
$rstest = &$zthis->_Execute($rewritesql,$inputarr);
if ($rstest) {
$qryRecs = $rstest->RecordCount();
if ($qryRecs == -1) {
global $ADODB_EXTENSION;
// some databases will return -1 on MoveLast() - change to MoveNext()
if ($ADODB_EXTENSION) {
while(!$rstest->EOF) {
adodb_movenext($rstest);
}
} else {
while(!$rstest->EOF) {
$rstest->MoveNext();
}
}
$qryRecs = $rstest->_currentRow;
}
$rstest->Close();
if ($qryRecs == -1) return 0;
}
return $qryRecs;
}
/*
Code originally from "Cornel G" <conyg@fx.ro>
This code will not work with SQL that has UNION in it
Also if you are using CachePageExecute(), there is a strong possibility that
data will get out of synch. use CachePageExecute() only with tables that
rarely change.
*/
function &_adodb_pageexecute_all_rows(&$zthis, $sql, $nrows, $page,
$inputarr=false, $secs2cache=0)
{
$atfirstpage = false;
$atlastpage = false;
$lastpageno=1;
// If an invalid nrows is supplied,
// we assume a default value of 10 rows per page
if (!isset($nrows) || $nrows <= 0) $nrows = 10;
$qryRecs = false; //count records for no offset
$qryRecs = _adodb_getcount($zthis,$sql,$inputarr,$secs2cache);
$lastpageno = (int) ceil($qryRecs / $nrows);
$zthis->_maxRecordCount = $qryRecs;
// ***** Here we check whether $page is the last page or
// whether we are trying to retrieve
// a page number greater than the last page number.
if ($page >= $lastpageno) {
$page = $lastpageno;
$atlastpage = true;
}
// If page number <= 1, then we are at the first page
if (empty($page) || $page <= 1) {
$page = 1;
$atfirstpage = true;
}
// We get the data we want
$offset = $nrows * ($page-1);
if ($secs2cache > 0)
$rsreturn = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
else
$rsreturn = &$zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
// Before returning the RecordSet, we set the pagination properties we need
if ($rsreturn) {
$rsreturn->_maxRecordCount = $qryRecs;
$rsreturn->rowsPerPage = $nrows;
$rsreturn->AbsolutePage($page);
$rsreturn->AtFirstPage($atfirstpage);
$rsreturn->AtLastPage($atlastpage);
$rsreturn->LastPageNo($lastpageno);
}
return $rsreturn;
}
// Iván Oliva version
function &_adodb_pageexecute_no_last_page(&$zthis, $sql, $nrows, $page, $inputarr=false, $secs2cache=0)
{
$atfirstpage = false;
$atlastpage = false;
if (!isset($page) || $page <= 1) { // If page number <= 1, then we are at the first page
$page = 1;
$atfirstpage = true;
}
if ($nrows <= 0) $nrows = 10; // If an invalid nrows is supplied, we assume a default value of 10 rows per page
// ***** Here we check whether $page is the last page or whether we are trying to retrieve a page number greater than
// the last page number.
$pagecounter = $page + 1;
$pagecounteroffset = ($pagecounter * $nrows) - $nrows;
if ($secs2cache>0) $rstest = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
else $rstest = &$zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
if ($rstest) {
while ($rstest && $rstest->EOF && $pagecounter>0) {
$atlastpage = true;
$pagecounter--;
$pagecounteroffset = $nrows * ($pagecounter - 1);
$rstest->Close();
if ($secs2cache>0) $rstest = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $pagecounteroffset, $inputarr);
else $rstest = &$zthis->SelectLimit($sql, $nrows, $pagecounteroffset, $inputarr, $secs2cache);
}
if ($rstest) $rstest->Close();
}
if ($atlastpage) { // If we are at the last page or beyond it, we are going to retrieve it
$page = $pagecounter;
if ($page == 1) $atfirstpage = true; // We have to do this again in case the last page is the same as the first
//... page, that is, the recordset has only 1 page.
}
// We get the data we want
$offset = $nrows * ($page-1);
if ($secs2cache > 0) $rsreturn = &$zthis->CacheSelectLimit($secs2cache, $sql, $nrows, $offset, $inputarr);
else $rsreturn = &$zthis->SelectLimit($sql, $nrows, $offset, $inputarr, $secs2cache);
// Before returning the RecordSet, we set the pagination properties we need
if ($rsreturn) {
$rsreturn->rowsPerPage = $nrows;
$rsreturn->AbsolutePage($page);
$rsreturn->AtFirstPage($atfirstpage);
$rsreturn->AtLastPage($atlastpage);
}
return $rsreturn;
}
function _adodb_getupdatesql(&$zthis,&$rs, $arrFields,$forceUpdate=false,$magicq=false,$forcenulls=false)
{
if (!$rs) {
printf(ADODB_BAD_RS,'GetUpdateSQL');
return false;
}
$fieldUpdatedCount = 0;
$arrFields = _array_change_key_case($arrFields);
$hasnumeric = isset($rs->fields[0]);
$setFields = '';
// Loop through all of the fields in the recordset
for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) {
// Get the field from the recordset
$field = $rs->FetchField($i);
// If the recordset field is one
// of the fields passed in then process.
$upperfname = strtoupper($field->name);
if (adodb_key_exists($upperfname,$arrFields,$forcenulls)) {
// If the existing field value in the recordset
// is different from the value passed in then
// go ahead and append the field name and new value to
// the update query.
if ($hasnumeric) $val = $rs->fields[$i];
else if (isset($rs->fields[$upperfname])) $val = $rs->fields[$upperfname];
else if (isset($rs->fields[$field->name])) $val = $rs->fields[$field->name];
else if (isset($rs->fields[strtolower($upperfname)])) $val = $rs->fields[strtolower($upperfname)];
else $val = '';
if ($forceUpdate || strcmp($val, $arrFields[$upperfname])) {
// Set the counter for the number of fields that will be updated.
$fieldUpdatedCount++;
// Based on the datatype of the field
// Format the value properly for the database
$type = $rs->MetaType($field->type);
// is_null requires php 4.0.4
if (($forcenulls && is_null($arrFields[$upperfname])) ||
$arrFields[$upperfname] === 'null') {
$setFields .= $field->name . " = null, ";
} else {
if ($type == 'null') {
$type = 'C';
}
if (strpos($upperfname,' ') !== false)
$fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;
else
$fnameq = $upperfname;
//we do this so each driver can customize the sql for
//DB specific column types.
//Oracle needs BLOB types to be handled with a returning clause
//postgres has special needs as well
$setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,
$arrFields, $magicq);
}
}
}
}
// If there were any modified fields then build the rest of the update query.
if ($fieldUpdatedCount > 0 || $forceUpdate) {
// Get the table name from the existing query.
preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName);
// Get the full where clause excluding the word "WHERE" from
// the existing query.
preg_match('/\sWHERE\s(.*)/is', $rs->sql, $whereClause);
$discard = false;
// not a good hack, improvements?
if ($whereClause) {
if (preg_match('/\s(ORDER\s.*)/is', $whereClause[1], $discard));
else preg_match('/\s(LIMIT\s.*)/is', $whereClause[1], $discard);
} else
$whereClause = array(false,false);
if ($discard)
$whereClause[1] = substr($whereClause[1], 0, strlen($whereClause[1]) - strlen($discard[1]));
$sql = 'UPDATE '.$tableName[1].' SET '.substr($setFields, 0, -2);
if (strlen($whereClause[1]) > 0)
$sql .= ' WHERE '.$whereClause[1];
return $sql;
} else {
return false;
}
}
function adodb_key_exists($key, &$arr,$forcenulls=false)
{
if (!$forcenulls) {
// the following is the old behaviour where null or empty fields are ignored
return (!empty($arr[$key])) || (isset($arr[$key]) && strlen($arr[$key])>0);
}
if (isset($arr[$key])) return true;
## null check below
if (ADODB_PHPVER >= 0x4010) return array_key_exists($key,$arr);
return false;
}
/**
* There is a special case of this function for the oci8 driver.
* The proper way to handle an insert w/ a blob in oracle requires
* a returning clause with bind variables and a descriptor blob.
*
*
*/
function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false,$forcenulls=false)
{
$tableName = '';
$values = '';
$fields = '';
$recordSet = null;
$arrFields = _array_change_key_case($arrFields);
$fieldInsertedCount = 0;
if (is_string($rs)) {
//ok we have a table name
//try and get the column info ourself.
$tableName = $rs;
//we need an object for the recordSet
//because we have to call MetaType.
//php can't do a $rsclass::MetaType()
$rsclass = $zthis->rsPrefix.$zthis->databaseType;
$recordSet =& new $rsclass(-1,$zthis->fetchMode);
$recordSet->connection = &$zthis;
$columns = $zthis->MetaColumns( $tableName );
} else if (is_subclass_of($rs, 'adorecordset')) {
for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++)
$columns[] = $rs->FetchField($i);
$recordSet =& $rs;
} else {
printf(ADODB_BAD_RS,'GetInsertSQL');
return false;
}
// Loop through all of the fields in the recordset
foreach( $columns as $field ) {
$upperfname = strtoupper($field->name);
if (adodb_key_exists($upperfname,$arrFields,$forcenulls)) {
// Set the counter for the number of fields that will be inserted.
$fieldInsertedCount++;
if (strpos($upperfname,' ') !== false)
$fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;
else
$fnameq = $upperfname;
// Get the name of the fields to insert
$fields .= $fnameq . ", ";
$type = $recordSet->MetaType($field->type);
if (($forcenulls && is_null($arrFields[$upperfname])) ||
$arrFields[$upperfname] === 'null') {
$values .= "null, ";
} else {
//we do this so each driver can customize the sql for
//DB specific column types.
//Oracle needs BLOB types to be handled with a returning clause
//postgres has special needs as well
$values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,
$arrFields, $magicq);
}
}
}
// If there were any inserted fields then build the rest of the insert query.
if ($fieldInsertedCount <= 0) return false;
// Get the table name from the existing query.
if (!$tableName) {
if (preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName))
$tableName = $tableName[1];
else
return false;
}
// Strip off the comma and space on the end of both the fields
// and their values.
$fields = substr($fields, 0, -2);
$values = substr($values, 0, -2);
// Append the fields and their values to the insert query.
return 'INSERT INTO '.$tableName.' ( '.$fields.' ) VALUES ( '.$values.' )';
}
/**
* This private method is used to help construct
* the update/sql which is generated by GetInsertSQL and GetUpdateSQL.
* It handles the string construction of 1 column -> sql string based on
* the column type. We want to do 'safe' handling of BLOBs
*
* @param string the type of sql we are trying to create
* 'I' or 'U'.
* @param string column data type from the db::MetaType() method
* @param string the column name
* @param array the column value
*
* @return string
*
*/
function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFields, $magicq)
{
$sql = '';
// Based on the datatype of the field
// Format the value properly for the database
switch($type) {
case 'B':
//in order to handle Blobs correctly, we need
//to do some magic for Oracle
//we need to create a new descriptor to handle
//this properly
if (!empty($zthis->hasReturningInto)) {
if ($action == 'I') {
$sql = 'empty_blob(), ';
} else {
$sql = $fnameq. '=empty_blob(), ';
}
//add the variable to the returning clause array
//so the user can build this later in
//case they want to add more to it
$zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
} else if (empty($arrFields[$fname])){
if ($action == 'I') {
$sql = 'empty_blob(), ';
} else {
$sql = $fnameq. '=empty_blob(), ';
}
} else {
//this is to maintain compatibility
//with older adodb versions.
$sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
}
break;
case "X":
//we need to do some more magic here for long variables
//to handle these correctly in oracle.
//create a safe bind var name
//to avoid conflicts w/ dupes.
if (!empty($zthis->hasReturningInto)) {
if ($action == 'I') {
$sql = ':xx'.$fname.'xx, ';
} else {
$sql = $fnameq.'=:xx'.$fname.'xx, ';
}
//add the variable to the returning clause array
//so the user can build this later in
//case they want to add more to it
$zthis->_returningArray[$fname] = ':xx'.$fname.'xx';
} else {
//this is to maintain compatibility
//with older adodb versions.
$sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
}
break;
default:
$sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
break;
}
return $sql;
}
function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, $recurse=true)
{
if ($recurse) {
switch($zthis->dataProvider) {
case 'postgres':
if ($type == 'L') $type = 'C';
break;
case 'oci8':
return _adodb_column_sql_oci8($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq);
}
}
$sql = '';
switch($type) {
case "C":
case "X":
case 'B':
if ($action == 'I') {
$sql = $zthis->qstr($arrFields[$fname],$magicq) . ", ";
} else {
$sql .= $fnameq . "=" . $zthis->qstr($arrFields[$fname],$magicq) . ", ";
}
break;
case "D":
if ($action == 'I') {
$sql = $zthis->DBDate($arrFields[$fname]) . ", ";
} else {
$sql .= $fnameq . "=" . $zthis->DBDate($arrFields[$fname]) . ", ";
}
break;
case "T":
if ($action == 'I') {
$sql = $zthis->DBTimeStamp($arrFields[$fname]) . ", ";
} else {
$sql .= $fnameq . "=" . $zthis->DBTimeStamp($arrFields[$fname]) . ", ";
}
break;
default:
$val = $arrFields[$fname];
if (empty($val)) $val = '0';
if ($action == 'I') {
$sql .= $val . ", ";
} else {
$sql .= $fnameq . "=" . $val . ", ";
}
break;
}
return $sql;
}
function _adodb_debug_execute(&$zthis, $sql, $inputarr)
{
global $HTTP_SERVER_VARS;
$ss = '';
if ($inputarr) {
foreach($inputarr as $kk=>$vv) {
if (is_string($vv) && strlen($vv)>64) $vv = substr($vv,0,64).'...';
$ss .= "($kk=>'$vv') ";
}
$ss = "[ $ss ]";
}
$sqlTxt = str_replace(',',', ',is_array($sql) ? $sql[0] : $sql);
// check if running from browser or command-line
$inBrowser = isset($HTTP_SERVER_VARS['HTTP_USER_AGENT']);
if ($inBrowser) {
$ss = htmlspecialchars($ss);
if ($zthis->debug === -1)
ADOConnection::outp( "<br>\n($zthis->databaseType): ".htmlspecialchars($sqlTxt)." &nbsp; <code>$ss</code>\n<br>\n",false);
else
ADOConnection::outp( "<hr>\n($zthis->databaseType): ".htmlspecialchars($sqlTxt)." &nbsp; <code>$ss</code>\n<hr>\n",false);
} else {
ADOConnection::outp("-----\n($zthis->databaseType): ".$sqlTxt."\n-----\n",false);
}
$qID = $zthis->_query($sql,$inputarr);
/*
Alexios Fakios notes that ErrorMsg() must be called before ErrorNo() for mssql
because ErrorNo() calls Execute('SELECT @ERROR'), causing recursion
*/
if ($zthis->databaseType == 'mssql') {
// ErrorNo is a slow function call in mssql, and not reliable in PHP 4.0.6
if($emsg = $zthis->ErrorMsg()) {
if ($err = $zthis->ErrorNo()) ADOConnection::outp($err.': '.$emsg);
}
} else if (!$qID) {
ADOConnection::outp($zthis->ErrorNo() .': '. $zthis->ErrorMsg());
}
return $qID;
}
function _adodb_backtrace($printOrArr=true,$levels=9999)
{
if (PHPVERSION() < 4.3) return '';
$html = (isset($_SERVER['HTTP_USER_AGENT']));
$fmt = ($html) ? "</font><font color=#808080 size=-1> %% line %4d, file: <a href=\"file:/%s\">%s</a></font>" : "%% line %4d, file: %s";
$MAXSTRLEN = 64;
$s = ($html) ? '<pre align=left>' : '';
if (is_array($printOrArr)) $traceArr = $printOrArr;
else $traceArr = debug_backtrace();
array_shift($traceArr);
array_shift($traceArr);
$tabs = sizeof($traceArr)-2;
foreach ($traceArr as $arr) {
$levels -= 1;
if ($levels < 0) break;
$args = array();
for ($i=0; $i < $tabs; $i++) $s .= ($html) ? ' &nbsp; ' : "\t";
$tabs -= 1;
if ($html) $s .= '<font face="Courier New,Courier">';
if (isset($arr['class'])) $s .= $arr['class'].'.';
if (isset($arr['args']))
foreach($arr['args'] as $v) {
if (is_null($v)) $args[] = 'null';
else if (is_array($v)) $args[] = 'Array['.sizeof($v).']';
else if (is_object($v)) $args[] = 'Object:'.get_class($v);
else if (is_bool($v)) $args[] = $v ? 'true' : 'false';
else {
$v = (string) @$v;
$str = htmlspecialchars(substr($v,0,$MAXSTRLEN));
if (strlen($v) > $MAXSTRLEN) $str .= '...';
$args[] = $str;
}
}
$s .= $arr['function'].'('.implode(', ',$args).')';
$s .= @sprintf($fmt, $arr['line'],$arr['file'],basename($arr['file']));
$s .= "\n";
}
if ($html) $s .= '</pre>';
if ($printOrArr) print $s;
return $s;
}
?>

View File

@ -0,0 +1,287 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
This class provides recordset pagination with
First/Prev/Next/Last links.
Feel free to modify this class for your own use as
it is very basic. To learn how to use it, see the
example in adodb/tests/testpaging.php.
"Pablo Costa" <pablo@cbsp.com.br> implemented Render_PageLinks().
Please note, this class is entirely unsupported,
and no free support requests except for bug reports
will be entertained by the author.
*/
class ADODB_Pager {
var $id; // unique id for pager (defaults to 'adodb')
var $db; // ADODB connection object
var $sql; // sql used
var $rs; // recordset generated
var $curr_page; // current page number before Render() called, calculated in constructor
var $rows; // number of rows per page
var $linksPerPage=10; // number of links per page in navigation bar
var $showPageLinks;
var $gridAttributes = 'width=100% border=1 bgcolor=white';
// Localize text strings here
var $first = '<code>|&lt;</code>';
var $prev = '<code>&lt;&lt;</code>';
var $next = '<code>>></code>';
var $last = '<code>>|</code>';
var $moreLinks = '...';
var $startLinks = '...';
var $gridHeader = false;
var $htmlSpecialChars = true;
var $page = 'Page';
var $linkSelectedColor = 'red';
var $cache = 0; #secs to cache with CachePageExecute()
//----------------------------------------------
// constructor
//
// $db adodb connection object
// $sql sql statement
// $id optional id to identify which pager,
// if you have multiple on 1 page.
// $id should be only be [a-z0-9]*
//
function ADODB_Pager(&$db,$sql,$id = 'adodb', $showPageLinks = false)
{
global $HTTP_SERVER_VARS,$PHP_SELF,$HTTP_SESSION_VARS,$HTTP_GET_VARS;
$curr_page = $id.'_curr_page';
if (empty($PHP_SELF)) $PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
$this->sql = $sql;
$this->id = $id;
$this->db = $db;
$this->showPageLinks = $showPageLinks;
$next_page = $id.'_next_page';
if (isset($HTTP_GET_VARS[$next_page])) {
$HTTP_SESSION_VARS[$curr_page] = $HTTP_GET_VARS[$next_page];
}
if (empty($HTTP_SESSION_VARS[$curr_page])) $HTTP_SESSION_VARS[$curr_page] = 1; ## at first page
$this->curr_page = $HTTP_SESSION_VARS[$curr_page];
}
//---------------------------
// Display link to first page
function Render_First($anchor=true)
{
global $PHP_SELF;
if ($anchor) {
?>
<a href="<?php echo $PHP_SELF,'?',$this->id;?>_next_page=1"><?php echo $this->first;?></a> &nbsp;
<?php
} else {
print "$this->first &nbsp; ";
}
}
//--------------------------
// Display link to next page
function render_next($anchor=true)
{
global $PHP_SELF;
if ($anchor) {
?>
<a href="<?php echo $PHP_SELF,'?',$this->id,'_next_page=',$this->rs->AbsolutePage() + 1 ?>"><?php echo $this->next;?></a> &nbsp;
<?php
} else {
print "$this->next &nbsp; ";
}
}
//------------------
// Link to last page
//
// for better performance with large recordsets, you can set
// $this->db->pageExecuteCountRows = false, which disables
// last page counting.
function render_last($anchor=true)
{
global $PHP_SELF;
if (!$this->db->pageExecuteCountRows) return;
if ($anchor) {
?>
<a href="<?php echo $PHP_SELF,'?',$this->id,'_next_page=',$this->rs->LastPageNo() ?>"><?php echo $this->last;?></a> &nbsp;
<?php
} else {
print "$this->last &nbsp; ";
}
}
//---------------------------------------------------
// original code by "Pablo Costa" <pablo@cbsp.com.br>
function render_pagelinks()
{
global $PHP_SELF;
$pages = $this->rs->LastPageNo();
$linksperpage = $this->linksPerPage ? $this->linksPerPage : $pages;
for($i=1; $i <= $pages; $i+=$linksperpage)
{
if($this->rs->AbsolutePage() >= $i)
{
$start = $i;
}
}
$numbers = '';
$end = $start+$linksperpage-1;
$link = $this->id . "_next_page";
if($end > $pages) $end = $pages;
if ($this->startLinks && $start > 1) {
$pos = $start - 1;
$numbers .= "<a href=$PHP_SELF?$link=$pos>$this->startLinks</a> ";
}
for($i=$start; $i <= $end; $i++) {
if ($this->rs->AbsolutePage() == $i)
$numbers .= "<font color=$this->linkSelectedColor><b>$i</b></font> ";
else
$numbers .= "<a href=$PHP_SELF?$link=$i>$i</a> ";
}
if ($this->moreLinks && $end < $pages)
$numbers .= "<a href=$PHP_SELF?$link=$i>$this->moreLinks</a> ";
print $numbers . ' &nbsp; ';
}
// Link to previous page
function render_prev($anchor=true)
{
global $PHP_SELF;
if ($anchor) {
?>
<a href="<?php echo $PHP_SELF,'?',$this->id,'_next_page=',$this->rs->AbsolutePage() - 1 ?>"><?php echo $this->prev;?></a> &nbsp;
<?php
} else {
print "$this->prev &nbsp; ";
}
}
//--------------------------------------------------------
// Simply rendering of grid. You should override this for
// better control over the format of the grid
//
// We use output buffering to keep code clean and readable.
function RenderGrid()
{
global $gSQLBlockRows; // used by rs2html to indicate how many rows to display
include_once(ADODB_DIR.'/tohtml.inc.php');
ob_start();
$gSQLBlockRows = $this->rows;
rs2html($this->rs,$this->gridAttributes,$this->gridHeader,$this->htmlSpecialChars);
$s = ob_get_contents();
ob_end_clean();
return $s;
}
//-------------------------------------------------------
// Navigation bar
//
// we use output buffering to keep the code easy to read.
function RenderNav()
{
ob_start();
if (!$this->rs->AtFirstPage()) {
$this->Render_First();
$this->Render_Prev();
} else {
$this->Render_First(false);
$this->Render_Prev(false);
}
if ($this->showPageLinks){
$this->Render_PageLinks();
}
if (!$this->rs->AtLastPage()) {
$this->Render_Next();
$this->Render_Last();
} else {
$this->Render_Next(false);
$this->Render_Last(false);
}
$s = ob_get_contents();
ob_end_clean();
return $s;
}
//-------------------
// This is the footer
function RenderPageCount()
{
if (!$this->db->pageExecuteCountRows) return '';
$lastPage = $this->rs->LastPageNo();
if ($lastPage == -1) $lastPage = 1; // check for empty rs.
if ($this->curr_page > $lastPage) $this->curr_page = 1;
return "<font size=-1>$this->page ".$this->curr_page."/".$lastPage."</font>";
}
//-----------------------------------
// Call this class to draw everything.
function Render($rows=10)
{
global $ADODB_COUNTRECS;
$this->rows = $rows;
$savec = $ADODB_COUNTRECS;
if ($this->db->pageExecuteCountRows) $ADODB_COUNTRECS = true;
if ($this->cache)
$rs = &$this->db->CachePageExecute($this->cache,$this->sql,$rows,$this->curr_page);
else
$rs = &$this->db->PageExecute($this->sql,$rows,$this->curr_page);
$ADODB_COUNTRECS = $savec;
$this->rs = &$rs;
if (!$rs) {
print "<h3>Query failed: $this->sql</h3>";
return;
}
if (!$rs->EOF && (!$rs->AtFirstPage() || !$rs->AtLastPage()))
$header = $this->RenderNav();
else
$header = "&nbsp;";
$grid = $this->RenderGrid();
$footer = $this->RenderPageCount();
$rs->Close();
$this->rs = false;
$this->RenderLayout($header,$grid,$footer);
}
//------------------------------------------------------
// override this to control overall layout and formating
function RenderLayout($header,$grid,$footer,$attributes='border=1 bgcolor=beige')
{
echo "<table ".$attributes."><tr><td>",
$header,
"</td></tr><tr><td>",
$grid,
"</td></tr><tr><td>",
$footer,
"</td></tr></table>";
}
}
?>

View File

@ -0,0 +1,909 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Library for basic performance monitoring and tuning.
My apologies if you see code mixed with presentation. The presentation suits
my needs. If you want to separate code from presentation, be my guest. Patches
are welcome.
*/
if (!defined(ADODB_DIR)) include_once(dirname(__FILE__).'/adodb.inc.php');
include_once(ADODB_DIR.'/tohtml.inc.php');
// avoids localization problems where , is used instead of .
function adodb_round($n,$prec)
{
return number_format($n, $prec, '.', '');
}
/* return microtime value as a float */
function adodb_microtime()
{
$t = microtime();
$t = explode(' ',$t);
return (float)$t[1]+ (float)$t[0];
}
/* sql code timing */
function& adodb_log_sql(&$conn,$sql,$inputarr)
{
global $HTTP_SERVER_VARS;
$perf_table = adodb_perf::table();
$conn->fnExecute = false;
$t0 = microtime();
$rs =& $conn->Execute($sql,$inputarr);
$t1 = microtime();
if (!empty($conn->_logsql)) {
$conn->_logsql = false; // disable logsql error simulation
$dbT = $conn->databaseType;
$a0 = split(' ',$t0);
$a0 = (float)$a0[1]+(float)$a0[0];
$a1 = split(' ',$t1);
$a1 = (float)$a1[1]+(float)$a1[0];
$time = $a1 - $a0;
if (!$rs) {
$errM = $conn->ErrorMsg();
$errN = $conn->ErrorNo();
$conn->lastInsID = 0;
$tracer = substr('ERROR: '.htmlspecialchars($errM),0,250);
} else {
$tracer = '';
$errM = '';
$errN = 0;
$dbg = $conn->debug;
$conn->debug = false;
if (!is_object($rs) || $rs->dataProvider == 'empty')
$conn->_affected = $conn->affected_rows(true);
$conn->lastInsID = @$conn->Insert_ID();
$conn->debug = $dbg;
}
if (isset($HTTP_SERVER_VARS['HTTP_HOST'])) {
$tracer .= '<br>'.$HTTP_SERVER_VARS['HTTP_HOST'];
if (isset($HTTP_SERVER_VARS['PHP_SELF'])) $tracer .= $HTTP_SERVER_VARS['PHP_SELF'];
} else
if (isset($HTTP_SERVER_VARS['PHP_SELF'])) $tracer .= '<br>'.$HTTP_SERVER_VARS['PHP_SELF'];
//$tracer .= (string) adodb_backtrace(false);
$tracer = substr($tracer,0,500);
if (is_array($inputarr)) {
if (is_array(reset($inputarr))) $params = 'Array sizeof='.sizeof($inputarr);
else {
$params = '';
$params = implode(', ',$inputarr);
if (strlen($params) >= 3000) $params = substr($params, 0, 3000);
}
} else {
$params = '';
}
if (is_array($sql)) $sql = $sql[0];
$arr = array('b'=>trim(substr($sql,0,230)),
'c'=>substr($sql,0,3900), 'd'=>$params,'e'=>$tracer,'f'=>adodb_round($time,6));
//var_dump($arr);
$saved = $conn->debug;
$conn->debug = 0;
if ($conn->dataProvider == 'oci8' && $dbT != 'oci8po') {
$isql = "insert into $perf_table values($conn->sysTimeStamp,:b,:c,:d,:e,:f)";
} else if ($dbT == 'odbc_mssql' || $dbT == 'informix') {
$timer = $arr['f'];
if ($dbT == 'informix') $sql2 = substr($sql2,0,230);
$sql1 = $conn->qstr($arr['b']);
$sql2 = $conn->qstr($arr['c']);
$params = $conn->qstr($arr['d']);
$tracer = $conn->qstr($arr['e']);
$isql = "insert into $perf_table (created,sql0,sql1,params,tracer,timer) values($conn->sysTimeStamp,$sql1,$sql2,$params,$tracer,$timer)";
if ($dbT == 'informix') $isql = str_replace(chr(10),' ',$isql);
$arr = false;
} else {
$isql = "insert into $perf_table (created,sql0,sql1,params,tracer,timer) values( $conn->sysTimeStamp,?,?,?,?,?)";
}
$ok = $conn->Execute($isql,$arr);
$conn->debug = $saved;
if ($ok) {
$conn->_logsql = true;
} else {
$err2 = $conn->ErrorMsg();
$conn->_logsql = true; // enable logsql error simulation
$perf =& NewPerfMonitor($conn);
if ($perf) {
if ($perf->CreateLogTable()) $ok = $conn->Execute($isql,$arr);
} else {
$ok = $conn->Execute("create table $perf_table (
created varchar(50),
sql0 varchar(250),
sql1 varchar(4000),
params varchar(3000),
tracer varchar(500),
timer decimal(16,6))");
}
if (!$ok) {
ADOConnection::outp( "<b>LOGSQL Insert Failed</b>: $isql<br>$err2</br>");
$conn->_logsql = false;
}
}
$conn->_errorMsg = $errM;
$conn->_errorCode = $errN;
}
$conn->fnExecute = 'adodb_log_sql';
return $rs;
}
/*
The settings data structure is an associative array that database parameter per element.
Each database parameter element in the array is itself an array consisting of:
0: category code, used to group related db parameters
1: either
a. sql string to retrieve value, eg. "select value from v\$parameter where name='db_block_size'",
b. array holding sql string and field to look for, e.g. array('show variables','table_cache'),
c. a string prefixed by =, then a PHP method of the class is invoked,
e.g. to invoke $this->GetIndexValue(), set this array element to '=GetIndexValue',
2: description of the database parameter
*/
class adodb_perf {
var $conn;
var $color = '#F0F0F0';
var $table = '<table border=1 bgcolor=white>';
var $titles = '<tr><td><b>Parameter</b></td><td><b>Value</b></td><td><b>Description</b></td></tr>';
var $warnRatio = 90;
var $tablesSQL = false;
var $cliFormat = "%32s => %s \r\n";
var $sql1 = 'sql1'; // used for casting sql1 to text for mssql
var $explain = true;
var $helpurl = "<a href=http://phplens.com/adodb/reference.functions.fnexecute.and.fncacheexecute.properties.html#logsql>LogSQL help</a>";
var $createTableSQL = false;
var $maxLength = 2000;
// Sets the tablename to be used
function table($newtable = false)
{
static $_table;
if (!empty($newtable)) $_table = $newtable;
if (empty($_table)) $_table = 'adodb_logsql';
return $_table;
}
// returns array with info to calculate CPU Load
function _CPULoad()
{
/*
cpu 524152 2662 2515228 336057010
cpu0 264339 1408 1257951 168025827
cpu1 259813 1254 1257277 168031181
page 622307 25475680
swap 24 1891
intr 890153570 868093576 6 0 4 4 0 6 1 2 0 0 0 124 0 8098760 2 13961053 0 0 0 0 0 0 0 0 0 0 0 0 0 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
disk_io: (3,0):(3144904,54369,610378,3090535,50936192) (3,1):(3630212,54097,633016,3576115,50951320)
ctxt 66155838
btime 1062315585
processes 69293
*/
// Algorithm is taken from
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/example__obtaining_raw_performance_data.asp
if (strncmp(PHP_OS,'WIN',3)==0) {
@$c = new COM("WinMgmts:{impersonationLevel=impersonate}!Win32_PerfRawData_PerfOS_Processor.Name='_Total'");
if (!$c) return false;
$info[0] = $c->PercentProcessorTime;
$info[1] = 0;
$info[2] = 0;
$info[3] = $c->TimeStamp_Sys100NS;
//print_r($info);
return $info;
}
// Algorithm - Steve Blinch (BlitzAffe Online, http://www.blitzaffe.com)
$statfile = '/proc/stat';
if (!file_exists($statfile)) return false;
$fd = fopen($statfile,"r");
if (!$fd) return false;
$statinfo = explode("\n",fgets($fd, 1024));
fclose($fd);
foreach($statinfo as $line) {
$info = explode(" ",$line);
if($info[0]=="cpu") {
array_shift($info); // pop off "cpu"
if(!$info[0]) array_shift($info); // pop off blank space (if any)
return $info;
}
}
return false;
}
/* NOT IMPLEMENTED */
function MemInfo()
{
/*
total: used: free: shared: buffers: cached:
Mem: 1055289344 917299200 137990144 0 165437440 599773184
Swap: 2146775040 11055104 2135719936
MemTotal: 1030556 kB
MemFree: 134756 kB
MemShared: 0 kB
Buffers: 161560 kB
Cached: 581384 kB
SwapCached: 4332 kB
Active: 494468 kB
Inact_dirty: 322856 kB
Inact_clean: 24256 kB
Inact_target: 168316 kB
HighTotal: 131064 kB
HighFree: 1024 kB
LowTotal: 899492 kB
LowFree: 133732 kB
SwapTotal: 2096460 kB
SwapFree: 2085664 kB
Committed_AS: 348732 kB
*/
}
/*
Remember that this is client load, not db server load!
*/
var $_lastLoad;
function CPULoad()
{
$info = $this->_CPULoad();
if (!$info) return false;
if (empty($this->_lastLoad)) {
sleep(1);
$this->_lastLoad = $info;
$info = $this->_CPULoad();
}
$last = $this->_lastLoad;
$this->_lastLoad = $info;
$d_user = $info[0] - $last[0];
$d_nice = $info[1] - $last[1];
$d_system = $info[2] - $last[2];
$d_idle = $info[3] - $last[3];
//printf("Delta - User: %f Nice: %f System: %f Idle: %f<br>",$d_user,$d_nice,$d_system,$d_idle);
if (strncmp(PHP_OS,'WIN',3)==0) {
if ($d_idle < 1) $d_idle = 1;
return 100*(1-$d_user/$d_idle);
}else {
$total=$d_user+$d_nice+$d_system+$d_idle;
if ($total<1) $total=1;
return 100*($d_user+$d_nice+$d_system)/$total;
}
}
function Tracer($sql)
{
$perf_table = adodb_perf::table();
$saveE = $this->conn->fnExecute;
$this->conn->fnExecute = false;
$sqlq = $this->conn->qstr($sql);
$arr = $this->conn->GetArray(
"select count(*),tracer
from $perf_table where sql1=$sqlq
group by tracer
order by 1 desc");
$s = '';
if ($arr) {
$s .= '<h3>Scripts Affected</h3>';
foreach($arr as $k) {
$s .= sprintf("%4d",$k[0]).' &nbsp; '.strip_tags($k[1]).'<br>';
}
}
$this->conn->fnExecute = $saveE;
return $s;
}
/*
Explain Plan for $sql.
If only a snippet of the $sql is passed in, then $partial will hold the crc32 of the
actual sql.
*/
function Explain($sql,$partial=false)
{
return false;
}
function InvalidSQL($numsql = 10)
{
global $HTTP_GET_VARS;
if (isset($HTTP_GET_VARS['sql'])) return;
$s = '<h3>Invalid SQL</h3>';
$saveE = $this->conn->fnExecute;
$this->conn->fnExecute = false;
$perf_table = adodb_perf::table();
$rs =& $this->conn->SelectLimit("select distinct count(*),sql1,tracer as error_msg from $perf_table where tracer like 'ERROR:%' group by sql1,tracer order by 1 desc",$numsql);//,$numsql);
$this->conn->fnExecute = $saveE;
if ($rs) {
$s .= rs2html($rs,false,false,false,false);
} else
return "<p>$this->helpurl. ".$this->conn->ErrorMsg()."</p>";
return $s;
}
/*
This script identifies the longest running SQL
*/
function _SuspiciousSQL($numsql = 10)
{
global $ADODB_FETCH_MODE,$HTTP_GET_VARS;
$perf_table = adodb_perf::table();
$saveE = $this->conn->fnExecute;
$this->conn->fnExecute = false;
if (isset($HTTP_GET_VARS['exps']) && isset($HTTP_GET_VARS['sql'])) {
$partial = !empty($HTTP_GET_VARS['part']);
echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'],$partial)."\n";
}
if (isset($HTTP_GET_VARS['sql'])) return;
$sql1 = $this->sql1;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
//$this->conn->debug=1;
$rs =& $this->conn->SelectLimit(
"select avg(timer) as avg_timer,$sql1,count(*),max(timer) as max_timer,min(timer) as min_timer
from $perf_table
where {$this->conn->upperCase}({$this->conn->substr}(sql0,1,5)) not in ('DROP ','INSER','COMMI','CREAT')
and (tracer is null or tracer not like 'ERROR:%')
group by sql1
order by 1 desc",$numsql);
$ADODB_FETCH_MODE = $save;
$this->conn->fnExecute = $saveE;
if (!$rs) return "<p>$this->helpurl. ".$this->conn->ErrorMsg()."</p>";
$s = "<h3>Suspicious SQL</h3>
<font size=1>The following SQL have high average execution times</font><br>
<table border=1 bgcolor=white><tr><td><b>Avg Time</b><td><b>Count</b><td><b>SQL</b><td><b>Max</b><td><b>Min</b></tr>\n";
$max = $this->maxLength;
while (!$rs->EOF) {
$sql = $rs->fields[1];
$raw = urlencode($sql);
if (strlen($raw)>$max-100) {
$sql2 = substr($sql,0,$max-500);
$raw = urlencode($sql2).'&part='.crc32($sql);
}
$prefix = "<a target=sql".rand()." href=\"?hidem=1&exps=1&sql=".$raw."&x#explain\">";
$suffix = "</a>";
if ($this->explain == false || strlen($prefix)>$max) {
$suffix = ' ... <i>String too long for GET parameter: '.strlen($prefix).'</i>';
$prefix = '';
}
$s .= "<tr><td>".adodb_round($rs->fields[0],6)."<td align=right>".$rs->fields[2]."<td><font size=-1>".$prefix.htmlspecialchars($sql).$suffix."</font>".
"<td>".$rs->fields[3]."<td>".$rs->fields[4]."</tr>";
$rs->MoveNext();
}
return $s."</table>";
}
function CheckMemory()
{
return '';
}
function SuspiciousSQL($numsql=10)
{
return adodb_perf::_SuspiciousSQL($numsql);
}
function ExpensiveSQL($numsql=10)
{
return adodb_perf::_ExpensiveSQL($numsql);
}
/*
This reports the percentage of load on the instance due to the most
expensive few SQL statements. Tuning these statements can often
make huge improvements in overall system performance.
*/
function _ExpensiveSQL($numsql = 10)
{
global $HTTP_GET_VARS,$ADODB_FETCH_MODE;
$perf_table = adodb_perf::table();
$saveE = $this->conn->fnExecute;
$this->conn->fnExecute = false;
if (isset($HTTP_GET_VARS['expe']) && isset($HTTP_GET_VARS['sql'])) {
$partial = !empty($HTTP_GET_VARS['part']);
echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'],$partial)."\n";
}
if (isset($HTTP_GET_VARS['sql'])) return;
$sql1 = $this->sql1;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs =& $this->conn->SelectLimit(
"select sum(timer) as total,$sql1,count(*),max(timer) as max_timer,min(timer) as min_timer
from $perf_table
where {$this->conn->upperCase}({$this->conn->substr}(sql0,1,5)) not in ('DROP ','INSER','COMMI','CREAT')
and (tracer is null or tracer not like 'ERROR:%')
group by sql1
order by 1 desc",$numsql);
$this->conn->fnExecute = $saveE;
$ADODB_FETCH_MODE = $save;
if (!$rs) return "<p>$this->helpurl. ".$this->conn->ErrorMsg()."</p>";
$s = "<h3>Expensive SQL</h3>
<font size=1>Tuning the following SQL will reduce the server load substantially</font><br>
<table border=1 bgcolor=white><tr><td><b>Load</b><td><b>Count</b><td><b>SQL</b><td><b>Max</b><td><b>Min</b></tr>\n";
$max = $this->maxLength;
while (!$rs->EOF) {
$sql = $rs->fields[1];
$raw = urlencode($sql);
if (strlen($raw)>$max-100) {
$sql2 = substr($sql,0,$max-500);
$raw = urlencode($sql2).'&part='.crc32($sql);
}
$prefix = "<a target=sqle".rand()." href=\"?hidem=1&expe=1&sql=".$raw."&x#explain\">";
$suffix = "</a>";
if($this->explain == false || strlen($prefix>$max)) {
$prefix = '';
$suffix = '';
}
$s .= "<tr><td>".adodb_round($rs->fields[0],6)."<td align=right>".$rs->fields[2]."<td><font size=-1>".$prefix.htmlspecialchars($sql).$suffix."</font>".
"<td>".$rs->fields[3]."<td>".$rs->fields[4]."</tr>";
$rs->MoveNext();
}
return $s."</table>";
}
/*
Raw function to return parameter value from $settings.
*/
function DBParameter($param)
{
if (empty($this->settings[$param])) return false;
$sql = $this->settings[$param][1];
return $this->_DBParameter($sql);
}
/*
Raw function returning array of poll paramters
*/
function &PollParameters()
{
$arr[0] = (float)$this->DBParameter('data cache hit ratio');
$arr[1] = (float)$this->DBParameter('data reads');
$arr[2] = (float)$this->DBParameter('data writes');
$arr[3] = (integer) $this->DBParameter('current connections');
return $arr;
}
/*
Low-level Get Database Parameter
*/
function _DBParameter($sql)
{
$savelog = $this->conn->LogSQL(false);
if (is_array($sql)) {
global $ADODB_FETCH_MODE;
$sql1 = $sql[0];
$key = $sql[1];
if (sizeof($sql)>2) $pos = $sql[2];
else $pos = 1;
if (sizeof($sql)>3) $coef = $sql[3];
else $coef = false;
$ret = false;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->conn->Execute($sql1);
$ADODB_FETCH_MODE = $save;
if ($rs) {
while (!$rs->EOF) {
$keyf = reset($rs->fields);
if (trim($keyf) == $key) {
$ret = $rs->fields[$pos];
if ($coef) $ret *= $coef;
break;
}
$rs->MoveNext();
}
$rs->Close();
}
$this->conn->LogSQL($savelog);
return $ret;
} else {
if (strncmp($sql,'=',1) == 0) {
$fn = substr($sql,1);
return $this->$fn();
}
$sql = str_replace('$DATABASE',$this->conn->database,$sql);
$ret = $this->conn->GetOne($sql);
$this->conn->LogSQL($savelog);
return $ret;
}
}
/*
Warn if cache ratio falls below threshold. Displayed in "Description" column.
*/
function WarnCacheRatio($val)
{
if ($val < $this->warnRatio)
return '<font color=red><b>Cache ratio should be at least '.$this->warnRatio.'%</b></font>';
else return '';
}
/***********************************************************************************************/
// HIGH LEVEL UI FUNCTIONS
/***********************************************************************************************/
function UI($pollsecs=5)
{
global $HTTP_GET_VARS,$HTTP_SERVER_VARS,$HTTP_POST_VARS;
$perf_table = adodb_perf::table();
$conn = $this->conn;
$app = $conn->host;
if ($conn->host && $conn->database) $app .= ', db=';
$app .= $conn->database;
if ($app) $app .= ', ';
$savelog = $this->conn->LogSQL(false);
$info = $conn->ServerInfo();
if (isset($HTTP_GET_VARS['clearsql'])) {
$this->conn->Execute("delete from $perf_table");
}
$this->conn->LogSQL($savelog);
// magic quotes
if (isset($HTTP_GET_VARS['sql']) && get_magic_quotes_gpc()) {
$_GET['sql'] = $HTTP_GET_VARS['sql'] = str_replace(array("\\'",'\"'),array("'",'"'),$HTTP_GET_VARS['sql']);
}
if (!isset($_SESSION['ADODB_PERF_SQL'])) $nsql = $_SESSION['ADODB_PERF_SQL'] = 10;
else $nsql = $_SESSION['ADODB_PERF_SQL'];
$app .= $info['description'];
if (isset($HTTP_GET_VARS['do'])) $do = $HTTP_GET_VARS['do'];
else if (isset($HTTP_POST_VARS['do'])) $do = $HTTP_POST_VARS['do'];
else if (isset($HTTP_GET_VARS['sql'])) $do = 'viewsql';
else $do = 'stats';
if (isset($HTTP_GET_VARS['nsql'])) {
if ($HTTP_GET_VARS['nsql'] > 0) $nsql = $_SESSION['ADODB_PERF_SQL'] = (integer) $HTTP_GET_VARS['nsql'];
}
echo "<title>ADOdb Performance Monitor on $app</title><body bgcolor=white>";
if ($do == 'viewsql') $form = "<td><form># SQL:<input type=hidden value=viewsql name=do> <input type=text size=4 name=nsql value=$nsql><input type=submit value=Go></td></form>";
else $form = "<td>&nbsp;</td>";
$allowsql = !defined('ADODB_PERF_NO_RUN_SQL');
if (empty($HTTP_GET_VARS['hidem']))
echo "<table border=1 width=100% bgcolor=lightyellow><tr><td colspan=2>
<b><a href=http://adodb.sourceforge.net/?perf=1>ADOdb</a> Performance Monitor</b> <font size=1>for $app</font></tr><tr><td>
<a href=?do=stats><b>Performance Stats</b></a> &nbsp; <a href=?do=viewsql><b>View SQL</b></a>
&nbsp; <a href=?do=tables><b>View Tables</b></a> &nbsp; <a href=?do=poll><b>Poll Stats</b></a>",
$allowsql ? ' &nbsp; <a href=?do=dosql><b>Run SQL</b></a>' : '',
"$form",
"</tr></table>";
switch ($do) {
default:
case 'stats':
echo $this->HealthCheck();
//$this->conn->debug=1;
echo $this->CheckMemory();
break;
case 'poll':
echo "<iframe width=720 height=80%
src=\"{$HTTP_SERVER_VARS['PHP_SELF']}?do=poll2&hidem=1\"></iframe>";
break;
case 'poll2':
echo "<pre>";
$this->Poll($pollsecs);
break;
case 'dosql':
if (!$allowsql) break;
$this->DoSQLForm();
break;
case 'viewsql':
if (empty($HTTP_GET_VARS['hidem']))
echo "&nbsp; <a href=\"?do=viewsql&clearsql=1\">Clear SQL Log</a><br>";
echo($this->SuspiciousSQL($nsql));
echo($this->ExpensiveSQL($nsql));
echo($this->InvalidSQL($nsql));
break;
case 'tables':
echo $this->Tables(); break;
}
global $ADODB_vers;
echo "<p><div align=center><font size=1>$ADODB_vers Sponsored by <a href=http://phplens.com/>phpLens</a></font></div>";
}
/*
Runs in infinite loop, returning real-time statistics
*/
function Poll($secs=5)
{
$this->conn->fnExecute = false;
//$this->conn->debug=1;
if ($secs <= 1) $secs = 1;
echo "Accumulating statistics, every $secs seconds...\n";flush();
$arro =& $this->PollParameters();
$cnt = 0;
set_time_limit(0);
sleep($secs);
while (1) {
$arr =& $this->PollParameters();
$hits = sprintf('%2.2f',$arr[0]);
$reads = sprintf('%12.4f',($arr[1]-$arro[1])/$secs);
$writes = sprintf('%12.4f',($arr[2]-$arro[2])/$secs);
$sess = sprintf('%5d',$arr[3]);
$load = $this->CPULoad();
if ($load !== false) {
$oslabel = 'WS-CPU%';
$osval = sprintf(" %2.1f ",(float) $load);
}else {
$oslabel = '';
$osval = '';
}
if ($cnt % 10 == 0) echo " Time ".$oslabel." Hit% Sess Reads/s Writes/s\n";
$cnt += 1;
echo date('H:i:s').' '.$osval."$hits $sess $reads $writes\n";
flush();
sleep($secs);
$arro = $arr;
}
}
/*
Returns basic health check in a command line interface
*/
function HealthCheckCLI()
{
return $this->HealthCheck(true);
}
/*
Returns basic health check as HTML
*/
function HealthCheck($cli=false)
{
$saveE = $this->conn->fnExecute;
$this->conn->fnExecute = false;
if ($cli) $html = '';
else $html = $this->table.'<tr><td colspan=3><h3>'.$this->conn->databaseType.'</h3></td></tr>'.$this->titles;
$oldc = false;
$bgc = '';
foreach($this->settings as $name => $arr) {
if ($arr === false) break;
if (!is_string($name)) {
if ($cli) $html .= " -- $arr -- \n";
else $html .= "<tr bgcolor=$this->color><td colspan=3><i>$arr</i> &nbsp;</td></tr>";
continue;
}
if (!is_array($arr)) break;
$category = $arr[0];
$how = $arr[1];
if (sizeof($arr)>2) $desc = $arr[2];
else $desc = ' &nbsp; ';
if ($category == 'HIDE') continue;
$val = $this->_DBParameter($how);
if ($desc && strncmp($desc,"=",1) === 0) {
$fn = substr($desc,1);
$desc = $this->$fn($val);
}
if ($val === false) {
$m = $this->conn->ErrorMsg();
$val = "Error: $m";
} else {
if (is_numeric($val) && $val >= 256*1024) {
if ($val % (1024*1024) == 0) {
$val /= (1024*1024);
$val .= 'M';
} else if ($val % 1024 == 0) {
$val /= 1024;
$val .= 'K';
}
//$val = htmlspecialchars($val);
}
}
if ($category != $oldc) {
$oldc = $category;
//$bgc = ($bgc == ' bgcolor='.$this->color) ? ' bgcolor=white' : ' bgcolor='.$this->color;
}
if (strlen($desc)==0) $desc = '&nbsp;';
if (strlen($val)==0) $val = '&nbsp;';
if ($cli) {
$html .= str_replace('&nbsp;','',sprintf($this->cliFormat,strip_tags($name),strip_tags($val),strip_tags($desc)));
}else {
$html .= "<tr$bgc><td>".$name.'</td><td>'.$val.'</td><td>'.$desc."</td></tr>\n";
}
}
if (!$cli) $html .= "</table>\n";
$this->conn->fnExecute = $saveE;
return $html;
}
function Tables($orderby='1')
{
if (!$this->tablesSQL) return false;
$savelog = $this->conn->LogSQL(false);
$rs = $this->conn->Execute($this->tablesSQL.' order by '.$orderby);
$this->conn->LogSQL($savelog);
$html = rs2html($rs,false,false,false,false);
return $html;
}
function CreateLogTable()
{
if (!$this->createTableSQL) return false;
$savelog = $this->conn->LogSQL(false);
$ok = $this->conn->Execute($this->createTableSQL);
$this->conn->LogSQL($savelog);
return ($ok) ? true : false;
}
function DoSQLForm()
{
global $HTTP_SERVER_VARS,$HTTP_GET_VARS,$HTTP_POST_VARS,$HTTP_SESSION_VARS;
$HTTP_VARS = array_merge($HTTP_GET_VARS,$HTTP_POST_VARS);
$PHP_SELF = $HTTP_SERVER_VARS['PHP_SELF'];
$sql = isset($HTTP_VARS['sql']) ? $HTTP_VARS['sql'] : '';
if (isset($HTTP_SESSION_VARS['phplens_sqlrows'])) $rows = $HTTP_SESSION_VARS['phplens_sqlrows'];
else $rows = 3;
if (isset($HTTP_VARS['SMALLER'])) {
$rows /= 2;
if ($rows < 3) $rows = 3;
$HTTP_SESSION_VARS['phplens_sqlrows'] = $rows;
}
if (isset($HTTP_VARS['BIGGER'])) {
$rows *= 2;
$HTTP_SESSION_VARS['phplens_sqlrows'] = $rows;
}
?>
<form method="POST" action="<?php echo $PHP_SELF ?>">
<table><tr>
<td> Form size: <input type="submit" value=" &lt; " name="SMALLER"><input type="submit" value=" &gt; &gt; " name="BIGGER">
</td>
<td align=right>
<input type="submit" value=" Run SQL Below " name="RUN"><input type=hidden name=do value=dosql>
</td></tr>
<tr>
<td colspan=2><textarea rows=<?php print $rows; ?> name="sql" cols="80"><?php print htmlspecialchars($sql) ?></textarea>
</td>
</tr>
</table>
</form>
<?php
if (!isset($HTTP_VARS['sql'])) return;
$sql = $this->undomq(trim($sql));
if (substr($sql,strlen($sql)-1) === ';') {
$print = true;
$sqla = $this->SplitSQL($sql);
} else {
$print = false;
$sqla = array($sql);
}
foreach($sqla as $sqls) {
if (!$sqls) continue;
if ($print) {
print "<p>".htmlspecialchars($sqls)."</p>";
flush();
}
$savelog = $this->conn->LogSQL(false);
$rs = $this->conn->Execute($sqls);
$this->conn->LogSQL($savelog);
if ($rs && is_object($rs) && !$rs->EOF) {
rs2html($rs);
while ($rs->NextRecordSet()) {
print "<table width=98% bgcolor=#C0C0FF><tr><td>&nbsp;</td></tr></table>";
rs2html($rs);
}
} else {
$e1 = (integer) $this->conn->ErrorNo();
$e2 = $this->conn->ErrorMsg();
if (($e1) || ($e2)) {
if (empty($e1)) $e1 = '-1'; // postgresql fix
print ' &nbsp; '.$e1.': '.$e2;
} else {
print "<p>No Recordset returned<br></p>";
}
}
} // foreach
}
function SplitSQL($sql)
{
$arr = explode(';',$sql);
return $arr;
}
function undomq(&$m)
{
if (get_magic_quotes_gpc()) {
// undo the damage
$m = str_replace('\\\\','\\',$m);
$m = str_replace('\"','"',$m);
$m = str_replace('\\\'','\'',$m);
}
return $m;
}
}
?>

View File

@ -0,0 +1,16 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4.
*/
class ADODB_BASE_RS {
}
?>

View File

@ -0,0 +1,967 @@
<?php
/**
ADOdb Date Library, part of the ADOdb abstraction library
Download: http://php.weblogs.com/adodb_date_time_library
PHP native date functions use integer timestamps for computations.
Because of this, dates are restricted to the years 1901-2038 on Unix
and 1970-2038 on Windows due to integer overflow for dates beyond
those years. This library overcomes these limitations by replacing the
native function's signed integers (normally 32-bits) with PHP floating
point numbers (normally 64-bits).
Dates from 100 A.D. to 3000 A.D. and later
have been tested. The minimum is 100 A.D. as <100 will invoke the
2 => 4 digit year conversion. The maximum is billions of years in the
future, but this is a theoretical limit as the computation of that year
would take too long with the current implementation of adodb_mktime().
This library replaces native functions as follows:
<pre>
getdate() with adodb_getdate()
date() with adodb_date()
gmdate() with adodb_gmdate()
mktime() with adodb_mktime()
gmmktime() with adodb_gmmktime()
</pre>
The parameters are identical, except that adodb_date() accepts a subset
of date()'s field formats. Mktime() will convert from local time to GMT,
and date() will convert from GMT to local time, but daylight savings is
not handled currently.
This library is independant of the rest of ADOdb, and can be used
as standalone code.
PERFORMANCE
For high speed, this library uses the native date functions where
possible, and only switches to PHP code when the dates fall outside
the 32-bit signed integer range.
GREGORIAN CORRECTION
Pope Gregory shortened October of A.D. 1582 by ten days. Thursday,
October 4, 1582 (Julian) was followed immediately by Friday, October 15,
1582 (Gregorian).
Since 0.06, we handle this correctly, so:
adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582)
== 24 * 3600 (1 day)
=============================================================================
COPYRIGHT
(c) 2003 John Lim and released under BSD-style license except for code by jackbbs,
which includes adodb_mktime, adodb_get_gmt_diff, adodb_is_leap_year
and originally found at http://www.php.net/manual/en/function.mktime.php
=============================================================================
BUG REPORTS
These should be posted to the ADOdb forums at
http://phplens.com/lens/lensforum/topics.php?id=4
=============================================================================
FUNCTION DESCRIPTIONS
FUNCTION adodb_getdate($date=false)
Returns an array containing date information, as getdate(), but supports
dates greater than 1901 to 2038.
FUNCTION adodb_date($fmt, $timestamp = false)
Convert a timestamp to a formatted local date. If $timestamp is not defined, the
current timestamp is used. Unlike the function date(), it supports dates
outside the 1901 to 2038 range.
The format fields that adodb_date supports:
<pre>
a - "am" or "pm"
A - "AM" or "PM"
d - day of the month, 2 digits with leading zeros; i.e. "01" to "31"
D - day of the week, textual, 3 letters; e.g. "Fri"
F - month, textual, long; e.g. "January"
g - hour, 12-hour format without leading zeros; i.e. "1" to "12"
G - hour, 24-hour format without leading zeros; i.e. "0" to "23"
h - hour, 12-hour format; i.e. "01" to "12"
H - hour, 24-hour format; i.e. "00" to "23"
i - minutes; i.e. "00" to "59"
j - day of the month without leading zeros; i.e. "1" to "31"
l (lowercase 'L') - day of the week, textual, long; e.g. "Friday"
L - boolean for whether it is a leap year; i.e. "0" or "1"
m - month; i.e. "01" to "12"
M - month, textual, 3 letters; e.g. "Jan"
n - month without leading zeros; i.e. "1" to "12"
O - Difference to Greenwich time in hours; e.g. "+0200"
Q - Quarter, as in 1, 2, 3, 4
r - RFC 822 formatted date; e.g. "Thu, 21 Dec 2000 16:01:07 +0200"
s - seconds; i.e. "00" to "59"
S - English ordinal suffix for the day of the month, 2 characters;
i.e. "st", "nd", "rd" or "th"
t - number of days in the given month; i.e. "28" to "31"
T - Timezone setting of this machine; e.g. "EST" or "MDT"
U - seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
w - day of the week, numeric, i.e. "0" (Sunday) to "6" (Saturday)
Y - year, 4 digits; e.g. "1999"
y - year, 2 digits; e.g. "99"
z - day of the year; i.e. "0" to "365"
Z - timezone offset in seconds (i.e. "-43200" to "43200").
The offset for timezones west of UTC is always negative,
and for those east of UTC is always positive.
</pre>
Unsupported:
<pre>
B - Swatch Internet time
I (capital i) - "1" if Daylight Savings Time, "0" otherwise.
W - ISO-8601 week number of year, weeks starting on Monday
</pre>
FUNCTION adodb_date2($fmt, $isoDateString = false)
Same as adodb_date, but 2nd parameter accepts iso date, eg.
adodb_date2('d-M-Y H:i','2003-12-25 13:01:34');
FUNCTION adodb_gmdate($fmt, $timestamp = false)
Convert a timestamp to a formatted GMT date. If $timestamp is not defined, the
current timestamp is used. Unlike the function date(), it supports dates
outside the 1901 to 2038 range.
FUNCTION adodb_mktime($hr, $min, $sec [, $month, $day, $year])
Converts a local date to a unix timestamp. Unlike the function mktime(), it supports
dates outside the 1901 to 2038 range. Differs from mktime() in that all parameters
are currently compulsory.
FUNCTION adodb_gmmktime($hr, $min, $sec [, $month, $day, $year])
Converts a gmt date to a unix timestamp. Unlike the function gmmktime(), it supports
dates outside the 1901 to 2038 range. Differs from gmmktime() in that all parameters
are currently compulsory.
=============================================================================
NOTES
Useful url for generating test timestamps:
http://www.4webhelp.net/us/timestamp.php
Possible future optimizations include
a. Using an algorithm similar to Plauger's in "The Standard C Library"
(page 428, xttotm.c _Ttotm() function). Plauger's algorithm will not
work outside 32-bit signed range, so i decided not to implement it.
b. Iterate over a block of years (say 12) when searching for the
correct year.
c. Implement daylight savings, which looks awfully complicated, see
http://webexhibits.org/daylightsaving/
CHANGELOG
- 18 July 2004 0.15
All params in adodb_mktime were formerly compulsory. Now only the hour, min, secs is compulsory. This
brings it more in line with mktime (still not identical).
- 23 June 2004 0.14
Allow you to define your own daylights savings function, adodb_daylight_sv.
If the function is defined (somewhere in an include), then you can correct for daylights savings.
In this example, we apply daylights savings in June or July, adding one hour. This is extremely
unrealistic as it does not take into account time-zone, geographic location, current year.
function adodb_daylight_sv(&$arr, $is_gmt)
{
if ($is_gmt) return;
$m = $arr['mon'];
if ($m == 6 || $m == 7) $arr['hours'] += 1;
}
This is only called by adodb_date() and not by adodb_mktime().
The format of $arr is
Array (
[seconds] => 0
[minutes] => 0
[hours] => 0
[mday] => 1 # day of month, eg 1st day of the month
[mon] => 2 # month (eg. Feb)
[year] => 2102
[yday] => 31 # days in current year
[leap] => # true if leap year
[ndays] => 28 # no of days in current month
)
- 28 Apr 2004 0.13
Fixed adodb_date to properly support $is_gmt. Thx to Dimitar Angelov.
- 20 Mar 2004 0.12
Fixed month calculation error in adodb_date. 2102-June-01 appeared as 2102-May-32.
- 26 Oct 2003 0.11
Because of daylight savings problems (some systems apply daylight savings to
January!!!), changed adodb_get_gmt_diff() to ignore daylight savings.
- 9 Aug 2003 0.10
Fixed bug with dates after 2038.
See http://phplens.com/lens/lensforum/msgs.php?id=6980
- 1 July 2003 0.09
Added support for Q (Quarter).
Added adodb_date2(), which accepts ISO date in 2nd param
- 3 March 2003 0.08
Added support for 'S' adodb_date() format char. Added constant ADODB_ALLOW_NEGATIVE_TS
if you want PHP to handle negative timestamps between 1901 to 1969.
- 27 Feb 2003 0.07
All negative numbers handled by adodb now because of RH 7.3+ problems.
See http://bugs.php.net/bug.php?id=20048&edit=2
- 4 Feb 2003 0.06
Fixed a typo, 1852 changed to 1582! This means that pre-1852 dates
are now correctly handled.
- 29 Jan 2003 0.05
Leap year checking differs under Julian calendar (pre 1582). Also
leap year code optimized by checking for most common case first.
We also handle month overflow correctly in mktime (eg month set to 13).
Day overflow for less than one month's days is supported.
- 28 Jan 2003 0.04
Gregorian correction handled. In PHP5, we might throw an error if
mktime uses invalid dates around 5-14 Oct 1582. Released with ADOdb 3.10.
Added limbo 5-14 Oct 1582 check, when we set to 15 Oct 1582.
- 27 Jan 2003 0.03
Fixed some more month problems due to gmt issues. Added constant ADODB_DATE_VERSION.
Fixed calculation of days since start of year for <1970.
- 27 Jan 2003 0.02
Changed _adodb_getdate() to inline leap year checking for better performance.
Fixed problem with time-zones west of GMT +0000.
- 24 Jan 2003 0.01
First implementation.
*/
/* Initialization */
/*
Version Number
*/
define('ADODB_DATE_VERSION',0.15);
/*
We check for Windows as only +ve ints are accepted as dates on Windows.
Apparently this problem happens also with Linux, RH 7.3 and later!
glibc-2.2.5-34 and greater has been changed to return -1 for dates <
1970. This used to work. The problem exists with RedHat 7.3 and 8.0
echo (mktime(0, 0, 0, 1, 1, 1960)); // prints -1
References:
http://bugs.php.net/bug.php?id=20048&edit=2
http://lists.debian.org/debian-glibc/2002/debian-glibc-200205/msg00010.html
*/
if (!defined('ADODB_ALLOW_NEGATIVE_TS')) define('ADODB_NO_NEGATIVE_TS',1);
function adodb_date_test_date($y1,$m)
{
//print " $y1/$m ";
$t = adodb_mktime(0,0,0,$m,13,$y1);
if ("$y1-$m-13 00:00:00" != adodb_date('Y-n-d H:i:s',$t)) {
print "<b>$y1 error</b><br>";
return false;
}
return true;
}
/**
Test Suite
*/
function adodb_date_test()
{
error_reporting(E_ALL);
print "<h4>Testing adodb_date and adodb_mktime. version=".ADODB_DATE_VERSION. "</h4>";
@set_time_limit(0);
$fail = false;
// This flag disables calling of PHP native functions, so we can properly test the code
if (!defined('ADODB_TEST_DATES')) define('ADODB_TEST_DATES',1);
$t = adodb_mktime(0,0,0);
if (!(adodb_date('Y-m-d') == date('Y-m-d'))) print 'Error in '.adodb_mktime(0,0,0).'<br>';
$t = adodb_mktime(0,0,0,6,1,2102);
if (!(adodb_date('Y-m-d',$t) == '2102-06-01')) print 'Error in '.adodb_date('Y-m-d',$t).'<br>';
$t = adodb_mktime(0,0,0,2,1,2102);
if (!(adodb_date('Y-m-d',$t) == '2102-02-01')) print 'Error in '.adodb_date('Y-m-d',$t).'<br>';
print "<p>Testing gregorian <=> julian conversion<p>";
$t = adodb_mktime(0,0,0,10,11,1492);
//http://www.holidayorigins.com/html/columbus_day.html - Friday check
if (!(adodb_date('D Y-m-d',$t) == 'Fri 1492-10-11')) print 'Error in Columbus landing<br>';
$t = adodb_mktime(0,0,0,2,29,1500);
if (!(adodb_date('Y-m-d',$t) == '1500-02-29')) print 'Error in julian leap years<br>';
$t = adodb_mktime(0,0,0,2,29,1700);
if (!(adodb_date('Y-m-d',$t) == '1700-03-01')) print 'Error in gregorian leap years<br>';
print adodb_mktime(0,0,0,10,4,1582).' ';
print adodb_mktime(0,0,0,10,15,1582);
$diff = (adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582));
if ($diff != 3600*24) print " <b>Error in gregorian correction = ".($diff/3600/24)." days </b><br>";
print " 15 Oct 1582, Fri=".(adodb_dow(1582,10,15) == 5 ? 'Fri' : '<b>Error</b>')."<br>";
print " 4 Oct 1582, Thu=".(adodb_dow(1582,10,4) == 4 ? 'Thu' : '<b>Error</b>')."<br>";
print "<p>Testing overflow<p>";
$t = adodb_mktime(0,0,0,3,33,1965);
if (!(adodb_date('Y-m-d',$t) == '1965-04-02')) print 'Error in day overflow 1 <br>';
$t = adodb_mktime(0,0,0,4,33,1971);
if (!(adodb_date('Y-m-d',$t) == '1971-05-03')) print 'Error in day overflow 2 <br>';
$t = adodb_mktime(0,0,0,1,60,1965);
if (!(adodb_date('Y-m-d',$t) == '1965-03-01')) print 'Error in day overflow 3 '.adodb_date('Y-m-d',$t).' <br>';
$t = adodb_mktime(0,0,0,12,32,1965);
if (!(adodb_date('Y-m-d',$t) == '1966-01-01')) print 'Error in day overflow 4 '.adodb_date('Y-m-d',$t).' <br>';
$t = adodb_mktime(0,0,0,12,63,1965);
if (!(adodb_date('Y-m-d',$t) == '1966-02-01')) print 'Error in day overflow 5 '.adodb_date('Y-m-d',$t).' <br>';
$t = adodb_mktime(0,0,0,13,3,1965);
if (!(adodb_date('Y-m-d',$t) == '1966-01-03')) print 'Error in mth overflow 1 <br>';
print "Testing 2-digit => 4-digit year conversion<p>";
if (adodb_year_digit_check(00) != 2000) print "Err 2-digit 2000<br>";
if (adodb_year_digit_check(10) != 2010) print "Err 2-digit 2010<br>";
if (adodb_year_digit_check(20) != 2020) print "Err 2-digit 2020<br>";
if (adodb_year_digit_check(30) != 2030) print "Err 2-digit 2030<br>";
if (adodb_year_digit_check(40) != 1940) print "Err 2-digit 1940<br>";
if (adodb_year_digit_check(50) != 1950) print "Err 2-digit 1950<br>";
if (adodb_year_digit_check(90) != 1990) print "Err 2-digit 1990<br>";
// Test string formating
print "<p>Testing date formating</p>";
$fmt = '\d\a\t\e T Y-m-d H:i:s a A d D F g G h H i j l L m M n O \R\F\C822 r s t U w y Y z Z 2003';
$s1 = date($fmt,0);
$s2 = adodb_date($fmt,0);
if ($s1 != $s2) {
print " date() 0 failed<br>$s1<br>$s2<br>";
}
flush();
for ($i=100; --$i > 0; ) {
$ts = 3600.0*((rand()%60000)+(rand()%60000))+(rand()%60000);
$s1 = date($fmt,$ts);
$s2 = adodb_date($fmt,$ts);
//print "$s1 <br>$s2 <p>";
$pos = strcmp($s1,$s2);
if (($s1) != ($s2)) {
for ($j=0,$k=strlen($s1); $j < $k; $j++) {
if ($s1[$j] != $s2[$j]) {
print substr($s1,$j).' ';
break;
}
}
print "<b>Error date(): $ts<br><pre>
&nbsp; \"$s1\" (date len=".strlen($s1).")
&nbsp; \"$s2\" (adodb_date len=".strlen($s2).")</b></pre><br>";
$fail = true;
}
$a1 = getdate($ts);
$a2 = adodb_getdate($ts);
$rez = array_diff($a1,$a2);
if (sizeof($rez)>0) {
print "<b>Error getdate() $ts</b><br>";
print_r($a1);
print "<br>";
print_r($a2);
print "<p>";
$fail = true;
}
}
// Test generation of dates outside 1901-2038
print "<p>Testing random dates between 100 and 4000</p>";
adodb_date_test_date(100,1);
for ($i=100; --$i >= 0;) {
$y1 = 100+rand(0,1970-100);
$m = rand(1,12);
adodb_date_test_date($y1,$m);
$y1 = 3000-rand(0,3000-1970);
adodb_date_test_date($y1,$m);
}
print '<p>';
$start = 1960+rand(0,10);
$yrs = 12;
$i = 365.25*86400*($start-1970);
$offset = 36000+rand(10000,60000);
$max = 365*$yrs*86400;
$lastyear = 0;
// we generate a timestamp, convert it to a date, and convert it back to a timestamp
// and check if the roundtrip broke the original timestamp value.
print "Testing $start to ".($start+$yrs).", or $max seconds, offset=$offset: ";
$cnt = 0;
for ($max += $i; $i < $max; $i += $offset) {
$ret = adodb_date('m,d,Y,H,i,s',$i);
$arr = explode(',',$ret);
if ($lastyear != $arr[2]) {
$lastyear = $arr[2];
print " $lastyear ";
flush();
}
$newi = adodb_mktime($arr[3],$arr[4],$arr[5],$arr[0],$arr[1],$arr[2]);
if ($i != $newi) {
print "Error at $i, adodb_mktime returned $newi ($ret)";
$fail = true;
break;
}
$cnt += 1;
}
echo "Tested $cnt dates<br>";
if (!$fail) print "<p>Passed !</p>";
else print "<p><b>Failed</b> :-(</p>";
}
/**
Returns day of week, 0 = Sunday,... 6=Saturday.
Algorithm from PEAR::Date_Calc
*/
function adodb_dow($year, $month, $day)
{
/*
Pope Gregory removed 10 days - October 5 to October 14 - from the year 1582 and
proclaimed that from that time onwards 3 days would be dropped from the calendar
every 400 years.
Thursday, October 4, 1582 (Julian) was followed immediately by Friday, October 15, 1582 (Gregorian).
*/
if ($year <= 1582) {
if ($year < 1582 ||
($year == 1582 && ($month < 10 || ($month == 10 && $day < 15)))) $greg_correction = 3;
else
$greg_correction = 0;
} else
$greg_correction = 0;
if($month > 2)
$month -= 2;
else {
$month += 10;
$year--;
}
$day = ( floor((13 * $month - 1) / 5) +
$day + ($year % 100) +
floor(($year % 100) / 4) +
floor(($year / 100) / 4) - 2 *
floor($year / 100) + 77);
return (($day - 7 * floor($day / 7))) + $greg_correction;
}
/**
Checks for leap year, returns true if it is. No 2-digit year check. Also
handles julian calendar correctly.
*/
function _adodb_is_leap_year($year)
{
if ($year % 4 != 0) return false;
if ($year % 400 == 0) {
return true;
// if gregorian calendar (>1582), century not-divisible by 400 is not leap
} else if ($year > 1582 && $year % 100 == 0 ) {
return false;
}
return true;
}
/**
checks for leap year, returns true if it is. Has 2-digit year check
*/
function adodb_is_leap_year($year)
{
return _adodb_is_leap_year(adodb_year_digit_check($year));
}
/**
Fix 2-digit years. Works for any century.
Assumes that if 2-digit is more than 30 years in future, then previous century.
*/
function adodb_year_digit_check($y)
{
if ($y < 100) {
$yr = (integer) date("Y");
$century = (integer) ($yr /100);
if ($yr%100 > 50) {
$c1 = $century + 1;
$c0 = $century;
} else {
$c1 = $century;
$c0 = $century - 1;
}
$c1 *= 100;
// if 2-digit year is less than 30 years in future, set it to this century
// otherwise if more than 30 years in future, then we set 2-digit year to the prev century.
if (($y + $c1) < $yr+30) $y = $y + $c1;
else $y = $y + $c0*100;
}
return $y;
}
/**
get local time zone offset from GMT
*/
function adodb_get_gmt_diff()
{
static $TZ;
if (isset($TZ)) return $TZ;
$TZ = mktime(0,0,0,1,2,1970,0) - gmmktime(0,0,0,1,2,1970,0);
return $TZ;
}
/**
Returns an array with date info.
*/
function adodb_getdate($d=false,$fast=false)
{
if ($d === false) return getdate();
if (!defined('ADODB_TEST_DATES')) {
if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer
return @getdate($d);
}
}
return _adodb_getdate($d);
}
/**
Low-level function that returns the getdate() array. We have a special
$fast flag, which if set to true, will return fewer array values,
and is much faster as it does not calculate dow, etc.
*/
function _adodb_getdate($origd=false,$fast=false,$is_gmt=false)
{
$d = $origd - ($is_gmt ? 0 : adodb_get_gmt_diff());
$_day_power = 86400;
$_hour_power = 3600;
$_min_power = 60;
if ($d < -12219321600) $d -= 86400*10; // if 15 Oct 1582 or earlier, gregorian correction
$_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31);
$_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31);
$d366 = $_day_power * 366;
$d365 = $_day_power * 365;
if ($d < 0) {
$origd = $d;
// The valid range of a 32bit signed timestamp is typically from
// Fri, 13 Dec 1901 20:45:54 GMT to Tue, 19 Jan 2038 03:14:07 GMT
for ($a = 1970 ; --$a >= 0;) {
$lastd = $d;
if ($leaf = _adodb_is_leap_year($a)) $d += $d366;
else $d += $d365;
if ($d >= 0) {
$year = $a;
break;
}
}
$secsInYear = 86400 * ($leaf ? 366 : 365) + $lastd;
$d = $lastd;
$mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal;
for ($a = 13 ; --$a > 0;) {
$lastd = $d;
$d += $mtab[$a] * $_day_power;
if ($d >= 0) {
$month = $a;
$ndays = $mtab[$a];
break;
}
}
$d = $lastd;
$day = $ndays + ceil(($d+1) / ($_day_power));
$d += ($ndays - $day+1)* $_day_power;
$hour = floor($d/$_hour_power);
} else {
for ($a = 1970 ;; $a++) {
$lastd = $d;
if ($leaf = _adodb_is_leap_year($a)) $d -= $d366;
else $d -= $d365;
if ($d < 0) {
$year = $a;
break;
}
}
$secsInYear = $lastd;
$d = $lastd;
$mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal;
for ($a = 1 ; $a <= 12; $a++) {
$lastd = $d;
$d -= $mtab[$a] * $_day_power;
if ($d < 0) {
$month = $a;
$ndays = $mtab[$a];
break;
}
}
$d = $lastd;
$day = ceil(($d+1) / $_day_power);
$d = $d - ($day-1) * $_day_power;
$hour = floor($d /$_hour_power);
}
$d -= $hour * $_hour_power;
$min = floor($d/$_min_power);
$secs = $d - $min * $_min_power;
if ($fast) {
return array(
'seconds' => $secs,
'minutes' => $min,
'hours' => $hour,
'mday' => $day,
'mon' => $month,
'year' => $year,
'yday' => floor($secsInYear/$_day_power),
'leap' => $leaf,
'ndays' => $ndays
);
}
$dow = adodb_dow($year,$month,$day);
return array(
'seconds' => $secs,
'minutes' => $min,
'hours' => $hour,
'mday' => $day,
'wday' => $dow,
'mon' => $month,
'year' => $year,
'yday' => floor($secsInYear/$_day_power),
'weekday' => gmdate('l',$_day_power*(3+$dow)),
'month' => gmdate('F',mktime(0,0,0,$month,2,1971)),
0 => $origd
);
}
function adodb_gmdate($fmt,$d=false)
{
return adodb_date($fmt,$d,true);
}
// accepts unix timestamp and iso date format in $d
function adodb_date2($fmt, $d=false, $is_gmt=false)
{
if ($d !== false) {
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}))?|",
($d), $rr)) return adodb_date($fmt,false,$is_gmt);
if ($rr[1] <= 100 && $rr[2]<= 1) return adodb_date($fmt,false,$is_gmt);
// h-m-s-MM-DD-YY
if (!isset($rr[5])) $d = adodb_mktime(0,0,0,$rr[2],$rr[3],$rr[1]);
else $d = @adodb_mktime($rr[5],$rr[6],$rr[7],$rr[2],$rr[3],$rr[1]);
}
return adodb_date($fmt,$d,$is_gmt);
}
/**
Return formatted date based on timestamp $d
*/
function adodb_date($fmt,$d=false,$is_gmt=false)
{
static $daylight;
if ($d === false) return ($is_gmt)? @gmdate($fmt): @date($fmt);
if (!defined('ADODB_TEST_DATES')) {
if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer
return ($is_gmt)? @gmdate($fmt,$d): @date($fmt,$d);
}
}
$_day_power = 86400;
$arr = _adodb_getdate($d,true,$is_gmt);
if (!isset($daylight)) $daylight = function_exists('adodb_daylight_sv');
if ($daylight) adodb_daylight_sv($arr, $is_gmt);
$year = $arr['year'];
$month = $arr['mon'];
$day = $arr['mday'];
$hour = $arr['hours'];
$min = $arr['minutes'];
$secs = $arr['seconds'];
$max = strlen($fmt);
$dates = '';
/*
at this point, we have the following integer vars to manipulate:
$year, $month, $day, $hour, $min, $secs
*/
for ($i=0; $i < $max; $i++) {
switch($fmt[$i]) {
case 'T': $dates .= date('T');break;
// YEAR
case 'L': $dates .= $arr['leap'] ? '1' : '0'; break;
case 'r': // Thu, 21 Dec 2000 16:01:07 +0200
$dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))).', '
. ($day<10?' '.$day:$day) . ' '.date('M',mktime(0,0,0,$month,2,1971)).' '.$year.' ';
if ($hour < 10) $dates .= '0'.$hour; else $dates .= $hour;
if ($min < 10) $dates .= ':0'.$min; else $dates .= ':'.$min;
if ($secs < 10) $dates .= ':0'.$secs; else $dates .= ':'.$secs;
$gmt = adodb_get_gmt_diff();
$dates .= sprintf(' %s%04d',($gmt<0)?'+':'-',abs($gmt)/36); break;
case 'Y': $dates .= $year; break;
case 'y': $dates .= substr($year,strlen($year)-2,2); break;
// MONTH
case 'm': if ($month<10) $dates .= '0'.$month; else $dates .= $month; break;
case 'Q': $dates .= ($month+3)>>2; break;
case 'n': $dates .= $month; break;
case 'M': $dates .= date('M',mktime(0,0,0,$month,2,1971)); break;
case 'F': $dates .= date('F',mktime(0,0,0,$month,2,1971)); break;
// DAY
case 't': $dates .= $arr['ndays']; break;
case 'z': $dates .= $arr['yday']; break;
case 'w': $dates .= adodb_dow($year,$month,$day); break;
case 'l': $dates .= gmdate('l',$_day_power*(3+adodb_dow($year,$month,$day))); break;
case 'D': $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))); break;
case 'j': $dates .= $day; break;
case 'd': if ($day<10) $dates .= '0'.$day; else $dates .= $day; break;
case 'S':
$d10 = $day % 10;
if ($d10 == 1) $dates .= 'st';
else if ($d10 == 2) $dates .= 'nd';
else if ($d10 == 3) $dates .= 'rd';
else $dates .= 'th';
break;
// HOUR
case 'Z':
$dates .= ($is_gmt) ? 0 : -adodb_get_gmt_diff(); break;
case 'O':
$gmt = ($is_gmt) ? 0 : adodb_get_gmt_diff();
$dates .= sprintf('%s%04d',($gmt<0)?'+':'-',abs($gmt)/36); break;
case 'H':
if ($hour < 10) $dates .= '0'.$hour;
else $dates .= $hour;
break;
case 'h':
if ($hour > 12) $hh = $hour - 12;
else {
if ($hour == 0) $hh = '12';
else $hh = $hour;
}
if ($hh < 10) $dates .= '0'.$hh;
else $dates .= $hh;
break;
case 'G':
$dates .= $hour;
break;
case 'g':
if ($hour > 12) $hh = $hour - 12;
else {
if ($hour == 0) $hh = '12';
else $hh = $hour;
}
$dates .= $hh;
break;
// MINUTES
case 'i': if ($min < 10) $dates .= '0'.$min; else $dates .= $min; break;
// SECONDS
case 'U': $dates .= $d; break;
case 's': if ($secs < 10) $dates .= '0'.$secs; else $dates .= $secs; break;
// AM/PM
// Note 00:00 to 11:59 is AM, while 12:00 to 23:59 is PM
case 'a':
if ($hour>=12) $dates .= 'pm';
else $dates .= 'am';
break;
case 'A':
if ($hour>=12) $dates .= 'PM';
else $dates .= 'AM';
break;
default:
$dates .= $fmt[$i]; break;
// ESCAPE
case "\\":
$i++;
if ($i < $max) $dates .= $fmt[$i];
break;
}
}
return $dates;
}
/**
Returns a timestamp given a GMT/UTC time.
Note that $is_dst is not implemented and is ignored.
*/
function adodb_gmmktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false)
{
return adodb_mktime($hr,$min,$sec,$mon,$day,$year,$is_dst,true);
}
/**
Return a timestamp given a local time. Originally by jackbbs.
Note that $is_dst is not implemented and is ignored.
Not a very fast algorithm - O(n) operation. Could be optimized to O(1).
*/
function adodb_mktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false,$is_gmt=false)
{
if (!defined('ADODB_TEST_DATES')) {
// for windows, we don't check 1970 because with timezone differences,
// 1 Jan 1970 could generate negative timestamp, which is illegal
if (1971 < $year && $year < 2038
|| $mon === false
|| !defined('ADODB_NO_NEGATIVE_TS') && (1901 < $year && $year < 2038)
)
return $is_gmt?
@gmmktime($hr,$min,$sec,$mon,$day,$year):
@mktime($hr,$min,$sec,$mon,$day,$year);
}
$gmt_different = ($is_gmt) ? 0 : adodb_get_gmt_diff();
$hr = intval($hr);
$min = intval($min);
$sec = intval($sec);
$mon = intval($mon);
$day = intval($day);
$year = intval($year);
$year = adodb_year_digit_check($year);
if ($mon > 12) {
$y = floor($mon / 12);
$year += $y;
$mon -= $y*12;
}
$_day_power = 86400;
$_hour_power = 3600;
$_min_power = 60;
$_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31);
$_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31);
$_total_date = 0;
if ($year >= 1970) {
for ($a = 1970 ; $a <= $year; $a++) {
$leaf = _adodb_is_leap_year($a);
if ($leaf == true) {
$loop_table = $_month_table_leaf;
$_add_date = 366;
} else {
$loop_table = $_month_table_normal;
$_add_date = 365;
}
if ($a < $year) {
$_total_date += $_add_date;
} else {
for($b=1;$b<$mon;$b++) {
$_total_date += $loop_table[$b];
}
}
}
$_total_date +=$day-1;
$ret = $_total_date * $_day_power + $hr * $_hour_power + $min * $_min_power + $sec + $gmt_different;
} else {
for ($a = 1969 ; $a >= $year; $a--) {
$leaf = _adodb_is_leap_year($a);
if ($leaf == true) {
$loop_table = $_month_table_leaf;
$_add_date = 366;
} else {
$loop_table = $_month_table_normal;
$_add_date = 365;
}
if ($a > $year) { $_total_date += $_add_date;
} else {
for($b=12;$b>$mon;$b--) {
$_total_date += $loop_table[$b];
}
}
}
$_total_date += $loop_table[$mon] - $day;
$_day_time = $hr * $_hour_power + $min * $_min_power + $sec;
$_day_time = $_day_power - $_day_time;
$ret = -( $_total_date * $_day_power + $_day_time - $gmt_different);
if ($ret < -12220185600) $ret += 10*86400; // if earlier than 5 Oct 1582 - gregorian correction
else if ($ret < -12219321600) $ret = -12219321600; // if in limbo, reset to 15 Oct 1582.
}
//print " dmy=$day/$mon/$year $hr:$min:$sec => " .$ret;
return $ret;
}
?>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,95 @@
<?php
/**
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_access extends ADODB_DataDict {
var $databaseType = 'access';
var $seqField = false;
function ActualType($meta)
{
switch($meta) {
case 'C': return 'TEXT';
case 'XL':
case 'X': return 'MEMO';
case 'C2': return 'TEXT'; // up to 32K
case 'X2': return 'MEMO';
case 'B': return 'BINARY';
case 'D': return 'DATETIME';
case 'T': return 'DATETIME';
case 'L': return 'BYTE';
case 'I': return 'INTEGER';
case 'I1': return 'BYTE';
case 'I2': return 'SMALLINT';
case 'I4': return 'INTEGER';
case 'I8': return 'INTEGER';
case 'F': return 'DOUBLE';
case 'N': return 'NUMERIC';
default:
return $meta;
}
}
// return string must begin with space
function _CreateSuffix($fname, &$ftype, $fnotnull,$fdefault,$fautoinc,$fconstraint)
{
if ($fautoinc) {
$ftype = 'COUNTER';
return '';
}
if (substr($ftype,0,7) == 'DECIMAL') $ftype = 'DECIMAL';
$suffix = '';
if (strlen($fdefault)) {
//$suffix .= " DEFAULT $fdefault";
if ($this->debug) ADOConnection::outp("Warning: Access does not supported DEFAULT values (field $fname)");
}
if ($fnotnull) $suffix .= ' NOT NULL';
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
function CreateDatabase($dbname,$options=false)
{
return array();
}
function SetSchema($schema)
{
}
function AlterColumnSQL($tabname, $flds)
{
if ($this->debug) ADOConnection::outp("AlterColumnSQL not supported");
return array();
}
function DropColumnSQL($tabname, $flds)
{
if ($this->debug) ADOConnection::outp("DropColumnSQL not supported");
return array();
}
}
?>

View File

@ -0,0 +1,76 @@
<?php
/**
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_db2 extends ADODB_DataDict {
var $databaseType = 'db2';
var $seqField = false;
function ActualType($meta)
{
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL': return 'CLOB';
case 'X': return 'VARCHAR(3600)';
case 'C2': return 'VARCHAR'; // up to 32K
case 'X2': return 'VARCHAR(3600)'; // up to 32000, but default page size too small
case 'B': return 'BLOB';
case 'D': return 'DATE';
case 'T': return 'TIMESTAMP';
case 'L': return 'SMALLINT';
case 'I': return 'INTEGER';
case 'I1': return 'SMALLINT';
case 'I2': return 'SMALLINT';
case 'I4': return 'INTEGER';
case 'I8': return 'BIGINT';
case 'F': return 'DOUBLE';
case 'N': return 'DECIMAL';
default:
return $meta;
}
}
// return string must begin with space
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint)
{
$suffix = '';
if ($fautoinc) return ' GENERATED ALWAYS AS IDENTITY'; # as identity start with
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fnotnull) $suffix .= ' NOT NULL';
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
function AlterColumnSQL($tabname, $flds)
{
if ($this->debug) ADOConnection::outp("AlterColumnSQL not supported");
return array();
}
function DropColumnSQL($tabname, $flds)
{
if ($this->debug) ADOConnection::outp("DropColumnSQL not supported");
return array();
}
}
?>

View File

@ -0,0 +1,151 @@
<?php
/**
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
class ADODB2_firebird15 extends ADODB_DataDict {
var $databaseType = 'firebird15';
var $seqField = false;
var $seqPrefix = 'gen_';
var $blobSize = 40000;
function ActualType($meta)
{
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL':
case 'X': return 'VARCHAR(4000)';
case 'C2': return 'VARCHAR'; // up to 32K
case 'X2': return 'VARCHAR(4000)';
case 'B': return 'BLOB';
case 'D': return 'DATE';
case 'T': return 'TIMESTAMP';
case 'L': return 'SMALLINT';
case 'I': return 'INTEGER';
case 'I1': return 'SMALLINT';
case 'I2': return 'SMALLINT';
case 'I4': return 'INTEGER';
case 'I8': return 'INTEGER';
case 'F': return 'DOUBLE PRECISION';
case 'N': return 'DECIMAL';
default:
return $meta;
}
}
function NameQuote($name = NULL)
{
if (!is_string($name)) {
return FALSE;
}
$name = trim($name);
if ( !is_object($this->connection) ) {
return $name;
}
$quote = $this->connection->nameQuote;
// if name is of the form `name`, quote it
if ( preg_match('/^`(.+)`$/', $name, $matches) ) {
return $quote . $matches[1] . $quote;
}
// if name contains special characters, quote it
if ( !preg_match('/^[' . $this->nameRegex . ']+$/', $name) ) {
return $quote . $name . $quote;
}
return $quote . $name . $quote;
}
function CreateDatabase($dbname, $options=false)
{
$options = $this->_Options($options);
$sql = array();
$sql[] = "DECLARE EXTERNAL FUNCTION LOWER CSTRING(80) RETURNS CSTRING(80) FREE_IT ENTRY_POINT 'IB_UDF_lower' MODULE_NAME 'ib_udf'";
return $sql;
}
function _DropAutoIncrement($t)
{
if (strpos($t,'.') !== false) {
$tarr = explode('.',$t);
return 'DROP GENERATOR '.$tarr[0].'."gen_'.$tarr[1].'"';
}
return 'DROP GENERATOR "GEN_'.$t;
}
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned)
{
$suffix = '';
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fnotnull) $suffix .= ' NOT NULL';
if ($fautoinc) $this->seqField = $fname;
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
/*
CREATE or replace TRIGGER jaddress_insert
before insert on jaddress
for each row
begin
IF ( NEW."seqField" IS NULL OR NEW."seqField" = 0 ) THEN
NEW."seqField" = GEN_ID("GEN_tabname", 1);
end;
*/
function _Triggers($tabname,$tableoptions)
{
if (!$this->seqField) return array();
$tab1 = preg_replace( '/"/', '', $tabname );
if ($this->schema) {
$t = strpos($tab1,'.');
if ($t !== false) $tab = substr($tab1,$t+1);
else $tab = $tab1;
$seqField = $this->seqField;
$seqname = $this->schema.'.'.$this->seqPrefix.$tab;
$trigname = $this->schema.'.trig_'.$this->seqPrefix.$tab;
} else {
$seqField = $this->seqField;
$seqname = $this->seqPrefix.$tab1;
$trigname = 'trig_'.$seqname;
}
if (isset($tableoptions['REPLACE']))
{ $sql[] = "DROP GENERATOR \"$seqname\"";
$sql[] = "CREATE GENERATOR \"$seqname\"";
$sql[] = "ALTER TRIGGER \"$trigname\" BEFORE INSERT OR UPDATE AS BEGIN IF ( NEW.$seqField IS NULL OR NEW.$seqField = 0 ) THEN NEW.$seqField = GEN_ID(\"$seqname\", 1); END";
}
else
{ $sql[] = "CREATE GENERATOR \"$seqname\"";
$sql[] = "CREATE TRIGGER \"$trigname\" FOR $tabname BEFORE INSERT OR UPDATE AS BEGIN IF ( NEW.$seqField IS NULL OR NEW.$seqField = 0 ) THEN NEW.$seqField = GEN_ID(\"$seqname\", 1); END";
}
$this->seqField = false;
return $sql;
}
}
?>

View File

@ -0,0 +1,125 @@
<?php
/**
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_generic extends ADODB_DataDict {
var $databaseType = 'generic';
var $seqField = false;
function ActualType($meta)
{
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL':
case 'X': return 'VARCHAR(250)';
case 'C2': return 'VARCHAR';
case 'X2': return 'VARCHAR(250)';
case 'B': return 'VARCHAR';
case 'D': return 'DATE';
case 'T': return 'DATE';
case 'L': return 'DECIMAL(1)';
case 'I': return 'DECIMAL(10)';
case 'I1': return 'DECIMAL(3)';
case 'I2': return 'DECIMAL(5)';
case 'I4': return 'DECIMAL(10)';
case 'I8': return 'DECIMAL(20)';
case 'F': return 'DECIMAL(32,8)';
case 'N': return 'DECIMAL';
default:
return $meta;
}
}
function AlterColumnSQL($tabname, $flds)
{
if ($this->debug) ADOConnection::outp("AlterColumnSQL not supported");
return array();
}
function DropColumnSQL($tabname, $flds)
{
if ($this->debug) ADOConnection::outp("DropColumnSQL not supported");
return array();
}
}
/*
//db2
function ActualType($meta)
{
switch($meta) {
case 'C': return 'VARCHAR';
case 'X': return 'VARCHAR';
case 'C2': return 'VARCHAR'; // up to 32K
case 'X2': return 'VARCHAR';
case 'B': return 'BLOB';
case 'D': return 'DATE';
case 'T': return 'TIMESTAMP';
case 'L': return 'SMALLINT';
case 'I': return 'INTEGER';
case 'I1': return 'SMALLINT';
case 'I2': return 'SMALLINT';
case 'I4': return 'INTEGER';
case 'I8': return 'BIGINT';
case 'F': return 'DOUBLE';
case 'N': return 'DECIMAL';
default:
return $meta;
}
}
// ifx
function ActualType($meta)
{
switch($meta) {
case 'C': return 'VARCHAR';// 255
case 'X': return 'TEXT';
case 'C2': return 'NVARCHAR';
case 'X2': return 'TEXT';
case 'B': return 'BLOB';
case 'D': return 'DATE';
case 'T': return 'DATETIME';
case 'L': return 'SMALLINT';
case 'I': return 'INTEGER';
case 'I1': return 'SMALLINT';
case 'I2': return 'SMALLINT';
case 'I4': return 'INTEGER';
case 'I8': return 'DECIMAL(20)';
case 'F': return 'FLOAT';
case 'N': return 'DECIMAL';
default:
return $meta;
}
}
*/
?>

View File

@ -0,0 +1,67 @@
<?php
/**
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_ibase extends ADODB_DataDict {
var $databaseType = 'ibase';
var $seqField = false;
function ActualType($meta)
{
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL':
case 'X': return 'VARCHAR(4000)';
case 'C2': return 'VARCHAR'; // up to 32K
case 'X2': return 'VARCHAR(4000)';
case 'B': return 'BLOB';
case 'D': return 'DATE';
case 'T': return 'TIMESTAMP';
case 'L': return 'SMALLINT';
case 'I': return 'INTEGER';
case 'I1': return 'SMALLINT';
case 'I2': return 'SMALLINT';
case 'I4': return 'INTEGER';
case 'I8': return 'INTEGER';
case 'F': return 'DOUBLE PRECISION';
case 'N': return 'DECIMAL';
default:
return $meta;
}
}
function AlterColumnSQL($tabname, $flds)
{
if ($this->debug) ADOConnection::outp("AlterColumnSQL not supported");
return array();
}
function DropColumnSQL($tabname, $flds)
{
if ($this->debug) ADOConnection::outp("DropColumnSQL not supported");
return array();
}
}
?>

View File

@ -0,0 +1,80 @@
<?php
/**
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_informix extends ADODB_DataDict {
var $databaseType = 'informix';
var $seqField = false;
function ActualType($meta)
{
switch($meta) {
case 'C': return 'VARCHAR';// 255
case 'XL':
case 'X': return 'TEXT';
case 'C2': return 'NVARCHAR';
case 'X2': return 'TEXT';
case 'B': return 'BLOB';
case 'D': return 'DATE';
case 'T': return 'DATETIME';
case 'L': return 'SMALLINT';
case 'I': return 'INTEGER';
case 'I1': return 'SMALLINT';
case 'I2': return 'SMALLINT';
case 'I4': return 'INTEGER';
case 'I8': return 'DECIMAL(20)';
case 'F': return 'FLOAT';
case 'N': return 'DECIMAL';
default:
return $meta;
}
}
function AlterColumnSQL($tabname, $flds)
{
if ($this->debug) ADOConnection::outp("AlterColumnSQL not supported");
return array();
}
function DropColumnSQL($tabname, $flds)
{
if ($this->debug) ADOConnection::outp("DropColumnSQL not supported");
return array();
}
// return string must begin with space
function _CreateSuffix($fname, &$ftype, $fnotnull,$fdefault,$fautoinc,$fconstraint)
{
if ($fautoinc) {
$ftype = 'SERIAL';
return '';
}
$suffix = '';
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fnotnull) $suffix .= ' NOT NULL';
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
}
?>

View File

@ -0,0 +1,250 @@
<?php
/**
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_mssql extends ADODB_DataDict {
var $databaseType = 'mssql';
var $dropIndex = 'DROP INDEX %2$s.%1$s';
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
case 'INT':
case 'INTEGER': return 'I';
case 'BIT':
case 'TINYINT': return 'I1';
case 'SMALLINT': return 'I2';
case 'BIGINT': return 'I8';
case 'REAL':
case 'FLOAT': return 'F';
default: return parent::MetaType($t,$len,$fieldobj);
}
}
function ActualType($meta)
{
switch(strtoupper($meta)) {
case 'C': return 'VARCHAR';
case 'XL':
case 'X': return 'TEXT';
case 'C2': return 'NVARCHAR';
case 'X2': return 'NTEXT';
case 'B': return 'IMAGE';
case 'D': return 'DATETIME';
case 'T': return 'DATETIME';
case 'L': return 'BIT';
case 'I': return 'INT';
case 'I1': return 'TINYINT';
case 'I2': return 'SMALLINT';
case 'I4': return 'INT';
case 'I8': return 'BIGINT';
case 'F': return 'REAL';
case 'N': return 'NUMERIC';
default:
return $meta;
}
}
function AddColumnSQL($tabname, $flds)
{
$tabname = $this->TableName ($tabname);
$f = array();
list($lines,$pkey) = $this->_GenFields($flds);
$s = "ALTER TABLE $tabname $this->addCol";
foreach($lines as $v) {
$f[] = "\n $v";
}
$s .= implode(',',$f);
$sql[] = $s;
return $sql;
}
/*
function AlterColumnSQL($tabname, $flds)
{
$tabname = $this->TableName ($tabname);
$sql = array();
list($lines,$pkey) = $this->_GenFields($flds);
foreach($lines as $v) {
$sql[] = "ALTER TABLE $tabname $this->alterCol $v";
}
return $sql;
}
*/
function DropColumnSQL($tabname, $flds)
{
$tabname = $this->TableName ($tabname);
if (!is_array($flds))
$flds = explode(',',$flds);
$f = array();
$s = 'ALTER TABLE ' . $tabname;
foreach($flds as $v) {
$f[] = "\n$this->dropCol $v";
}
$s .= implode(',',$f);
$sql[] = $s;
return $sql;
}
// return string must begin with space
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint)
{
$suffix = '';
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fautoinc) $suffix .= ' IDENTITY(1,1)';
if ($fnotnull) $suffix .= ' NOT NULL';
else if ($suffix == '') $suffix .= ' NULL';
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
/*
CREATE TABLE
[ database_name.[ owner ] . | owner. ] table_name
( { < column_definition >
| column_name AS computed_column_expression
| < table_constraint > ::= [ CONSTRAINT constraint_name ] }
| [ { PRIMARY KEY | UNIQUE } [ ,...n ]
)
[ ON { filegroup | DEFAULT } ]
[ TEXTIMAGE_ON { filegroup | DEFAULT } ]
< column_definition > ::= { column_name data_type }
[ COLLATE < collation_name > ]
[ [ DEFAULT constant_expression ]
| [ IDENTITY [ ( seed , increment ) [ NOT FOR REPLICATION ] ] ]
]
[ ROWGUIDCOL]
[ < column_constraint > ] [ ...n ]
< column_constraint > ::= [ CONSTRAINT constraint_name ]
{ [ NULL | NOT NULL ]
| [ { PRIMARY KEY | UNIQUE }
[ CLUSTERED | NONCLUSTERED ]
[ WITH FILLFACTOR = fillfactor ]
[ON {filegroup | DEFAULT} ] ]
]
| [ [ FOREIGN KEY ]
REFERENCES ref_table [ ( ref_column ) ]
[ ON DELETE { CASCADE | NO ACTION } ]
[ ON UPDATE { CASCADE | NO ACTION } ]
[ NOT FOR REPLICATION ]
]
| CHECK [ NOT FOR REPLICATION ]
( logical_expression )
}
< table_constraint > ::= [ CONSTRAINT constraint_name ]
{ [ { PRIMARY KEY | UNIQUE }
[ CLUSTERED | NONCLUSTERED ]
{ ( column [ ASC | DESC ] [ ,...n ] ) }
[ WITH FILLFACTOR = fillfactor ]
[ ON { filegroup | DEFAULT } ]
]
| FOREIGN KEY
[ ( column [ ,...n ] ) ]
REFERENCES ref_table [ ( ref_column [ ,...n ] ) ]
[ ON DELETE { CASCADE | NO ACTION } ]
[ ON UPDATE { CASCADE | NO ACTION } ]
[ NOT FOR REPLICATION ]
| CHECK [ NOT FOR REPLICATION ]
( search_conditions )
}
*/
/*
CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name
ON { table | view } ( column [ ASC | DESC ] [ ,...n ] )
[ WITH < index_option > [ ,...n] ]
[ ON filegroup ]
< index_option > :: =
{ PAD_INDEX |
FILLFACTOR = fillfactor |
IGNORE_DUP_KEY |
DROP_EXISTING |
STATISTICS_NORECOMPUTE |
SORT_IN_TEMPDB
}
*/
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
{
$sql = array();
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
$sql[] = sprintf ($this->dropIndex, $idxname, $tabname);
if ( isset($idxoptions['DROP']) )
return $sql;
}
if ( empty ($flds) ) {
return $sql;
}
$unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
$clustered = isset($idxoptions['CLUSTERED']) ? ' CLUSTERED' : '';
if ( is_array($flds) )
$flds = implode(', ',$flds);
$s = 'CREATE' . $unique . $clustered . ' INDEX ' . $idxname . ' ON ' . $tabname . ' (' . $flds . ')';
if ( isset($idxoptions[$this->upperName]) )
$s .= $idxoptions[$this->upperName];
$sql[] = $s;
return $sql;
}
function _GetSize($ftype, $ty, $fsize, $fprec)
{
switch ($ftype) {
case 'INT':
case 'SMALLINT':
case 'TINYINT':
case 'BIGINT':
return $ftype;
}
if (strlen($fsize) && $ty != 'X' && $ty != 'B' && strpos($ftype,'(') === false) {
$ftype .= "(".$fsize;
if (strlen($fprec)) $ftype .= ",".$fprec;
$ftype .= ')';
}
return $ftype;
}
}
?>

View File

@ -0,0 +1,179 @@
<?php
/**
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_mysql extends ADODB_DataDict {
var $databaseType = 'mysql';
var $alterCol = ' MODIFY COLUMN';
var $alterTableAddIndex = true;
var $dropTable = 'DROP TABLE IF EXISTS %s'; // requires mysql 3.22 or later
var $dropIndex = 'DROP INDEX %s ON %s';
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
case 'STRING':
case 'CHAR':
case 'VARCHAR':
case 'TINYBLOB':
case 'TINYTEXT':
case 'ENUM':
case 'SET':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
case 'LONGTEXT':
case 'MEDIUMTEXT':
return 'X';
// php_mysql extension always returns 'blob' even if 'text'
// so we have to check whether binary...
case 'IMAGE':
case 'LONGBLOB':
case 'BLOB':
case 'MEDIUMBLOB':
return !empty($fieldobj->binary) ? 'B' : 'X';
case 'YEAR':
case 'DATE': return 'D';
case 'TIME':
case 'DATETIME':
case 'TIMESTAMP': return 'T';
case 'FLOAT':
case 'DOUBLE':
return 'F';
case 'INT':
case 'INTEGER': return (!empty($fieldobj->primary_key)) ? 'R' : 'I';
case 'TINYINT': return (!empty($fieldobj->primary_key)) ? 'R' : 'I1';
case 'SMALLINT': return (!empty($fieldobj->primary_key)) ? 'R' : 'I2';
case 'MEDIUMINT': return (!empty($fieldobj->primary_key)) ? 'R' : 'I4';
case 'BIGINT': return (!empty($fieldobj->primary_key)) ? 'R' : 'I8';
default: return 'N';
}
}
function ActualType($meta)
{
switch(strtoupper($meta)) {
case 'C': return 'VARCHAR';
case 'XL':
case 'X': return 'LONGTEXT';
case 'C2': return 'VARCHAR';
case 'X2': return 'LONGTEXT';
case 'B': return 'LONGBLOB';
case 'D': return 'DATE';
case 'T': return 'DATETIME';
case 'L': return 'TINYINT';
case 'R':
case 'I': return 'INTEGER';
case 'I1': return 'TINYINT';
case 'I2': return 'SMALLINT';
case 'I4': return 'MEDIUMINT';
case 'I8': return 'BIGINT';
case 'F': return 'DOUBLE';
case 'N': return 'NUMERIC';
default:
return $meta;
}
}
// return string must begin with space
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned)
{
$suffix = '';
if ($funsigned) $suffix .= ' UNSIGNED';
if ($fnotnull) $suffix .= ' NOT NULL';
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fautoinc) $suffix .= ' AUTO_INCREMENT';
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
/*
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)]
[table_options] [select_statement]
create_definition:
col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
[PRIMARY KEY] [reference_definition]
or PRIMARY KEY (index_col_name,...)
or KEY [index_name] (index_col_name,...)
or INDEX [index_name] (index_col_name,...)
or UNIQUE [INDEX] [index_name] (index_col_name,...)
or FULLTEXT [INDEX] [index_name] (index_col_name,...)
or [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_col_name,...)
[reference_definition]
or CHECK (expr)
*/
/*
CREATE [UNIQUE|FULLTEXT] INDEX index_name
ON tbl_name (col_name[(length)],... )
*/
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
{
$sql = array();
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
if ($this->alterTableAddIndex) $sql[] = "ALTER TABLE $tabname DROP INDEX $idxname";
else $sql[] = sprintf($this->dropIndex, $idxname, $tabname);
if ( isset($idxoptions['DROP']) )
return $sql;
}
if ( empty ($flds) ) {
return $sql;
}
if (isset($idxoptions['FULLTEXT'])) {
$unique = ' FULLTEXT';
} elseif (isset($idxoptions['UNIQUE'])) {
$unique = ' UNIQUE';
} else {
$unique = '';
}
if ( is_array($flds) ) $flds = implode(', ',$flds);
if ($this->alterTableAddIndex) $s = "ALTER TABLE $tabname ADD $unique INDEX $idxname ";
else $s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname;
$s .= ' (' . $flds . ')';
if ( isset($idxoptions[$this->upperName]) )
$s .= $idxoptions[$this->upperName];
$sql[] = $s;
return $sql;
}
}
?>

View File

@ -0,0 +1,277 @@
<?php
/**
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_oci8 extends ADODB_DataDict {
var $databaseType = 'oci8';
var $seqField = false;
var $seqPrefix = 'SEQ_';
var $dropTable = "DROP TABLE %s CASCADE CONSTRAINTS";
var $trigPrefix = 'TRIG_';
function MetaType($t,$len=-1)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
switch (strtoupper($t)) {
case 'VARCHAR':
case 'VARCHAR2':
case 'CHAR':
case 'VARBINARY':
case 'BINARY':
if (isset($this) && $len <= $this->blobSize) return 'C';
return 'X';
case 'NCHAR':
case 'NVARCHAR2':
case 'NVARCHAR':
if (isset($this) && $len <= $this->blobSize) return 'C2';
return 'X2';
case 'NCLOB':
case 'CLOB':
return 'XL';
case 'LONG RAW':
case 'LONG VARBINARY':
case 'BLOB':
return 'B';
case 'DATE':
return 'T';
case 'INT':
case 'SMALLINT':
case 'INTEGER':
return 'I';
default:
return 'N';
}
}
function ActualType($meta)
{
switch($meta) {
case 'C': return 'VARCHAR';
case 'X': return 'VARCHAR(4000)';
case 'XL': return 'CLOB';
case 'C2': return 'NVARCHAR';
case 'X2': return 'NVARCHAR(2000)';
case 'B': return 'BLOB';
case 'D':
case 'T': return 'DATE';
case 'L': return 'DECIMAL(1)';
case 'I1': return 'DECIMAL(3)';
case 'I2': return 'DECIMAL(5)';
case 'I':
case 'I4': return 'DECIMAL(10)';
case 'I8': return 'DECIMAL(20)';
case 'F': return 'DECIMAL';
case 'N': return 'DECIMAL';
default:
return $meta;
}
}
function CreateDatabase($dbname, $options=false)
{
$options = $this->_Options($options);
$password = isset($options['PASSWORD']) ? $options['PASSWORD'] : 'tiger';
$tablespace = isset($options["TABLESPACE"]) ? " DEFAULT TABLESPACE ".$options["TABLESPACE"] : '';
$sql[] = "CREATE USER ".$dbname." IDENTIFIED BY ".$password.$tablespace;
$sql[] = "GRANT CREATE SESSION, CREATE TABLE,UNLIMITED TABLESPACE,CREATE SEQUENCE TO $dbname";
return $sql;
}
function AddColumnSQL($tabname, $flds)
{
$f = array();
list($lines,$pkey) = $this->_GenFields($flds);
$s = "ALTER TABLE $tabname ADD (";
foreach($lines as $v) {
$f[] = "\n $v";
}
$s .= implode(',',$f).')';
$sql[] = $s;
return $sql;
}
function AlterColumnSQL($tabname, $flds)
{
$f = array();
list($lines,$pkey) = $this->_GenFields($flds);
$s = "ALTER TABLE $tabname MODIFY(";
foreach($lines as $v) {
$f[] = "\n $v";
}
$s .= implode(',',$f).')';
$sql[] = $s;
return $sql;
}
function DropColumnSQL($tabname, $flds)
{
if (!is_array($flds)) $flds = explode(',',$flds);
$sql = array();
$s = "ALTER TABLE $tabname DROP(";
$s .= implode(',',$flds).') CASCADE COSTRAINTS';
$sql[] = $s;
return $sql;
}
function _DropAutoIncrement($t)
{
if (strpos($t,'.') !== false) {
$tarr = explode('.',$t);
return "drop sequence ".$tarr[0].".seq_".$tarr[1];
}
return "drop sequence seq_".$t;
}
// return string must begin with space
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned)
{
$suffix = '';
if ($fdefault == "''" && $fnotnull) {// this is null in oracle
$fnotnull = false;
if ($this->debug) ADOConnection::outp("NOT NULL and DEFAULT='' illegal in Oracle");
}
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fnotnull) $suffix .= ' NOT NULL';
if ($fautoinc) $this->seqField = $fname;
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
/*
CREATE or replace TRIGGER jaddress_insert
before insert on jaddress
for each row
begin
select seqaddress.nextval into :new.A_ID from dual;
end;
*/
function _Triggers($tabname,$tableoptions)
{
if (!$this->seqField) return array();
if ($this->schema) {
$t = strpos($tabname,'.');
if ($t !== false) $tab = substr($tabname,$t+1);
else $tab = $tabname;
$seqname = $this->schema.'.'.$this->seqPrefix.$tab;
$trigname = $this->schema.'.'.$this->trigPrefix.$this->seqPrefix.$tab;
} else {
$seqname = $this->seqPrefix.$tabname;
$trigname = $this->trigPrefix.$seqname;
}
if (isset($tableoptions['REPLACE'])) $sql[] = "DROP SEQUENCE $seqname";
$seqCache = '';
if (isset($tableoptions['SEQUENCE_CACHE'])){$seqCache = $tableoptions['SEQUENCE_CACHE'];}
$seqIncr = '';
if (isset($tableoptions['SEQUENCE_INCREMENT'])){$seqIncr = ' INCREMENT BY '.$tableoptions['SEQUENCE_INCREMENT'];}
$seqStart = '';
if (isset($tableoptions['SEQUENCE_START'])){$seqIncr = ' START WITH '.$tableoptions['SEQUENCE_START'];}
$sql[] = "CREATE SEQUENCE $seqname $seqStart $seqIncr $seqCache";
$sql[] = "CREATE OR REPLACE TRIGGER $trigname BEFORE insert ON $tabname FOR EACH ROW WHEN (NEW.$this->seqField IS NULL OR NEW.$this->seqField = 0) BEGIN select $seqname.nextval into :new.$this->seqField from dual; END;";
$this->seqField = false;
return $sql;
}
/*
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)]
[table_options] [select_statement]
create_definition:
col_name type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
[PRIMARY KEY] [reference_definition]
or PRIMARY KEY (index_col_name,...)
or KEY [index_name] (index_col_name,...)
or INDEX [index_name] (index_col_name,...)
or UNIQUE [INDEX] [index_name] (index_col_name,...)
or FULLTEXT [INDEX] [index_name] (index_col_name,...)
or [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_col_name,...)
[reference_definition]
or CHECK (expr)
*/
function _IndexSQL($idxname, $tabname, $flds,$idxoptions)
{
$sql = array();
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
$sql[] = sprintf ($this->dropIndex, $idxname, $tabname);
if ( isset($idxoptions['DROP']) )
return $sql;
}
if ( empty ($flds) ) {
return $sql;
}
if (isset($idxoptions['BITMAP'])) {
$unique = ' BITMAP';
} elseif (isset($idxoptions['UNIQUE'])) {
$unique = ' UNIQUE';
} else {
$unique = '';
}
if ( is_array($flds) )
$flds = implode(', ',$flds);
$s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' (' . $flds . ')';
if ( isset($idxoptions[$this->upperName]) )
$s .= $idxoptions[$this->upperName];
if (isset($idxoptions['oci8']))
$s .= $idxoptions['oci8'];
$sql[] = $s;
return $sql;
}
function GetCommentSQL($table,$col)
{
$table = $this->connection->qstr($table);
$col = $this->connection->qstr($col);
return "select comments from USER_COL_COMMENTS where TABLE_NAME=$table and COLUMN_NAME=$col";
}
function SetCommentSQL($table,$col,$cmt)
{
$cmt = $this->connection->qstr($cmt);
return "COMMENT ON COLUMN $table.$col IS $cmt";
}
}
?>

View File

@ -0,0 +1,217 @@
<?php
/**
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_postgres extends ADODB_DataDict {
var $databaseType = 'postgres';
var $seqField = false;
var $seqPrefix = 'SEQ_';
var $addCol = ' ADD COLUMN';
var $quote = '"';
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
switch (strtoupper($t)) {
case 'INTERVAL':
case 'CHAR':
case 'CHARACTER':
case 'VARCHAR':
case 'NAME':
case 'BPCHAR':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
return 'X';
case 'IMAGE': // user defined type
case 'BLOB': // user defined type
case 'BIT': // This is a bit string, not a single bit, so don't return 'L'
case 'VARBIT':
case 'BYTEA':
return 'B';
case 'BOOL':
case 'BOOLEAN':
return 'L';
case 'DATE':
return 'D';
case 'TIME':
case 'DATETIME':
case 'TIMESTAMP':
case 'TIMESTAMPTZ':
return 'T';
case 'INTEGER': return (empty($fieldobj->primary_key) && empty($fieldobj->unique))? 'I' : 'R';
case 'SMALLINT':
case 'INT2': return (empty($fieldobj->primary_key) && empty($fieldobj->unique))? 'I2' : 'R';
case 'INT4': return (empty($fieldobj->primary_key) && empty($fieldobj->unique))? 'I4' : 'R';
case 'BIGINT':
case 'INT8': return (empty($fieldobj->primary_key) && empty($fieldobj->unique))? 'I8' : 'R';
case 'OID':
case 'SERIAL':
return 'R';
case 'FLOAT4':
case 'FLOAT8':
case 'DOUBLE PRECISION':
case 'REAL':
return 'F';
default:
return 'N';
}
}
function ActualType($meta)
{
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL':
case 'X': return 'TEXT';
case 'C2': return 'VARCHAR';
case 'X2': return 'TEXT';
case 'B': return 'BYTEA';
case 'D': return 'DATE';
case 'T': return 'TIMESTAMP';
case 'L': return 'SMALLINT';
case 'I': return 'INTEGER';
case 'I1': return 'SMALLINT';
case 'I2': return 'INT2';
case 'I4': return 'INT4';
case 'I8': return 'INT8';
case 'F': return 'FLOAT8';
case 'N': return 'NUMERIC';
default:
return $meta;
}
}
/* The following does not work in Pg 6.0 - does anyone want to contribute code?
//"ALTER TABLE table ALTER COLUMN column SET DEFAULT mydef" and
//"ALTER TABLE table ALTER COLUMN column DROP DEFAULT mydef"
//"ALTER TABLE table ALTER COLUMN column SET NOT NULL" and
//"ALTER TABLE table ALTER COLUMN column DROP NOT NULL"*/
function AlterColumnSQL($tabname, $flds)
{
if ($this->debug) ADOConnection::outp("AlterColumnSQL not supported for PostgreSQL");
return array();
}
function DropColumnSQL($tabname, $flds)
{
if ($this->debug) ADOConnection::outp("DropColumnSQL only works with PostgreSQL 7.3+");
return ADODB_DataDict::DropColumnSQL($tabname, $flds)."/* only works for PostgreSQL 7.3+ */";
}
// return string must begin with space
function _CreateSuffix($fname, &$ftype, $fnotnull,$fdefault,$fautoinc,$fconstraint)
{
if ($fautoinc) {
$ftype = 'SERIAL';
return '';
}
$suffix = '';
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fnotnull) $suffix .= ' NOT NULL';
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
function _DropAutoIncrement($t)
{
return "drop sequence ".$t."_m_id_seq";
}
/*
CREATE [ [ LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name (
{ column_name data_type [ DEFAULT default_expr ] [ column_constraint [, ... ] ]
| table_constraint } [, ... ]
)
[ INHERITS ( parent_table [, ... ] ) ]
[ WITH OIDS | WITHOUT OIDS ]
where column_constraint is:
[ CONSTRAINT constraint_name ]
{ NOT NULL | NULL | UNIQUE | PRIMARY KEY |
CHECK (expression) |
REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL ]
[ ON DELETE action ] [ ON UPDATE action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
and table_constraint is:
[ CONSTRAINT constraint_name ]
{ UNIQUE ( column_name [, ... ] ) |
PRIMARY KEY ( column_name [, ... ] ) |
CHECK ( expression ) |
FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ]
[ MATCH FULL | MATCH PARTIAL ] [ ON DELETE action ] [ ON UPDATE action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
*/
/*
CREATE [ UNIQUE ] INDEX index_name ON table
[ USING acc_method ] ( column [ ops_name ] [, ...] )
[ WHERE predicate ]
CREATE [ UNIQUE ] INDEX index_name ON table
[ USING acc_method ] ( func_name( column [, ... ]) [ ops_name ] )
[ WHERE predicate ]
*/
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
{
$sql = array();
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
$sql[] = sprintf ($this->dropIndex, $idxname, $tabname);
if ( isset($idxoptions['DROP']) )
return $sql;
}
if ( empty ($flds) ) {
return $sql;
}
$unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
$s = 'CREATE' . $unique . ' INDEX ' . $idxname . ' ON ' . $tabname . ' ';
if (isset($idxoptions['HASH']))
$s .= 'USING HASH ';
if ( isset($idxoptions[$this->upperName]) )
$s .= $idxoptions[$this->upperName];
if ( is_array($flds) )
$flds = implode(', ',$flds);
$s .= '(' . $flds . ')';
$sql[] = $s;
return $sql;
}
}
?>

View File

@ -0,0 +1,228 @@
<?php
/**
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_sybase extends ADODB_DataDict {
var $databaseType = 'sybase';
var $dropIndex = 'DROP INDEX %2$s.%1$s';
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
case 'INT':
case 'INTEGER': return 'I';
case 'BIT':
case 'TINYINT': return 'I1';
case 'SMALLINT': return 'I2';
case 'BIGINT': return 'I8';
case 'REAL':
case 'FLOAT': return 'F';
default: return parent::MetaType($t,$len,$fieldobj);
}
}
function ActualType($meta)
{
switch(strtoupper($meta)) {
case 'C': return 'VARCHAR';
case 'XL':
case 'X': return 'TEXT';
case 'C2': return 'NVARCHAR';
case 'X2': return 'NTEXT';
case 'B': return 'IMAGE';
case 'D': return 'DATETIME';
case 'T': return 'DATETIME';
case 'L': return 'BIT';
case 'I': return 'INT';
case 'I1': return 'TINYINT';
case 'I2': return 'SMALLINT';
case 'I4': return 'INT';
case 'I8': return 'BIGINT';
case 'F': return 'REAL';
case 'N': return 'NUMERIC';
default:
return $meta;
}
}
function AddColumnSQL($tabname, $flds)
{
$tabname = $this->TableName ($tabname);
$f = array();
list($lines,$pkey) = $this->_GenFields($flds);
$s = "ALTER TABLE $tabname $this->addCol";
foreach($lines as $v) {
$f[] = "\n $v";
}
$s .= implode(',',$f);
$sql[] = $s;
return $sql;
}
function AlterColumnSQL($tabname, $flds)
{
$tabname = $this->TableName ($tabname);
$sql = array();
list($lines,$pkey) = $this->_GenFields($flds);
foreach($lines as $v) {
$sql[] = "ALTER TABLE $tabname $this->alterCol $v";
}
return $sql;
}
function DropColumnSQL($tabname, $flds)
{
$tabname = $this->TableName ($tabname);
if (!is_array($flds)) $flds = explode(',',$flds);
$f = array();
$s = "ALTER TABLE $tabname";
foreach($flds as $v) {
$f[] = "\n$this->dropCol $v";
}
$s .= implode(',',$f);
$sql[] = $s;
return $sql;
}
// return string must begin with space
function _CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint)
{
$suffix = '';
if (strlen($fdefault)) $suffix .= " DEFAULT $fdefault";
if ($fautoinc) $suffix .= ' DEFAULT AUTOINCREMENT';
if ($fnotnull) $suffix .= ' NOT NULL';
else if ($suffix == '') $suffix .= ' NULL';
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
/*
CREATE TABLE
[ database_name.[ owner ] . | owner. ] table_name
( { < column_definition >
| column_name AS computed_column_expression
| < table_constraint > ::= [ CONSTRAINT constraint_name ] }
| [ { PRIMARY KEY | UNIQUE } [ ,...n ]
)
[ ON { filegroup | DEFAULT } ]
[ TEXTIMAGE_ON { filegroup | DEFAULT } ]
< column_definition > ::= { column_name data_type }
[ COLLATE < collation_name > ]
[ [ DEFAULT constant_expression ]
| [ IDENTITY [ ( seed , increment ) [ NOT FOR REPLICATION ] ] ]
]
[ ROWGUIDCOL]
[ < column_constraint > ] [ ...n ]
< column_constraint > ::= [ CONSTRAINT constraint_name ]
{ [ NULL | NOT NULL ]
| [ { PRIMARY KEY | UNIQUE }
[ CLUSTERED | NONCLUSTERED ]
[ WITH FILLFACTOR = fillfactor ]
[ON {filegroup | DEFAULT} ] ]
]
| [ [ FOREIGN KEY ]
REFERENCES ref_table [ ( ref_column ) ]
[ ON DELETE { CASCADE | NO ACTION } ]
[ ON UPDATE { CASCADE | NO ACTION } ]
[ NOT FOR REPLICATION ]
]
| CHECK [ NOT FOR REPLICATION ]
( logical_expression )
}
< table_constraint > ::= [ CONSTRAINT constraint_name ]
{ [ { PRIMARY KEY | UNIQUE }
[ CLUSTERED | NONCLUSTERED ]
{ ( column [ ASC | DESC ] [ ,...n ] ) }
[ WITH FILLFACTOR = fillfactor ]
[ ON { filegroup | DEFAULT } ]
]
| FOREIGN KEY
[ ( column [ ,...n ] ) ]
REFERENCES ref_table [ ( ref_column [ ,...n ] ) ]
[ ON DELETE { CASCADE | NO ACTION } ]
[ ON UPDATE { CASCADE | NO ACTION } ]
[ NOT FOR REPLICATION ]
| CHECK [ NOT FOR REPLICATION ]
( search_conditions )
}
*/
/*
CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name
ON { table | view } ( column [ ASC | DESC ] [ ,...n ] )
[ WITH < index_option > [ ,...n] ]
[ ON filegroup ]
< index_option > :: =
{ PAD_INDEX |
FILLFACTOR = fillfactor |
IGNORE_DUP_KEY |
DROP_EXISTING |
STATISTICS_NORECOMPUTE |
SORT_IN_TEMPDB
}
*/
function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
{
$sql = array();
if ( isset($idxoptions['REPLACE']) || isset($idxoptions['DROP']) ) {
$sql[] = sprintf ($this->dropIndex, $idxname, $tabname);
if ( isset($idxoptions['DROP']) )
return $sql;
}
if ( empty ($flds) ) {
return $sql;
}
$unique = isset($idxoptions['UNIQUE']) ? ' UNIQUE' : '';
$clustered = isset($idxoptions['CLUSTERED']) ? ' CLUSTERED' : '';
if ( is_array($flds) )
$flds = implode(', ',$flds);
$s = 'CREATE' . $unique . $clustered . ' INDEX ' . $idxname . ' ON ' . $tabname . ' (' . $flds . ')';
if ( isset($idxoptions[$this->upperName]) )
$s .= $idxoptions[$this->upperName];
$sql[] = $s;
return $sql;
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,276 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>ADODB Data Dictionary Manual</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<style type="text/css">
body, td {
/*font-family: Arial, Helvetica, sans-serif;*/
font-size: 11pt;
}
pre {
font-size: 9pt;
background-color: #EEEEEE; padding: .5em; margin: 0px;
}
.toplink {
font-size: 8pt;
}
</style>
</head>
<body style="background-color: rgb(255, 255, 255);">
<h2>ADOdb Data Dictionary Library for PHP</h2>
<p>V4.50 6 July 2004 (c) 2000-2004 John Lim (<a
href="mailto:jlim#natsoft.com.my">jlim#natsoft.com.my</a>).<br>
AXMLS (c) 2004 ars Cognita, Inc</p>
<p><font size="1">This software is dual licensed using BSD-Style and
LGPL. This means you can use it in compiled proprietary and commercial
products.</font></p>
<table border="1">
<tbody>
<tr>
<td><font color="red">Kindly note that the ADOdb home page has
moved to <a href="http://adodb.sourceforge.net/">http://adodb.sourceforge.net/</a>
because of the persistent unreliability of http://php.weblogs.com. <b>Please
change your links</b>!</font></td>
</tr>
</tbody>
</table>
<p>Useful ADOdb links: <a href="http://adodb.sourceforge.net/#download">Download</a>
&nbsp; <a href="http://adodb.sourceforge.net/#docs">Other Docs</a>
</p>
<p>This documentation describes a PHP class library to automate the
creation of tables, indexes and foreign key constraints portably for
multiple databases. Richard Tango-Lowy and Dan Cech have been kind
enough to contribute <a href="#xmlschema">AXMLS</a>, an XML schema
system for defining databases. You can contact them at
dcech#phpwerx.net and richtl#arscognita.com.</p>
<p>Currently the following databases are supported:</p>
<p> <b>Well-tested:</b> PostgreSQL, MySQL, Oracle, MSSQL.<br>
<b>Beta-quality:</b> DB2, Informix, Sybase, Interbase, Firebird.<br>
<b>Alpha-quality:</b> MS Access (does not support DEFAULT values) and
generic ODBC.
</p>
<h3>Example Usage</h3>
<pre> include_once('adodb.inc.php');<br> <font color="#006600"># First create a normal connection</font><br> $db-&gt;NewADOConnection('mysql');<br> $db-&gt;Connect(...);<br><br> <font
color="#006600"># Then create a data dictionary object, using this connection</font><br> $dict = <strong>NewDataDictionary</strong>($db);<br><br> <font
color="#006600"># We have a portable declarative data dictionary format in ADOdb, similar to SQL.<br> # Field types use 1 character codes, and fields are separated by commas.<br> # The following example creates three fields: "col1", "col2" and "col3":</font><br> $flds = " <br> <font
color="#663300"><strong> col1 C(32) NOTNULL DEFAULT 'abc',<br> col2 I DEFAULT 0,<br> col3 N(12.2)</strong></font><br> ";<br><br> <font
color="#006600"># We demonstrate creating tables and indexes</font><br> $sqlarray = $dict-&gt;<strong>CreateTableSQL</strong>($tabname, $flds, $taboptarray);<br> $dict-&gt;<strong>ExecuteSQLArray</strong>($sqlarray);<br><br> $idxflds = 'co11, col2';<br> $sqlarray = $dict-&gt;<strong>CreateIndexSQL</strong>($idxname, $tabname, $idxflds);<br> $dict-&gt;<strong>ExecuteSQLArray</strong>($sqlarray);<br></pre>
<h3>Functions</h3>
<h4>function CreateDatabase($dbname, $optionsarray=false)</h4>
<p>Create a database with the name $dbname;</p>
<h4>function CreateTableSQL($tabname, $fldarray, $taboptarray=false)</h4>
<pre> RETURNS: an array of strings, the sql to be executed, or false<br> $tabname: name of table<br> $fldarray: string (or array) containing field info<br> $taboptarray: array containing table options<br></pre>
<p>The new format of $fldarray uses a free text format, where each
field is comma-delimited.
The first token for each field is the field name, followed by the type
and optional
field size. Then optional keywords in $otheroptions:</p>
<pre> "$fieldname $type $colsize $otheroptions"</pre>
<p>The older (and still supported) format of $fldarray is a
2-dimensional array, where each row in the 1st dimension represents one
field. Each row has this format:</p>
<pre> array($fieldname, $type, [,$colsize] [,$otheroptions]*)</pre>
<p>The first 2 fields must be the field name and the field type. The
field type can be a portable type codes or the actual type for that
database.</p>
<p>Legal portable type codes include:</p>
<pre> C: varchar<br> X: Largest varchar size <br> XL: For Oracle, returns CLOB, otherwise same as 'X' above<br><br> C2: Multibyte varchar<br> X2: Multibyte varchar (largest size)<br><br> B: BLOB (binary large object)<br><br> D: Date (some databases do not support this, and we return a datetime type)<br> T: Datetime or Timestamp<br> L: Integer field suitable for storing booleans (0 or 1)<br> I: Integer (mapped to I4)<br> I1: 1-byte integer<br> I2: 2-byte integer<br> I4: 4-byte integer<br> I8: 8-byte integer<br> F: Floating point number<br> N: Numeric or decimal number<br></pre>
<p>The $colsize field represents the size of the field. If a decimal
number is used, then it is assumed that the number following the dot is
the precision, so 6.2 means a number of size 6 digits and 2 decimal
places. It is recommended that the default for number types be
represented as a string to avoid any rounding errors.</p>
<p>The $otheroptions include the following keywords (case-insensitive):</p>
<pre> AUTO For autoincrement number. Emulated with triggers if not available.<br> Sets NOTNULL also.<br> AUTOINCREMENT Same as auto.<br> KEY Primary key field. Sets NOTNULL also. Compound keys are supported.<br> PRIMARY Same as KEY.<br> DEF Synonym for DEFAULT for lazy typists.<br> DEFAULT The default value. Character strings are auto-quoted unless<br> the string begins and ends with spaces, eg ' SYSDATE '.<br> NOTNULL If field is not null.<br> DEFDATE Set default value to call function to get today's date.<br> DEFTIMESTAMP Set default to call function to get today's datetime.<br> NOQUOTE Prevents autoquoting of default string values.<br> CONSTRAINTS Additional constraints defined at the end of the field<br> definition.<br></pre>
<p>The Data Dictonary accepts two formats, the older array
specification:</p>
<pre> $flds = array(<br> array('COLNAME', 'DECIMAL', '8.4', 'DEFAULT' =&gt; 0, 'NOTNULL'),<br> array('id', 'I' , 'AUTO'),<br> array('`MY DATE`', 'D' , 'DEFDATE'),<br> array('NAME', 'C' , '32', 'CONSTRAINTS' =&gt; 'FOREIGN KEY REFERENCES reftable')<br> );<br></pre>
<p>Or the simpler declarative format:</p>
<pre> $flds = "<font color="#660000"><strong><br> COLNAME DECIMAL(8.4) DEFAULT 0 NOTNULL,<br> id I AUTO,<br> `MY DATE` D DEFDATE,<br> NAME C(32) CONSTRAINTS 'FOREIGN KEY REFERENCES reftable'</strong></font><br> ";<br></pre>
<p>Note that if you have special characters in the field name (e.g. My
Date), you should enclose it in back-quotes. Normally field names are
not case-sensitive, but if you enclose it in back-quotes, some
databases will treat the names as case-sensitive (eg. Oracle) , and
others won't. So be careful.</p>
<p>The $taboptarray is the 3rd parameter of the CreateTableSQL
function. This contains table specific settings. Legal keywords include:</p>
<ul>
<li><b>REPLACE</b><br>
Indicates that the previous table definition should be removed
(dropped)together with ALL data. See first example below. </li>
<li><b>DROP</b><br>
Drop table. Useful for removing unused tables. </li>
<li><b>CONSTRAINTS</b><br>
Define this as the key, with the constraint as the value. See the
postgresql example below. Additional constraints defined for the whole
table. You will probably need to prefix this with a comma. </li>
</ul>
<p>Database specific table options can be defined also using the name
of the database type as the array key. In the following example, <em>create
the table as ISAM with MySQL, and store the table in the "users"
tablespace if using Oracle</em>. And because we specified REPLACE, drop
the table first.</p>
<pre> $taboptarray = array('mysql' =&gt; 'TYPE=ISAM', 'oci8' =&gt; 'tablespace users', 'REPLACE');</pre>
<p>You can also define foreignkey constraints. The following is syntax
for postgresql:
</p>
<pre> $taboptarray = array('constraints' =&gt; ', FOREIGN KEY (col1) REFERENCES reftable (refcol)');</pre>
<h4>function DropTableSQL($tabname)</h4>
<p>Returns the SQL to drop the specified table.</p>
<h4>function ChangeTableSQL($tabname, $flds)</h4>
<p>Checks to see if table exists, if table does not exist, behaves like
CreateTableSQL. If table exists, generates appropriate ALTER TABLE
MODIFY COLUMN commands if field already exists, or ALTER TABLE ADD
$column if field does not exist.</p>
<p>The class must be connected to the database for ChangeTableSQL to
detect the existence of the table. Idea and code contributed by Florian
Buzin.</p>
<h4>function CreateIndexSQL($idxname, $tabname, $flds,
$idxoptarray=false)</h4>
<pre> RETURNS: an array of strings, the sql to be executed, or false<br> $idxname: name of index<br> $tabname: name of table<br> $flds: list of fields as a comma delimited string or an array of strings<br> $idxoptarray: array of index creation options<br></pre>
<p>$idxoptarray is similar to $taboptarray in that index specific
information can be embedded in the array. Other options include:</p>
<pre> CLUSTERED Create clustered index (only mssql)<br> BITMAP Create bitmap index (only oci8)<br> UNIQUE Make unique index<br> FULLTEXT Make fulltext index (only mysql)<br> HASH Create hash index (only postgres)<br> DROP Drop legacy index<br></pre>
<h4>function DropIndexSQL ($idxname, $tabname = NULL)</h4>
<p>Returns the SQL to drop the specified index.</p>
<h4>function AddColumnSQL($tabname, $flds)</h4>
<p>Add one or more columns. Not guaranteed to work under all situations.</p>
<h4>function AlterColumnSQL($tabname, $flds)</h4>
<p>Warning, not all databases support this feature.</p>
<h4>function DropColumnSQL($tabname, $flds)</h4>
<p>Drop 1 or more columns.</p>
<h4>function SetSchema($schema)</h4>
<p>Set the schema.</p>
<h4>function &amp;MetaTables()</h4>
<h4>function &amp;MetaColumns($tab, $upper=true, $schema=false)</h4>
<h4>function &amp;MetaPrimaryKeys($tab,$owner=false,$intkey=false)</h4>
<h4>function &amp;MetaIndexes($table, $primary = false, $owner = false)</h4>
<p>These functions are wrappers for the corresponding functions in the
connection object. However, the table names will be autoquoted by the
TableName function (see below) before being passed to the connection
object.</p>
<h4>function NameQuote($name = NULL)</h4>
<p>If the provided name is quoted with backquotes (`) or contains
special characters, returns the name quoted with the appropriate quote
character, otherwise the name is returned unchanged.</p>
<h4>function TableName($name)</h4>
<p>The same as NameQuote, but will prepend the current schema if
specified</p>
<h4>function MetaType($t,$len=-1,$fieldobj=false)</h4>
<h4>function ActualType($meta)</h4>
<p>Convert between database-independent 'Meta' and database-specific
'Actual' type codes.</p>
<h4>function ExecuteSQLArray($sqlarray, $contOnError = true)</h4>
<pre> RETURNS: 0 if failed, 1 if executed all but with errors, 2 if executed successfully<br> $sqlarray: an array of strings with sql code (no semicolon at the end of string)<br> $contOnError: if true, then continue executing even if error occurs<br></pre>
<p>Executes an array of SQL strings returned by CreateTableSQL or
CreateIndexSQL.</p>
<hr>
<a name="xmlschema"></a>
<h2>ADOdb XML Schema (AXMLS)</h2>
<p>This is a class contributed by Richard Tango-Lowy and Dan Cech that
allows the user to quickly
and easily build a database using the excellent ADODB database library
and a simple XML formatted file.
You can <a href="http://sourceforge.net/projects/adodb-xmlschema/">download
the latest version of AXMLS here</a>.</p>
<h3>Quick Start</h3>
<p>Adodb-xmlschema, or AXMLS, is a set of classes that allow the user
to quickly and easily build or upgrade a database on almost any RDBMS
using the excellent ADOdb database library and a simple XML formatted
schema file. Our goal is to give developers a tool that's simple to
use, but that will allow them to create a single file that can build,
upgrade, and manipulate databases on most RDBMS platforms.</p>
<span style="font-weight: bold;"> Installing axmls</span>
<p>The easiest way to install AXMLS to download and install any recent
version of the ADOdb database abstraction library. To install AXMLS
manually, simply copy the adodb-xmlschema.inc.php file and the xsl
directory into your adodb directory.</p>
<span style="font-weight: bold;"> Using AXMLS in Your Application</span>
<p>There are two steps involved in using AXMLS in your application:
first, you must create a schema, or XML representation of your
database, and second, you must create the PHP code that will parse and
execute the schema.</p>
<p>Let's begin with a schema that describes a typical, if simplistic
user management table for an application.</p>
<pre class="listing"><pre>&lt;?xml version="1.0"?&gt;<br>&lt;schema version="0.2"&gt;<br><br> &lt;table name="users"&gt;<br> &lt;desc&gt;A typical users table for our application.&lt;/desc&gt;<br> &lt;field name="userId" type="I"&gt;<br> &lt;descr&gt;A unique ID assigned to each user.&lt;/descr&gt;<br><br> &lt;KEY/&gt;<br> &lt;AUTOINCREMENT/&gt;<br> &lt;/field&gt;<br> <br> &lt;field name="userName" type="C" size="16"&gt;&lt;NOTNULL/&gt;&lt;/field&gt;<br><br> <br> &lt;index name="userName"&gt;<br> &lt;descr&gt;Put a unique index on the user name&lt;/descr&gt;<br> &lt;col&gt;userName&lt;/col&gt;<br> &lt;UNIQUE/&gt;<br><br> &lt;/index&gt;<br> &lt;/table&gt;<br> <br> &lt;sql&gt;<br> &lt;descr&gt;Insert some data into the users table.&lt;/descr&gt;<br> &lt;query&gt;insert into users (userName) values ( 'admin' )&lt;/query&gt;<br><br> &lt;query&gt;insert into users (userName) values ( 'Joe' )&lt;/query&gt;<br> &lt;/sql&gt;<br>&lt;/schema&gt; <br></pre></pre>
<p>Let's take a detailed look at this schema.</p>
<p>The opening &lt;?xml version="1.0"?&gt; tag is required by XML. The
&lt;schema&gt; tag tells the parser that the enclosed markup defines an
XML schema. The version="0.2" attribute sets <em>the version of the
AXMLS DTD used by the XML schema.</em> </p>
<p>All versions of AXMLS prior to version 1.0 have a schema version of
"0.1". The current schema version is "0.2".</p>
<pre class="listing"><pre>&lt;?xml version="1.0"?&gt;<br>&lt;schema version="0.2"&gt;<br> ...<br>&lt;/schema&gt;<br></pre></pre>
<p>Next we define one or more tables. A table consists of a fields (and
other objects) enclosed by &lt;table&gt; tags. The name="" attribute
specifies the name of the table that will be created in the database.</p>
<pre class="listing"><pre>&lt;table name="users"&gt;<br><br> &lt;desc&gt;A typical users table for our application.&lt;/desc&gt;<br> &lt;field name="userId" type="I"&gt;<br><br> &lt;descr&gt;A unique ID assigned to each user.&lt;/descr&gt;<br> &lt;KEY/&gt;<br> &lt;AUTOINCREMENT/&gt;<br> &lt;/field&gt;<br> <br> &lt;field name="userName" type="C" size="16"&gt;&lt;NOTNULL/&gt;&lt;/field&gt;<br><br> <br>&lt;/table&gt;<br></pre></pre>
<p>This table is called "users" and has a description and two fields.
The description is optional, and is currently only for your own
information; it is not applied to the database.</p>
<p>The first &lt;field&gt; tag will create a field named "userId" of
type "I", or integer. (See the ADOdb Data Dictionary documentation for
a list of valid types.) This &lt;field&gt; tag encloses two special
field options: &lt;KEY/&gt;, which specifies this field as a primary
key, and &lt;AUTOINCREMENT/&gt;, which specifies that the database
engine should automatically fill this field with the next available
value when a new row is inserted.</p>
<p>The second &lt;field&gt; tag will create a field named "userName" of
type "C", or character, and of length 16 characters. The
&lt;NOTNULL/&gt; option specifies that this field does not allow NULLs.</p>
<p>There are two ways to add indexes to a table. The simplest is to
mark a field with the &lt;KEY/&gt; option as described above; a primary
key is a unique index. The second and more powerful method uses the
&lt;index&gt; tags.</p>
<pre class="listing"><pre>&lt;table name="users"&gt;<br> ...<br> <br> &lt;index name="userName"&gt;<br> &lt;descr&gt;Put a unique index on the user name&lt;/descr&gt;<br> &lt;col&gt;userName&lt;/col&gt;<br><br> &lt;UNIQUE/&gt;<br> &lt;/index&gt;<br> <br>&lt;/table&gt;<br></pre></pre>
<p>The &lt;index&gt; tag specifies that an index should be created on
the enclosing table. The name="" attribute provides the name of the
index that will be created in the database. The description, as above,
is for your information only. The &lt;col&gt; tags list each column
that will be included in the index. Finally, the &lt;UNIQUE/&gt; tag
specifies that this will be created as a unique index.</p>
<p>Finally, AXMLS allows you to include arbitrary SQL that will be
applied to the database when the schema is executed.</p>
<pre class="listing"><pre>&lt;sql&gt;<br> &lt;descr&gt;Insert some data into the users table.&lt;/descr&gt;<br> &lt;query&gt;insert into users (userName) values ( 'admin' )&lt;/query&gt;<br><br> &lt;query&gt;insert into users (userName) values ( 'Joe' )&lt;/query&gt;<br>&lt;/sql&gt;<br></pre></pre>
<p>The &lt;sql&gt; tag encloses any number of SQL queries that you
define for your own use.</p>
<p>Now that we've defined an XML schema, you need to know how to apply
it to your database. Here's a simple PHP script that shows how to load
the schema.</p>
<pre class="listing"><pre>&lt;?PHP<br>/* You must tell the script where to find the ADOdb and<br> * the AXMLS libraries.<br> */<br>require( "path_to_adodb/adodb.inc.php");<br>require( "path_to_adodb/adodb-xmlschema.inc.php" );<br><br>/* Configuration information. Define the schema filename,<br> * RDBMS platform (see the ADODB documentation for valid<br> * platform names), and database connection information here.<br> */<br>$schemaFile = 'example.xml';<br>$platform = 'mysql';<br>$dbHost = 'localhost';<br>$dbName = 'database';<br>$dbUser = 'username';<br>$dbPassword = 'password';<br><br>/* Start by creating a normal ADODB connection.<br> */<br>$db = ADONewConnection( $platform );<br>$db-&gt;Connect( $dbHost, $dbUser, $dbPassword, $dbName );<br><br>/* Use the database connection to create a new adoSchema object.<br> */<br>$schema = new adoSchema( $db );<br><br>/* Call ParseSchema() to build SQL from the XML schema file.<br> * Then call ExecuteSchema() to apply the resulting SQL to <br> * the database.<br> */<br>$sql = $schema-&gt;ParseSchema( $schemaFile );<br>$result = $schema-&gt;ExecuteSchema();<br>?&gt;<br></pre></pre>
<p>Let's look at each part of the example in turn. After you manually
create the database, there are three steps required to load (or
upgrade) your schema.</p>
<p>First, create a normal ADOdb connection. The variables and values
here should be those required to connect to your database.</p>
<pre class="listing"><pre>$db = ADONewConnection( 'mysql' );<br>$db-&gt;Connect( 'host', 'user', 'password', 'database' );<br></pre></pre>
<p>Second, create the adoSchema object that load and manipulate your
schema. You must pass an ADOdb database connection object in order to
create the adoSchema object.</p>
<pre class="listing"><pre>$schema = new adoSchema( $db );<br></pre></pre>
<p>Third, call ParseSchema() to parse the schema and then
ExecuteSchema() to apply it to the database. You must pass
ParseSchema() the path and filename of your schema file.</p>
<pre class="listing"><pre><br>$schema-&gt;ParseSchema( $schemaFile ); <br>$schema-&gt;ExecuteSchema(); <br></pre></pre>
<p>Execute the above code and then log into your database. If you've
done all this right, you should see your tables, indexes, and SQL.</p>
<p>You can find the source files for this tutorial in the examples
directory as tutorial_shema.xml and tutorial.php. See the class
documentation for a more detailed description of the adoSchema methods,
including methods and schema elements that are not described in this
tutorial.</p>
<h3>Upgrading</h3>
If your schema version is older, than XSLT is used to transform the
schema to the newest version. This means that if you are using an older
XML schema format, you need to have the XSLT extension installed.
If you do not want to require your users to have the XSLT extension
installed, make sure you modify your XML schema to conform to the
latest version.
<hr>
<address>If you have any questions or comments, please email them to
Richard at richtl#arscognita.com.
</address>
</body>
</html>

View File

@ -0,0 +1,972 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>ADOdb Performance Monitoring Library</title>
<style type="text/css">
body, td {
/*font-family: Arial, Helvetica, sans-serif;*/
font-size: 11pt;
}
pre {
font-size: 9pt;
background-color: #EEEEEE; padding: .5em; margin: 0px;
}
.toplink {
font-size: 8pt;
}
</style>
</head>
<body>
<h3>The ADOdb Performance Monitoring Library</h3>
<p>V4.50 6 July 2004 (c) 2000-2004 John Lim (jlim#natsoft.com.my)</p>
<p><font size="1">This software is dual licensed using BSD-Style and
LGPL. This means you can use it in compiled proprietary and commercial
products.</font></p>
<table border="1">
<tbody>
<tr>
<td><font color="red">Kindly note that the ADOdb home page has
moved to <a href="http://adodb.sourceforge.net/">http://adodb.sourceforge.net/</a>
because of the persistent unreliability of http://php.weblogs.com. <b>Please
change your links</b>!</font></td>
</tr>
</tbody>
</table>
<p>Useful ADOdb links: <a href="http://adodb.sourceforge.net/#download">Download</a>
&nbsp; <a href="http://adodb.sourceforge.net/#docs">Other Docs</a>
</p>
<h3>Introduction</h3>
<p>This module, part of the ADOdb package, provides both CLI and HTML
interfaces for viewing key performance indicators of your database.
This is very useful because web apps such as the popular phpMyAdmin
currently do not provide effective database health monitoring tools.
The module provides the following: </p>
<ul>
<li>A quick health check of your database server using <code>$perf-&gt;HealthCheck()</code>
or <code>$perf-&gt;HealthCheckCLI()</code>. </li>
<li>User interface for performance monitoring, <code>$perf-&gt;UI()</code>.
This UI displays:
<ul>
<li>the health check, </li>
<li>all SQL logged and their query plans, </li>
<li>a list of all tables in the current database</li>
<li>an interface to continiously poll the server for key
performance indicators such as CPU, Hit Ratio, Disk I/O</li>
<li>a form where you can enter and run SQL interactively.</li>
</ul>
</li>
<li>Gives you an API to build database monitoring tools for a server
farm, for example calling <code>$perf-&gt;DBParameter('data cache hit
ratio')</code> returns this very important statistic in a database
independant manner. </li>
</ul>
<p>ADOdb also has the ability to log all SQL executed, using <a
href="docs-adodb.htm#logsql">LogSQL</a>. All SQL logged can be
analyzed through the performance monitor <a href="#ui">UI</a>. In the <i>View
SQL</i> mode, we categorize the SQL into 3 types:
</p>
<ul>
<li><b>Suspicious SQL</b>: queries with high average execution times,
and are potential candidates for rewriting</li>
<li><b>Expensive SQL</b>: queries with high total execution times
(#executions * avg execution time). Optimizing these queries will
reduce your database server load.</li>
<li><b>Invalid SQL</b>: queries that generate errors.</li>
</ul>
<p>Each query is hyperlinked to a description of the query plan, and
every PHP script that executed that query is also shown.</p>
<p>Please note that the information presented is a very basic database
health check, and does not provide a complete overview of database
performance. Although some attempt has been made to make it work across
multiple databases in the same way, it is impossible to do so. For the
health check, we do try to display the following key database
parameters for all drivers:</p>
<ul>
<li><b>data cache size</b> - The amount of memory allocated to the
cache.</li>
<li><b>data cache hit ratio</b> - A measure of how effective the
cache is, as a percentage. The higher, the better.</li>
<li><b>current connections</b> - The number of sessions currently
connected to the database. </li>
</ul>
<p>You will need to connect to the database as an administrator to view
most of the parameters. </p>
<p>Code improvements as very welcome, particularly adding new database
parameters and automated tuning hints.</p>
<a name="usage"></a>
<h3>Usage</h3>
<p>Currently, the following drivers: <em>mysql</em>, <em>postgres</em>,
<em>oci8</em>, <em>mssql</em>, <i>informix</i> and <em>db2</em> are
supported. To create a new performance monitor, call NewPerfMonitor( )
as demonstrated below: </p>
<pre>&lt;?php<br>include_once('adodb.inc.php');<br>session_start(); <font
color="#006600"># session variables required for monitoring</font><br>$conn = ADONewConnection($driver);<br>$conn-&gt;Connect($server,$user,$pwd,$db);<br>$perf =&amp; NewPerfMonitor($conn);<br>$perf-&gt;UI($pollsecs=5);<br>?&gt;<br></pre>
<p>It is also possible to retrieve a single database parameter:</p>
<pre>$size = $perf-&gt;DBParameter('data cache size');<br></pre>
<p>
Thx to Fernando Ortiz for the informix module. </p>
<h3>Methods</h3>
<a name="ui"></a>
<p><font face="Courier New, Courier, mono">function <b>UI($pollsecs=5)</b></font></p>
<p>Creates a web-based user interface for performance monitoring. When
you click on Poll, server statistics will be displayed every $pollsecs
seconds. See <a href="#usage">Usage</a> above. </p>
<p>Since 4.11, we allow users to enter and run SQL interactively via
the "Run SQL" link. To disable this for security reasons, set this
constant before calling $perf-&gt;UI(). </p>
<p> </p>
<pre>define('ADODB_PERF_NO_RUN_SQL',1);</pre>
<p>Sample output follows below:</p>
<table bgcolor="lightyellow" border="1" width="100%">
<tbody>
<tr>
<td> <b><a href="http://php.weblogs.com/adodb?perf=1">ADOdb</a>
Performance Monitor</b> for localhost, db=test<br>
<font size="-1">PostgreSQL 7.3.2 on i686-pc-cygwin, compiled by
GCC gcc (GCC) 3.2 20020927 (prerelease)</font></td>
</tr>
<tr>
<td> <a href="#">Performance Stats</a> &nbsp; <a href="#">View
SQL</a> &nbsp; <a href="#">View Tables</a> &nbsp; <a href="#">Poll
Stats</a></td>
</tr>
</tbody>
</table>
<table bgcolor="white" border="1">
<tbody>
<tr>
<td colspan="3">
<h3>postgres7</h3>
</td>
</tr>
<tr>
<td><b>Parameter</b></td>
<td><b>Value</b></td>
<td><b>Description</b></td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Ratios</i> &nbsp;</td>
</tr>
<tr>
<td>statistics collector</td>
<td>TRUE</td>
<td>Value must be TRUE to enable hit ratio statistics (<i>stats_start_collector</i>,<i>stats_row_level</i>
and <i>stats_block_level</i> must be set to true in postgresql.conf)</td>
</tr>
<tr>
<td>data cache hit ratio</td>
<td>99.7967555299239</td>
<td>&nbsp;</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>IO</i> &nbsp;</td>
</tr>
<tr>
<td>data reads</td>
<td>125</td>
<td>&nbsp; </td>
</tr>
<tr>
<td>data writes</td>
<td>21.78125000000000000</td>
<td>Count of inserts/updates/deletes * coef</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Data Cache</i> &nbsp;</td>
</tr>
<tr>
<td>data cache buffers</td>
<td>640</td>
<td>Number of cache buffers. <a
href="http://www.varlena.com/GeneralBits/Tidbits/perf.html#basic">Tuning</a></td>
</tr>
<tr>
<td>cache blocksize</td>
<td>8192</td>
<td>(estimate)</td>
</tr>
<tr>
<td>data cache size</td>
<td>5M</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>operating system cache size</td>
<td>80M</td>
<td>(effective cache size)</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Memory Usage</i> &nbsp;</td>
</tr>
<tr>
<td>sort buffer size</td>
<td>1M</td>
<td>Size of sort buffer (per query)</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Connections</i> &nbsp;</td>
</tr>
<tr>
<td>current connections</td>
<td>0</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>max connections</td>
<td>32</td>
<td>&nbsp;</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Parameters</i> &nbsp;</td>
</tr>
<tr>
<td>rollback buffers</td>
<td>8</td>
<td>WAL buffers</td>
</tr>
<tr>
<td>random page cost</td>
<td>4</td>
<td>Cost of doing a seek (default=4). See <a
href="http://www.varlena.com/GeneralBits/Tidbits/perf.html#less">random_page_cost</a></td>
</tr>
</tbody>
</table>
<p><font face="Courier New, Courier, mono">function <b>HealthCheck</b>()</font></p>
<p>Returns database health check parameters as a HTML table. You will
need to echo or print the output of this function,</p>
<p><font face="Courier New, Courier, mono">function <b>HealthCheckCLI</b>()</font></p>
<p>Returns database health check parameters formatted for a command
line interface. You will need to echo or print the output of this
function. Sample output for mysql:</p>
<pre>-- Ratios -- <br> MyISAM cache hit ratio =&gt; 56.5635738832 <br> InnoDB cache hit ratio =&gt; 0 <br> sql cache hit ratio =&gt; 0 <br> -- IO -- <br> data reads =&gt; 2622 <br> data writes =&gt; 2415.5 <br> -- Data Cache -- <br> MyISAM data cache size =&gt; 512K <br> BDB data cache size =&gt; 8388600<br> InnoDB data cache size =&gt; 8M<br> -- Memory Pools -- <br> read buffer size =&gt; 131072 <br> sort buffer size =&gt; 65528 <br> table cache =&gt; 4 <br> -- Connections -- <br> current connections =&gt; 3<br> max connections =&gt; 100</pre>
<p><font face="Courier New, Courier, mono">function <b>Poll</b>($pollSecs=5)
</font> </p>
<p> Run in infinite loop, displaying the following information every
$pollSecs. This will not work properly if output buffering is enabled.
In the example below, $pollSecs=3:
</p>
<pre>Accumulating statistics...<br> Time WS-CPU% Hit% Sess Reads/s Writes/s<br>11:08:30 0.7 56.56 1 0.0000 0.0000<br>11:08:33 1.8 56.56 2 0.0000 0.0000<br>11:08:36 11.1 56.55 3 2.5000 0.0000<br>11:08:39 9.8 56.55 2 3.1121 0.0000<br>11:08:42 2.8 56.55 1 0.0000 0.0000<br>11:08:45 7.4 56.55 2 0.0000 1.5000<br></pre>
<p><b>WS-CPU%</b> is the Web Server CPU load of the server that PHP is
running from (eg. the database client), and not the database. The <b>Hit%</b>
is the data cache hit ratio. <b>Sess</b> is the current number of
sessions connected to the database. If you are using persistent
connections, this should not change much. The <b>Reads/s</b> and <b>Writes/s</b>
are synthetic values to give the viewer a rough guide to I/O, and are
not to be taken literally. </p>
<p><font face="Courier New, Courier, mono">function <b>SuspiciousSQL</b>($numsql=10)</font></p>
<p>Returns SQL which have high average execution times as a HTML table.
Each sql statement
is hyperlinked to a new window which details the execution plan and the
scripts that execute this SQL.
</p>
<p> The number of statements returned is determined by $numsql. Data is
taken from the adodb_logsql table, where the sql statements are logged
when
$connection-&gt;LogSQL(true) is enabled. The adodb_logsql table is
populated using <a href="docs-adodb.htm#logsql">$conn-&gt;LogSQL</a>.
</p>
<p>For Oracle, Ixora Suspicious SQL returns a list of SQL statements
that are most cache intensive as a HTML table. These are data intensive
SQL statements that could benefit most from tuning. </p>
<p><font face="Courier New, Courier, mono">function <b>ExpensiveSQL</b>($numsql=10)</font></p>
<p>Returns SQL whose total execution time (avg time * #executions) is
high as a HTML table. Each sql statement
is hyperlinked to a new window which details the execution plan and the
scripts that execute this SQL.
</p>
<p> The number of statements returned is determined by $numsql. Data is
taken from the adodb_logsql table, where the sql statements are logged
when
$connection-&gt;LogSQL(true) is enabled. The adodb_logsql table is
populated using <a href="docs-adodb.htm#logsql">$conn-&gt;LogSQL</a>.
</p>
<p>For Oracle, Ixora Expensive SQL returns a list of SQL statements
that are taking the most CPU load when run.
</p>
<p><font face="Courier New, Courier, mono">function <b>InvalidSQL</b>($numsql=10)</font></p>
<p>Returns a list of invalid SQL as an HTML table.
</p>
<p>Data is taken from the adodb_logsql table, where the sql statements
are logged when
$connection-&gt;LogSQL(true) is enabled.
</p>
<p><font face="Courier New, Courier, mono">function <b>Tables</b>($orderby=1)</font></p>
<p>Returns information on all tables in a database, with the first two
fields containing the table name and table size, the remaining fields
depend on the database driver. If $orderby is set to 1, it will sort by
name. If $orderby is set to 2, then it will sort by table size. Some
database drivers (mssql and mysql) will ignore the $orderby clause. For
postgresql, the information is up-to-date since the last <i>vacuum</i>.
Not supported currently for db2.</p>
<h3>Raw Functions</h3>
<p>Raw functions return values without any formatting.</p>
<p><font face="Courier New, Courier, mono">function <b>DBParameter</b>($paramname)</font></p>
<p>Returns the value of a database parameter, such as
$this-&gt;DBParameter("data cache size").</p>
<p><font face="Courier New, Courier, mono">function <b>CPULoad</b>()</font></p>
<p>Returns the CPU load of the database client (NOT THE SERVER) as a
percentage. Only works for Linux and Windows. For Windows, WMI must be
available.</p>
<h3>Format of $settings Property</h3>
<p> To create new database parameters, you need to understand
$settings. The $settings data structure is an associative array. Each
element of the array defines a database parameter. The key is the name
of the database parameter. If no key is defined, then it is assumed to
be a section break, and the value is the name of the section break. If
this is too confusing, looking at the source code will help a lot!</p>
<p> Each database parameter is itself an array consisting of the
following elements:</p>
<ol start="0">
<li> Category code, used to group related db parameters. If the
category code is 'HIDE', then
the database parameter is not shown when HTML() is called. <br>
</li>
<li> either
<ol type="a">
<li>sql string to retrieve value, eg. "select value from
v\$parameter where name='db_block_size'", </li>
<li>array holding sql string and field to look for, e.g.
array('show variables','table_cache'); optional 3rd parameter is the
$rs-&gt;fields[$index] to use (otherwise $index=1), and optional 4th
parameter is a constant to multiply the result with (typically 100 for
percentage calculations),</li>
<li>a string prefixed by =, then a PHP method of the class is
invoked, e.g. to invoke $this-&gt;GetIndexValue(), set this array
element to '=GetIndexValue', <br>
</li>
</ol>
</li>
<li> Description of database parameter. If description begins with an
=, then it is interpreted as a method call, just as in (1c) above,
taking one parameter, the current value. E.g. '=GetIndexDescription'
will invoke $this-&gt;GetIndexDescription($val). This is useful for
generating tuning suggestions. For an example, see WarnCacheRatio().</li>
</ol>
<p>Example from MySQL, table_cache database parameter:</p>
<pre>'table cache' =&gt; array('CACHE', # category code<br> array("show variables", 'table_cache'), # array (type 1b)<br> 'Number of tables to keep open'), # description</pre>
<h3>Example Health Check Output</h3>
<p><a href="#db2">db2</a> <a href="#informix">informix</a> <a
href="#mysql">mysql</a> <a href="#mssql">mssql</a> <a href="#oci8">oci8</a>
<a href="#postgres">postgres</a></p>
<p><a name="db2"></a></p>
<table bgcolor="white" border="1">
<tbody>
<tr>
<td colspan="3">
<h3>db2</h3>
</td>
</tr>
<tr>
<td><b>Parameter</b></td>
<td><b>Value</b></td>
<td><b>Description</b></td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Ratios</i> &nbsp;</td>
</tr>
<tr bgcolor="#ffffff">
<td>data cache hit ratio</td>
<td>0 &nbsp; </td>
<td>&nbsp;</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Data Cache</i></td>
</tr>
<tr bgcolor="#ffffff">
<td>data cache buffers</td>
<td>250 &nbsp; </td>
<td>See <a
href="http://www7b.boulder.ibm.com/dmdd/library/techarticle/anshum/0107anshum.html#bufferpoolsize">tuning
reference</a>.</td>
</tr>
<tr bgcolor="#ffffff">
<td>cache blocksize</td>
<td>4096 &nbsp; </td>
<td>&nbsp;</td>
</tr>
<tr bgcolor="#ffffff">
<td>data cache size</td>
<td>1000K &nbsp; </td>
<td>&nbsp;</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Connections</i></td>
</tr>
<tr bgcolor="#ffffff">
<td>current connections</td>
<td>2 &nbsp; </td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><a name="informix"></a>
<table bgcolor="white" border="1">
<tbody>
<tr>
<td colspan="3">
<h3>informix</h3>
</td>
</tr>
<tr>
<td><b>Parameter</b></td>
<td><b>Val
ue</b></td>
<td><b>Description</b></td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Ratios</i> &nbsp;</td>
</tr>
<tr>
<td>data cache hit
ratio</td>
<td>95.89</td>
<td>&nbsp;</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>IO</i> &nbsp;</td>
</tr>
<tr>
<td>data
reads</td>
<td>1883884</td>
<td>Page reads</td>
</tr>
<tr>
<td>data writes</td>
<td>1716724</td>
<td>Page writes</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Connections</i>
&nbsp;</td>
</tr>
<tr>
<td>current connections</td>
<td>263.0</td>
<td>Number of
sessions</td>
</tr>
</tbody>
</table>
</p>
<p>&nbsp;</p>
<p><a name="mysql" id="mysql"></a></p>
<table bgcolor="white" border="1">
<tbody>
<tr>
<td colspan="3">
<h3>mysql</h3>
</td>
</tr>
<tr>
<td><b>Parameter</b></td>
<td><b>Value</b></td>
<td><b>Description</b></td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Ratios</i> &nbsp;</td>
</tr>
<tr>
<td>MyISAM cache hit ratio</td>
<td>56.5658301822</td>
<td><font color="red"><b>Cache ratio should be at least 90%</b></font></td>
</tr>
<tr>
<td>InnoDB cache hit ratio</td>
<td>0</td>
<td><font color="red"><b>Cache ratio should be at least 90%</b></font></td>
</tr>
<tr>
<td>sql cache hit ratio</td>
<td>0</td>
<td>&nbsp;</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>IO</i> &nbsp;</td>
</tr>
<tr>
<td>data reads</td>
<td>2622</td>
<td>Number of selects (Key_reads is not accurate)</td>
</tr>
<tr>
<td>data writes</td>
<td>2415.5</td>
<td>Number of inserts/updates/deletes * coef (Key_writes is not
accurate)</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Data Cache</i> &nbsp;</td>
</tr>
<tr>
<td>MyISAM data cache size</td>
<td>512K</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>BDB data cache size</td>
<td>8388600</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>InnoDB data cache size</td>
<td>8M</td>
<td>&nbsp;</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Memory Pools</i> &nbsp;</td>
</tr>
<tr>
<td>read buffer size</td>
<td>131072</td>
<td>(per session)</td>
</tr>
<tr>
<td>sort buffer size</td>
<td>65528</td>
<td>Size of sort buffer (per session)</td>
</tr>
<tr>
<td>table cache</td>
<td>4</td>
<td>Number of tables to keep open</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Connections</i> &nbsp;</td>
</tr>
<tr>
<td>current connections</td>
<td>3</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>max connections</td>
<td>100</td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><a name="mssql" id="mssql"></a></p>
<table bgcolor="white" border="1">
<tbody>
<tr>
<td colspan="3">
<h3>mssql</h3>
</td>
</tr>
<tr>
<td><b>Parameter</b></td>
<td><b>Value</b></td>
<td><b>Description</b></td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Ratios</i> &nbsp;</td>
</tr>
<tr>
<td>data cache hit ratio</td>
<td>99.9999694824</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>prepared sql hit ratio</td>
<td>99.7738579828</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>adhoc sql hit ratio</td>
<td>98.4540169133</td>
<td>&nbsp;</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>IO</i> &nbsp;</td>
</tr>
<tr>
<td>data reads</td>
<td>2858</td>
<td>&nbsp; </td>
</tr>
<tr>
<td>data writes</td>
<td>1438</td>
<td>&nbsp; </td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Data Cache</i> &nbsp;</td>
</tr>
<tr>
<td>data cache size</td>
<td>4362</td>
<td>in K</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Connections</i> &nbsp;</td>
</tr>
<tr>
<td>current connections</td>
<td>14</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>max connections</td>
<td>32767</td>
<td>&nbsp;</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><a name="oci8" id="oci8"></a></p>
<table bgcolor="white" border="1">
<tbody>
<tr>
<td colspan="3">
<h3>oci8</h3>
</td>
</tr>
<tr>
<td><b>Parameter</b></td>
<td><b>Value</b></td>
<td><b>Description</b></td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Ratios</i> &nbsp;</td>
</tr>
<tr>
<td>data cache hit ratio</td>
<td>96.98</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>sql cache hit ratio</td>
<td>99.96</td>
<td>&nbsp;</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>IO</i> &nbsp;</td>
</tr>
<tr>
<td>data reads</td>
<td>842938</td>
<td>&nbsp; </td>
</tr>
<tr>
<td>data writes</td>
<td>16852</td>
<td>&nbsp; </td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Data Cache</i> &nbsp;</td>
</tr>
<tr>
<td>data cache buffers</td>
<td>3072</td>
<td>Number of cache buffers</td>
</tr>
<tr>
<td>data cache blocksize</td>
<td>8192</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>data cache size</td>
<td>48M</td>
<td>shared_pool_size</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Memory Pools</i> &nbsp;</td>
</tr>
<tr>
<td>java pool size</td>
<td>0</td>
<td>java_pool_size</td>
</tr>
<tr>
<td>sort buffer size</td>
<td>512K</td>
<td>sort_area_size (per query)</td>
</tr>
<tr>
<td>user session buffer size</td>
<td>8M</td>
<td>large_pool_size</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Connections</i> &nbsp;</td>
</tr>
<tr>
<td>current connections</td>
<td>1</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>max connections</td>
<td>170</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>data cache utilization ratio</td>
<td>88.46</td>
<td>Percentage of data cache actually in use</td>
</tr>
<tr>
<td>user cache utilization ratio</td>
<td>91.76</td>
<td>Percentage of user cache (large_pool) actually in use</td>
</tr>
<tr>
<td>rollback segments</td>
<td>11</td>
<td>&nbsp;</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Transactions</i> &nbsp;</td>
</tr>
<tr>
<td>peak transactions</td>
<td>24</td>
<td>Taken from high-water-mark</td>
</tr>
<tr>
<td>max transactions</td>
<td>187</td>
<td>max transactions / rollback segments &lt; 3.5 (or
transactions_per_rollback_segment)</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Parameters</i> &nbsp;</td>
</tr>
<tr>
<td>cursor sharing</td>
<td>EXACT</td>
<td>Cursor reuse strategy. Recommended is FORCE (8i+) or SIMILAR
(9i+). See <a
href="http://www.praetoriate.com/oracle_tips_cursor_sharing.htm">cursor_sharing</a>.</td>
</tr>
<tr>
<td>index cache cost</td>
<td>0</td>
<td>% of indexed data blocks expected in the cache. Recommended
is 20-80. Default is 0. See <a
href="http://www.dba-oracle.com/oracle_tips_cbo_part1.htm">optimizer_index_caching</a>.</td>
</tr>
<tr>
<td>random page cost</td>
<td>100</td>
<td>Recommended is 10-50 for TP, and 50 for data warehouses.
Default is 100. See <a
href="http://www.dba-oracle.com/oracle_tips_cost_adj.htm">optimizer_index_cost_adj</a>.
</td>
</tr>
</tbody>
</table>
<h3>Suspicious SQL</h3>
<table bgcolor="white" border="1">
<tbody>
<tr>
<td><b>LOAD</b></td>
<td><b>EXECUTES</b></td>
<td><b>SQL_TEXT</b></td>
</tr>
<tr>
<td align="right"> .73%</td>
<td align="right">89</td>
<td>select u.name, o.name, t.spare1, t.pctfree$ from sys.obj$ o,
sys.user$ u, sys.tab$ t where (bitand(t.trigflag, 1048576) = 1048576)
and o.obj#=t.obj# and o.owner# = u.user# select i.obj#, i.flags,
u.name, o.name from sys.obj$ o, sys.user$ u, sys.ind$ i where
(bitand(i.flags, 256) = 256 or bitand(i.flags, 512) = 512) and
(not((i.type# = 9) and bitand(i.flags,8) = 8)) and o.obj#=i.obj# and
o.owner# = u.user# </td>
</tr>
<tr>
<td align="right"> .84%</td>
<td align="right">3</td>
<td>select /*+ RULE */ distinct tabs.table_name, tabs.owner ,
partitioned, iot_type , TEMPORARY, table_type, table_type_owner from
DBA_ALL_TABLES tabs where tabs.owner = :own </td>
</tr>
<tr>
<td align="right"> 3.95%</td>
<td align="right">6</td>
<td>SELECT round(count(1)*avg(buf.block_size)/1048576) FROM
DBA_OBJECTS obj, V$BH bh, dba_segments seg, v$buffer_pool buf WHERE
obj.object_id = bh.objd AND obj.owner != 'SYS' and obj.owner =
seg.owner and obj.object_name = seg.segment_name and obj.object_type =
seg.segment_type and seg.buffer_pool = buf.name and buf.name =
'DEFAULT' </td>
</tr>
<tr>
<td align="right"> 4.50%</td>
<td align="right">6</td>
<td>SELECT round(count(1)*avg(tsp.block_size)/1048576) FROM
DBA_OBJECTS obj, V$BH bh, dba_segments seg, dba_tablespaces tsp WHERE
obj.object_id = bh.objd AND obj.owner != 'SYS' and obj.owner =
seg.owner and obj.object_name = seg.segment_name and obj.object_type =
seg.segment_type and seg.tablespace_name = tsp.tablespace_name </td>
</tr>
<tr>
<td align="right">57.34%</td>
<td align="right">9267</td>
<td>select t.schema, t.name, t.flags, q.name from
system.aq$_queue_tables t, sys.aq$_queue_table_affinities aft,
system.aq$_queues q where aft.table_objno = t.objno and
aft.owner_instance = :1 and q.table_objno = t.objno and q.usage = 0 and
bitand(t.flags, 4+16+32+64+128+256) = 0 for update of t.name,
aft.table_objno skip locked </td>
</tr>
</tbody>
</table>
<h3>Expensive SQL</h3>
<table bgcolor="white" border="1">
<tbody>
<tr>
<td><b>LOAD</b></td>
<td><b>EXECUTES</b></td>
<td><b>SQL_TEXT</b></td>
</tr>
<tr>
<td align="right"> 5.24%</td>
<td align="right">1</td>
<td>select round(sum(bytes)/1048576) from dba_segments </td>
</tr>
<tr>
<td align="right"> 6.89%</td>
<td align="right">6</td>
<td>SELECT round(count(1)*avg(buf.block_size)/1048576) FROM
DBA_OBJECTS obj, V$BH bh, dba_segments seg, v$buffer_pool buf WHERE
obj.object_id = bh.objd AND obj.owner != 'SYS' and obj.owner =
seg.owner and obj.object_name = seg.segment_name and obj.object_type =
seg.segment_type and seg.buffer_pool = buf.name and buf.name =
'DEFAULT' </td>
</tr>
<tr>
<td align="right"> 7.85%</td>
<td align="right">6</td>
<td>SELECT round(count(1)*avg(tsp.block_size)/1048576) FROM
DBA_OBJECTS obj, V$BH bh, dba_segments seg, dba_tablespaces tsp WHERE
obj.object_id = bh.objd AND obj.owner != 'SYS' and obj.owner =
seg.owner and obj.object_name = seg.segment_name and obj.object_type =
seg.segment_type and seg.tablespace_name = tsp.tablespace_name </td>
</tr>
<tr>
<td align="right">33.69%</td>
<td align="right">89</td>
<td>select u.name, o.name, t.spare1, t.pctfree$ from sys.obj$ o,
sys.user$ u, sys.tab$ t where (bitand(t.trigflag, 1048576) = 1048576)
and o.obj#=t.obj# and o.owner# = u.user# </td>
</tr>
<tr>
<td align="right">36.44%</td>
<td align="right">89</td>
<td>select i.obj#, i.flags, u.name, o.name from sys.obj$ o,
sys.user$ u, sys.ind$ i where (bitand(i.flags, 256) = 256 or
bitand(i.flags, 512) = 512) and (not((i.type# = 9) and
bitand(i.flags,8) = 8)) and o.obj#=i.obj# and o.owner# = u.user# </td>
</tr>
</tbody>
</table>
<p><a name="postgres" id="postgres"></a></p>
<table bgcolor="white" border="1">
<tbody>
<tr>
<td colspan="3">
<h3>postgres7</h3>
</td>
</tr>
<tr>
<td><b>Parameter</b></td>
<td><b>Value</b></td>
<td><b>Description</b></td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Ratios</i> &nbsp;</td>
</tr>
<tr>
<td>statistics collector</td>
<td>FALSE</td>
<td>Must be set to TRUE to enable hit ratio statistics (<i>stats_start_collector</i>,<i>stats_row_level</i>
and <i>stats_block_level</i> must be set to true in postgresql.conf)</td>
</tr>
<tr>
<td>data cache hit ratio</td>
<td>99.9666031916603</td>
<td>&nbsp;</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>IO</i> &nbsp;</td>
</tr>
<tr>
<td>data reads</td>
<td>15</td>
<td>&nbsp; </td>
</tr>
<tr>
<td>data writes</td>
<td>0.000000000000000000</td>
<td>Count of inserts/updates/deletes * coef</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Data Cache</i> &nbsp;</td>
</tr>
<tr>
<td>data cache buffers</td>
<td>1280</td>
<td>Number of cache buffers. <a
href="http://www.varlena.com/GeneralBits/Tidbits/perf.html#basic">Tuning</a></td>
</tr>
<tr>
<td>cache blocksize</td>
<td>8192</td>
<td>(estimate)</td>
</tr>
<tr>
<td>data cache size</td>
<td>10M</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>operating system cache size</td>
<td>80000K</td>
<td>(effective cache size)</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Memory Pools</i> &nbsp;</td>
</tr>
<tr>
<td>sort buffer size</td>
<td>1M</td>
<td>Size of sort buffer (per query)</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Connections</i> &nbsp;</td>
</tr>
<tr>
<td>current connections</td>
<td>13</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>max connections</td>
<td>32</td>
<td>&nbsp;</td>
</tr>
<tr bgcolor="#f0f0f0">
<td colspan="3"><i>Parameters</i> &nbsp;</td>
</tr>
<tr>
<td>rollback buffers</td>
<td>8</td>
<td>WAL buffers</td>
</tr>
<tr>
<td>random page cost</td>
<td>4</td>
<td>Cost of doing a seek (default=4). See <a
href="http://www.varlena.com/GeneralBits/Tidbits/perf.html#less">random_page_cost</a></td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,179 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>ADODB Session Management Manual</title>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<style type="text/css">
body, td {
/*font-family: Arial, Helvetica, sans-serif;*/
font-size: 11pt;
}
pre {
font-size: 9pt;
background-color: #EEEEEE; padding: .5em; margin: 0px;
}
.toplink {
font-size: 8pt;
}
</style>
</head>
<body style="background-color: rgb(255, 255, 255);">
<h3>ADODB Session Management Manual</h3>
<p>
V4.50 6 July 2004 (c) 2000-2004 John Lim (jlim#natsoft.com.my)
</p>
<p> <font size="1">This software is dual licensed using BSD-Style and
LGPL. This means you can use it in compiled proprietary and commercial
products. </font>
<table border="1">
<tbody>
<tr>
<td><font color="red">Kindly note that the ADOdb home page has
moved to <a href="http://adodb.sourceforge.net/">http://adodb.sourceforge.net/</a>
because of the persistent unreliability of http://php.weblogs.com. <b>Please
change your links</b>!</font></td>
</tr>
<tr>
</tr>
</tbody>
</table>
</p>
<p>Useful ADOdb links: <a href="http://adodb.sourceforge.net/#download">Download</a>
&nbsp; <a href="http://adodb.sourceforge.net/#docs">Other Docs</a>
</p>
<h3>Introduction</h3>
<p> We store state information specific to a user or web client in
session variables. These session variables persist throughout a
session, as the user moves from page to page. </p>
<p>To use session variables, call session_start() at the beginning of
your web page, before your HTTP headers are sent. Then for every
variable you want to keep alive for the duration of the session, call
session_register($variable_name). By default, the session handler will
keep track of the session by using a cookie. You can save objects or
arrays in session variables also.
</p>
<p>The default method of storing sessions is to store it in a file.
However if you have special needs such as you:
</p>
<ul>
<li>Have multiple web servers that need to share session info</li>
<li>Need to do special processing of each session</li>
<li>Require notification when a session expires</li>
</ul>
<p>Then the ADOdb session handler provides you with the above
additional capabilities by storing the session information as records
in a database table that can be shared across multiple servers. </p>
<p><b>Important Upgrade Notice:</b> Since ADOdb 4.05, the session files
have been moved to its own folder, adodb/session. This is a rewrite
of the session code by Ross Smith. The old session code is in
adodb/session/old. </p>
<h4>ADOdb Session Handler Features</h4>
<ul>
<li>Ability to define a notification function that is called when a
session expires. Typically
used to detect session logout and release global resources. </li>
<li>Optimization of database writes. We crc32 the session data and
only perform an update
to the session data if there is a data change. </li>
<li>Support for large amounts of session data with CLOBs (see
adodb-session-clob.php). Useful
for Oracle. </li>
<li>Support for encrypted session data, see
adodb-cryptsession.inc.php. Enabling encryption is simply a matter of
including adodb-cryptsession.inc.php instead of adodb-session.inc.php. </li>
</ul>
<h3>Setup</h3>
<p>There are 3 session management files that you can use:
</p>
<pre>adodb-session.php : The default<br>adodb-session-clob.php : Use this if you are storing DATA in clobs<br>adodb-cryptsession.php : Use this if you want to store encrypted session data in the database<br><br>
</pre>
<p><strong>Examples</strong>
<p><pre>
<font
color="#004040"> include('adodb/adodb.inc.php');<br> <br><b> $ADODB_SESSION_DRIVER='mysql';<br> $ADODB_SESSION_CONNECT='localhost';<br> $ADODB_SESSION_USER ='scott';<br> $ADODB_SESSION_PWD ='tiger';<br> $ADODB_SESSION_DB ='sessiondb';</b><br> <br> <b>include('adodb/session/adodb-session.php');</b><br> session_start();<br> <br> #<br> # Test session vars, the following should increment on refresh<br> #<br> $_SESSION['AVAR'] += 1;<br> print "&lt;p&gt;\$_SESSION['AVAR']={$_SESSION['AVAR']}&lt;/p&gt;";<br></font></pre>
<p>To force non-persistent connections, call adodb_session_open first before session_start():<p>
<pre>
<font color="#004040"><br> include('adodb/adodb.inc.php');<br> <br><b> $ADODB_SESSION_DRIVER='mysql';<br> $ADODB_SESSION_CONNECT='localhost';<br> $ADODB_SESSION_USER ='scott';<br> $ADODB_SESSION_PWD ='tiger';<br> $ADODB_SESSION_DB ='sessiondb';</b><br> <br> <b>include('adodb/session/adodb-session.php');<br> adodb_sess_open(false,false,false);</b><br> session_start();<br> </font>
</pre>
<p> To use a encrypted sessions, simply replace the file:</p>
<pre> <font
color="#004040"><br> include('adodb/adodb.inc.php');<br> <br><b> $ADODB_SESSION_DRIVER='mysql';<br> $ADODB_SESSION_CONNECT='localhost';<br> $ADODB_SESSION_USER ='scott';<br> $ADODB_SESSION_PWD ='tiger';<br> $ADODB_SESSION_DB ='sessiondb';<br> <br> include('adodb/session/adodb-cryptsession.php');</b><br> session_start();</font><br>
</pre>
<p>And the same technique for adodb-session-clob.php:</p>
<pre> <font
color="#004040"><br> include('adodb/adodb.inc.php');<br> <br><b> $ADODB_SESSION_DRIVER='mysql';<br> $ADODB_SESSION_CONNECT='localhost';<br> $ADODB_SESSION_USER ='scott';<br> $ADODB_SESSION_PWD ='tiger';<br> $ADODB_SESSION_DB ='sessiondb';<br> <br> include('adodb/session/adodb-session-clob.php');</b><br> session_start();</font>
</pre>
<h4>Installation</h4>
<p>1. Create this table in your database (syntax might vary depending on your db):
<p><pre> <a
name="sessiontab"></a> <font color="#004040"><br> create table sessions (<br> SESSKEY char(32) not null,<br> EXPIRY int(11) unsigned not null,<br> EXPIREREF varchar(64),<br> DATA text not null,<br> primary key (sesskey)<br> );</font><br>
</pre>
<p> For the adodb-session-clob.php version, create this:
<pre>
<font
color="#004040"><br> create table sessions (<br> SESSKEY char(32) not null,<br> EXPIRY int(11) unsigned not null,<br> EXPIREREF varchar(64),<br> DATA CLOB,<br> primary key (sesskey)<br> );</font>
</pre>
<p>2. Then define the following parameters. You can either modify this file, or define them before this file is included:
<pre> <font
color="#004040"><br> $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase';<br> $ADODB_SESSION_CONNECT='server to connect to';<br> $ADODB_SESSION_USER ='user';<br> $ADODB_SESSION_PWD ='password';<br> $ADODB_SESSION_DB ='database';<br> $ADODB_SESSION_TBL = 'sessions'; # setting this is optional<br> </font>
</pre><p>
When the session is created, $<b>ADODB_SESS_CONN</b> holds the connection object.<br> <br> 3. Recommended is PHP 4.0.6 or later. There are documented session bugs <br> in earlier versions of PHP.
<h3>Notifications</h3>
<p>If you want to receive notification when a session expires, then tag
the session record with a <a href="#sessiontab">EXPIREREF</a> tag (see
the definition of the sessions table above). Before any session record
is deleted, ADOdb will call a notification function, passing in the
EXPIREREF.
</p>
<p>When a session is first created, we check a global variable
$ADODB_SESSION_EXPIRE_NOTIFY. This is an array with 2 elements, the
first being the name of the session variable you would like to store in
the EXPIREREF field, and the 2nd is the notification function's name. </p>
<p> Suppose we want to be notified when a user's session has expired,
based on the userid. The user id in the global session variable
$USERID. The function name is 'NotifyFn'. So we define: </p>
<pre> <font color="#004040"><br> $ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn');<br> </font></pre>
And when the NotifyFn is called (when the session expires), we pass the
$USERID as the first parameter, eg. NotifyFn($userid, $sesskey). The
session key (which is the primary key of the record in the sessions
table) is the 2nd parameter.
<p> Here is an example of a Notification function that deletes some
records in the database and temporary files: </p>
<pre><font color="#004040"><br> function NotifyFn($expireref, $sesskey)<br> {<br> global $ADODB_SESS_CONN; # the session connection object<br><br> $user = $ADODB_SESS_CONN-&gt;qstr($expireref);<br> $ADODB_SESS_CONN-&gt;Execute("delete from shopping_cart where user=$user");<br> system("rm /work/tmpfiles/$expireref/*");<br> }</font><br> </pre>
<p> NOTE 1: If you have register_globals disabled in php.ini, then you
will have to manually set the EXPIREREF. E.g. </p>
<pre> <font color="#004040">
$GLOBALS['USERID'] =&amp; $_SESSION['USERID'];
$ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn');</font>
</pre>
<p> NOTE 2: If you want to change the EXPIREREF after the session
record has been created, you will need to modify any session variable
to force a database record update.
</p>
<h4>Neat Notification Tricks</h4>
<p><i>ExpireRef</i> normally holds the user id of the current session.
</p>
<p>1. You can then write a session monitor, scanning expireref to see
who is currently logged on.
</p>
<p>2. If you delete the sessions record for a specific user, eg.
</p>
<pre>delete from sessions where expireref = '$USER'<br></pre>
then the user is logged out. Useful for ejecting someone from a
site.
<p>3. You can scan the sessions table to ensure no user
can be logged in twice. Useful for security reasons.
</p>
<h3>Compression/Encryption Schemes</h3>
Since ADOdb 4.05, thanks to Ross Smith, multiple encryption and
compression schemes are supported. Currently, supported are:
<p>
<pre> MD5Crypt (crypt.inc.php)<br> MCrypt<br> Secure (Horde's emulation of MCrypt, if MCrypt module is not available.)<br> GZip<br> BZip2<br></pre>
<p>These are stackable. E.g.
<p><pre>ADODB_Session::filter(new ADODB_Compress_Bzip2());<br>ADODB_Session::filter(new ADODB_Encrypt_MD5());<br></pre>
will compress and then encrypt the record in the database.
<p>Also see the <a href="docs-adodb.htm">core ADOdb documentation</a>.
</p>
</body>
</html>

View File

@ -0,0 +1,86 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Microsoft Access data driver. Requires ODBC. Works only on MS Windows.
*/
if (!defined('_ADODB_ODBC_LAYER')) {
if (!defined('ADODB_DIR')) die();
include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
}
if (!defined('_ADODB_ACCESS')) {
define('_ADODB_ACCESS',1);
class ADODB_access extends ADODB_odbc {
var $databaseType = 'access';
var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE
var $fmtDate = "#Y-m-d#";
var $fmtTimeStamp = "#Y-m-d h:i:sA#"; // note not comma
var $_bindInputArray = false; // strangely enough, setting to true does not work reliably
var $sysDate = "FORMAT(NOW,'yyyy-mm-dd')";
var $sysTimeStamp = 'NOW';
var $hasTransactions = false;
function ADODB_access()
{
global $ADODB_EXTENSION;
$ADODB_EXTENSION = false;
$this->ADODB_odbc();
}
function Time()
{
return time();
}
function BeginTrans() { return false;}
function IfNull( $field, $ifNull )
{
return " IIF(IsNull($field), $ifNull, $field) "; // if Access
}
/*
function &MetaTables()
{
global $ADODB_FETCH_MODE;
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$qid = odbc_tables($this->_connectionID);
$rs = new ADORecordSet_odbc($qid);
$ADODB_FETCH_MODE = $savem;
if (!$rs) return false;
$rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
$arr = &$rs->GetArray();
//print_pre($arr);
$arr2 = array();
for ($i=0; $i < sizeof($arr); $i++) {
if ($arr[$i][2] && $arr[$i][3] != 'SYSTEM TABLE')
$arr2[] = $arr[$i][2];
}
return $arr2;
}*/
}
class ADORecordSet_access extends ADORecordSet_odbc {
var $databaseType = "access";
function ADORecordSet_access($id,$mode=false)
{
return $this->ADORecordSet_odbc($id,$mode);
}
}// class
}
?>

View File

@ -0,0 +1,630 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Microsoft ADO data driver. Requires ADO. Works only on MS Windows.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
define("_ADODB_ADO_LAYER", 1 );
/*--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------*/
class ADODB_ado extends ADOConnection {
var $databaseType = "ado";
var $_bindInputArray = false;
var $fmtDate = "'Y-m-d'";
var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
var $replaceQuote = "''"; // string to use to replace quotes
var $dataProvider = "ado";
var $hasAffectedRows = true;
var $adoParameterType = 201; // 201 = long varchar, 203=long wide varchar, 205 = long varbinary
var $_affectedRows = false;
var $_thisTransactions;
var $_cursor_type = 3; // 3=adOpenStatic,0=adOpenForwardOnly,1=adOpenKeyset,2=adOpenDynamic
var $_cursor_location = 3; // 2=adUseServer, 3 = adUseClient;
var $_lock_type = -1;
var $_execute_option = -1;
var $poorAffectedRows = true;
var $charPage;
function ADODB_ado()
{
$this->_affectedRows = new VARIANT;
}
function ServerInfo()
{
if (!empty($this->_connectionID)) $desc = $this->_connectionID->provider;
return array('description' => $desc, 'version' => '');
}
function _affectedrows()
{
if (PHP_VERSION >= 5) return $this->_affectedRows;
return $this->_affectedRows->value;
}
// you can also pass a connection string like this:
//
// $DB->Connect('USER ID=sa;PASSWORD=pwd;SERVER=mangrove;DATABASE=ai',false,false,'SQLOLEDB');
function _connect($argHostname, $argUsername, $argPassword, $argProvider= 'MSDASQL')
{
$u = 'UID';
$p = 'PWD';
if (!empty($this->charPage))
$dbc = new COM('ADODB.Connection',null,$this->charPage);
else
$dbc = new COM('ADODB.Connection');
if (! $dbc) return false;
/* special support if provider is mssql or access */
if ($argProvider=='mssql') {
$u = 'User Id'; //User parameter name for OLEDB
$p = 'Password';
$argProvider = "SQLOLEDB"; // SQL Server Provider
// not yet
//if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename";
//use trusted conection for SQL if username not specified
if (!$argUsername) $argHostname .= ";Trusted_Connection=Yes";
} else if ($argProvider=='access')
$argProvider = "Microsoft.Jet.OLEDB.4.0"; // Microsoft Jet Provider
if ($argProvider) $dbc->Provider = $argProvider;
if ($argUsername) $argHostname .= ";$u=$argUsername";
if ($argPassword)$argHostname .= ";$p=$argPassword";
if ($this->debug) ADOConnection::outp( "Host=".$argHostname."<BR>\n version=$dbc->version");
// @ added below for php 4.0.1 and earlier
@$dbc->Open((string) $argHostname);
$this->_connectionID = $dbc;
$dbc->CursorLocation = $this->_cursor_location;
return $dbc->State > 0;
}
// returns true or false
function _pconnect($argHostname, $argUsername, $argPassword, $argProvider='MSDASQL')
{
return $this->_connect($argHostname,$argUsername,$argPassword,$argProvider);
}
/*
adSchemaCatalogs = 1,
adSchemaCharacterSets = 2,
adSchemaCollations = 3,
adSchemaColumns = 4,
adSchemaCheckConstraints = 5,
adSchemaConstraintColumnUsage = 6,
adSchemaConstraintTableUsage = 7,
adSchemaKeyColumnUsage = 8,
adSchemaReferentialContraints = 9,
adSchemaTableConstraints = 10,
adSchemaColumnsDomainUsage = 11,
adSchemaIndexes = 12,
adSchemaColumnPrivileges = 13,
adSchemaTablePrivileges = 14,
adSchemaUsagePrivileges = 15,
adSchemaProcedures = 16,
adSchemaSchemata = 17,
adSchemaSQLLanguages = 18,
adSchemaStatistics = 19,
adSchemaTables = 20,
adSchemaTranslations = 21,
adSchemaProviderTypes = 22,
adSchemaViews = 23,
adSchemaViewColumnUsage = 24,
adSchemaViewTableUsage = 25,
adSchemaProcedureParameters = 26,
adSchemaForeignKeys = 27,
adSchemaPrimaryKeys = 28,
adSchemaProcedureColumns = 29,
adSchemaDBInfoKeywords = 30,
adSchemaDBInfoLiterals = 31,
adSchemaCubes = 32,
adSchemaDimensions = 33,
adSchemaHierarchies = 34,
adSchemaLevels = 35,
adSchemaMeasures = 36,
adSchemaProperties = 37,
adSchemaMembers = 38
*/
function &MetaTables()
{
$arr= array();
$dbc = $this->_connectionID;
$adors=@$dbc->OpenSchema(20);//tables
if ($adors){
$f = $adors->Fields(2);//table/view name
$t = $adors->Fields(3);//table type
while (!$adors->EOF){
$tt=substr($t->value,0,6);
if ($tt!='SYSTEM' && $tt !='ACCESS')
$arr[]=$f->value;
//print $f->value . ' ' . $t->value.'<br>';
$adors->MoveNext();
}
$adors->Close();
}
return $arr;
}
function &MetaColumns($table)
{
$table = strtoupper($table);
$arr= array();
$dbc = $this->_connectionID;
$adors=@$dbc->OpenSchema(4);//tables
if ($adors){
$t = $adors->Fields(2);//table/view name
while (!$adors->EOF){
if (strtoupper($t->Value) == $table) {
$fld = new ADOFieldObject();
$c = $adors->Fields(3);
$fld->name = $c->Value;
$fld->type = 'CHAR'; // cannot discover type in ADO!
$fld->max_length = -1;
$arr[strtoupper($fld->name)]=$fld;
}
$adors->MoveNext();
}
$adors->Close();
}
return $arr;
}
/* returns queryID or false */
function &_query($sql,$inputarr=false)
{
$dbc = $this->_connectionID;
// return rs
if ($inputarr) {
if (!empty($this->charPage))
$oCmd = new COM('ADODB.Command',null,$this->charPage);
else
$oCmd = new COM('ADODB.Command');
$oCmd->ActiveConnection = $dbc;
$oCmd->CommandText = $sql;
$oCmd->CommandType = 1;
foreach($inputarr as $val) {
// name, type, direction 1 = input, len,
$this->adoParameterType = 130;
$p = $oCmd->CreateParameter('name',$this->adoParameterType,1,strlen($val),$val);
//print $p->Type.' '.$p->value;
$oCmd->Parameters->Append($p);
}
$p = false;
$rs = $oCmd->Execute();
$e = $dbc->Errors;
if ($dbc->Errors->Count > 0) return false;
return $rs;
}
$rs = @$dbc->Execute($sql,$this->_affectedRows, $this->_execute_option);
/*
$rs = new COM('ADODB.Recordset');
if ($rs) {
$rs->Open ($sql, $dbc, $this->_cursor_type,$this->_lock_type, $this->_execute_option);
}
*/
if ($dbc->Errors->Count > 0) return false;
if (! $rs) return false;
if ($rs->State == 0) return true; // 0 = adStateClosed means no records returned
return $rs;
}
function BeginTrans()
{
if ($this->transOff) return true;
if (isset($this->_thisTransactions))
if (!$this->_thisTransactions) return false;
else {
$o = $this->_connectionID->Properties("Transaction DDL");
$this->_thisTransactions = $o ? true : false;
if (!$o) return false;
}
@$this->_connectionID->BeginTrans();
$this->transCnt += 1;
return true;
}
function CommitTrans($ok=true)
{
if (!$ok) return $this->RollbackTrans();
if ($this->transOff) return true;
@$this->_connectionID->CommitTrans();
if ($this->transCnt) @$this->transCnt -= 1;
return true;
}
function RollbackTrans() {
if ($this->transOff) return true;
@$this->_connectionID->RollbackTrans();
if ($this->transCnt) @$this->transCnt -= 1;
return true;
}
/* Returns: the last error message from previous database operation */
function ErrorMsg()
{
$errc = $this->_connectionID->Errors;
if ($errc->Count == 0) return '';
$err = $errc->Item($errc->Count-1);
return $err->Description;
}
function ErrorNo()
{
$errc = $this->_connectionID->Errors;
if ($errc->Count == 0) return 0;
$err = $errc->Item($errc->Count-1);
return $err->NativeError;
}
// returns true or false
function _close()
{
if ($this->_connectionID) $this->_connectionID->Close();
$this->_connectionID = false;
return true;
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordSet_ado extends ADORecordSet {
var $bind = false;
var $databaseType = "ado";
var $dataProvider = "ado";
var $_tarr = false; // caches the types
var $_flds; // and field objects
var $canSeek = true;
var $hideErrors = true;
function ADORecordSet_ado($id,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
$this->fetchMode = $mode;
return $this->ADORecordSet($id,$mode);
}
// returns the field object
function FetchField($fieldOffset = -1) {
$off=$fieldOffset+1; // offsets begin at 1
$o= new ADOFieldObject();
$rs = $this->_queryID;
$f = $rs->Fields($fieldOffset);
$o->name = $f->Name;
$t = $f->Type;
$o->type = $this->MetaType($t);
$o->max_length = $f->DefinedSize;
$o->ado_type = $t;
//print "off=$off name=$o->name type=$o->type len=$o->max_length<br>";
return $o;
}
/* Use associative array to get fields array */
function Fields($colname)
{
if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
if (!$this->bind) {
$this->bind = array();
for ($i=0; $i < $this->_numOfFields; $i++) {
$o = $this->FetchField($i);
$this->bind[strtoupper($o->name)] = $i;
}
}
return $this->fields[$this->bind[strtoupper($colname)]];
}
function _initrs()
{
$rs = $this->_queryID;
$this->_numOfRows = $rs->RecordCount;
$f = $rs->Fields;
$this->_numOfFields = $f->Count;
}
// should only be used to move forward as we normally use forward-only cursors
function _seek($row)
{
$rs = $this->_queryID;
// absoluteposition doesn't work -- my maths is wrong ?
// $rs->AbsolutePosition->$row-2;
// return true;
if ($this->_currentRow > $row) return false;
@$rs->Move((integer)$row - $this->_currentRow-1); //adBookmarkFirst
return true;
}
/*
OLEDB types
enum DBTYPEENUM
{ DBTYPE_EMPTY = 0,
DBTYPE_NULL = 1,
DBTYPE_I2 = 2,
DBTYPE_I4 = 3,
DBTYPE_R4 = 4,
DBTYPE_R8 = 5,
DBTYPE_CY = 6,
DBTYPE_DATE = 7,
DBTYPE_BSTR = 8,
DBTYPE_IDISPATCH = 9,
DBTYPE_ERROR = 10,
DBTYPE_BOOL = 11,
DBTYPE_VARIANT = 12,
DBTYPE_IUNKNOWN = 13,
DBTYPE_DECIMAL = 14,
DBTYPE_UI1 = 17,
DBTYPE_ARRAY = 0x2000,
DBTYPE_BYREF = 0x4000,
DBTYPE_I1 = 16,
DBTYPE_UI2 = 18,
DBTYPE_UI4 = 19,
DBTYPE_I8 = 20,
DBTYPE_UI8 = 21,
DBTYPE_GUID = 72,
DBTYPE_VECTOR = 0x1000,
DBTYPE_RESERVED = 0x8000,
DBTYPE_BYTES = 128,
DBTYPE_STR = 129,
DBTYPE_WSTR = 130,
DBTYPE_NUMERIC = 131,
DBTYPE_UDT = 132,
DBTYPE_DBDATE = 133,
DBTYPE_DBTIME = 134,
DBTYPE_DBTIMESTAMP = 135
ADO Types
adEmpty = 0,
adTinyInt = 16,
adSmallInt = 2,
adInteger = 3,
adBigInt = 20,
adUnsignedTinyInt = 17,
adUnsignedSmallInt = 18,
adUnsignedInt = 19,
adUnsignedBigInt = 21,
adSingle = 4,
adDouble = 5,
adCurrency = 6,
adDecimal = 14,
adNumeric = 131,
adBoolean = 11,
adError = 10,
adUserDefined = 132,
adVariant = 12,
adIDispatch = 9,
adIUnknown = 13,
adGUID = 72,
adDate = 7,
adDBDate = 133,
adDBTime = 134,
adDBTimeStamp = 135,
adBSTR = 8,
adChar = 129,
adVarChar = 200,
adLongVarChar = 201,
adWChar = 130,
adVarWChar = 202,
adLongVarWChar = 203,
adBinary = 128,
adVarBinary = 204,
adLongVarBinary = 205,
adChapter = 136,
adFileTime = 64,
adDBFileTime = 137,
adPropVariant = 138,
adVarNumeric = 139
*/
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
if (!is_numeric($t)) return $t;
switch ($t) {
case 0:
case 12: // variant
case 8: // bstr
case 129: //char
case 130: //wc
case 200: // varc
case 202:// varWC
case 128: // bin
case 204: // varBin
case 72: // guid
if ($len <= $this->blobSize) return 'C';
case 201:
case 203:
return 'X';
case 128:
case 204:
case 205:
return 'B';
case 7:
case 133: return 'D';
case 134:
case 135: return 'T';
case 11: return 'L';
case 16:// adTinyInt = 16,
case 2://adSmallInt = 2,
case 3://adInteger = 3,
case 4://adBigInt = 20,
case 17://adUnsignedTinyInt = 17,
case 18://adUnsignedSmallInt = 18,
case 19://adUnsignedInt = 19,
case 20://adUnsignedBigInt = 21,
return 'I';
default: return 'N';
}
}
// time stamp not supported yet
function _fetch()
{
$rs = $this->_queryID;
if (!$rs or $rs->EOF) {
$this->fields = false;
return false;
}
$this->fields = array();
if (!$this->_tarr) {
$tarr = array();
$flds = array();
for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
$f = $rs->Fields($i);
$flds[] = $f;
$tarr[] = $f->Type;
}
// bind types and flds only once
$this->_tarr = $tarr;
$this->_flds = $flds;
}
$t = reset($this->_tarr);
$f = reset($this->_flds);
if ($this->hideErrors) $olde = error_reporting(E_ERROR|E_CORE_ERROR);// sometimes $f->value be null
for ($i=0,$max = $this->_numOfFields; $i < $max; $i++) {
//echo "<p>",$t,' ';var_dump($f->value); echo '</p>';
switch($t) {
case 135: // timestamp
if (!strlen((string)$f->value)) $this->fields[] = false;
else {
if (!is_numeric($f->value)) $val = variant_date_to_timestamp($f->value);
else $val = $f->value;
$this->fields[] = adodb_date('Y-m-d H:i:s',$val);
}
break;
case 133:// A date value (yyyymmdd)
if ($val = $f->value) {
$this->fields[] = substr($val,0,4).'-'.substr($val,4,2).'-'.substr($val,6,2);
} else
$this->fields[] = false;
break;
case 7: // adDate
if (!strlen((string)$f->value)) $this->fields[] = false;
else {
if (!is_numeric($f->value)) $val = variant_date_to_timestamp($f->value);
else $val = $f->value;
if (($val % 86400) == 0) $this->fields[] = adodb_date('Y-m-d',$val);
else $this->fields[] = adodb_date('Y-m-d H:i:s',$val);
}
break;
case 1: // null
$this->fields[] = false;
break;
case 6: // currency is not supported properly;
ADOConnection::outp( '<b>'.$f->Name.': currency type not supported by PHP</b>');
$this->fields[] = (float) $f->value;
break;
default:
$this->fields[] = $f->value;
break;
}
//print " $f->value $t, ";
$f = next($this->_flds);
$t = next($this->_tarr);
} // for
if ($this->hideErrors) error_reporting($olde);
@$rs->MoveNext(); // @ needed for some versions of PHP!
if ($this->fetchMode & ADODB_FETCH_ASSOC) {
$this->fields = &$this->GetRowAssoc(ADODB_ASSOC_CASE);
}
return true;
}
function NextRecordSet()
{
$rs = $this->_queryID;
$this->_queryID = $rs->NextRecordSet();
//$this->_queryID = $this->_QueryId->NextRecordSet();
if ($this->_queryID == null) return false;
$this->_currentRow = -1;
$this->_currentPage = -1;
$this->bind = false;
$this->fields = false;
$this->_flds = false;
$this->_tarr = false;
$this->_inited = false;
$this->Init();
return true;
}
function _close() {
$this->_flds = false;
@$this->_queryID->Close();// by Pete Dishman (peterd@telephonetics.co.uk)
$this->_queryID = false;
}
}
?>

View File

@ -0,0 +1,49 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Microsoft Access ADO data driver. Requires ADO and ODBC. Works only on MS Windows.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
if (!defined('_ADODB_ADO_LAYER')) {
include(ADODB_DIR."/drivers/adodb-ado.inc.php");
}
class ADODB_ado_access extends ADODB_ado {
var $databaseType = 'ado_access';
var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE
var $fmtDate = "#Y-m-d#";
var $fmtTimeStamp = "#Y-m-d h:i:sA#";// note no comma
var $sysDate = "FORMAT(NOW,'yyyy-mm-dd')";
var $sysTimeStamp = 'NOW';
var $hasTransactions = false;
function ADODB_ado_access()
{
$this->ADODB_ado();
}
function BeginTrans() { return false;}
}
class ADORecordSet_ado_access extends ADORecordSet_ado {
var $databaseType = "ado_access";
function ADORecordSet_ado_access($id,$mode=false)
{
return $this->ADORecordSet_ado($id,$mode);
}
}
?>

View File

@ -0,0 +1,96 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Microsoft SQL Server ADO data driver. Requires ADO and MSSQL client.
Works only on MS Windows.
It is normally better to use the mssql driver directly because it is much faster.
This file is only a technology demonstration and for test purposes.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
if (!defined('_ADODB_ADO_LAYER')) {
include(ADODB_DIR."/drivers/adodb-ado.inc.php");
}
class ADODB_ado_mssql extends ADODB_ado {
var $databaseType = 'ado_mssql';
var $hasTop = 'top';
var $hasInsertID = true;
var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
var $sysTimeStamp = 'GetDate()';
var $leftOuter = '*=';
var $rightOuter = '=*';
var $ansiOuter = true; // for mssql7 or later
var $substr = "substring";
var $length = 'len';
//var $_inTransaction = 1; // always open recordsets, so no transaction problems.
function ADODB_ado_mssql()
{
$this->ADODB_ado();
}
function _insertid()
{
return $this->GetOne('select @@identity');
}
function _affectedrows()
{
return $this->GetOne('select @@rowcount');
}
function MetaColumns($table)
{
$table = strtoupper($table);
$arr= array();
$dbc = $this->_connectionID;
$osoptions = array();
$osoptions[0] = null;
$osoptions[1] = null;
$osoptions[2] = $table;
$osoptions[3] = null;
$adors=@$dbc->OpenSchema(4, $osoptions);//tables
if ($adors){
while (!$adors->EOF){
$fld = new ADOFieldObject();
$c = $adors->Fields(3);
$fld->name = $c->Value;
$fld->type = 'CHAR'; // cannot discover type in ADO!
$fld->max_length = -1;
$arr[strtoupper($fld->name)]=$fld;
$adors->MoveNext();
}
$adors->Close();
}
return $arr;
}
}
class ADORecordSet_ado_mssql extends ADORecordSet_ado {
var $databaseType = 'ado_mssql';
function ADORecordSet_ado_mssql($id,$mode=false)
{
return $this->ADORecordSet_ado($id,$mode);
}
}
?>

View File

@ -0,0 +1,91 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Support Borland Interbase 6.5 and later
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
include_once(ADODB_DIR."/drivers/adodb-ibase.inc.php");
class ADODB_borland_ibase extends ADODB_ibase {
var $databaseType = "borland_ibase";
function ADODB_borland_ibase()
{
$this->ADODB_ibase();
}
function BeginTrans()
{
if ($this->transOff) return true;
$this->transCnt += 1;
$this->autoCommit = false;
$this->_transactionID = ibase_trans($this->ibasetrans, $this->_connectionID);
return $this->_transactionID;
}
function ServerInfo()
{
$arr['dialect'] = $this->dialect;
switch($arr['dialect']) {
case '':
case '1': $s = 'Interbase 6.5, Dialect 1'; break;
case '2': $s = 'Interbase 6.5, Dialect 2'; break;
default:
case '3': $s = 'Interbase 6.5, Dialect 3'; break;
}
$arr['version'] = '6.5';
$arr['description'] = $s;
return $arr;
}
// Note that Interbase 6.5 uses ROWS instead - don't you love forking wars!
// SELECT col1, col2 FROM table ROWS 5 -- get 5 rows
// SELECT col1, col2 FROM TABLE ORDER BY col1 ROWS 3 TO 7 -- first 5 skip 2
// Firebird uses
// SELECT FIRST 5 SKIP 2 col1, col2 FROM TABLE
function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
{
if ($nrows > 0) {
if ($offset <= 0) $str = " ROWS $nrows ";
else {
$a = $offset+1;
$b = $offset+$nrows;
$str = " ROWS $a TO $b";
}
} else {
// ok, skip
$a = $offset + 1;
$str = " ROWS $a TO 999999999"; // 999 million
}
$sql .= $str;
return ($secs2cache) ?
$this->CacheExecute($secs2cache,$sql,$inputarr)
:
$this->Execute($sql,$inputarr);
}
};
class ADORecordSet_borland_ibase extends ADORecordSet_ibase {
var $databaseType = "borland_ibase";
function ADORecordSet_borland_ibase($id,$mode=false)
{
$this->ADORecordSet_ibase($id,$mode);
}
}
?>

View File

@ -0,0 +1,203 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4.
Currently unsupported: MetaDatabases, MetaTables and MetaColumns, and also inputarr in Execute.
Native types have been converted to MetaTypes.
Transactions not supported yet.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
if (! defined("_ADODB_CSV_LAYER")) {
define("_ADODB_CSV_LAYER", 1 );
include_once(ADODB_DIR.'/adodb-csvlib.inc.php');
class ADODB_csv extends ADOConnection {
var $databaseType = 'csv';
var $databaseProvider = 'csv';
var $hasInsertID = true;
var $hasAffectedRows = true;
var $fmtTimeStamp = "'Y-m-d H:i:s'";
var $_affectedrows=0;
var $_insertid=0;
var $_url;
var $replaceQuote = "''"; // string to use to replace quotes
var $hasTransactions = false;
var $_errorNo = false;
function ADODB_csv()
{
}
function _insertid()
{
return $this->_insertid;
}
function _affectedrows()
{
return $this->_affectedrows;
}
function &MetaDatabases()
{
return false;
}
// returns true or false
function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (strtolower(substr($argHostname,0,7)) !== 'http://') return false;
$this->_url = $argHostname;
return true;
}
// returns true or false
function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (strtolower(substr($argHostname,0,7)) !== 'http://') return false;
$this->_url = $argHostname;
return true;
}
function &MetaColumns($table)
{
return false;
}
// parameters use PostgreSQL convention, not MySQL
function &SelectLimit($sql,$nrows=-1,$offset=-1)
{
global $ADODB_FETCH_MODE;
$url = $this->_url.'?sql='.urlencode($sql)."&nrows=$nrows&fetch=".
(($this->fetchMode !== false)?$this->fetchMode : $ADODB_FETCH_MODE).
"&offset=$offset";
$err = false;
$rs = csv2rs($url,$err,false);
if ($this->debug) print "$url<br><i>$err</i><br>";
$at = strpos($err,'::::');
if ($at === false) {
$this->_errorMsg = $err;
$this->_errorNo = (integer)$err;
} else {
$this->_errorMsg = substr($err,$at+4,1024);
$this->_errorNo = -9999;
}
if ($this->_errorNo)
if ($fn = $this->raiseErrorFn) {
$fn($this->databaseType,'EXECUTE',$this->ErrorNo(),$this->ErrorMsg(),$sql,'');
}
if (is_object($rs)) {
$rs->databaseType='csv';
$rs->fetchMode = ($this->fetchMode !== false) ? $this->fetchMode : $ADODB_FETCH_MODE;
$rs->connection = &$this;
}
return $rs;
}
// returns queryID or false
function &_Execute($sql,$inputarr=false)
{
global $ADODB_FETCH_MODE;
if (!$this->_bindInputArray && $inputarr) {
$sqlarr = explode('?',$sql);
$sql = '';
$i = 0;
foreach($inputarr as $v) {
$sql .= $sqlarr[$i];
if (gettype($v) == 'string')
$sql .= $this->qstr($v);
else if ($v === null)
$sql .= 'NULL';
else
$sql .= $v;
$i += 1;
}
$sql .= $sqlarr[$i];
if ($i+1 != sizeof($sqlarr))
print "Input Array does not match ?: ".htmlspecialchars($sql);
$inputarr = false;
}
$url = $this->_url.'?sql='.urlencode($sql)."&fetch=".
(($this->fetchMode !== false)?$this->fetchMode : $ADODB_FETCH_MODE);
$err = false;
$rs = csv2rs($url,$err,false);
if ($this->debug) print urldecode($url)."<br><i>$err</i><br>";
$at = strpos($err,'::::');
if ($at === false) {
$this->_errorMsg = $err;
$this->_errorNo = (integer)$err;
} else {
$this->_errorMsg = substr($err,$at+4,1024);
$this->_errorNo = -9999;
}
if ($this->_errorNo)
if ($fn = $this->raiseErrorFn) {
$fn($this->databaseType,'EXECUTE',$this->ErrorNo(),$this->ErrorMsg(),$sql,$inputarr);
}
if (is_object($rs)) {
$rs->fetchMode = ($this->fetchMode !== false) ? $this->fetchMode : $ADODB_FETCH_MODE;
$this->_affectedrows = $rs->affectedrows;
$this->_insertid = $rs->insertid;
$rs->databaseType='csv';
$rs->connection = &$this;
}
return $rs;
}
/* Returns: the last error message from previous database operation */
function ErrorMsg()
{
return $this->_errorMsg;
}
/* Returns: the last error number from previous database operation */
function ErrorNo()
{
return $this->_errorNo;
}
// returns true or false
function _close()
{
return true;
}
} // class
class ADORecordset_csv extends ADORecordset {
function ADORecordset_csv($id,$mode=false)
{
$this->ADORecordset($id,$mode);
}
function _close()
{
return true;
}
}
} // define
?>

View File

@ -0,0 +1,316 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
DB2 data driver. Requires ODBC.
From phpdb list:
Hi Andrew,
thanks a lot for your help. Today we discovered what
our real problem was:
After "playing" a little bit with the php-scripts that try
to connect to the IBM DB2, we set the optional parameter
Cursortype when calling odbc_pconnect(....).
And the exciting thing: When we set the cursor type
to SQL_CUR_USE_ODBC Cursor Type, then
the whole query speed up from 1 till 10 seconds
to 0.2 till 0.3 seconds for 100 records. Amazing!!!
Therfore, PHP is just almost fast as calling the DB2
from Servlets using JDBC (don't take too much care
about the speed at whole: the database was on a
completely other location, so the whole connection
was made over a slow network connection).
I hope this helps when other encounter the same
problem when trying to connect to DB2 from
PHP.
Kind regards,
Christian Szardenings
2 Oct 2001
Mark Newnham has discovered that the SQL_CUR_USE_ODBC is not supported by
IBM's DB2 ODBC driver, so this must be a 3rd party ODBC driver.
From the IBM CLI Reference:
SQL_ATTR_ODBC_CURSORS (DB2 CLI v5)
This connection attribute is defined by ODBC, but is not supported by DB2
CLI. Any attempt to set or get this attribute will result in an SQLSTATE of
HYC00 (Driver not capable).
A 32-bit option specifying how the Driver Manager uses the ODBC cursor
library.
So I guess this means the message [above] was related to using a 3rd party
odbc driver.
Setting SQL_CUR_USE_ODBC
========================
To set SQL_CUR_USE_ODBC for drivers that require it, do this:
$db = NewADOConnection('db2');
$db->curMode = SQL_CUR_USE_ODBC;
$db->Connect($dsn, $userid, $pwd);
USING CLI INTERFACE
===================
I have had reports that the $host and $database params have to be reversed in
Connect() when using the CLI interface. From Halmai Csongor csongor.halmai#nexum.hu:
> The symptom is that if I change the database engine from postgres or any other to DB2 then the following
> connection command becomes wrong despite being described this version to be correct in the docs.
>
> $connection_object->Connect( $DATABASE_HOST, $DATABASE_AUTH_USER_NAME, $DATABASE_AUTH_PASSWORD, $DATABASE_NAME )
>
> In case of DB2 I had to swap the first and last arguments in order to connect properly.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
if (!defined('_ADODB_ODBC_LAYER')) {
include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
}
if (!defined('ADODB_DB2')){
define('ADODB_DB2',1);
class ADODB_DB2 extends ADODB_odbc {
var $databaseType = "db2";
var $concat_operator = '||';
var $sysDate = 'CURRENT_DATE';
var $sysTimeStamp = 'CURRENT TIMESTAMP';
// The complete string representation of a timestamp has the form
// yyyy-mm-dd-hh.mm.ss.nnnnnn.
var $fmtTimeStamp = "'Y-m-d-H.i.s'";
var $ansiOuter = true;
var $identitySQL = 'values IDENTITY_VAL_LOCAL()';
var $_bindInputArray = true;
var $hasInsertID = true;
function ADODB_DB2()
{
if (strncmp(PHP_OS,'WIN',3) === 0) $this->curmode = SQL_CUR_USE_ODBC;
$this->ADODB_odbc();
}
function IfNull( $field, $ifNull )
{
return " COALESCE($field, $ifNull) "; // if DB2 UDB
}
function ServerInfo()
{
//odbc_setoption($this->_connectionID,1,101 /*SQL_ATTR_ACCESS_MODE*/, 1 /*SQL_MODE_READ_ONLY*/);
$vers = $this->GetOne('select versionnumber from sysibm.sysversions');
//odbc_setoption($this->_connectionID,1,101, 0 /*SQL_MODE_READ_WRITE*/);
return array('description'=>'DB2 ODBC driver', 'version'=>$vers);
}
function _insertid()
{
return $this->GetOne($this->identitySQL);
}
function RowLock($tables,$where)
{
if ($this->_autocommit) $this->BeginTrans();
return $this->GetOne("select 1 as ignore from $tables where $where for update");
}
function &MetaTables($ttype=false,$showSchema=false, $qtable="%", $qschema="%")
{
global $ADODB_FETCH_MODE;
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$qid = odbc_tables($this->_connectionID, "", $qschema, $qtable, "");
$rs = new ADORecordSet_odbc($qid);
$ADODB_FETCH_MODE = $savem;
if (!$rs) return false;
$rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
$arr =& $rs->GetArray();
//print_r($arr);
$rs->Close();
$arr2 = array();
if ($ttype) {
$isview = strncmp($ttype,'V',1) === 0;
}
for ($i=0; $i < sizeof($arr); $i++) {
if (!$arr[$i][2]) continue;
if (strncmp($arr[$i][1],'SYS',3) === 0) continue;
$type = $arr[$i][3];
if ($showSchema) $arr[$i][2] = $arr[$i][1].'.'.$arr[$i][2];
if ($ttype) {
if ($isview) {
if (strncmp($type,'V',1) === 0) $arr2[] = $arr[$i][2];
} else if (strncmp($type,'T',1) === 0) $arr2[] = $arr[$i][2];
} else if (strncmp($type,'S',1) !== 0) $arr2[] = $arr[$i][2];
}
return $arr2;
}
// Format date column in sql string given an input format that understands Y M D
function SQLDate($fmt, $col=false)
{
// use right() and replace() ?
if (!$col) $col = $this->sysDate;
$s = '';
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
if ($s) $s .= '||';
$ch = $fmt[$i];
switch($ch) {
case 'Y':
case 'y':
$s .= "char(year($col))";
break;
case 'M':
$s .= "substr(monthname($col),1,3)";
break;
case 'm':
$s .= "right(digits(month($col)),2)";
break;
case 'D':
case 'd':
$s .= "right(digits(day($col)),2)";
break;
case 'H':
case 'h':
if ($col != $this->sysDate) $s .= "right(digits(hour($col)),2)";
else $s .= "''";
break;
case 'i':
case 'I':
if ($col != $this->sysDate)
$s .= "right(digits(minute($col)),2)";
else $s .= "''";
break;
case 'S':
case 's':
if ($col != $this->sysDate)
$s .= "right(digits(second($col)),2)";
else $s .= "''";
break;
default:
if ($ch == '\\') {
$i++;
$ch = substr($fmt,$i,1);
}
$s .= $this->qstr($ch);
}
}
return $s;
}
function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputArr=false)
{
if ($offset <= 0) {
// could also use " OPTIMIZE FOR $nrows ROWS "
if ($nrows >= 0) $sql .= " FETCH FIRST $nrows ROWS ONLY ";
$rs =& $this->Execute($sql,$inputArr);
} else {
if ($offset > 0 && $nrows < 0);
else {
$nrows += $offset;
$sql .= " FETCH FIRST $nrows ROWS ONLY ";
}
$rs =& ADOConnection::SelectLimit($sql,-1,$offset,$inputArr);
}
return $rs;
}
};
class ADORecordSet_db2 extends ADORecordSet_odbc {
var $databaseType = "db2";
function ADORecordSet_db2($id,$mode=false)
{
$this->ADORecordSet_odbc($id,$mode);
}
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
switch (strtoupper($t)) {
case 'VARCHAR':
case 'CHAR':
case 'CHARACTER':
if ($len <= $this->blobSize) return 'C';
case 'LONGCHAR':
case 'TEXT':
case 'CLOB':
case 'DBCLOB': // double-byte
return 'X';
case 'BLOB':
case 'GRAPHIC':
case 'VARGRAPHIC':
return 'B';
case 'DATE':
return 'D';
case 'TIME':
case 'TIMESTAMP':
return 'T';
//case 'BOOLEAN':
//case 'BIT':
// return 'L';
//case 'COUNTER':
// return 'R';
case 'INT':
case 'INTEGER':
case 'BIGINT':
case 'SMALLINT':
return 'I';
default: return 'N';
}
}
}
} //define
?>

View File

@ -0,0 +1,75 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
include_once(ADODB_DIR."/drivers/adodb-ibase.inc.php");
class ADODB_firebird extends ADODB_ibase {
var $databaseType = "firebird";
var $dialect = 3;
var $sysTimeStamp = "cast('NOW' as timestamp)";
function ADODB_firebird()
{
$this->ADODB_ibase();
}
function ServerInfo()
{
$arr['dialect'] = $this->dialect;
switch($arr['dialect']) {
case '':
case '1': $s = 'Firebird Dialect 1'; break;
case '2': $s = 'Firebird Dialect 2'; break;
default:
case '3': $s = 'Firebird Dialect 3'; break;
}
$arr['version'] = ADOConnection::_findvers($s);
$arr['description'] = $s;
return $arr;
}
// Note that Interbase 6.5 uses this ROWS instead - don't you love forking wars!
// SELECT col1, col2 FROM table ROWS 5 -- get 5 rows
// SELECT col1, col2 FROM TABLE ORDER BY col1 ROWS 3 TO 7 -- first 5 skip 2
function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false, $secs=0)
{
$str = 'SELECT ';
if ($nrows >= 0) $str .= "FIRST $nrows ";
$str .=($offset>=0) ? "SKIP $offset " : '';
$sql = preg_replace('/^[ \t]*select/i',$str,$sql);
if ($secs)
$rs =& $this->CacheExecute($secs,$sql,$inputarr);
else
$rs =& $this->Execute($sql,$inputarr);
return $rs;
}
};
class ADORecordSet_firebird extends ADORecordSet_ibase {
var $databaseType = "firebird";
function ADORecordSet_firebird($id,$mode=false)
{
$this->ADORecordSet_ibase($id,$mode);
}
}
?>

View File

@ -0,0 +1,856 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Latest version is available at http://adodb.sourceforge.net
Interbase data driver. Requires interbase client. Works on Windows and Unix.
3 Jan 2002 -- suggestions by Hans-Peter Oeri <kampfcaspar75@oeri.ch>
changed transaction handling and added experimental blob stuff
Docs to interbase at the website
http://www.synectics.co.za/php3/tutorial/IB_PHP3_API.html
To use gen_id(), see
http://www.volny.cz/iprenosil/interbase/ip_ib_code.htm#_code_creategen
$rs = $conn->Execute('select gen_id(adodb,1) from rdb$database');
$id = $rs->fields[0];
$conn->Execute("insert into table (id, col1,...) values ($id, $val1,...)");
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB_ibase extends ADOConnection {
var $databaseType = "ibase";
var $dataProvider = "ibase";
var $replaceQuote = "''"; // string to use to replace quotes
var $ibase_datefmt = '%Y-%m-%d'; // For hours,mins,secs change to '%Y-%m-%d %H:%M:%S';
var $fmtDate = "'Y-m-d'";
var $ibase_timestampfmt = "%Y-%m-%d %H:%M:%S";
var $ibase_timefmt = "%H:%M:%S";
var $fmtTimeStamp = "'Y-m-d, H:i:s'";
var $concat_operator='||';
var $_transactionID;
var $metaTablesSQL = "select rdb\$relation_name from rdb\$relations where rdb\$relation_name not like 'RDB\$%'";
//OPN STUFF start
var $metaColumnsSQL = "select a.rdb\$field_name, a.rdb\$null_flag, a.rdb\$default_source, b.rdb\$field_length, b.rdb\$field_scale, b.rdb\$field_sub_type, b.rdb\$field_precision, b.rdb\$field_type from rdb\$relation_fields a, rdb\$fields b where a.rdb\$field_source = b.rdb\$field_name and a.rdb\$relation_name = '%s' order by a.rdb\$field_position asc";
//OPN STUFF end
var $ibasetrans;
var $hasGenID = true;
var $_bindInputArray = true;
var $buffers = 0;
var $dialect = 1;
var $sysDate = "cast('TODAY' as timestamp)";
var $sysTimeStamp = "cast('NOW' as timestamp)";
var $ansiOuter = true;
var $hasAffectedRows = false;
var $poorAffectedRows = true;
var $blobEncodeType = 'C';
function ADODB_ibase()
{
if (defined('IBASE_DEFAULT')) $this->ibasetrans = IBASE_DEFAULT;
}
// returns true or false
function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$persist=false)
{
if (!function_exists('ibase_pconnect')) return null;
if ($argDatabasename) $argHostname .= ':'.$argDatabasename;
$fn = ($persist) ? 'ibase_pconnect':'ibase_connect';
$this->_connectionID = $fn($argHostname,$argUsername,$argPassword,
$this->charSet,$this->buffers,$this->dialect);
if ($this->dialect != 1) { // http://www.ibphoenix.com/ibp_60_del_id_ds.html
$this->replaceQuote = "''";
}
if ($this->_connectionID === false) {
$this->_handleerror();
return false;
}
// PHP5 change.
if (function_exists('ibase_timefmt')) {
ibase_timefmt($this->ibase_datefmt,IBASE_DATE );
if ($this->dialect == 1) ibase_timefmt($this->ibase_datefmt,IBASE_TIMESTAMP );
else ibase_timefmt($this->ibase_timestampfmt,IBASE_TIMESTAMP );
ibase_timefmt($this->ibase_timefmt,IBASE_TIME );
} else {
ini_set("ibase.timestampformat", $this->ibase_timestampfmt);
ini_set("ibase.dateformat", $this->ibase_datefmt);
ini_set("ibase.timeformat", $this->ibase_timefmt);
}
return true;
}
// returns true or false
function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,true);
}
function MetaPrimaryKeys($table,$owner_notused=false,$internalKey=false)
{
if ($internalKey) return array('RDB$DB_KEY');
$table = strtoupper($table);
$sql = 'SELECT S.RDB$FIELD_NAME AFIELDNAME
FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON I.RDB$INDEX_NAME=S.RDB$INDEX_NAME
WHERE I.RDB$RELATION_NAME=\''.$table.'\' and I.RDB$INDEX_NAME like \'RDB$PRIMARY%\'
ORDER BY I.RDB$INDEX_NAME,S.RDB$FIELD_POSITION';
$a = $this->GetCol($sql,false,true);
if ($a && sizeof($a)>0) return $a;
return false;
}
function ServerInfo()
{
$arr['dialect'] = $this->dialect;
switch($arr['dialect']) {
case '':
case '1': $s = 'Interbase 5.5 or earlier'; break;
case '2': $s = 'Interbase 5.6'; break;
default:
case '3': $s = 'Interbase 6.0'; break;
}
$arr['version'] = ADOConnection::_findvers($s);
$arr['description'] = $s;
return $arr;
}
function BeginTrans()
{
if ($this->transOff) return true;
$this->transCnt += 1;
$this->autoCommit = false;
$this->_transactionID = $this->_connectionID;//ibase_trans($this->ibasetrans, $this->_connectionID);
return $this->_transactionID;
}
function CommitTrans($ok=true)
{
if (!$ok) return $this->RollbackTrans();
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
$ret = false;
$this->autoCommit = true;
if ($this->_transactionID) {
//print ' commit ';
$ret = ibase_commit($this->_transactionID);
}
$this->_transactionID = false;
return $ret;
}
// there are some compat problems with ADODB_COUNTRECS=false and $this->_logsql currently.
// it appears that ibase extension cannot support multiple concurrent queryid's
function &_Execute($sql,$inputarr=false)
{
global $ADODB_COUNTRECS;
if ($this->_logsql) {
$savecrecs = $ADODB_COUNTRECS;
$ADODB_COUNTRECS = true; // force countrecs
$ret =& ADOConnection::_Execute($sql,$inputarr);
$ADODB_COUNTRECS = $savecrecs;
} else {
$ret =& ADOConnection::_Execute($sql,$inputarr);
}
return $ret;
}
function RollbackTrans()
{
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
$ret = false;
$this->autoCommit = true;
if ($this->_transactionID)
$ret = ibase_rollback($this->_transactionID);
$this->_transactionID = false;
return $ret;
}
function &MetaIndexes ($table, $primary = FALSE, $owner=false)
{
// save old fetch mode
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
$savem = $this->SetFetchMode(FALSE);
}
$table = strtoupper($table);
$sql = "SELECT * FROM RDB\$INDICES WHERE RDB\$RELATION_NAME = '".$table."'";
if (!$primary) {
$sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$%'";
} else {
$sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$FOREIGN%'";
}
// get index details
$rs = $this->Execute($sql);
if (!is_object($rs)) {
// restore fetchmode
if (isset($savem)) {
$this->SetFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
return FALSE;
}
$indexes = array ();
while ($row = $rs->FetchRow()) {
$index = $row[0];
if (!isset($indexes[$index])) {
if (is_null($row[3])) {$row[3] = 0;}
$indexes[$index] = array(
'unique' => ($row[3] == 1),
'columns' => array()
);
}
$sql = "SELECT * FROM RDB\$INDEX_SEGMENTS WHERE RDB\$INDEX_NAME = '".$name."' ORDER BY RDB\$FIELD_POSITION ASC";
$rs1 = $this->Execute($sql);
while ($row1 = $rs1->FetchRow()) {
$indexes[$index]['columns'][$row1[2]] = $row1[1];
}
}
// restore fetchmode
if (isset($savem)) {
$this->SetFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
return $indexes;
}
// See http://community.borland.com/article/0,1410,25844,00.html
function RowLock($tables,$where,$col)
{
if ($this->autoCommit) $this->BeginTrans();
$this->Execute("UPDATE $table SET $col=$col WHERE $where "); // is this correct - jlim?
return 1;
}
function CreateSequence($seqname,$startID=1)
{
$ok = $this->Execute(("INSERT INTO RDB\$GENERATORS (RDB\$GENERATOR_NAME) VALUES (UPPER('$seqname'))" ));
if (!$ok) return false;
return $this->Execute("SET GENERATOR $seqname TO ".($startID-1).';');
}
function DropSequence($seqname)
{
$seqname = strtoupper($seqname);
$this->Execute("delete from RDB\$GENERATORS where RDB\$GENERATOR_NAME='$seqname'");
}
function GenID($seqname='adodbseq',$startID=1)
{
$getnext = ("SELECT Gen_ID($seqname,1) FROM RDB\$DATABASE");
$rs = @$this->Execute($getnext);
if (!$rs) {
$this->Execute(("INSERT INTO RDB\$GENERATORS (RDB\$GENERATOR_NAME) VALUES (UPPER('$seqname'))" ));
$this->Execute("SET GENERATOR $seqname TO ".($startID-1).';');
$rs = $this->Execute($getnext);
}
if ($rs && !$rs->EOF) $this->genID = (integer) reset($rs->fields);
else $this->genID = 0; // false
if ($rs) $rs->Close();
return $this->genID;
}
function SelectDB($dbName)
{
return false;
}
function _handleerror()
{
$this->_errorMsg = ibase_errmsg();
}
function ErrorNo()
{
if (preg_match('/error code = ([\-0-9]*)/i', $this->_errorMsg,$arr)) return (integer) $arr[1];
else return 0;
}
function ErrorMsg()
{
return $this->_errorMsg;
}
function Prepare($sql)
{
$stmt = ibase_prepare($this->_connectionID,$sql);
if (!$stmt) return false;
return array($sql,$stmt);
}
// returns query ID if successful, otherwise false
// there have been reports of problems with nested queries - the code is probably not re-entrant?
function _query($sql,$iarr=false)
{
if (!$this->autoCommit && $this->_transactionID) {
$conn = $this->_transactionID;
$docommit = false;
} else {
$conn = $this->_connectionID;
$docommit = true;
}
if (is_array($sql)) {
$fn = 'ibase_execute';
$sql = $sql[1];
if (is_array($iarr)) {
if (ADODB_PHPVER >= 0x4050) { // actually 4.0.4
if ( !isset($iarr[0]) ) $iarr[0] = ''; // PHP5 compat hack
$fnarr =& array_merge( array($sql) , $iarr);
$ret = call_user_func_array($fn,$fnarr);
} else {
switch(sizeof($iarr)) {
case 1: $ret = $fn($sql,$iarr[0]); break;
case 2: $ret = $fn($sql,$iarr[0],$iarr[1]); break;
case 3: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2]); break;
case 4: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3]); break;
case 5: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4]); break;
case 6: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5]); break;
case 7: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6]); break;
default: ADOConnection::outp( "Too many parameters to ibase query $sql");
case 8: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6],$iarr[7]); break;
}
}
} else $ret = $fn($sql);
} else {
$fn = 'ibase_query';
if (is_array($iarr)) {
if (ADODB_PHPVER >= 0x4050) { // actually 4.0.4
if (sizeof($iarr) == 0) $iarr[0] = ''; // PHP5 compat hack
$fnarr =& array_merge( array($conn,$sql) , $iarr);
$ret = call_user_func_array($fn,$fnarr);
} else {
switch(sizeof($iarr)) {
case 1: $ret = $fn($conn,$sql,$iarr[0]); break;
case 2: $ret = $fn($conn,$sql,$iarr[0],$iarr[1]); break;
case 3: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2]); break;
case 4: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3]); break;
case 5: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4]); break;
case 6: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5]); break;
case 7: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6]); break;
default: ADOConnection::outp( "Too many parameters to ibase query $sql");
case 8: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6],$iarr[7]); break;
}
}
} else $ret = $fn($conn,$sql);
}
if ($docommit && $ret === true) ibase_commit($this->_connectionID);
$this->_handleerror();
return $ret;
}
// returns true or false
function _close()
{
if (!$this->autoCommit) @ibase_rollback($this->_connectionID);
return @ibase_close($this->_connectionID);
}
//OPN STUFF start
function _ConvertFieldType(&$fld, $ftype, $flen, $fscale, $fsubtype, $fprecision, $dialect3)
{
$fscale = abs($fscale);
$fld->max_length = $flen;
$fld->scale = null;
switch($ftype){
case 7:
case 8:
if ($dialect3) {
switch($fsubtype){
case 0:
$fld->type = ($ftype == 7 ? 'smallint' : 'integer');
break;
case 1:
$fld->type = 'numeric';
$fld->max_length = $fprecision;
$fld->scale = $fscale;
break;
case 2:
$fld->type = 'decimal';
$fld->max_length = $fprecision;
$fld->scale = $fscale;
break;
} // switch
} else {
if ($fscale !=0) {
$fld->type = 'decimal';
$fld->scale = $fscale;
$fld->max_length = ($ftype == 7 ? 4 : 9);
} else {
$fld->type = ($ftype == 7 ? 'smallint' : 'integer');
}
}
break;
case 16:
if ($dialect3) {
switch($fsubtype){
case 0:
$fld->type = 'decimal';
$fld->max_length = 18;
$fld->scale = 0;
break;
case 1:
$fld->type = 'numeric';
$fld->max_length = $fprecision;
$fld->scale = $fscale;
break;
case 2:
$fld->type = 'decimal';
$fld->max_length = $fprecision;
$fld->scale = $fscale;
break;
} // switch
}
break;
case 10:
$fld->type = 'float';
break;
case 14:
$fld->type = 'char';
break;
case 27:
if ($fscale !=0) {
$fld->type = 'decimal';
$fld->max_length = 15;
$fld->scale = 5;
} else {
$fld->type = 'double';
}
break;
case 35:
if ($dialect3) {
$fld->type = 'timestamp';
} else {
$fld->type = 'date';
}
break;
case 12:
$fld->type = 'date';
break;
case 13:
$fld->type = 'time';
break;
case 37:
$fld->type = 'varchar';
break;
case 40:
$fld->type = 'cstring';
break;
case 261:
$fld->type = 'blob';
$fld->max_length = -1;
break;
} // switch
}
//OPN STUFF end
// returns array of ADOFieldObjects for current table
function &MetaColumns($table)
{
global $ADODB_FETCH_MODE;
if ($this->metaColumnsSQL) {
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->Execute(sprintf($this->metaColumnsSQL,strtoupper($table)));
$ADODB_FETCH_MODE = $save;
if ($rs === false) return false;
$retarr = array();
//OPN STUFF start
$dialect3 = ($this->dialect==3 ? true : false);
//OPN STUFF end
while (!$rs->EOF) { //print_r($rs->fields);
$fld = new ADOFieldObject();
$fld->name = trim($rs->fields[0]);
//OPN STUFF start
$this->_ConvertFieldType($fld, $rs->fields[7], $rs->fields[3], $rs->fields[4], $rs->fields[5], $rs->fields[6], $dialect3);
if (isset($rs->fields[1]) && $rs->fields[1]) {
$fld->not_null = true;
}
if (isset($rs->fields[2])) {
$fld->has_default = true;
$d = substr($rs->fields[2],strlen('default '));
switch ($fld->type)
{
case 'smallint':
case 'integer': $fld->default_value = (int) $d; break;
case 'char':
case 'blob':
case 'text':
case 'varchar': $fld->default_value = (string) substr($d,1,strlen($d)-2); break;
case 'double':
case 'float': $fld->default_value = (float) $d; break;
default: $fld->default_value = $d; break;
}
// case 35:$tt = 'TIMESTAMP'; break;
}
if ((isset($rs->fields[5])) && ($fld->type == 'blob')) {
$fld->sub_type = $rs->fields[5];
} else {
$fld->sub_type = null;
}
//OPN STUFF end
if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
else $retarr[strtoupper($fld->name)] = $fld;
$rs->MoveNext();
}
$rs->Close();
return $retarr;
}
return false;
}
function BlobEncode( $blob )
{
$blobid = ibase_blob_create( $this->_connectionID);
ibase_blob_add( $blobid, $blob );
return ibase_blob_close( $blobid );
}
// since we auto-decode all blob's since 2.42,
// BlobDecode should not do any transforms
function BlobDecode($blob)
{
return $blob;
}
// old blobdecode function
// still used to auto-decode all blob's
function _BlobDecode( $blob )
{
$blobid = ibase_blob_open( $blob );
$realblob = ibase_blob_get( $blobid,$this->maxblobsize); // 2nd param is max size of blob -- Kevin Boillet <kevinboillet@yahoo.fr>
while($string = ibase_blob_get($blobid, 8192)){
$realblob .= $string;
}
ibase_blob_close( $blobid );
return( $realblob );
}
function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
{
$fd = fopen($path,'rb');
if ($fd === false) return false;
$blob_id = ibase_blob_create($this->_connectionID);
/* fill with data */
while ($val = fread($fd,32768)){
ibase_blob_add($blob_id, $val);
}
/* close and get $blob_id_str for inserting into table */
$blob_id_str = ibase_blob_close($blob_id);
fclose($fd);
return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
}
/*
Insert a null into the blob field of the table first.
Then use UpdateBlob to store the blob.
Usage:
$conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
$conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
*/
function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
{
$blob_id = ibase_blob_create($this->_connectionID);
// ibase_blob_add($blob_id, $val);
// replacement that solves the problem by which only the first modulus 64K /
// of $val are stored at the blob field ////////////////////////////////////
// Thx Abel Berenstein aberenstein#afip.gov.ar
$len = strlen($val);
$chunk_size = 32768;
$tail_size = $len % $chunk_size;
$n_chunks = ($len - $tail_size) / $chunk_size;
for ($n = 0; $n < $n_chunks; $n++) {
$start = $n * $chunk_size;
$data = substr($val, $start, $chunk_size);
ibase_blob_add($blob_id, $data);
}
if ($tail_size) {
$start = $n_chunks * $chunk_size;
$data = substr($val, $start, $tail_size);
ibase_blob_add($blob_id, $data);
}
// end replacement /////////////////////////////////////////////////////////
$blob_id_str = ibase_blob_close($blob_id);
return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
}
function OldUpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
{
$blob_id = ibase_blob_create($this->_connectionID);
ibase_blob_add($blob_id, $val);
$blob_id_str = ibase_blob_close($blob_id);
return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
}
// Format date column in sql string given an input format that understands Y M D
// Only since Interbase 6.0 - uses EXTRACT
// problem - does not zero-fill the day and month yet
function SQLDate($fmt, $col=false)
{
if (!$col) $col = $this->sysDate;
$s = '';
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
if ($s) $s .= '||';
$ch = $fmt[$i];
switch($ch) {
case 'Y':
case 'y':
$s .= "extract(year from $col)";
break;
case 'M':
case 'm':
$s .= "extract(month from $col)";
break;
case 'Q':
case 'q':
$s .= "cast(((extract(month from $col)+2) / 3) as integer)";
break;
case 'D':
case 'd':
$s .= "(extract(day from $col))";
break;
case 'H':
case 'h':
$s .= "(extract(hour from $col))";
break;
case 'I':
case 'i':
$s .= "(extract(minute from $col))";
break;
case 'S':
case 's':
$s .= "CAST((extract(second from $col)) AS INTEGER)";
break;
default:
if ($ch == '\\') {
$i++;
$ch = substr($fmt,$i,1);
}
$s .= $this->qstr($ch);
break;
}
}
return $s;
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordset_ibase extends ADORecordSet
{
var $databaseType = "ibase";
var $bind=false;
var $_cacheType;
function ADORecordset_ibase($id,$mode=false)
{
global $ADODB_FETCH_MODE;
$this->fetchMode = ($mode === false) ? $ADODB_FETCH_MODE : $mode;
$this->ADORecordSet($id);
}
/* Returns: an object containing field information.
Get column information in the Recordset object. fetchField() can be used in order to obtain information about
fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
fetchField() is retrieved. */
function &FetchField($fieldOffset = -1)
{
$fld = new ADOFieldObject;
$ibf = ibase_field_info($this->_queryID,$fieldOffset);
switch (ADODB_ASSOC_CASE) {
case 2: // the default
$fld->name = ($ibf['alias']);
if (empty($fld->name)) $fld->name = ($ibf['name']);
break;
case 0:
$fld->name = strtoupper($ibf['alias']);
if (empty($fld->name)) $fld->name = strtoupper($ibf['name']);
break;
case 1:
$fld->name = strtolower($ibf['alias']);
if (empty($fld->name)) $fld->name = strtolower($ibf['name']);
break;
}
$fld->type = $ibf['type'];
$fld->max_length = $ibf['length'];
/* This needs to be populated from the metadata */
$fld->not_null = false;
$fld->has_default = false;
$fld->default_value = 'null';
return $fld;
}
function _initrs()
{
$this->_numOfRows = -1;
$this->_numOfFields = @ibase_num_fields($this->_queryID);
// cache types for blob decode check
for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
$f1 = $this->FetchField($i);
$this->_cacheType[] = $f1->type;
}
}
function _seek($row)
{
return false;
}
function _fetch()
{
$f = @ibase_fetch_row($this->_queryID);
if ($f === false) {
$this->fields = false;
return false;
}
// OPN stuff start - optimized
// fix missing nulls and decode blobs automatically
global $ADODB_ANSI_PADDING_OFF;
//$ADODB_ANSI_PADDING_OFF=1;
$rtrim = !empty($ADODB_ANSI_PADDING_OFF);
for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
if ($this->_cacheType[$i]=="BLOB") {
if (isset($f[$i])) {
$f[$i] = $this->connection->_BlobDecode($f[$i]);
} else {
$f[$i] = null;
}
} else {
if (!isset($f[$i])) {
$f[$i] = null;
} else if ($rtrim && is_string($f[$i])) {
$f[$i] = rtrim($f[$i]);
}
}
}
// OPN stuff end
$this->fields = $f;
if ($this->fetchMode == ADODB_FETCH_ASSOC) {
$this->fields = &$this->GetRowAssoc(ADODB_ASSOC_CASE);
} else if ($this->fetchMode == ADODB_FETCH_BOTH) {
$this->fields =& array_merge($this->fields,$this->GetRowAssoc(ADODB_ASSOC_CASE));
}
return true;
}
/* Use associative array to get fields array */
function Fields($colname)
{
if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
if (!$this->bind) {
$this->bind = array();
for ($i=0; $i < $this->_numOfFields; $i++) {
$o = $this->FetchField($i);
$this->bind[strtoupper($o->name)] = $i;
}
}
return $this->fields[$this->bind[strtoupper($colname)]];
}
function _close()
{
return @ibase_free_result($this->_queryID);
}
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
switch (strtoupper($t)) {
case 'CHAR':
return 'C';
case 'TEXT':
case 'VARCHAR':
case 'VARYING':
if ($len <= $this->blobSize) return 'C';
return 'X';
case 'BLOB':
return 'B';
case 'TIMESTAMP':
case 'DATE': return 'D';
case 'TIME': return 'T';
//case 'T': return 'T';
//case 'L': return 'L';
case 'INT':
case 'SHORT':
case 'INTEGER': return 'I';
default: return 'N';
}
}
}
?>

View File

@ -0,0 +1,404 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim. All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Informix port by Mitchell T. Young (mitch@youngfamily.org)
Further mods by "Samuel CARRIERE" <samuel_carriere@hotmail.com>
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
if (!defined('IFX_SCROLL')) define('IFX_SCROLL',1);
class ADODB_informix72 extends ADOConnection {
var $databaseType = "informix72";
var $dataProvider = "informix";
var $replaceQuote = "''"; // string to use to replace quotes
var $fmtDate = "'Y-m-d'";
var $fmtTimeStamp = "'Y-m-d H:i:s'";
var $hasInsertID = true;
var $hasAffectedRows = true;
var $substr = 'substr';
var $metaTablesSQL="select tabname from systables where tabtype!=' ' and owner!='informix'"; //Don't get informix tables and pseudo-tables
var $metaColumnsSQL =
"select c.colname, c.coltype, c.collength, d.default,c.colno
from syscolumns c, systables t,outer sysdefaults d
where c.tabid=t.tabid and d.tabid=t.tabid and d.colno=c.colno
and tabname='%s' order by c.colno";
var $metaPrimaryKeySQL =
"select part1,part2,part3,part4,part5,part6,part7,part8 from
systables t,sysconstraints s,sysindexes i where t.tabname='%s'
and s.tabid=t.tabid and s.constrtype='P'
and i.idxname=s.idxname";
var $concat_operator = '||';
var $lastQuery = false;
var $has_insertid = true;
var $_autocommit = true;
var $_bindInputArray = true; // set to true if ADOConnection.Execute() permits binding of array parameters.
var $sysDate = 'TODAY';
var $sysTimeStamp = 'CURRENT';
var $cursorType = IFX_SCROLL; // IFX_SCROLL or IFX_HOLD or 0
function ADODB_informix72()
{
// alternatively, use older method:
//putenv("DBDATE=Y4MD-");
// force ISO date format
putenv('GL_DATE=%Y-%m-%d');
if (function_exists('ifx_byteasvarchar')) {
ifx_byteasvarchar(1); // Mode "0" will return a blob id, and mode "1" will return a varchar with text content.
ifx_textasvarchar(1); // Mode "0" will return a blob id, and mode "1" will return a varchar with text content.
ifx_blobinfile_mode(0); // Mode "0" means save Byte-Blobs in memory, and mode "1" means save Byte-Blobs in a file.
}
}
function ServerInfo()
{
if (isset($this->version)) return $this->version;
$arr['description'] = $this->GetOne("select DBINFO('version','full') from systables where tabid = 1");
$arr['version'] = $this->GetOne("select DBINFO('version','major')||"."||DBINFO('version','minor') from systables where tabid = 1");
$this->version = $arr;
return $arr;
}
function _insertid()
{
$sqlca =ifx_getsqlca($this->lastQuery);
return @$sqlca["sqlerrd1"];
}
function _affectedrows()
{
if ($this->lastQuery) {
return @ifx_affected_rows ($this->lastQuery);
}
return 0;
}
function BeginTrans()
{
if ($this->transOff) return true;
$this->transCnt += 1;
$this->Execute('BEGIN');
$this->_autocommit = false;
return true;
}
function CommitTrans($ok=true)
{
if (!$ok) return $this->RollbackTrans();
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
$this->Execute('COMMIT');
$this->_autocommit = true;
return true;
}
function RollbackTrans()
{
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
$this->Execute('ROLLBACK');
$this->_autocommit = true;
return true;
}
function RowLock($tables,$where)
{
if ($this->_autocommit) $this->BeginTrans();
return $this->GetOne("select 1 as ignore from $tables where $where for update");
}
/* Returns: the last error message from previous database operation
Note: This function is NOT available for Microsoft SQL Server. */
function ErrorMsg()
{
if (!empty($this->_logsql)) return $this->_errorMsg;
$this->_errorMsg = ifx_errormsg();
return $this->_errorMsg;
}
function ErrorNo()
{
preg_match("/.*SQLCODE=([^\]]*)/",ifx_error(),$parse); //!EOS
if (is_array($parse) && isset($parse[1])) return (int)$parse[1];
return 0;
}
function &MetaColumns($table)
{
global $ADODB_FETCH_MODE;
if (!empty($this->metaColumnsSQL)) {
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rs === false) return false;
$rspkey = $this->Execute(sprintf($this->metaPrimaryKeySQL,$table)); //Added to get primary key colno items
$retarr = array();
while (!$rs->EOF) { //print_r($rs->fields);
$fld = new ADOFieldObject();
$fld->name = $rs->fields[0];
$fld->type = $rs->fields[1];
$fld->primary_key=$rspkey->fields && array_search($rs->fields[4],$rspkey->fields); //Added to set primary key flag
$fld->max_length = $rs->fields[2];
if (trim($rs->fields[3]) != "AAAAAA 0") {
$fld->has_default = 1;
$fld->default_value = $rs->fields[3];
} else {
$fld->has_default = 0;
}
$retarr[strtolower($fld->name)] = $fld;
$rs->MoveNext();
}
$rs->Close();
return $retarr;
}
return false;
}
function &xMetaColumns($table)
{
return ADOConnection::MetaColumns($table,false);
}
function UpdateBlob($table, $column, $val, $where, $blobtype = 'BLOB')
{
$type = ($blobtype == 'TEXT') ? 1 : 0;
$blobid = ifx_create_blob($type,0,$val);
return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blobid));
}
function BlobDecode($blobid)
{
return function_exists('ifx_byteasvarchar') ? $blobid : @ifx_get_blob($blobid);
}
// returns true or false
function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (!function_exists('ifx_connect')) return null;
$dbs = $argDatabasename . "@" . $argHostname;
if ($argHostname) putenv("INFORMIXSERVER=$argHostname");
putenv("INFORMIXSERVER=".trim($argHostname));
$this->_connectionID = ifx_connect($dbs,$argUsername,$argPassword);
if ($this->_connectionID === false) return false;
#if ($argDatabasename) return $this->SelectDB($argDatabasename);
return true;
}
// returns true or false
function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (!function_exists('ifx_connect')) return null;
$dbs = $argDatabasename . "@" . $argHostname;
putenv("INFORMIXSERVER=".trim($argHostname));
$this->_connectionID = ifx_pconnect($dbs,$argUsername,$argPassword);
if ($this->_connectionID === false) return false;
#if ($argDatabasename) return $this->SelectDB($argDatabasename);
return true;
}
/*
// ifx_do does not accept bind parameters - weird ???
function Prepare($sql)
{
$stmt = ifx_prepare($sql);
if (!$stmt) return $sql;
else return array($sql,$stmt);
}
*/
// returns query ID if successful, otherwise false
function _query($sql,$inputarr)
{
global $ADODB_COUNTRECS;
// String parameters have to be converted using ifx_create_char
if ($inputarr) {
foreach($inputarr as $v) {
if (gettype($v) == 'string') {
$tab[] = ifx_create_char($v);
}
else {
$tab[] = $v;
}
}
}
// In case of select statement, we use a scroll cursor in order
// to be able to call "move", or "movefirst" statements
if (!$ADODB_COUNTRECS && preg_match("/^\s*select/is", $sql)) {
if ($inputarr) {
$this->lastQuery = ifx_query($sql,$this->_connectionID, $this->cursorType, $tab);
}
else {
$this->lastQuery = ifx_query($sql,$this->_connectionID, $this->cursorType);
}
}
else {
if ($inputarr) {
$this->lastQuery = ifx_query($sql,$this->_connectionID, $tab);
}
else {
$this->lastQuery = ifx_query($sql,$this->_connectionID);
}
}
// Following line have been commented because autocommit mode is
// not supported by informix SE 7.2
//if ($this->_autocommit) ifx_query('COMMIT',$this->_connectionID);
return $this->lastQuery;
}
// returns true or false
function _close()
{
$this->lastQuery = false;
return ifx_close($this->_connectionID);
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordset_informix72 extends ADORecordSet {
var $databaseType = "informix72";
var $canSeek = true;
var $_fieldprops = false;
function ADORecordset_informix72($id,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
$this->fetchMode = $mode;
return $this->ADORecordSet($id);
}
/* Returns: an object containing field information.
Get column information in the Recordset object. fetchField() can be used in order to obtain information about
fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
fetchField() is retrieved. */
function &FetchField($fieldOffset = -1)
{
if (empty($this->_fieldprops)) {
$fp = ifx_fieldproperties($this->_queryID);
foreach($fp as $k => $v) {
$o = new ADOFieldObject;
$o->name = $k;
$arr = split(';',$v); //"SQLTYPE;length;precision;scale;ISNULLABLE"
$o->type = $arr[0];
$o->max_length = $arr[1];
$this->_fieldprops[] = $o;
$o->not_null = $arr[4]=="N";
}
}
return $this->_fieldprops[$fieldOffset];
}
function _initrs()
{
$this->_numOfRows = -1; // ifx_affected_rows not reliable, only returns estimate -- ($ADODB_COUNTRECS)? ifx_affected_rows($this->_queryID):-1;
$this->_numOfFields = ifx_num_fields($this->_queryID);
}
function _seek($row)
{
return @ifx_fetch_row($this->_queryID, $row);
}
function MoveLast()
{
$this->fields = @ifx_fetch_row($this->_queryID, "LAST");
if ($this->fields) $this->EOF = false;
$this->_currentRow = -1;
if ($this->fetchMode == ADODB_FETCH_NUM) {
foreach($this->fields as $v) {
$arr[] = $v;
}
$this->fields = $arr;
}
return true;
}
function MoveFirst()
{
$this->fields = @ifx_fetch_row($this->_queryID, "FIRST");
if ($this->fields) $this->EOF = false;
$this->_currentRow = 0;
if ($this->fetchMode == ADODB_FETCH_NUM) {
foreach($this->fields as $v) {
$arr[] = $v;
}
$this->fields = $arr;
}
return true;
}
function _fetch($ignore_fields=false)
{
$this->fields = @ifx_fetch_row($this->_queryID);
if (!is_array($this->fields)) return false;
if ($this->fetchMode == ADODB_FETCH_NUM) {
foreach($this->fields as $v) {
$arr[] = $v;
}
$this->fields = $arr;
}
return true;
}
/* close() only needs to be called if you are worried about using too much memory while your script
is running. All associated result memory for the specified result identifier will automatically be freed. */
function _close()
{
return ifx_free_result($this->_queryID);
}
}
?>

View File

@ -0,0 +1,311 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim#natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 8.
Joshua Eldridge (joshuae74#hotmail.com)
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB_ldap extends ADOConnection {
var $databaseType = 'ldap';
var $dataProvider = 'ldap';
# Connection information
var $username = false;
var $password = false;
# Used during searches
var $filter;
var $dn;
function ADODB_ldap()
{
}
// returns true or false
function _connect( $host, $username, $password, $ldapbase )
{
if ( !function_exists( 'ldap_connect' ) ) return null;
$conn_info = array( $host );
if ( strstr( $host, ':' ) ) {
$conn_info = split( ':', $host );
}
$this->_connectionID = ldap_connect( $conn_info[0], $conn_info[1] )
or die( 'Could not connect to ' . $this->_connectionID );
if ($username && $password) {
$bind = ldap_bind( $this->_connectionID, $username, $password )
or die( 'Could not bind to ' . $this->_connectionID . ' with $username & $password');
} else {
$bind = ldap_bind( $this->_connectionID )
or die( 'Could not bind anonymously to ' . $this->_connectionID );
}
return $this->_connectionID;
}
/* returns _queryID or false */
function _query($sql,$inputarr)
{
$rs = ldap_search( $this->_connectionID, $this->database, $sql );
return $rs;
}
/* closes the LDAP connection */
function _close()
{
@ldap_close( $this->_connectionID );
$this->_connectionID = false;
}
function ServerInfo()
{
if( is_array( $this->version ) ) return $this->version;
$version = array();
/*
Determines how aliases are handled during search.
LDAP_DEREF_NEVER (0x00)
LDAP_DEREF_SEARCHING (0x01)
LDAP_DEREF_FINDING (0x02)
LDAP_DEREF_ALWAYS (0x03)
The LDAP_DEREF_SEARCHING value means aliases are dereferenced during the search but
not when locating the base object of the search. The LDAP_DEREF_FINDING value means
aliases are dereferenced when locating the base object but not during the search.
Default: LDAP_DEREF_NEVER
*/
ldap_get_option( $this->_connectionID, LDAP_OPT_DEREF, $version['LDAP_OPT_DEREF'] ) ;
switch ( $version['LDAP_OPT_DEREF'] ) {
case 0:
$version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_NEVER';
case 1:
$version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_SEARCHING';
case 2:
$version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_FINDING';
case 3:
$version['LDAP_OPT_DEREF'] = 'LDAP_DEREF_ALWAYS';
}
/*
A limit on the number of entries to return from a search.
LDAP_NO_LIMIT (0) means no limit.
Default: LDAP_NO_LIMIT
*/
ldap_get_option( $this->_connectionID, LDAP_OPT_SIZELIMIT, $version['LDAP_OPT_SIZELIMIT'] );
if ( $version['LDAP_OPT_SIZELIMIT'] == 0 ) {
$version['LDAP_OPT_SIZELIMIT'] = 'LDAP_NO_LIMIT';
}
/*
A limit on the number of seconds to spend on a search.
LDAP_NO_LIMIT (0) means no limit.
Default: LDAP_NO_LIMIT
*/
ldap_get_option( $this->_connectionID, LDAP_OPT_TIMELIMIT, $version['LDAP_OPT_TIMELIMIT'] );
if ( $version['LDAP_OPT_TIMELIMIT'] == 0 ) {
$version['LDAP_OPT_TIMELIMIT'] = 'LDAP_NO_LIMIT';
}
/*
Determines whether the LDAP library automatically follows referrals returned by LDAP servers or not.
LDAP_OPT_ON
LDAP_OPT_OFF
Default: ON
*/
ldap_get_option( $this->_connectionID, LDAP_OPT_REFERRALS, $version['LDAP_OPT_REFERRALS'] );
if ( $version['LDAP_OPT_REFERRALS'] == 0 ) {
$version['LDAP_OPT_REFERRALS'] = 'LDAP_OPT_OFF';
} else {
$version['LDAP_OPT_REFERRALS'] = 'LDAP_OPT_ON';
}
/*
Determines whether LDAP I/O operations are automatically restarted if they abort prematurely.
LDAP_OPT_ON
LDAP_OPT_OFF
Default: OFF
*/
ldap_get_option( $this->_connectionID, LDAP_OPT_RESTART, $version['LDAP_OPT_RESTART'] );
if ( $version['LDAP_OPT_RESTART'] == 0 ) {
$version['LDAP_OPT_RESTART'] = 'LDAP_OPT_OFF';
} else {
$version['LDAP_OPT_RESTART'] = 'LDAP_OPT_ON';
}
/*
This option indicates the version of the LDAP protocol used when communicating with the primary LDAP server.
LDAP_VERSION2 (2)
LDAP_VERSION3 (3)
Default: LDAP_VERSION2 (2)
*/
ldap_get_option( $this->_connectionID, LDAP_OPT_PROTOCOL_VERSION, $version['LDAP_OPT_PROTOCOL_VERSION'] );
if ( $version['LDAP_OPT_PROTOCOL_VERSION'] == 2 ) {
$version['LDAP_OPT_PROTOCOL_VERSION'] = 'LDAP_VERSION2';
} else {
$version['LDAP_OPT_PROTOCOL_VERSION'] = 'LDAP_VERSION3';
}
/* The host name (or list of hosts) for the primary LDAP server. */
ldap_get_option( $this->_connectionID, LDAP_OPT_HOST_NAME, $version['LDAP_OPT_HOST_NAME'] );
ldap_get_option( $this->_connectionID, OPT_ERROR_NUMBER, $version['OPT_ERROR_NUMBER'] );
ldap_get_option( $this->_connectionID, OPT_ERROR_STRING, $version['OPT_ERROR_STRING'] );
ldap_get_option( $this->_connectionID, LDAP_OPT_MATCHED_DN, $version['LDAP_OPT_MATCHED_DN'] );
return $this->version = $version;
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordSet_ldap extends ADORecordSet{
var $databaseType = "ldap";
var $canSeek = false;
var $_entryID; /* keeps track of the entry resource identifier */
function ADORecordSet_ldap($queryID,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
switch ($mode)
{
case ADODB_FETCH_NUM:
$this->fetchMode = LDAP_NUM;
break;
case ADODB_FETCH_ASSOC:
$this->fetchMode = LDAP_ASSOC;
break;
default:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:
$this->fetchMode = LDAP_BOTH;
break;
}
$this->ADORecordSet($queryID);
}
function _initrs()
{
/*
This could be teaked to respect the $COUNTRECS directive from ADODB
It's currently being used in the _fetch() function and the
GetAssoc() function
*/
$this->_numOfRows = ldap_count_entries( $this->connection->_connectionID, $this->_queryID );
}
/*
Return whole recordset as a multi-dimensional associative array
*/
function &GetAssoc($force_array = false, $first2cols = false)
{
$records = $this->_numOfRows;
$results = array();
for ( $i=0; $i < $records; $i++ ) {
foreach ( $this->fields as $k=>$v ) {
if ( is_array( $v ) ) {
if ( $v['count'] == 1 ) {
$results[$i][$k] = $v[0];
} else {
array_shift( $v );
$results[$i][$k] = $v;
}
}
}
}
return $results;
}
function &GetRowAssoc()
{
$results = array();
foreach ( $this->fields as $k=>$v ) {
if ( is_array( $v ) ) {
if ( $v['count'] == 1 ) {
$results[$k] = $v[0];
} else {
array_shift( $v );
$results[$k] = $v;
}
}
}
return $results;
}
function GetRowNums()
{
$results = array();
foreach ( $this->fields as $k=>$v ) {
static $i = 0;
if (is_array( $v )) {
if ( $v['count'] == 1 ) {
$results[$i] = $v[0];
} else {
array_shift( $v );
$results[$i] = $v;
}
$i++;
}
}
return $results;
}
function _fetch()
{
if ( $this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0 )
return false;
if ( $this->_currentRow == 0 ) {
$this->_entryID = ldap_first_entry( $this->connection->_connectionID, $this->_queryID );
} else {
$this->_entryID = ldap_next_entry( $this->connection->_connectionID, $this->_entryID );
}
$this->fields = ldap_get_attributes( $this->connection->_connectionID, $this->_entryID );
$this->_numOfFields = $this->fields['count'];
switch ( $this->fetchMode ) {
case LDAP_ASSOC:
$this->fields = $this->GetRowAssoc();
break;
case LDAP_NUM:
$this->fields = $this->GetRowNums();
break;
case LDAP_BOTH:
default:
break;
}
return ( is_array( $this->fields ) );
}
function _close() {
@ldap_free_result( $this->_queryID );
$this->_queryID = false;
}
}
?>

View File

@ -0,0 +1,952 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Native mssql driver. Requires mssql client. Works on Windows.
To configure for Unix, see
http://phpbuilder.com/columns/alberto20000919.php3
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
//----------------------------------------------------------------
// MSSQL returns dates with the format Oct 13 2002 or 13 Oct 2002
// and this causes tons of problems because localized versions of
// MSSQL will return the dates in dmy or mdy order; and also the
// month strings depends on what language has been configured. The
// following two variables allow you to control the localization
// settings - Ugh.
//
// MORE LOCALIZATION INFO
// ----------------------
// To configure datetime, look for and modify sqlcommn.loc,
// typically found in c:\mssql\install
// Also read :
// http://support.microsoft.com/default.aspx?scid=kb;EN-US;q220918
// Alternatively use:
// CONVERT(char(12),datecol,120)
//----------------------------------------------------------------
// has datetime converstion to YYYY-MM-DD format, and also mssql_fetch_assoc
if (ADODB_PHPVER >= 0x4300) {
// docs say 4.2.0, but testing shows only since 4.3.0 does it work!
ini_set('mssql.datetimeconvert',0);
} else {
global $ADODB_mssql_mths; // array, months must be upper-case
$ADODB_mssql_date_order = 'mdy';
$ADODB_mssql_mths = array(
'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,
'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
}
//---------------------------------------------------------------------------
// Call this to autoset $ADODB_mssql_date_order at the beginning of your code,
// just after you connect to the database. Supports mdy and dmy only.
// Not required for PHP 4.2.0 and above.
function AutoDetect_MSSQL_Date_Order($conn)
{
global $ADODB_mssql_date_order;
$adate = $conn->GetOne('select getdate()');
if ($adate) {
$anum = (int) $adate;
if ($anum > 0) {
if ($anum > 31) {
//ADOConnection::outp( "MSSQL: YYYY-MM-DD date format not supported currently");
} else
$ADODB_mssql_date_order = 'dmy';
} else
$ADODB_mssql_date_order = 'mdy';
}
}
class ADODB_mssql extends ADOConnection {
var $databaseType = "mssql";
var $dataProvider = "mssql";
var $replaceQuote = "''"; // string to use to replace quotes
var $fmtDate = "'Y-m-d'";
var $fmtTimeStamp = "'Y-m-d h:i:sA'";
var $hasInsertID = true;
var $substr = "substring";
var $length = 'len';
var $hasAffectedRows = true;
var $metaDatabasesSQL = "select name from sysdatabases where name <> 'master'";
var $metaTablesSQL="select name,case when type='U' then 'T' else 'V' end from sysobjects where (type='U' or type='V') and (name not in ('sysallocations','syscolumns','syscomments','sysdepends','sysfilegroups','sysfiles','sysfiles1','sysforeignkeys','sysfulltextcatalogs','sysindexes','sysindexkeys','sysmembers','sysobjects','syspermissions','sysprotects','sysreferences','systypes','sysusers','sysalternates','sysconstraints','syssegments','REFERENTIAL_CONSTRAINTS','CHECK_CONSTRAINTS','CONSTRAINT_TABLE_USAGE','CONSTRAINT_COLUMN_USAGE','VIEWS','VIEW_TABLE_USAGE','VIEW_COLUMN_USAGE','SCHEMATA','TABLES','TABLE_CONSTRAINTS','TABLE_PRIVILEGES','COLUMNS','COLUMN_DOMAIN_USAGE','COLUMN_PRIVILEGES','DOMAINS','DOMAIN_CONSTRAINTS','KEY_COLUMN_USAGE','dtproperties'))";
var $metaColumnsSQL = # xtype==61 is datetime
"select c.name,t.name,c.length,
(case when c.xusertype=61 then 0 else c.xprec end),
(case when c.xusertype=61 then 0 else c.xscale end)
from syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id where o.name='%s'";
var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE
var $hasGenID = true;
var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
var $sysTimeStamp = 'GetDate()';
var $_has_mssql_init;
var $maxParameterLen = 4000;
var $arrayClass = 'ADORecordSet_array_mssql';
var $uniqueSort = true;
var $leftOuter = '*=';
var $rightOuter = '=*';
var $ansiOuter = true; // for mssql7 or later
var $poorAffectedRows = true;
var $identitySQL = 'select @@IDENTITY'; // 'select SCOPE_IDENTITY'; # for mssql 2000
var $uniqueOrderBy = true;
var $_bindInputArray = true;
function ADODB_mssql()
{
$this->_has_mssql_init = (strnatcmp(PHP_VERSION,'4.1.0')>=0);
}
function ServerInfo()
{
global $ADODB_FETCH_MODE;
$stmt = $this->PrepareSP('sp_server_info');
$val = 2;
if ($this->fetchMode === false) {
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
} else
$savem = $this->SetFetchMode(ADODB_FETCH_NUM);
$this->Parameter($stmt,$val,'attribute_id');
$row = $this->GetRow($stmt);
//$row = $this->GetRow("execute sp_server_info 2");
if ($this->fetchMode === false) {
$ADODB_FETCH_MODE = $savem;
} else
$this->SetFetchMode($savem);
$arr['description'] = $row[2];
$arr['version'] = ADOConnection::_findvers($arr['description']);
return $arr;
}
function IfNull( $field, $ifNull )
{
return " ISNULL($field, $ifNull) "; // if MS SQL Server
}
function _insertid()
{
// SCOPE_IDENTITY()
// Returns the last IDENTITY value inserted into an IDENTITY column in
// the same scope. A scope is a module -- a stored procedure, trigger,
// function, or batch. Thus, two statements are in the same scope if
// they are in the same stored procedure, function, or batch.
return $this->GetOne($this->identitySQL);
}
function _affectedrows()
{
return $this->GetOne('select @@rowcount');
}
var $_dropSeqSQL = "drop table %s";
function CreateSequence($seq='adodbseq',$start=1)
{
$start -= 1;
$this->Execute("create table $seq (id float(53))");
$ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
if (!$ok) {
$this->Execute('ROLLBACK TRANSACTION adodbseq');
return false;
}
$this->Execute('COMMIT TRANSACTION adodbseq');
return true;
}
function GenID($seq='adodbseq',$start=1)
{
//$this->debug=1;
$this->Execute('BEGIN TRANSACTION adodbseq');
$ok = $this->Execute("update $seq with (tablock,holdlock) set id = id + 1");
if (!$ok) {
$this->Execute("create table $seq (id float(53))");
$ok = $this->Execute("insert into $seq with (tablock,holdlock) values($start)");
if (!$ok) {
$this->Execute('ROLLBACK TRANSACTION adodbseq');
return false;
}
$this->Execute('COMMIT TRANSACTION adodbseq');
return $start;
}
$num = $this->GetOne("select id from $seq");
$this->Execute('COMMIT TRANSACTION adodbseq');
return $num;
// in old implementation, pre 1.90, we returned GUID...
//return $this->GetOne("SELECT CONVERT(varchar(255), NEWID()) AS 'Char'");
}
function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
{
if ($nrows > 0 && $offset <= 0) {
$sql = preg_replace(
'/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql);
$rs =& $this->Execute($sql,$inputarr);
} else
$rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
return $rs;
}
// Format date column in sql string given an input format that understands Y M D
function SQLDate($fmt, $col=false)
{
if (!$col) $col = $this->sysTimeStamp;
$s = '';
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
if ($s) $s .= '+';
$ch = $fmt[$i];
switch($ch) {
case 'Y':
case 'y':
$s .= "datename(yyyy,$col)";
break;
case 'M':
$s .= "convert(char(3),$col,0)";
break;
case 'm':
$s .= "replace(str(month($col),2),' ','0')";
break;
case 'Q':
case 'q':
$s .= "datename(quarter,$col)";
break;
case 'D':
case 'd':
$s .= "replace(str(day($col),2),' ','0')";
break;
case 'h':
$s .= "substring(convert(char(14),$col,0),13,2)";
break;
case 'H':
$s .= "replace(str(datepart(hh,$col),2),' ','0')";
break;
case 'i':
$s .= "replace(str(datepart(mi,$col),2),' ','0')";
break;
case 's':
$s .= "replace(str(datepart(ss,$col),2),' ','0')";
break;
case 'a':
case 'A':
$s .= "substring(convert(char(19),$col,0),18,2)";
break;
default:
if ($ch == '\\') {
$i++;
$ch = substr($fmt,$i,1);
}
$s .= $this->qstr($ch);
break;
}
}
return $s;
}
function BeginTrans()
{
if ($this->transOff) return true;
$this->transCnt += 1;
$this->Execute('BEGIN TRAN');
return true;
}
function CommitTrans($ok=true)
{
if ($this->transOff) return true;
if (!$ok) return $this->RollbackTrans();
if ($this->transCnt) $this->transCnt -= 1;
$this->Execute('COMMIT TRAN');
return true;
}
function RollbackTrans()
{
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
$this->Execute('ROLLBACK TRAN');
return true;
}
/*
Usage:
$this->BeginTrans();
$this->RowLock('table1,table2','table1.id=33 and table2.id=table1.id'); # lock row 33 for both tables
# some operation on both tables table1 and table2
$this->CommitTrans();
See http://www.swynk.com/friends/achigrik/SQL70Locks.asp
*/
function RowLock($tables,$where)
{
if (!$this->transCnt) $this->BeginTrans();
return $this->GetOne("select top 1 null as ignore from $tables with (ROWLOCK,HOLDLOCK) where $where");
}
function MetaForeignKeys($table, $owner=false, $upper=false)
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$table = $this->qstr(strtoupper($table));
$sql =
"select object_name(constid) as constraint_name,
col_name(fkeyid, fkey) as column_name,
object_name(rkeyid) as referenced_table_name,
col_name(rkeyid, rkey) as referenced_column_name
from sysforeignkeys
where upper(object_name(fkeyid)) = $table
order by constraint_name, referenced_table_name, keyno";
$constraints =& $this->GetArray($sql);
$ADODB_FETCH_MODE = $save;
$arr = false;
foreach($constraints as $constr) {
//print_r($constr);
$arr[$constr[0]][$constr[2]][] = $constr[1].'='.$constr[3];
}
if (!$arr) return false;
$arr2 = false;
foreach($arr as $k => $v) {
foreach($v as $a => $b) {
if ($upper) $a = strtoupper($a);
$arr2[$a] = $b;
}
}
return $arr2;
}
//From: Fernando Moreira <FMoreira@imediata.pt>
function MetaDatabases()
{
if(@mssql_select_db("master")) {
$qry=$this->metaDatabasesSQL;
if($rs=@mssql_query($qry)){
$tmpAr=$ar=array();
while($tmpAr=@mssql_fetch_row($rs))
$ar[]=$tmpAr[0];
@mssql_select_db($this->databaseName);
if(sizeof($ar))
return($ar);
else
return(false);
} else {
@mssql_select_db($this->databaseName);
return(false);
}
}
return(false);
}
// "Stein-Aksel Basma" <basma@accelero.no>
// tested with MSSQL 2000
function &MetaPrimaryKeys($table)
{
global $ADODB_FETCH_MODE;
$schema = '';
$this->_findschema($table,$schema);
if (!$schema) $schema = $this->database;
if ($schema) $schema = "and k.table_catalog like '$schema%'";
$sql = "select distinct k.column_name,ordinal_position from information_schema.key_column_usage k,
information_schema.table_constraints tc
where tc.constraint_name = k.constraint_name and tc.constraint_type =
'PRIMARY KEY' and k.table_name = '$table' $schema order by ordinal_position ";
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$a = $this->GetCol($sql);
$ADODB_FETCH_MODE = $savem;
if ($a && sizeof($a)>0) return $a;
return false;
}
function &MetaTables($ttype=false,$showSchema=false,$mask=false)
{
if ($mask) {
$save = $this->metaTablesSQL;
$mask = $this->qstr(($mask));
$this->metaTablesSQL .= " AND name like $mask";
}
$ret =& ADOConnection::MetaTables($ttype,$showSchema);
if ($mask) {
$this->metaTablesSQL = $save;
}
return $ret;
}
function SelectDB($dbName)
{
$this->databaseName = $dbName;
if ($this->_connectionID) {
return @mssql_select_db($dbName);
}
else return false;
}
function ErrorMsg()
{
if (empty($this->_errorMsg)){
$this->_errorMsg = mssql_get_last_message();
}
return $this->_errorMsg;
}
function ErrorNo()
{
if ($this->_logsql && $this->_errorCode !== false) return $this->_errorCode;
if (empty($this->_errorMsg)) {
$this->_errorMsg = mssql_get_last_message();
}
$id = @mssql_query("select @@ERROR",$this->_connectionID);
if (!$id) return false;
$arr = mssql_fetch_array($id);
@mssql_free_result($id);
if (is_array($arr)) return $arr[0];
else return -1;
}
// returns true or false
function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (!function_exists('mssql_pconnect')) return null;
$this->_connectionID = mssql_connect($argHostname,$argUsername,$argPassword);
if ($this->_connectionID === false) return false;
if ($argDatabasename) return $this->SelectDB($argDatabasename);
return true;
}
// returns true or false
function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (!function_exists('mssql_pconnect')) return null;
$this->_connectionID = mssql_pconnect($argHostname,$argUsername,$argPassword);
if ($this->_connectionID === false) return false;
// persistent connections can forget to rollback on crash, so we do it here.
if ($this->autoRollback) {
$cnt = $this->GetOne('select @@TRANCOUNT');
while (--$cnt >= 0) $this->Execute('ROLLBACK TRAN');
}
if ($argDatabasename) return $this->SelectDB($argDatabasename);
return true;
}
function Prepare($sql)
{
$sqlarr = explode('?',$sql);
if (sizeof($sqlarr) <= 1) return $sql;
$sql2 = $sqlarr[0];
for ($i = 1, $max = sizeof($sqlarr); $i < $max; $i++) {
$sql2 .= '@P'.($i-1) . $sqlarr[$i];
}
return array($sql,$this->qstr($sql2),$max);
}
function PrepareSP($sql)
{
if (!$this->_has_mssql_init) {
ADOConnection::outp( "PrepareSP: mssql_init only available since PHP 4.1.0");
return $sql;
}
$stmt = mssql_init($sql,$this->_connectionID);
if (!$stmt) return $sql;
return array($sql,$stmt);
}
/*
Usage:
$stmt = $db->PrepareSP('SP_RUNSOMETHING'); -- takes 2 params, @myid and @group
# note that the parameter does not have @ in front!
$db->Parameter($stmt,$id,'myid');
$db->Parameter($stmt,$group,'group',false,64);
$db->Execute($stmt);
@param $stmt Statement returned by Prepare() or PrepareSP().
@param $var PHP variable to bind to. Can set to null (for isNull support).
@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.
See mssql_bind documentation at php.net.
*/
function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=false)
{
if (!$this->_has_mssql_init) {
ADOConnection::outp( "Parameter: mssql_bind only available since PHP 4.1.0");
return $sql;
}
$isNull = is_null($var); // php 4.0.4 and above...
if ($type === false)
switch(gettype($var)) {
default:
case 'string': $type = SQLCHAR; break;
case 'double': $type = SQLFLT8; break;
case 'integer': $type = SQLINT4; break;
case 'boolean': $type = SQLINT1; break; # SQLBIT not supported in 4.1.0
}
if ($this->debug) {
$prefix = ($isOutput) ? 'Out' : 'In';
$ztype = (empty($type)) ? 'false' : $type;
ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");
}
/*
See http://phplens.com/lens/lensforum/msgs.php?id=7231
RETVAL is HARD CODED into php_mssql extension:
The return value (a long integer value) is treated like a special OUTPUT parameter,
called "RETVAL" (without the @). See the example at mssql_execute to
see how it works. - type: one of this new supported PHP constants.
SQLTEXT, SQLVARCHAR,SQLCHAR, SQLINT1,SQLINT2, SQLINT4, SQLBIT,SQLFLT8
*/
if ($name !== 'RETVAL') $name = '@'.$name;
return mssql_bind($stmt[1], $name, $var, $type, $isOutput, $isNull, $maxLen);
}
/*
Unfortunately, it appears that mssql cannot handle varbinary > 255 chars
So all your blobs must be of type "image".
Remember to set in php.ini the following...
; Valid range 0 - 2147483647. Default = 4096.
mssql.textlimit = 0 ; zero to pass through
; Valid range 0 - 2147483647. Default = 4096.
mssql.textsize = 0 ; zero to pass through
*/
function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
{
if (strtoupper($blobtype) == 'CLOB') {
$sql = "UPDATE $table SET $column='" . $val . "' WHERE $where";
return $this->Execute($sql) != false;
}
$sql = "UPDATE $table SET $column=0x".bin2hex($val)." WHERE $where";
return $this->Execute($sql) != false;
}
// returns query ID if successful, otherwise false
function _query($sql,$inputarr)
{
$this->_errorMsg = false;
if (is_array($inputarr)) {
# bind input params with sp_executesql:
# see http://www.quest-pipelines.com/newsletter-v3/0402_F.htm
# works only with sql server 7 and newer
if (!is_array($sql)) $sql = $this->Prepare($sql);
$params = '';
$decl = '';
$i = 0;
foreach($inputarr as $v) {
if ($decl) {
$decl .= ', ';
$params .= ', ';
}
if (is_string($v)) {
$len = strlen($v);
if ($len == 0) $len = 1;
if ($len > 4000 ) {
// NVARCHAR is max 4000 chars. Let's use NTEXT
$decl .= "@P$i NTEXT";
} else {
$decl .= "@P$i NVARCHAR($len)";
}
$params .= "@P$i=N". (strncmp($v,"'",1)==0? $v : $this->qstr($v));
} else if (is_integer($v)) {
$decl .= "@P$i INT";
$params .= "@P$i=".$v;
} else if (is_float($v)) {
$decl .= "@P$i FLOAT";
$params .= "@P$i=".$v;
} else if (is_bool($v)) {
$decl .= "@P$i INT"; # Used INT just in case BIT in not supported on the user's MSSQL version. It will cast appropriately.
$params .= "@P$i=".(($v)?'1':'0'); # True == 1 in MSSQL BIT fields and acceptable for storing logical true in an int field
} else {
$decl .= "@P$i CHAR"; # Used char because a type is required even when the value is to be NULL.
$params .= "@P$i=NULL";
}
$i += 1;
}
$decl = $this->qstr($decl);
if ($this->debug) ADOConnection::outp("<font size=-1>sp_executesql N{$sql[1]},N$decl,$params</font>");
$rez = mssql_query("sp_executesql N{$sql[1]},N$decl,$params");
} else if (is_array($sql)) {
# PrepareSP()
$rez = mssql_execute($sql[1]);
} else {
$rez = mssql_query($sql,$this->_connectionID);
}
return $rez;
}
// returns true or false
function _close()
{
if ($this->transCnt) $this->RollbackTrans();
$rez = @mssql_close($this->_connectionID);
$this->_connectionID = false;
return $rez;
}
// mssql uses a default date like Dec 30 2000 12:00AM
function UnixDate($v)
{
return ADORecordSet_array_mssql::UnixDate($v);
}
function UnixTimeStamp($v)
{
return ADORecordSet_array_mssql::UnixTimeStamp($v);
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordset_mssql extends ADORecordSet {
var $databaseType = "mssql";
var $canSeek = true;
var $hasFetchAssoc; // see http://phplens.com/lens/lensforum/msgs.php?id=6083
// _mths works only in non-localised system
function ADORecordset_mssql($id,$mode=false)
{
// freedts check...
$this->hasFetchAssoc = function_exists('mssql_fetch_assoc');
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
$this->fetchMode = $mode;
return $this->ADORecordSet($id,$mode);
}
function _initrs()
{
GLOBAL $ADODB_COUNTRECS;
$this->_numOfRows = ($ADODB_COUNTRECS)? @mssql_num_rows($this->_queryID):-1;
$this->_numOfFields = @mssql_num_fields($this->_queryID);
}
//Contributed by "Sven Axelsson" <sven.axelsson@bokochwebb.se>
// get next resultset - requires PHP 4.0.5 or later
function NextRecordSet()
{
if (!mssql_next_result($this->_queryID)) return false;
$this->_inited = false;
$this->bind = false;
$this->_currentRow = -1;
$this->Init();
return true;
}
/* Use associative array to get fields array */
function Fields($colname)
{
if ($this->fetchMode != ADODB_FETCH_NUM) return $this->fields[$colname];
if (!$this->bind) {
$this->bind = array();
for ($i=0; $i < $this->_numOfFields; $i++) {
$o = $this->FetchField($i);
$this->bind[strtoupper($o->name)] = $i;
}
}
return $this->fields[$this->bind[strtoupper($colname)]];
}
/* Returns: an object containing field information.
Get column information in the Recordset object. fetchField() can be used in order to obtain information about
fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
fetchField() is retrieved. */
function FetchField($fieldOffset = -1)
{
if ($fieldOffset != -1) {
return @mssql_fetch_field($this->_queryID, $fieldOffset);
}
else if ($fieldOffset == -1) { /* The $fieldOffset argument is not provided thus its -1 */
return @mssql_fetch_field($this->_queryID);
}
return null;
}
function _seek($row)
{
return @mssql_data_seek($this->_queryID, $row);
}
// speedup
function MoveNext()
{
if ($this->EOF) return false;
$this->_currentRow++;
if ($this->fetchMode & ADODB_FETCH_ASSOC) {
if ($this->fetchMode & ADODB_FETCH_NUM) {
//ADODB_FETCH_BOTH mode
$this->fields = @mssql_fetch_array($this->_queryID);
}
else {
if ($this->hasFetchAssoc) {// only for PHP 4.2.0 or later
$this->fields = @mssql_fetch_assoc($this->_queryID);
} else {
$flds = @mssql_fetch_array($this->_queryID);
if (is_array($flds)) {
$fassoc = array();
foreach($flds as $k => $v) {
if (is_numeric($k)) continue;
$fassoc[$k] = $v;
}
$this->fields = $fassoc;
} else
$this->fields = false;
}
}
if (is_array($this->fields)) {
if (ADODB_ASSOC_CASE == 0) {
foreach($this->fields as $k=>$v) {
$this->fields[strtolower($k)] = $v;
}
} else if (ADODB_ASSOC_CASE == 1) {
foreach($this->fields as $k=>$v) {
$this->fields[strtoupper($k)] = $v;
}
}
}
} else {
$this->fields = @mssql_fetch_row($this->_queryID);
}
if ($this->fields) return true;
$this->EOF = true;
return false;
}
// INSERT UPDATE DELETE returns false even if no error occurs in 4.0.4
// also the date format has been changed from YYYY-mm-dd to dd MMM YYYY in 4.0.4. Idiot!
function _fetch($ignore_fields=false)
{
if ($this->fetchMode & ADODB_FETCH_ASSOC) {
if ($this->fetchMode & ADODB_FETCH_NUM) {
//ADODB_FETCH_BOTH mode
$this->fields = @mssql_fetch_array($this->_queryID);
} else {
if ($this->hasFetchAssoc) // only for PHP 4.2.0 or later
$this->fields = @mssql_fetch_assoc($this->_queryID);
else {
$this->fields = @mssql_fetch_array($this->_queryID);
if (@is_array($$this->fields)) {
$fassoc = array();
foreach($$this->fields as $k => $v) {
if (is_integer($k)) continue;
$fassoc[$k] = $v;
}
$this->fields = $fassoc;
}
}
}
if (!$this->fields) {
} else if (ADODB_ASSOC_CASE == 0) {
foreach($this->fields as $k=>$v) {
$this->fields[strtolower($k)] = $v;
}
} else if (ADODB_ASSOC_CASE == 1) {
foreach($this->fields as $k=>$v) {
$this->fields[strtoupper($k)] = $v;
}
}
} else {
$this->fields = @mssql_fetch_row($this->_queryID);
}
return $this->fields;
}
/* close() only needs to be called if you are worried about using too much memory while your script
is running. All associated result memory for the specified result identifier will automatically be freed. */
function _close()
{
$rez = mssql_free_result($this->_queryID);
$this->_queryID = false;
return $rez;
}
// mssql uses a default date like Dec 30 2000 12:00AM
function UnixDate($v)
{
return ADORecordSet_array_mssql::UnixDate($v);
}
function UnixTimeStamp($v)
{
return ADORecordSet_array_mssql::UnixTimeStamp($v);
}
}
class ADORecordSet_array_mssql extends ADORecordSet_array {
function ADORecordSet_array_mssql($id=-1,$mode=false)
{
$this->ADORecordSet_array($id,$mode);
}
// mssql uses a default date like Dec 30 2000 12:00AM
function UnixDate($v)
{
if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixDate($v);
global $ADODB_mssql_mths,$ADODB_mssql_date_order;
//Dec 30 2000 12:00AM
if ($ADODB_mssql_date_order == 'dmy') {
if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
return parent::UnixDate($v);
}
if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
$theday = $rr[1];
$themth = substr(strtoupper($rr[2]),0,3);
} else {
if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
return parent::UnixDate($v);
}
if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
$theday = $rr[2];
$themth = substr(strtoupper($rr[1]),0,3);
}
$themth = $ADODB_mssql_mths[$themth];
if ($themth <= 0) return false;
// h-m-s-MM-DD-YY
return mktime(0,0,0,$themth,$theday,$rr[3]);
}
function UnixTimeStamp($v)
{
if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixTimeStamp($v);
global $ADODB_mssql_mths,$ADODB_mssql_date_order;
//Dec 30 2000 12:00AM
if ($ADODB_mssql_date_order == 'dmy') {
if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|"
,$v, $rr)) return parent::UnixTimeStamp($v);
if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
$theday = $rr[1];
$themth = substr(strtoupper($rr[2]),0,3);
} else {
if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|"
,$v, $rr)) return parent::UnixTimeStamp($v);
if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
$theday = $rr[2];
$themth = substr(strtoupper($rr[1]),0,3);
}
$themth = $ADODB_mssql_mths[$themth];
if ($themth <= 0) return false;
switch (strtoupper($rr[6])) {
case 'P':
if ($rr[4]<12) $rr[4] += 12;
break;
case 'A':
if ($rr[4]==12) $rr[4] = 0;
break;
default:
break;
}
// h-m-s-MM-DD-YY
return mktime($rr[4],$rr[5],0,$themth,$theday,$rr[3]);
}
}
/*
Code Example 1:
select object_name(constid) as constraint_name,
object_name(fkeyid) as table_name,
col_name(fkeyid, fkey) as column_name,
object_name(rkeyid) as referenced_table_name,
col_name(rkeyid, rkey) as referenced_column_name
from sysforeignkeys
where object_name(fkeyid) = x
order by constraint_name, table_name, referenced_table_name, keyno
Code Example 2:
select constraint_name,
column_name,
ordinal_position
from information_schema.key_column_usage
where constraint_catalog = db_name()
and table_name = x
order by constraint_name, ordinal_position
http://www.databasejournal.com/scripts/article.php/1440551
*/
?>

View File

@ -0,0 +1,707 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 8.
MySQL code that does not support transactions. Use mysqlt if you need transactions.
Requires mysql client. Works on Windows and Unix.
28 Feb 2001: MetaColumns bug fix - suggested by Freek Dijkstra (phpeverywhere@macfreek.com)
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
if (! defined("_ADODB_MYSQL_LAYER")) {
define("_ADODB_MYSQL_LAYER", 1 );
class ADODB_mysql extends ADOConnection {
var $databaseType = 'mysql';
var $dataProvider = 'mysql';
var $hasInsertID = true;
var $hasAffectedRows = true;
var $metaTablesSQL = "SHOW TABLES";
var $metaColumnsSQL = "SHOW COLUMNS FROM %s";
var $fmtTimeStamp = "'Y-m-d H:i:s'";
var $hasLimit = true;
var $hasMoveFirst = true;
var $hasGenID = true;
var $isoDates = true; // accepts dates in ISO format
var $sysDate = 'CURDATE()';
var $sysTimeStamp = 'NOW()';
var $hasTransactions = false;
var $forceNewConnect = false;
var $poorAffectedRows = true;
var $clientFlags = 0;
var $substr = "substring";
var $nameQuote = '`'; /// string to use to quote identifiers and names
function ADODB_mysql()
{
if (defined('ADODB_EXTENSION')) $this->rsPrefix .= 'ext_';
}
function ServerInfo()
{
$arr['description'] = ADOConnection::GetOne("select version()");
$arr['version'] = ADOConnection::_findvers($arr['description']);
return $arr;
}
function IfNull( $field, $ifNull )
{
return " IFNULL($field, $ifNull) "; // if MySQL
}
function &MetaTables($ttype=false,$showSchema=false,$mask=false)
{
$save = $this->metaTablesSQL;
if ($showSchema && is_string($showSchema)) {
$this->metaTablesSQL .= " from $showSchema";
}
if ($mask) {
$mask = $this->qstr($mask);
$this->metaTablesSQL .= " like $mask";
}
$ret =& ADOConnection::MetaTables($ttype,$showSchema);
$this->metaTablesSQL = $save;
return $ret;
}
function &MetaIndexes ($table, $primary = FALSE, $owner=false)
{
// save old fetch mode
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
$savem = $this->SetFetchMode(FALSE);
}
// get index details
$rs = $this->Execute(sprintf('SHOW INDEX FROM %s',$table));
// restore fetchmode
if (isset($savem)) {
$this->SetFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
if (!is_object($rs)) {
return FALSE;
}
$indexes = array ();
// parse index data into array
while ($row = $rs->FetchRow()) {
if ($primary == FALSE AND $row[2] == 'PRIMARY') {
continue;
}
if (!isset($indexes[$row[2]])) {
$indexes[$row[2]] = array(
'unique' => ($row[1] == 0),
'columns' => array()
);
}
$indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
}
// sort columns by order in the index
foreach ( array_keys ($indexes) as $index )
{
ksort ($indexes[$index]['columns']);
}
return $indexes;
}
// if magic quotes disabled, use mysql_real_escape_string()
function qstr($s,$magic_quotes=false)
{
if (!$magic_quotes) {
if (ADODB_PHPVER >= 0x4300) {
if (is_resource($this->_connectionID))
return "'".mysql_real_escape_string($s,$this->_connectionID)."'";
}
if ($this->replaceQuote[0] == '\\'){
$s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
}
return "'".str_replace("'",$this->replaceQuote,$s)."'";
}
// undo magic quotes for "
$s = str_replace('\\"','"',$s);
return "'$s'";
}
function _insertid()
{
return mysql_insert_id($this->_connectionID);
}
function GetOne($sql,$inputarr=false)
{
if (strncasecmp($sql,'sele',4) == 0) {
$rs =& $this->SelectLimit($sql,1,-1,$inputarr);
if ($rs) {
$rs->Close();
if ($rs->EOF) return false;
return reset($rs->fields);
}
} else {
return ADOConnection::GetOne($sql,$inputarr);
}
return false;
}
function BeginTrans()
{
if ($this->debug) ADOConnection::outp("Transactions not supported in 'mysql' driver. Use 'mysqlt' or 'mysqli' driver");
}
function _affectedrows()
{
return mysql_affected_rows($this->_connectionID);
}
// See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
// Reference on Last_Insert_ID on the recommended way to simulate sequences
var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
var $_genSeqSQL = "create table %s (id int not null)";
var $_genSeq2SQL = "insert into %s values (%s)";
var $_dropSeqSQL = "drop table %s";
function CreateSequence($seqname='adodbseq',$startID=1)
{
if (empty($this->_genSeqSQL)) return false;
$u = strtoupper($seqname);
$ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
if (!$ok) return false;
return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
}
function GenID($seqname='adodbseq',$startID=1)
{
// post-nuke sets hasGenID to false
if (!$this->hasGenID) return false;
$savelog = $this->_logsql;
$this->_logsql = false;
$getnext = sprintf($this->_genIDSQL,$seqname);
$holdtransOK = $this->_transOK; // save the current status
$rs = @$this->Execute($getnext);
if (!$rs) {
if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset
$u = strtoupper($seqname);
$this->Execute(sprintf($this->_genSeqSQL,$seqname));
$this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
$rs = $this->Execute($getnext);
}
$this->genID = mysql_insert_id($this->_connectionID);
if ($rs) $rs->Close();
$this->_logsql = $savelog;
return $this->genID;
}
function &MetaDatabases()
{
$qid = mysql_list_dbs($this->_connectionID);
$arr = array();
$i = 0;
$max = mysql_num_rows($qid);
while ($i < $max) {
$db = mysql_tablename($qid,$i);
if ($db != 'mysql') $arr[] = $db;
$i += 1;
}
return $arr;
}
// Format date column in sql string given an input format that understands Y M D
function SQLDate($fmt, $col=false)
{
if (!$col) $col = $this->sysTimeStamp;
$s = 'DATE_FORMAT('.$col.",'";
$concat = false;
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
$ch = $fmt[$i];
switch($ch) {
default:
if ($ch == '\\') {
$i++;
$ch = substr($fmt,$i,1);
}
/** FALL THROUGH */
case '-':
case '/':
$s .= $ch;
break;
case 'Y':
case 'y':
$s .= '%Y';
break;
case 'M':
$s .= '%b';
break;
case 'm':
$s .= '%m';
break;
case 'D':
case 'd':
$s .= '%d';
break;
case 'Q':
case 'q':
$s .= "'),Quarter($col)";
if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
else $s .= ",('";
$concat = true;
break;
case 'H':
$s .= '%H';
break;
case 'h':
$s .= '%I';
break;
case 'i':
$s .= '%i';
break;
case 's':
$s .= '%s';
break;
case 'a':
case 'A':
$s .= '%p';
break;
}
}
$s.="')";
if ($concat) $s = "CONCAT($s)";
return $s;
}
// returns concatenated string
// much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
function Concat()
{
$s = "";
$arr = func_get_args();
// suggestion by andrew005@mnogo.ru
$s = implode(',',$arr);
if (strlen($s) > 0) return "CONCAT($s)";
else return '';
}
function OffsetDate($dayFraction,$date=false)
{
if (!$date) $date = $this->sysDate;
return "from_unixtime(unix_timestamp($date)+($dayFraction)*24*3600)";
}
// returns true or false
function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (ADODB_PHPVER >= 0x4300)
$this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword,
$this->forceNewConnect,$this->clientFlags);
else if (ADODB_PHPVER >= 0x4200)
$this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword,
$this->forceNewConnect);
else
$this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword);
if ($this->_connectionID === false) return false;
if ($argDatabasename) return $this->SelectDB($argDatabasename);
return true;
}
// returns true or false
function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (ADODB_PHPVER >= 0x4300)
$this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword,$this->clientFlags);
else
$this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword);
if ($this->_connectionID === false) return false;
if ($this->autoRollback) $this->RollbackTrans();
if ($argDatabasename) return $this->SelectDB($argDatabasename);
return true;
}
function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
$this->forceNewConnect = true;
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
}
function &MetaColumns($table)
{
if ($this->metaColumnsSQL) {
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rs === false) return false;
$retarr = array();
while (!$rs->EOF){
$fld = new ADOFieldObject();
$fld->name = $rs->fields[0];
$type = $rs->fields[1];
// split type into type(length):
$fld->scale = null;
if (strpos($type,',') && preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
$fld->type = $query_array[1];
$fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
$fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
} elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
$fld->type = $query_array[1];
$fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
} else {
$fld->max_length = -1;
$fld->type = $type;
}
/*
// split type into type(length):
if (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
$fld->type = $query_array[1];
$fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
} else {
$fld->max_length = -1;
$fld->type = $type;
}*/
$fld->not_null = ($rs->fields[2] != 'YES');
$fld->primary_key = ($rs->fields[3] == 'PRI');
$fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
$fld->binary = (strpos($fld->type,'blob') !== false);
if (!$fld->binary) {
$d = $rs->fields[4];
if ($d != "" && $d != "NULL") {
$fld->has_default = true;
$fld->default_value = $d;
} else {
$fld->has_default = false;
}
}
if ($save == ADODB_FETCH_NUM) $retarr[] = $fld;
else $retarr[strtoupper($fld->name)] = $fld;
$rs->MoveNext();
}
$rs->Close();
return $retarr;
}
return false;
}
// returns true or false
function SelectDB($dbName)
{
$this->databaseName = $dbName;
if ($this->_connectionID) {
return @mysql_select_db($dbName,$this->_connectionID);
}
else return false;
}
// parameters use PostgreSQL convention, not MySQL
function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs=0)
{
$offsetStr =($offset>=0) ? "$offset," : '';
// jason judge, see http://phplens.com/lens/lensforum/msgs.php?id=9220
if ($nrows < 0) $nrows = '18446744073709551615';
if ($secs)
$rs =& $this->CacheExecute($secs,$sql." LIMIT $offsetStr$nrows",$inputarr);
else
$rs =& $this->Execute($sql." LIMIT $offsetStr$nrows",$inputarr);
return $rs;
}
// returns queryID or false
function _query($sql,$inputarr)
{
//global $ADODB_COUNTRECS;
//if($ADODB_COUNTRECS)
return mysql_query($sql,$this->_connectionID);
//else return @mysql_unbuffered_query($sql,$this->_connectionID); // requires PHP >= 4.0.6
}
/* Returns: the last error message from previous database operation */
function ErrorMsg()
{
if ($this->_logsql) return $this->_errorMsg;
if (empty($this->_connectionID)) $this->_errorMsg = @mysql_error();
else $this->_errorMsg = @mysql_error($this->_connectionID);
return $this->_errorMsg;
}
/* Returns: the last error number from previous database operation */
function ErrorNo()
{
if ($this->_logsql) return $this->_errorCode;
if (empty($this->_connectionID)) return @mysql_errno();
else return @mysql_errno($this->_connectionID);
}
// returns true or false
function _close()
{
@mysql_close($this->_connectionID);
$this->_connectionID = false;
}
/*
* Maximum size of C field
*/
function CharMax()
{
return 255;
}
/*
* Maximum size of X field
*/
function TextMax()
{
return 4294967295;
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordSet_mysql extends ADORecordSet{
var $databaseType = "mysql";
var $canSeek = true;
function ADORecordSet_mysql($queryID,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
switch ($mode)
{
case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break;
case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break;
default:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:$this->fetchMode = MYSQL_BOTH; break;
}
$this->ADORecordSet($queryID);
}
function _initrs()
{
//GLOBAL $ADODB_COUNTRECS;
// $this->_numOfRows = ($ADODB_COUNTRECS) ? @mysql_num_rows($this->_queryID):-1;
$this->_numOfRows = @mysql_num_rows($this->_queryID);
$this->_numOfFields = @mysql_num_fields($this->_queryID);
}
function &FetchField($fieldOffset = -1)
{
if ($fieldOffset != -1) {
$o = @mysql_fetch_field($this->_queryID, $fieldOffset);
$f = @mysql_field_flags($this->_queryID,$fieldOffset);
$o->max_length = @mysql_field_len($this->_queryID,$fieldOffset); // suggested by: Jim Nicholson (jnich@att.com)
//$o->max_length = -1; // mysql returns the max length less spaces -- so it is unrealiable
$o->binary = (strpos($f,'binary')!== false);
}
else if ($fieldOffset == -1) { /* The $fieldOffset argument is not provided thus its -1 */
$o = @mysql_fetch_field($this->_queryID);
$o->max_length = @mysql_field_len($this->_queryID); // suggested by: Jim Nicholson (jnich@att.com)
//$o->max_length = -1; // mysql returns the max length less spaces -- so it is unrealiable
}
return $o;
}
function &GetRowAssoc($upper=true)
{
if ($this->fetchMode == MYSQL_ASSOC && !$upper) return $this->fields;
$row =& ADORecordSet::GetRowAssoc($upper);
return $row;
}
/* Use associative array to get fields array */
function Fields($colname)
{
// added @ by "Michael William Miller" <mille562@pilot.msu.edu>
if ($this->fetchMode != MYSQL_NUM) return @$this->fields[$colname];
if (!$this->bind) {
$this->bind = array();
for ($i=0; $i < $this->_numOfFields; $i++) {
$o = $this->FetchField($i);
$this->bind[strtoupper($o->name)] = $i;
}
}
return $this->fields[$this->bind[strtoupper($colname)]];
}
function _seek($row)
{
if ($this->_numOfRows == 0) return false;
return @mysql_data_seek($this->_queryID,$row);
}
function MoveNext()
{
//return adodb_movenext($this);
//if (defined('ADODB_EXTENSION')) return adodb_movenext($this);
if (@$this->fields =& mysql_fetch_array($this->_queryID,$this->fetchMode)) {
$this->_currentRow += 1;
return true;
}
if (!$this->EOF) {
$this->_currentRow += 1;
$this->EOF = true;
}
return false;
}
function _fetch()
{
$this->fields = @mysql_fetch_array($this->_queryID,$this->fetchMode);
return is_array($this->fields);
}
function _close() {
@mysql_free_result($this->_queryID);
$this->_queryID = false;
}
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
case 'STRING':
case 'CHAR':
case 'VARCHAR':
case 'TINYBLOB':
case 'TINYTEXT':
case 'ENUM':
case 'SET':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
case 'LONGTEXT':
case 'MEDIUMTEXT':
return 'X';
// php_mysql extension always returns 'blob' even if 'text'
// so we have to check whether binary...
case 'IMAGE':
case 'LONGBLOB':
case 'BLOB':
case 'MEDIUMBLOB':
return !empty($fieldobj->binary) ? 'B' : 'X';
case 'YEAR':
case 'DATE': return 'D';
case 'TIME':
case 'DATETIME':
case 'TIMESTAMP': return 'T';
case 'INT':
case 'INTEGER':
case 'BIGINT':
case 'TINYINT':
case 'MEDIUMINT':
case 'SMALLINT':
if (!empty($fieldobj->primary_key)) return 'R';
else return 'I';
default: return 'N';
}
}
}
class ADORecordSet_ext_mysql extends ADORecordSet_mysql {
function ADORecordSet_ext_mysql($queryID,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
switch ($mode)
{
case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break;
case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break;
default:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:$this->fetchMode = MYSQL_BOTH; break;
}
$this->ADORecordSet($queryID);
}
function MoveNext()
{
return adodb_movenext($this);
}
}
}
?>

View File

@ -0,0 +1,799 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 8.
MySQL code that does not support transactions. Use mysqlt if you need transactions.
Requires mysql client. Works on Windows and Unix.
21 October 2003: MySQLi extension implementation by Arjen de Rijke (a.de.rijke@xs4all.nl)
Based on adodb 3.40
*/
// security - hide paths
//if (!defined('ADODB_DIR')) die();
if (! defined("_ADODB_MYSQLI_LAYER")) {
define("_ADODB_MYSQLI_LAYER", 1 );
class ADODB_mysqli extends ADOConnection {
var $databaseType = 'mysqli';
var $dataProvider = 'native';
var $hasInsertID = true;
var $hasAffectedRows = true;
var $metaTablesSQL = "SHOW TABLES";
var $metaColumnsSQL = "SHOW COLUMNS FROM %s";
var $fmtTimeStamp = "'Y-m-d H:i:s'";
var $hasLimit = true;
var $hasMoveFirst = true;
var $hasGenID = true;
var $isoDates = true; // accepts dates in ISO format
var $sysDate = 'CURDATE()';
var $sysTimeStamp = 'NOW()';
var $hasTransactions = false;
var $forceNewConnect = false;
var $poorAffectedRows = true;
var $clientFlags = 0;
var $substr = "substring";
var $port = false;
var $socket = false;
var $_bindInputArray = false;
var $nameQuote = '`'; /// string to use to quote identifiers and names
function ADODB_mysqli()
{
if(!extension_loaded("mysqli"))
trigger_error("You must have the MySQLi extension.", E_USER_ERROR);
}
// returns true or false
// To add: parameter int $port,
// parameter string $socket
function _connect($argHostname = NULL,
$argUsername = NULL,
$argPassword = NULL,
$argDatabasename = NULL, $persist=false)
{
$this->_connectionID = @mysqli_init();
if (is_null($this->_connectionID)) {
// mysqli_init only fails if insufficient memory
if ($this->debug)
ADOConnection::outp("mysqli_init() failed : " . $this->ErrorMsg());
return false;
}
// Set connection options
// Not implemented now
// mysqli_options($this->_connection,,);
if (mysqli_real_connect($this->_connectionID,
$argHostname,
$argUsername,
$argPassword,
$argDatabasename,
$this->port,
$this->socket,
$this->clientFlags))
{
if ($argDatabasename) return $this->SelectDB($argDatabasename);
return true;
}
else {
if ($this->debug)
ADOConnection::outp("Could't connect : " . $this->ErrorMsg());
return false;
}
}
// returns true or false
// How to force a persistent connection
function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true);
}
// When is this used? Close old connection first?
// In _connect(), check $this->forceNewConnect?
function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
$this->forceNewConnect = true;
$this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
}
function IfNull( $field, $ifNull )
{
return " IFNULL($field, $ifNull) "; // if MySQL
}
function ServerInfo()
{
$arr['description'] = $this->GetOne("select version()");
$arr['version'] = ADOConnection::_findvers($arr['description']);
return $arr;
}
function BeginTrans()
{
if ($this->transOff) return true;
$this->transCnt += 1;
$this->Execute('SET AUTOCOMMIT=0');
$this->Execute('BEGIN');
return true;
}
function CommitTrans($ok=true)
{
if ($this->transOff) return true;
if (!$ok) return $this->RollbackTrans();
if ($this->transCnt) $this->transCnt -= 1;
$this->Execute('COMMIT');
$this->Execute('SET AUTOCOMMIT=1');
return true;
}
function RollbackTrans()
{
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
$this->Execute('ROLLBACK');
$this->Execute('SET AUTOCOMMIT=1');
return true;
}
// if magic quotes disabled, use mysql_real_escape_string()
// From readme.htm:
// Quotes a string to be sent to the database. The $magic_quotes_enabled
// parameter may look funny, but the idea is if you are quoting a
// string extracted from a POST/GET variable, then
// pass get_magic_quotes_gpc() as the second parameter. This will
// ensure that the variable is not quoted twice, once by qstr and once
// by the magic_quotes_gpc.
//
//Eg. $s = $db->qstr(HTTP_GET_VARS['name'],get_magic_quotes_gpc());
function qstr($s, $magic_quotes = false)
{
if (!$magic_quotes) {
if (PHP_VERSION >= 5)
return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'";
if ($this->replaceQuote[0] == '\\')
$s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
return "'".str_replace("'",$this->replaceQuote,$s)."'";
}
// undo magic quotes for "
$s = str_replace('\\"','"',$s);
return "'$s'";
}
function _insertid()
{
// $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);
$result = @mysqli_insert_id($this->_connectionID);
if ($result == -1){
if ($this->debug) ADOConnection::outp("mysqli_insert_id() failed : " . $this->ErrorMsg());
}
return $result;
}
// Only works for INSERT, UPDATE and DELETE query's
function _affectedrows()
{
// $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);
$result = @mysqli_affected_rows($this->_connectionID);
if ($result == -1) {
if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : " . $this->ErrorMsg());
}
return $result;
}
// See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
// Reference on Last_Insert_ID on the recommended way to simulate sequences
var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
var $_genSeqSQL = "create table %s (id int not null)";
var $_genSeq2SQL = "insert into %s values (%s)";
var $_dropSeqSQL = "drop table %s";
function CreateSequence($seqname='adodbseq',$startID=1)
{
if (empty($this->_genSeqSQL)) return false;
$u = strtoupper($seqname);
$ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
if (!$ok) return false;
return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
}
function GenID($seqname='adodbseq',$startID=1)
{
// post-nuke sets hasGenID to false
if (!$this->hasGenID) return false;
$getnext = sprintf($this->_genIDSQL,$seqname);
$holdtransOK = $this->_transOK; // save the current status
$rs = @$this->Execute($getnext);
if (!$rs) {
if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset
$u = strtoupper($seqname);
$this->Execute(sprintf($this->_genSeqSQL,$seqname));
$this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
$rs = $this->Execute($getnext);
}
$this->genID = mysqli_insert_id($this->_connectionID);
if ($rs) $rs->Close();
return $this->genID;
}
function &MetaDatabases()
{
$query = "SHOW DATABASES";
$ret =& $this->Execute($query);
return $ret;
}
function &MetaIndexes ($table, $primary = FALSE)
{
// save old fetch mode
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
$savem = $this->SetFetchMode(FALSE);
}
// get index details
$rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table));
// restore fetchmode
if (isset($savem)) {
$this->SetFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
if (!is_object($rs)) {
return FALSE;
}
$indexes = array ();
// parse index data into array
while ($row = $rs->FetchRow()) {
if ($primary == FALSE AND $row[2] == 'PRIMARY') {
continue;
}
if (!isset($indexes[$row[2]])) {
$indexes[$row[2]] = array(
'unique' => ($row[1] == 0),
'columns' => array()
);
}
$indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
}
// sort columns by order in the index
foreach ( array_keys ($indexes) as $index )
{
ksort ($indexes[$index]['columns']);
}
return $indexes;
}
// Format date column in sql string given an input format that understands Y M D
function SQLDate($fmt, $col=false)
{
if (!$col) $col = $this->sysTimeStamp;
$s = 'DATE_FORMAT('.$col.",'";
$concat = false;
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
$ch = $fmt[$i];
switch($ch) {
case 'Y':
case 'y':
$s .= '%Y';
break;
case 'Q':
case 'q':
$s .= "'),Quarter($col)";
if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
else $s .= ",('";
$concat = true;
break;
case 'M':
$s .= '%b';
break;
case 'm':
$s .= '%m';
break;
case 'D':
case 'd':
$s .= '%d';
break;
case 'H':
$s .= '%H';
break;
case 'h':
$s .= '%I';
break;
case 'i':
$s .= '%i';
break;
case 's':
$s .= '%s';
break;
case 'a':
case 'A':
$s .= '%p';
break;
default:
if ($ch == '\\') {
$i++;
$ch = substr($fmt,$i,1);
}
$s .= $ch;
break;
}
}
$s.="')";
if ($concat) $s = "CONCAT($s)";
return $s;
}
// returns concatenated string
// much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
function Concat()
{
$s = "";
$arr = func_get_args();
// suggestion by andrew005@mnogo.ru
$s = implode(',',$arr);
if (strlen($s) > 0) return "CONCAT($s)";
else return '';
}
// dayFraction is a day in floating point
function OffsetDate($dayFraction,$date=false)
{
if (!$date)
$date = $this->sysDate;
return "from_unixtime(unix_timestamp($date)+($dayFraction)*24*3600)";
}
function &MetaColumns($table)
{
if ($this->metaColumnsSQL) {
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$rs = false;
switch($ADODB_FETCH_MODE)
{
case ADODB_FETCH_NUM:
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->Execute(sprintf($this->metaColumnsSQL,
$table));
$ADODB_FETCH_MODE = $save;
if ($rs === false) break;
$retarr = array();
while (!$rs->EOF){
$fld = new ADOFieldObject();
$fld->name = $rs->fields[0];
$fld->type = $rs->fields[1];
// split type into type(length):
if (preg_match("/^(.+)\((\d+)\)$/", $fld->type, $query_array))
{
$fld->type = $query_array[1];
$fld->max_length = $query_array[2];
}
else
{
$fld->max_length = -1;
}
$fld->not_null = ($rs->fields[2] != 'YES');
$fld->primary_key = ($rs->fields[3] == 'PRI');
$fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
$fld->binary = (strpos($fld->type,'blob') !== false);
if (!$fld->binary)
{
$d = $rs->fields[4];
$d = $rs->fields['Default'];
if ($d != "" && $d != "NULL")
{
$fld->has_default = true;
$fld->default_value = $d;
}
else
{
$fld->has_default = false;
}
}
$retarr[strtoupper($fld->name)] = $fld;
$rs->MoveNext();
}
break;
case ADODB_FETCH_ASSOC:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$rs = $this->Execute(sprintf($this->metaColumnsSQL,
$table));
$ADODB_FETCH_MODE = $save;
if ($rs === false) break;
$retarr = array();
while (!$rs->EOF){
$fld = new ADOFieldObject();
$fld->name = $rs->fields['Field'];
$fld->type = $rs->fields['Type'];
// split type into type(length):
if (preg_match("/^(.+)\((\d+)\)$/", $fld->type, $query_array))
{
$fld->type = $query_array[1];
$fld->max_length = $query_array[2];
}
else
{
$fld->max_length = -1;
}
$fld->not_null = ($rs->fields['Null'] != 'YES');
$fld->primary_key = ($rs->fields['Key'] == 'PRI');
$fld->auto_increment = (strpos($rs->fields['Extra'], 'auto_increment') !== false);
$fld->binary = (strpos($fld->type,'blob') !== false);
if (!$fld->binary)
{
$d = $rs->fields['Default'];
if ($d != "" && $d != "NULL")
{
$fld->has_default = true;
$fld->default_value = $d;
}
else
{
$fld->has_default = false;
}
}
$retarr[strtoupper($fld->name)] = $fld;
$rs->MoveNext();
}
break;
default:
}
if ($rs === false) return false;
$rs->Close();
return $retarr;
}
return false;
}
// returns true or false
function SelectDB($dbName)
{
// $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);
$this->databaseName = $dbName;
if ($this->_connectionID) {
$result = @mysqli_select_db($this->_connectionID, $dbName);
if (!$result) {
ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg());
}
return $result;
}
return false;
}
// parameters use PostgreSQL convention, not MySQL
function &SelectLimit($sql,
$nrows = -1,
$offset = -1,
$inputarr = false,
$arg3 = false,
$secs = 0)
{
$offsetStr = ($offset >= 0) ? "$offset," : '';
if ($secs)
$rs =& $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr , $arg3);
else
$rs =& $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr , $arg3);
return $rs;
}
function Prepare($sql)
{
return $sql;
$stmt = $this->_connectionID->prepare($sql);
if (!$stmt) {
echo $this->ErrorMsg();
return $sql;
}
return array($sql,$stmt);
}
// returns queryID or false
function _query($sql, $inputarr)
{
global $ADODB_COUNTRECS;
if (is_array($sql)) {
$stmt = $sql[1];
$a = '';
foreach($inputarr as $k => $v) {
if (is_string($v)) $a .= 's';
else if (is_integer($v)) $a .= 'i';
else $a .= 'd';
}
$fnarr =& array_merge( array($stmt,$a) , $inputarr);
$ret = call_user_func_array('mysqli_stmt_bind_param',$fnarr);
$ret = mysqli_stmt_execute($stmt);
return $ret;
}
if (!$mysql_res = mysqli_query($this->_connectionID, $sql, ($ADODB_COUNTRECS) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT)) {
if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
return false;
}
return $mysql_res;
}
/* Returns: the last error message from previous database operation */
function ErrorMsg()
{
if (empty($this->_connectionID))
$this->_errorMsg = @mysqli_error();
else
$this->_errorMsg = @mysqli_error($this->_connectionID);
return $this->_errorMsg;
}
/* Returns: the last error number from previous database operation */
function ErrorNo()
{
if (empty($this->_connectionID))
return @mysqli_errno();
else
return @mysqli_errno($this->_connectionID);
}
// returns true or false
function _close()
{
@mysqli_close($this->_connectionID);
$this->_connectionID = false;
}
/*
* Maximum size of C field
*/
function CharMax()
{
return 255;
}
/*
* Maximum size of X field
*/
function TextMax()
{
return 4294967295;
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordSet_mysqli extends ADORecordSet{
var $databaseType = "mysqli";
var $canSeek = true;
function ADORecordSet_mysqli($queryID, $mode = false)
{
if ($mode === false)
{
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
switch ($mode)
{
case ADODB_FETCH_NUM:
$this->fetchMode = MYSQLI_NUM;
break;
case ADODB_FETCH_ASSOC:
$this->fetchMode = MYSQLI_ASSOC;
break;
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:
default:
$this->fetchMode = MYSQLI_BOTH;
break;
}
$this->ADORecordSet($queryID);
}
function _initrs()
{
global $ADODB_COUNTRECS;
$this->_numOfRows = $ADODB_COUNTRECS ? @mysqli_num_rows($this->_queryID) : -1;
$this->_numOfFields = @mysqli_num_fields($this->_queryID);
}
function &FetchField($fieldOffset = -1)
{
$fieldnr = $fieldOffset;
if ($fieldOffset != -1) {
$fieldOffset = mysqli_field_seek($this->_queryID, $fieldnr);
}
$o = mysqli_fetch_field($this->_queryID);
return $o;
}
function &GetRowAssoc($upper = true)
{
if ($this->fetchMode == MYSQLI_ASSOC && !$upper)
return $this->fields;
$row =& ADORecordSet::GetRowAssoc($upper);
return $row;
}
/* Use associative array to get fields array */
function Fields($colname)
{
if ($this->fetchMode != MYSQLI_NUM)
return @$this->fields[$colname];
if (!$this->bind) {
$this->bind = array();
for ($i = 0; $i < $this->_numOfFields; $i++) {
$o = $this->FetchField($i);
$this->bind[strtoupper($o->name)] = $i;
}
}
return $this->fields[$this->bind[strtoupper($colname)]];
}
function _seek($row)
{
if ($this->_numOfRows == 0)
return false;
if ($row < 0)
return false;
mysqli_data_seek($this->_queryID, $row);
$this->EOF = false;
return true;
}
// 10% speedup to move MoveNext to child class
// This is the only implementation that works now (23-10-2003).
// Other functions return no or the wrong results.
function MoveNext()
{
if ($this->EOF) return false;
$this->_currentRow++;
$this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode);
if (is_array($this->fields)) return true;
$this->EOF = true;
return false;
}
function _fetch()
{
$this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode);
return is_array($this->fields);
}
function _close()
{
mysqli_free_result($this->_queryID);
$this->_queryID = false;
}
function MetaType($t, $len = -1, $fieldobj = false)
{
if (is_object($t))
{
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
case 'STRING':
case 'CHAR':
case 'VARCHAR':
case 'TINYBLOB':
case 'TINYTEXT':
case 'ENUM':
case 'SET':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
case 'LONGTEXT':
case 'MEDIUMTEXT':
return 'X';
// php_mysql extension always returns 'blob' even if 'text'
// so we have to check whether binary...
case 'IMAGE':
case 'LONGBLOB':
case 'BLOB':
case 'MEDIUMBLOB':
return !empty($fieldobj->binary) ? 'B' : 'X';
case 'YEAR':
case 'DATE':
return 'D';
case 'TIME':
case 'DATETIME':
case 'TIMESTAMP': return 'T';
case 'INT':
case 'INTEGER':
case 'BIGINT':
case 'TINYINT':
case 'MEDIUMINT':
case 'SMALLINT':
if (!empty($fieldobj->primary_key)) return 'R';
else return 'I';
// Added floating-point types
// Maybe not necessery.
case 'FLOAT':
case 'DOUBLE':
// case 'DOUBLE PRECISION':
case 'DECIMAL':
case 'DEC':
case 'FIXED':
default:
return 'N';
}
}
}
}
?>

View File

@ -0,0 +1,125 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 8.
MySQL code that supports transactions. For MySQL 3.23 or later.
Code from James Poon <jpoon88@yahoo.com>
Requires mysql client. Works on Windows and Unix.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
include_once(ADODB_DIR."/drivers/adodb-mysql.inc.php");
class ADODB_mysqlt extends ADODB_mysql {
var $databaseType = 'mysqlt';
var $ansiOuter = true; // for Version 3.23.17 or later
var $hasTransactions = true;
var $autoRollback = true; // apparently mysql does not autorollback properly
function ADODB_mysqlt()
{
global $ADODB_EXTENSION; if ($ADODB_EXTENSION) $this->rsPrefix .= 'ext_';
}
function BeginTrans()
{
if ($this->transOff) return true;
$this->transCnt += 1;
$this->Execute('SET AUTOCOMMIT=0');
$this->Execute('BEGIN');
return true;
}
function CommitTrans($ok=true)
{
if ($this->transOff) return true;
if (!$ok) return $this->RollbackTrans();
if ($this->transCnt) $this->transCnt -= 1;
$this->Execute('COMMIT');
$this->Execute('SET AUTOCOMMIT=1');
return true;
}
function RollbackTrans()
{
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
$this->Execute('ROLLBACK');
$this->Execute('SET AUTOCOMMIT=1');
return true;
}
}
class ADORecordSet_mysqlt extends ADORecordSet_mysql{
var $databaseType = "mysqlt";
function ADORecordSet_mysqlt($queryID,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
switch ($mode)
{
case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break;
case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break;
default:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:$this->fetchMode = MYSQL_BOTH; break;
}
$this->ADORecordSet($queryID);
}
function MoveNext()
{
if (@$this->fields =& mysql_fetch_array($this->_queryID,$this->fetchMode)) {
$this->_currentRow += 1;
return true;
}
if (!$this->EOF) {
$this->_currentRow += 1;
$this->EOF = true;
}
return false;
}
}
class ADORecordSet_ext_mysqlt extends ADORecordSet_mysqlt {
function ADORecordSet_ext_mysqli($queryID,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
switch ($mode)
{
case ADODB_FETCH_NUM: $this->fetchMode = MYSQL_NUM; break;
case ADODB_FETCH_ASSOC:$this->fetchMode = MYSQL_ASSOC; break;
default:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:$this->fetchMode = MYSQL_BOTH; break;
}
$this->ADORecordSet($queryID);
}
function MoveNext()
{
return adodb_movenext($this);
}
}
?>

View File

@ -0,0 +1,168 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim#natsoft.com.my). All rights reserved.
First cut at the Netezza Driver by Josh Eldridge joshuae74#hotmail.com
Based on the previous postgres drivers.
http://www.netezza.com/
Major Additions/Changes:
MetaDatabasesSQL, MetaTablesSQL, MetaColumnsSQL
Note: You have to have admin privileges to access the system tables
Removed non-working keys code (Netezza has no concept of keys)
Fixed the way data types and lengths are returned in MetaColumns()
as well as added the default lengths for certain types
Updated public variables for Netezza
Still need to remove blob functions, as Netezza doesn't suppport blob
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
include_once(ADODB_DIR.'/drivers/adodb-postgres64.inc.php');
class ADODB_netezza extends ADODB_postgres64 {
var $databaseType = 'netezza';
var $dataProvider = 'netezza';
var $hasInsertID = false;
var $_resultid = false;
var $concat_operator='||';
var $random = 'random';
var $metaDatabasesSQL = "select objname from _v_object_data where objtype='database' order by 1";
var $metaTablesSQL = "select objname from _v_object_data where objtype='table' order by 1";
var $isoDates = true; // accepts dates in ISO format
var $sysDate = "CURRENT_DATE";
var $sysTimeStamp = "CURRENT_TIMESTAMP";
var $blobEncodeType = 'C';
var $metaColumnsSQL = "SELECT attname, atttype FROM _v_relation_column_def WHERE name = '%s' AND attnum > 0 ORDER BY attnum";
var $metaColumnsSQL1 = "SELECT attname, atttype FROM _v_relation_column_def WHERE name = '%s' AND attnum > 0 ORDER BY attnum";
// netezza doesn't have keys. it does have distributions, so maybe this is
// something that can be pulled from the system tables
var $metaKeySQL = "";
var $hasAffectedRows = true;
var $hasLimit = true;
var $true = 't'; // string that represents TRUE for a database
var $false = 'f'; // string that represents FALSE for a database
var $fmtDate = "'Y-m-d'"; // used by DBDate() as the default date format used by the database
var $fmtTimeStamp = "'Y-m-d G:i:s'"; // used by DBTimeStamp as the default timestamp fmt.
var $ansiOuter = true;
var $autoRollback = true; // apparently pgsql does not autorollback properly before 4.3.4
// http://bugs.php.net/bug.php?id=25404
function ADODB_netezza()
{
}
function &MetaColumns($table,$upper=true)
{
// Changed this function to support Netezza which has no concept of keys
// could posisbly work on other things from the system table later.
global $ADODB_FETCH_MODE;
$table = strtolower($table);
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
$rs =& $this->Execute(sprintf($this->metaColumnsSQL,$table,$table));
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rs === false) return false;
$retarr = array();
while (!$rs->EOF) {
$fld = new ADOFieldObject();
$fld->name = $rs->fields[0];
// since we're returning type and length as one string,
// split them out here.
if ($first = strstr($rs->fields[1], "(")) {
$fld->max_length = trim($first, "()");
} else {
$fld->max_length = -1;
}
if ($first = strpos($rs->fields[1], "(")) {
$fld->type = substr($rs->fields[1], 0, $first);
} else {
$fld->type = $rs->fields[1];
}
switch ($fld->type) {
case "byteint":
case "boolean":
$fld->max_length = 1;
break;
case "smallint":
$fld->max_length = 2;
break;
case "integer":
case "numeric":
case "date":
$fld->max_length = 4;
break;
case "bigint":
case "time":
case "timestamp":
$fld->max_length = 8;
break;
case "timetz":
case "time with time zone":
$fld->max_length = 12;
break;
}
if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
else $retarr[($upper) ? strtoupper($fld->name) : $fld->name] = $fld;
$rs->MoveNext();
}
$rs->Close();
return $retarr;
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordSet_netezza extends ADORecordSet_postgres64
{
var $databaseType = "netezza";
var $canSeek = true;
function ADORecordSet_netezza($queryID,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
switch ($mode)
{
case ADODB_FETCH_NUM: $this->fetchMode = PGSQL_NUM; break;
case ADODB_FETCH_ASSOC:$this->fetchMode = PGSQL_ASSOC; break;
default:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:$this->fetchMode = PGSQL_BOTH; break;
}
$this->ADORecordSet($queryID);
}
// _initrs modified to disable blob handling
function _initrs()
{
global $ADODB_COUNTRECS;
$this->_numOfRows = ($ADODB_COUNTRECS)? @pg_numrows($this->_queryID):-1;
$this->_numOfFields = @pg_numfields($this->_queryID);
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,209 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim. All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Latest version is available at http://adodb.sourceforge.net
Portable version of oci8 driver, to make it more similar to other database drivers.
The main differences are
1. that the OCI_ASSOC names are in lowercase instead of uppercase.
2. bind variables are mapped using ? instead of :<bindvar>
Should some emulation of RecordCount() be implemented?
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
include_once(ADODB_DIR.'/drivers/adodb-oci8.inc.php');
class ADODB_oci8po extends ADODB_oci8 {
var $databaseType = 'oci8po';
var $dataProvider = 'oci8';
var $metaColumnsSQL = "select lower(cname),coltype,width, SCALE, PRECISION, NULLS, DEFAULTVAL from col where tname='%s' order by colno"; //changed by smondino@users.sourceforge. net
var $metaTablesSQL = "select lower(table_name),table_type from cat where table_type in ('TABLE','VIEW')";
function ADODB_oci8po()
{
$this->_hasOCIFetchStatement = ADODB_PHPVER >= 0x4200;
# oci8po does not support adodb extension: adodb_movenext()
}
function Param($name)
{
return '?';
}
function Prepare($sql,$cursor=false)
{
$sqlarr = explode('?',$sql);
$sql = $sqlarr[0];
for ($i = 1, $max = sizeof($sqlarr); $i < $max; $i++) {
$sql .= ':'.($i-1) . $sqlarr[$i];
}
return ADODB_oci8::Prepare($sql,$cursor);
}
// emulate handling of parameters ? ?, replacing with :bind0 :bind1
function _query($sql,$inputarr)
{
if (is_array($inputarr)) {
$i = 0;
if (is_array($sql)) {
foreach($inputarr as $v) {
$arr['bind'.$i++] = $v;
}
} else {
$sqlarr = explode('?',$sql);
$sql = $sqlarr[0];
foreach($inputarr as $k => $v) {
$sql .= ":$k" . $sqlarr[++$i];
}
}
}
return ADODB_oci8::_query($sql,$inputarr);
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordset_oci8po extends ADORecordset_oci8 {
var $databaseType = 'oci8po';
function ADORecordset_oci8po($queryID,$mode=false)
{
$this->ADORecordset_oci8($queryID,$mode);
}
function Fields($colname)
{
if ($this->fetchMode & OCI_ASSOC) return $this->fields[$colname];
if (!$this->bind) {
$this->bind = array();
for ($i=0; $i < $this->_numOfFields; $i++) {
$o = $this->FetchField($i);
$this->bind[strtoupper($o->name)] = $i;
}
}
return $this->fields[$this->bind[strtoupper($colname)]];
}
// lowercase field names...
function &_FetchField($fieldOffset = -1)
{
$fld = new ADOFieldObject;
$fieldOffset += 1;
$fld->name = strtolower(OCIcolumnname($this->_queryID, $fieldOffset));
$fld->type = OCIcolumntype($this->_queryID, $fieldOffset);
$fld->max_length = OCIcolumnsize($this->_queryID, $fieldOffset);
if ($fld->type == 'NUMBER') {
//$p = OCIColumnPrecision($this->_queryID, $fieldOffset);
$sc = OCIColumnScale($this->_queryID, $fieldOffset);
if ($sc == 0) $fld->type = 'INT';
}
return $fld;
}
/*
function MoveNext()
{
if (@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) {
$this->_currentRow += 1;
return true;
}
if (!$this->EOF) {
$this->_currentRow += 1;
$this->EOF = true;
}
return false;
}*/
// 10% speedup to move MoveNext to child class
function MoveNext()
{
if(@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) {
global $ADODB_ANSI_PADDING_OFF;
$this->_currentRow++;
if ($this->fetchMode & OCI_ASSOC) $this->_updatefields();
if (!empty($ADODB_ANSI_PADDING_OFF)) {
foreach($this->fields as $k => $v) {
if (is_string($v)) $this->fields[$k] = rtrim($v);
}
}
return true;
}
if (!$this->EOF) {
$this->EOF = true;
$this->_currentRow++;
}
return false;
}
/* Optimize SelectLimit() by using OCIFetch() instead of OCIFetchInto() */
function &GetArrayLimit($nrows,$offset=-1)
{
if ($offset <= 0) return $this->GetArray($nrows);
for ($i=1; $i < $offset; $i++)
if (!@OCIFetch($this->_queryID)) return array();
if (!@OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode)) return array();
if ($this->fetchMode & OCI_ASSOC) $this->_updatefields();
$results = array();
$cnt = 0;
while (!$this->EOF && $nrows != $cnt) {
$results[$cnt++] = $this->fields;
$this->MoveNext();
}
return $results;
}
// Create associative array
function _updatefields()
{
if (ADODB_ASSOC_CASE == 2) return; // native
$arr = array();
$lowercase = (ADODB_ASSOC_CASE == 0);
foreach($this->fields as $k => $v) {
if (is_integer($k)) $arr[$k] = $v;
else {
if ($lowercase)
$arr[strtolower($k)] = $v;
else
$arr[strtoupper($k)] = $v;
}
}
$this->fields = $arr;
}
function _fetch()
{
$ret = @OCIfetchinto($this->_queryID,$this->fields,$this->fetchMode);
if ($ret) {
global $ADODB_ANSI_PADDING_OFF;
if ($this->fetchMode & OCI_ASSOC) $this->_updatefields();
if (!empty($ADODB_ANSI_PADDING_OFF)) {
foreach($this->fields as $k => $v) {
if (is_string($v)) $this->fields[$k] = rtrim($v);
}
}
}
return $ret;
}
}
?>

View File

@ -0,0 +1,726 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim#natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Requires ODBC. Works on Windows and Unix.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
define("_ADODB_ODBC_LAYER", 2 );
/*--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------*/
class ADODB_odbc extends ADOConnection {
var $databaseType = "odbc";
var $fmtDate = "'Y-m-d'";
var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
var $replaceQuote = "''"; // string to use to replace quotes
var $dataProvider = "odbc";
var $hasAffectedRows = true;
var $binmode = ODBC_BINMODE_RETURN;
var $useFetchArray = false; // setting this to true will make array elements in FETCH_ASSOC mode case-sensitive
// breaking backward-compat
//var $longreadlen = 8000; // default number of chars to return for a Blob/Long field
var $_bindInputArray = false;
var $curmode = SQL_CUR_USE_DRIVER; // See sqlext.h, SQL_CUR_DEFAULT == SQL_CUR_USE_DRIVER == 2L
var $_genSeqSQL = "create table %s (id integer)";
var $_autocommit = true;
var $_haserrorfunctions = true;
var $_has_stupid_odbc_fetch_api_change = true;
var $_lastAffectedRows = 0;
var $uCaseTables = true; // for meta* functions, uppercase table names
function ADODB_odbc()
{
$this->_haserrorfunctions = ADODB_PHPVER >= 0x4050;
$this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
}
function ServerInfo()
{
if (!empty($this->host) && ADODB_PHPVER >= 0x4300) {
$dsn = strtoupper($this->host);
$first = true;
$found = false;
if (!function_exists('odbc_data_source')) return false;
while(true) {
$rez = @odbc_data_source($this->_connectionID,
$first ? SQL_FETCH_FIRST : SQL_FETCH_NEXT);
$first = false;
if (!is_array($rez)) break;
if (strtoupper($rez['server']) == $dsn) {
$found = true;
break;
}
}
if (!$found) return ADOConnection::ServerInfo();
if (!isset($rez['version'])) $rez['version'] = '';
return $rez;
} else {
return ADOConnection::ServerInfo();
}
}
function CreateSequence($seqname='adodbseq',$start=1)
{
if (empty($this->_genSeqSQL)) return false;
$ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
if (!$ok) return false;
$start -= 1;
return $this->Execute("insert into $seqname values($start)");
}
var $_dropSeqSQL = 'drop table %s';
function DropSequence($seqname)
{
if (empty($this->_dropSeqSQL)) return false;
return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
}
/*
This algorithm is not very efficient, but works even if table locking
is not available.
Will return false if unable to generate an ID after $MAXLOOPS attempts.
*/
function GenID($seq='adodbseq',$start=1)
{
// if you have to modify the parameter below, your database is overloaded,
// or you need to implement generation of id's yourself!
$MAXLOOPS = 100;
//$this->debug=1;
while (--$MAXLOOPS>=0) {
$num = $this->GetOne("select id from $seq");
if ($num === false) {
$this->Execute(sprintf($this->_genSeqSQL ,$seq));
$start -= 1;
$num = '0';
$ok = $this->Execute("insert into $seq values($start)");
if (!$ok) return false;
}
$this->Execute("update $seq set id=id+1 where id=$num");
if ($this->affected_rows() > 0) {
$num += 1;
$this->genID = $num;
return $num;
}
}
if ($fn = $this->raiseErrorFn) {
$fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
}
return false;
}
function ErrorMsg()
{
if ($this->_haserrorfunctions) {
if ($this->_errorMsg !== false) return $this->_errorMsg;
if (empty($this->_connectionID)) return @odbc_errormsg();
return @odbc_errormsg($this->_connectionID);
} else return ADOConnection::ErrorMsg();
}
function ErrorNo()
{
if ($this->_haserrorfunctions) {
if ($this->_errorCode !== false) {
// bug in 4.0.6, error number can be corrupted string (should be 6 digits)
return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode;
}
if (empty($this->_connectionID)) $e = @odbc_error();
else $e = @odbc_error($this->_connectionID);
// bug in 4.0.6, error number can be corrupted string (should be 6 digits)
// so we check and patch
if (strlen($e)<=2) return 0;
return $e;
} else return ADOConnection::ErrorNo();
}
// returns true or false
function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
{
global $php_errormsg;
if (!function_exists('odbc_connect')) return null;
if ($this->debug && $argDatabasename && $this->databaseType != 'vfp') {
ADOConnection::outp("For odbc Connect(), $argDatabasename is not used. Place dsn in 1st parameter.");
}
if (isset($php_errormsg)) $php_errormsg = '';
if ($this->curmode === false) $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword);
else $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword,$this->curmode);
$this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
//if ($this->_connectionID) odbc_autocommit($this->_connectionID,true);
return $this->_connectionID != false;
}
// returns true or false
function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
{
global $php_errormsg;
if (!function_exists('odbc_connect')) return null;
if (isset($php_errormsg)) $php_errormsg = '';
$this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
if ($this->debug && $argDatabasename) {
ADOConnection::outp("For odbc PConnect(), $argDatabasename is not used. Place dsn in 1st parameter.");
}
// print "dsn=$argDSN u=$argUsername p=$argPassword<br>"; flush();
if ($this->curmode === false) $this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword);
else $this->_connectionID = odbc_pconnect($argDSN,$argUsername,$argPassword,$this->curmode);
$this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
if ($this->_connectionID && $this->autoRollback) @odbc_rollback($this->_connectionID);
if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
return $this->_connectionID != false;
}
function BeginTrans()
{
if (!$this->hasTransactions) return false;
if ($this->transOff) return true;
$this->transCnt += 1;
$this->_autocommit = false;
return odbc_autocommit($this->_connectionID,false);
}
function CommitTrans($ok=true)
{
if ($this->transOff) return true;
if (!$ok) return $this->RollbackTrans();
if ($this->transCnt) $this->transCnt -= 1;
$this->_autocommit = true;
$ret = odbc_commit($this->_connectionID);
odbc_autocommit($this->_connectionID,true);
return $ret;
}
function RollbackTrans()
{
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
$this->_autocommit = true;
$ret = odbc_rollback($this->_connectionID);
odbc_autocommit($this->_connectionID,true);
return $ret;
}
function MetaPrimaryKeys($table)
{
global $ADODB_FETCH_MODE;
if ($this->uCaseTables) $table = strtoupper($table);
$schema = '';
$this->_findschema($table,$schema);
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$qid = @odbc_primarykeys($this->_connectionID,'',$schema,$table);
if (!$qid) {
$ADODB_FETCH_MODE = $savem;
return false;
}
$rs = new ADORecordSet_odbc($qid);
$ADODB_FETCH_MODE = $savem;
if (!$rs) return false;
$rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
$arr =& $rs->GetArray();
$rs->Close();
//print_r($arr);
$arr2 = array();
for ($i=0; $i < sizeof($arr); $i++) {
if ($arr[$i][3]) $arr2[] = $arr[$i][3];
}
return $arr2;
}
function &MetaTables($ttype=false)
{
global $ADODB_FETCH_MODE;
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$qid = odbc_tables($this->_connectionID);
$rs = new ADORecordSet_odbc($qid);
$ADODB_FETCH_MODE = $savem;
if (!$rs) return false;
$rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
$arr =& $rs->GetArray();
//print_r($arr);
$rs->Close();
$arr2 = array();
if ($ttype) {
$isview = strncmp($ttype,'V',1) === 0;
}
for ($i=0; $i < sizeof($arr); $i++) {
if (!$arr[$i][2]) continue;
$type = $arr[$i][3];
if ($ttype) {
if ($isview) {
if (strncmp($type,'V',1) === 0) $arr2[] = $arr[$i][2];
} else if (strncmp($type,'SYS',3) !== 0) $arr2[] = $arr[$i][2];
} else if (strncmp($type,'SYS',3) !== 0) $arr2[] = $arr[$i][2];
}
return $arr2;
}
/*
/ SQL data type codes /
#define SQL_UNKNOWN_TYPE 0
#define SQL_CHAR 1
#define SQL_NUMERIC 2
#define SQL_DECIMAL 3
#define SQL_INTEGER 4
#define SQL_SMALLINT 5
#define SQL_FLOAT 6
#define SQL_REAL 7
#define SQL_DOUBLE 8
#if (ODBCVER >= 0x0300)
#define SQL_DATETIME 9
#endif
#define SQL_VARCHAR 12
/ One-parameter shortcuts for date/time data types /
#if (ODBCVER >= 0x0300)
#define SQL_TYPE_DATE 91
#define SQL_TYPE_TIME 92
#define SQL_TYPE_TIMESTAMP 93
#define SQL_UNICODE (-95)
#define SQL_UNICODE_VARCHAR (-96)
#define SQL_UNICODE_LONGVARCHAR (-97)
*/
function ODBCTypes($t)
{
switch ((integer)$t) {
case 1:
case 12:
case 0:
case -95:
case -96:
return 'C';
case -97:
case -1: //text
return 'X';
case -4: //image
return 'B';
case 91:
case 11:
return 'D';
case 92:
case 93:
case 9: return 'T';
case 4:
case 5:
case -6:
return 'I';
case -11: // uniqidentifier
return 'R';
case -7: //bit
return 'L';
default:
return 'N';
}
}
function &MetaColumns($table)
{
global $ADODB_FETCH_MODE;
if ($this->uCaseTables) $table = strtoupper($table);
$schema = '';
$this->_findschema($table,$schema);
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
/*if (false) { // after testing, confirmed that the following does not work becoz of a bug
$qid2 = odbc_tables($this->_connectionID);
$rs = new ADORecordSet_odbc($qid2);
$ADODB_FETCH_MODE = $savem;
if (!$rs) return false;
$rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
$rs->_fetch();
while (!$rs->EOF) {
if ($table == strtoupper($rs->fields[2])) {
$q = $rs->fields[0];
$o = $rs->fields[1];
break;
}
$rs->MoveNext();
}
$rs->Close();
$qid = odbc_columns($this->_connectionID,$q,$o,strtoupper($table),'%');
} */
switch ($this->databaseType) {
case 'access':
case 'vfp':
$qid = odbc_columns($this->_connectionID);#,'%','',strtoupper($table),'%');
break;
case 'db2':
$colname = "%";
$qid = odbc_columns($this->_connectionID, "", $schema, $table, $colname);
break;
default:
$qid = @odbc_columns($this->_connectionID,'%','%',strtoupper($table),'%');
if (empty($qid)) $qid = odbc_columns($this->_connectionID);
break;
}
if (empty($qid)) return false;
$rs = new ADORecordSet_odbc($qid);
$ADODB_FETCH_MODE = $savem;
if (!$rs) return false;
$rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
$rs->_fetch();
$retarr = array();
/*
$rs->fields indices
0 TABLE_QUALIFIER
1 TABLE_SCHEM
2 TABLE_NAME
3 COLUMN_NAME
4 DATA_TYPE
5 TYPE_NAME
6 PRECISION
7 LENGTH
8 SCALE
9 RADIX
10 NULLABLE
11 REMARKS
*/
while (!$rs->EOF) {
//adodb_pr($rs->fields);
if (strtoupper($rs->fields[2]) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
$fld = new ADOFieldObject();
$fld->name = $rs->fields[3];
$fld->type = $this->ODBCTypes($rs->fields[4]);
// ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp
// access uses precision to store length for char/varchar
if ($fld->type == 'C' or $fld->type == 'X') {
if ($this->databaseType == 'access')
$fld->max_length = $rs->fields[6];
else if ($rs->fields[4] <= -95) // UNICODE
$fld->max_length = $rs->fields[7]/2;
else
$fld->max_length = $rs->fields[7];
} else
$fld->max_length = $rs->fields[7];
$fld->not_null = !empty($rs->fields[10]);
$fld->scale = $rs->fields[8];
$retarr[strtoupper($fld->name)] = $fld;
} else if (sizeof($retarr)>0)
break;
$rs->MoveNext();
}
$rs->Close(); //-- crashes 4.03pl1 -- why?
return $retarr;
}
function Prepare($sql)
{
if (! $this->_bindInputArray) return $sql; // no binding
$stmt = odbc_prepare($this->_connectionID,$sql);
if (!$stmt) {
// we don't know whether odbc driver is parsing prepared stmts, so just return sql
return $sql;
}
return array($sql,$stmt,false);
}
/* returns queryID or false */
function _query($sql,$inputarr=false)
{
GLOBAL $php_errormsg;
if (isset($php_errormsg)) $php_errormsg = '';
$this->_error = '';
if ($inputarr) {
if (is_array($sql)) {
$stmtid = $sql[1];
} else {
$stmtid = odbc_prepare($this->_connectionID,$sql);
if ($stmtid == false) {
$this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
return false;
}
}
if (! odbc_execute($stmtid,$inputarr)) {
//@odbc_free_result($stmtid);
if ($this->_haserrorfunctions) {
$this->_errorMsg = odbc_errormsg();
$this->_errorCode = odbc_error();
}
return false;
}
} else if (is_array($sql)) {
$stmtid = $sql[1];
if (!odbc_execute($stmtid)) {
//@odbc_free_result($stmtid);
if ($this->_haserrorfunctions) {
$this->_errorMsg = odbc_errormsg();
$this->_errorCode = odbc_error();
}
return false;
}
} else
$stmtid = odbc_exec($this->_connectionID,$sql);
$this->_lastAffectedRows = 0;
if ($stmtid) {
if (@odbc_num_fields($stmtid) == 0) {
$this->_lastAffectedRows = odbc_num_rows($stmtid);
$stmtid = true;
} else {
$this->_lastAffectedRows = 0;
odbc_binmode($stmtid,$this->binmode);
odbc_longreadlen($stmtid,$this->maxblobsize);
}
if ($this->_haserrorfunctions) {
$this->_errorMsg = '';
$this->_errorCode = 0;
} else
$this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
} else {
if ($this->_haserrorfunctions) {
$this->_errorMsg = odbc_errormsg();
$this->_errorCode = odbc_error();
} else
$this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
}
return $stmtid;
}
/*
Insert a null into the blob field of the table first.
Then use UpdateBlob to store the blob.
Usage:
$conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
$conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
*/
function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
{
return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false;
}
// returns true or false
function _close()
{
$ret = @odbc_close($this->_connectionID);
$this->_connectionID = false;
return $ret;
}
function _affectedrows()
{
return $this->_lastAffectedRows;
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordSet_odbc extends ADORecordSet {
var $bind = false;
var $databaseType = "odbc";
var $dataProvider = "odbc";
var $useFetchArray;
var $_has_stupid_odbc_fetch_api_change;
function ADORecordSet_odbc($id,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
$this->fetchMode = $mode;
$this->_queryID = $id;
// the following is required for mysql odbc driver in 4.3.1 -- why?
$this->EOF = false;
$this->_currentRow = -1;
//$this->ADORecordSet($id);
}
// returns the field object
function &FetchField($fieldOffset = -1)
{
$off=$fieldOffset+1; // offsets begin at 1
$o= new ADOFieldObject();
$o->name = @odbc_field_name($this->_queryID,$off);
$o->type = @odbc_field_type($this->_queryID,$off);
$o->max_length = @odbc_field_len($this->_queryID,$off);
if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
return $o;
}
/* Use associative array to get fields array */
function Fields($colname)
{
if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
if (!$this->bind) {
$this->bind = array();
for ($i=0; $i < $this->_numOfFields; $i++) {
$o = $this->FetchField($i);
$this->bind[strtoupper($o->name)] = $i;
}
}
return $this->fields[$this->bind[strtoupper($colname)]];
}
function _initrs()
{
global $ADODB_COUNTRECS;
$this->_numOfRows = ($ADODB_COUNTRECS) ? @odbc_num_rows($this->_queryID) : -1;
$this->_numOfFields = @odbc_num_fields($this->_queryID);
// some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0
if ($this->_numOfRows == 0) $this->_numOfRows = -1;
//$this->useFetchArray = $this->connection->useFetchArray;
$this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
}
function _seek($row)
{
return false;
}
// speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated
function &GetArrayLimit($nrows,$offset=-1)
{
if ($offset <= 0) {
$rs =& $this->GetArray($nrows);
return $rs;
}
$savem = $this->fetchMode;
$this->fetchMode = ADODB_FETCH_NUM;
$this->Move($offset);
$this->fetchMode = $savem;
if ($this->fetchMode & ADODB_FETCH_ASSOC) {
$this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
}
$results = array();
$cnt = 0;
while (!$this->EOF && $nrows != $cnt) {
$results[$cnt++] = $this->fields;
$this->MoveNext();
}
return $results;
}
function MoveNext()
{
if ($this->_numOfRows != 0 && !$this->EOF) {
$this->_currentRow++;
$row = 0;
if ($this->_has_stupid_odbc_fetch_api_change)
$rez = @odbc_fetch_into($this->_queryID,$this->fields);
else
$rez = @odbc_fetch_into($this->_queryID,$row,$this->fields);
if ($rez) {
if ($this->fetchMode & ADODB_FETCH_ASSOC) {
$this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
}
return true;
}
}
$this->fields = false;
$this->EOF = true;
return false;
}
function _fetch()
{
$row = 0;
if ($this->_has_stupid_odbc_fetch_api_change)
$rez = @odbc_fetch_into($this->_queryID,$this->fields,$row);
else
$rez = @odbc_fetch_into($this->_queryID,$row,$this->fields);
if ($rez) {
if ($this->fetchMode & ADODB_FETCH_ASSOC) {
$this->fields =& $this->GetRowAssoc(ADODB_ASSOC_CASE);
}
return true;
}
$this->fields = false;
return false;
}
function _close()
{
return @odbc_free_result($this->_queryID);
}
}
?>

View File

@ -0,0 +1,252 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
MSSQL support via ODBC. Requires ODBC. Works on Windows and Unix.
For Unix configuration, see http://phpbuilder.com/columns/alberto20000919.php3
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
if (!defined('_ADODB_ODBC_LAYER')) {
include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
}
class ADODB_odbc_mssql extends ADODB_odbc {
var $databaseType = 'odbc_mssql';
var $fmtDate = "'Y-m-d'";
var $fmtTimeStamp = "'Y-m-d h:i:sA'";
var $_bindInputArray = true;
var $metaTablesSQL="select name,case when type='U' then 'T' else 'V' end from sysobjects where (type='U' or type='V') and (name not in ('sysallocations','syscolumns','syscomments','sysdepends','sysfilegroups','sysfiles','sysfiles1','sysforeignkeys','sysfulltextcatalogs','sysindexes','sysindexkeys','sysmembers','sysobjects','syspermissions','sysprotects','sysreferences','systypes','sysusers','sysalternates','sysconstraints','syssegments','REFERENTIAL_CONSTRAINTS','CHECK_CONSTRAINTS','CONSTRAINT_TABLE_USAGE','CONSTRAINT_COLUMN_USAGE','VIEWS','VIEW_TABLE_USAGE','VIEW_COLUMN_USAGE','SCHEMATA','TABLES','TABLE_CONSTRAINTS','TABLE_PRIVILEGES','COLUMNS','COLUMN_DOMAIN_USAGE','COLUMN_PRIVILEGES','DOMAINS','DOMAIN_CONSTRAINTS','KEY_COLUMN_USAGE'))";
var $metaColumnsSQL = "select c.name,t.name,c.length from syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id where o.name='%s'";
var $hasTop = 'top'; // support mssql/interbase SELECT TOP 10 * FROM TABLE
var $sysDate = 'GetDate()';
var $sysTimeStamp = 'GetDate()';
var $leftOuter = '*=';
var $rightOuter = '=*';
var $substr = 'substring';
var $length = 'len';
var $ansiOuter = true; // for mssql7 or later
var $identitySQL = 'select @@IDENTITY'; // 'select SCOPE_IDENTITY'; # for mssql 2000
var $hasInsertID = true;
var $connectStmt = 'SET CONCAT_NULL_YIELDS_NULL OFF'; # When SET CONCAT_NULL_YIELDS_NULL is ON,
# concatenating a null value with a string yields a NULL result
function ADODB_odbc_mssql()
{
$this->ADODB_odbc();
$this->curmode = SQL_CUR_USE_ODBC;
}
// crashes php...
function ServerInfo()
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$row = $this->GetRow("execute sp_server_info 2");
$ADODB_FETCH_MODE = $save;
if (!is_array($row)) return false;
$arr['description'] = $row[2];
$arr['version'] = ADOConnection::_findvers($arr['description']);
return $arr;
}
function IfNull( $field, $ifNull )
{
return " ISNULL($field, $ifNull) "; // if MS SQL Server
}
function _insertid()
{
// SCOPE_IDENTITY()
// Returns the last IDENTITY value inserted into an IDENTITY column in
// the same scope. A scope is a module -- a stored procedure, trigger,
// function, or batch. Thus, two statements are in the same scope if
// they are in the same stored procedure, function, or batch.
return $this->GetOne($this->identitySQL);
}
function MetaForeignKeys($table, $owner=false, $upper=false)
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$table = $this->qstr(strtoupper($table));
$sql =
"select object_name(constid) as constraint_name,
col_name(fkeyid, fkey) as column_name,
object_name(rkeyid) as referenced_table_name,
col_name(rkeyid, rkey) as referenced_column_name
from sysforeignkeys
where upper(object_name(fkeyid)) = $table
order by constraint_name, referenced_table_name, keyno";
$constraints =& $this->GetArray($sql);
$ADODB_FETCH_MODE = $save;
$arr = false;
foreach($constraints as $constr) {
//print_r($constr);
$arr[$constr[0]][$constr[2]][] = $constr[1].'='.$constr[3];
}
if (!$arr) return false;
$arr2 = false;
foreach($arr as $k => $v) {
foreach($v as $a => $b) {
if ($upper) $a = strtoupper($a);
$arr2[$a] = $b;
}
}
return $arr2;
}
function &MetaTables($ttype=false,$showSchema=false,$mask=false)
{
if ($mask) {$this->debug=1;
$save = $this->metaTablesSQL;
$mask = $this->qstr($mask);
$this->metaTablesSQL .= " AND name like $mask";
}
$ret =& ADOConnection::MetaTables($ttype,$showSchema);
if ($mask) {
$this->metaTablesSQL = $save;
}
return $ret;
}
function &MetaColumns($table)
{
return ADOConnection::MetaColumns($table);
}
function _query($sql,$inputarr)
{
if (is_string($sql)) $sql = str_replace('||','+',$sql);
return ADODB_odbc::_query($sql,$inputarr);
}
// "Stein-Aksel Basma" <basma@accelero.no>
// tested with MSSQL 2000
function &MetaPrimaryKeys($table)
{
global $ADODB_FETCH_MODE;
$schema = '';
$this->_findschema($table,$schema);
//if (!$schema) $schema = $this->database;
if ($schema) $schema = "and k.table_catalog like '$schema%'";
$sql = "select distinct k.column_name,ordinal_position from information_schema.key_column_usage k,
information_schema.table_constraints tc
where tc.constraint_name = k.constraint_name and tc.constraint_type =
'PRIMARY KEY' and k.table_name = '$table' $schema order by ordinal_position ";
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$a = $this->GetCol($sql);
$ADODB_FETCH_MODE = $savem;
if ($a && sizeof($a)>0) return $a;
return false;
}
function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
{
if ($nrows > 0 && $offset <= 0) {
$sql = preg_replace(
'/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql);
$rs =& $this->Execute($sql,$inputarr);
} else
$rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
return $rs;
}
// Format date column in sql string given an input format that understands Y M D
function SQLDate($fmt, $col=false)
{
if (!$col) $col = $this->sysTimeStamp;
$s = '';
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
if ($s) $s .= '+';
$ch = $fmt[$i];
switch($ch) {
case 'Y':
case 'y':
$s .= "datename(yyyy,$col)";
break;
case 'M':
$s .= "convert(char(3),$col,0)";
break;
case 'm':
$s .= "replace(str(month($col),2),' ','0')";
break;
case 'Q':
case 'q':
$s .= "datename(quarter,$col)";
break;
case 'D':
case 'd':
$s .= "replace(str(day($col),2),' ','0')";
break;
case 'h':
$s .= "substring(convert(char(14),$col,0),13,2)";
break;
case 'H':
$s .= "replace(str(datepart(hh,$col),2),' ','0')";
break;
case 'i':
$s .= "replace(str(datepart(mi,$col),2),' ','0')";
break;
case 's':
$s .= "replace(str(datepart(ss,$col),2),' ','0')";
break;
case 'a':
case 'A':
$s .= "substring(convert(char(19),$col,0),18,2)";
break;
default:
if ($ch == '\\') {
$i++;
$ch = substr($fmt,$i,1);
}
$s .= $this->qstr($ch);
break;
}
}
return $s;
}
}
class ADORecordSet_odbc_mssql extends ADORecordSet_odbc {
var $databaseType = 'odbc_mssql';
function ADORecordSet_odbc_mssql($id,$mode=false)
{
return $this->ADORecordSet_odbc($id,$mode);
}
}
?>

View File

@ -0,0 +1,117 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Oracle support via ODBC. Requires ODBC. Works on Windows.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
if (!defined('_ADODB_ODBC_LAYER')) {
include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
}
class ADODB_odbc_oracle extends ADODB_odbc {
var $databaseType = 'odbc_oracle';
var $replaceQuote = "''"; // string to use to replace quotes
var $concat_operator='||';
var $fmtDate = "'Y-m-d 00:00:00'";
var $fmtTimeStamp = "'Y-m-d h:i:sA'";
var $metaTablesSQL = 'select table_name from cat';
var $metaColumnsSQL = "select cname,coltype,width from col where tname='%s' order by colno";
var $sysDate = "TRUNC(SYSDATE)";
var $sysTimeStamp = 'SYSDATE';
//var $_bindInputArray = false;
function ADODB_odbc_oracle()
{
$this->ADODB_odbc();
}
function &MetaTables()
{
if ($this->metaTablesSQL) {
$rs = $this->Execute($this->metaTablesSQL);
if ($rs === false) return false;
$arr = $rs->GetArray();
$arr2 = array();
for ($i=0; $i < sizeof($arr); $i++) {
$arr2[] = $arr[$i][0];
}
$rs->Close();
return $arr2;
}
return false;
}
function &MetaColumns($table)
{
if (!empty($this->metaColumnsSQL)) {
$rs = $this->Execute(sprintf($this->metaColumnsSQL,strtoupper($table)));
if ($rs === false) return false;
$retarr = array();
while (!$rs->EOF) { //print_r($rs->fields);
$fld = new ADOFieldObject();
$fld->name = $rs->fields[0];
$fld->type = $rs->fields[1];
$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;
}
// returns true or false
function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
{
global $php_errormsg;
$php_errormsg = '';
$this->_connectionID = odbc_connect($argDSN,$argUsername,$argPassword,SQL_CUR_USE_ODBC );
$this->_errorMsg = $php_errormsg;
$this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'");
//if ($this->_connectionID) odbc_autocommit($this->_connectionID,true);
return $this->_connectionID != false;
}
// returns true or false
function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
{
global $php_errormsg;
$php_errormsg = '';
$this->_connectionID = odbc_pconnect($argDSN,$argUsername,$argPassword,SQL_CUR_USE_ODBC );
$this->_errorMsg = $php_errormsg;
$this->Execute("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS'");
//if ($this->_connectionID) odbc_autocommit($this->_connectionID,true);
return $this->_connectionID != false;
}
}
class ADORecordSet_odbc_oracle extends ADORecordSet_odbc {
var $databaseType = 'odbc_oracle';
function ADORecordSet_odbc_oracle($id,$mode=false)
{
return $this->ADORecordSet_odbc($id,$mode);
}
}
?>

View File

@ -0,0 +1,628 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
*/
// Code contributed by "stefan bogdan" <sbogdan#rsb.ro>
// security - hide paths
if (!defined('ADODB_DIR')) die();
define("_ADODB_ODBTP_LAYER", 2 );
class ADODB_odbtp extends ADOConnection{
var $databaseType = "odbtp";
var $dataProvider = "odbtp";
var $fmtDate = "'Y-m-d'";
var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
var $replaceQuote = "''"; // string to use to replace quotes
var $odbc_driver = 0;
var $hasAffectedRows = true;
var $hasInsertID = false;
var $hasGenID = true;
var $hasMoveFirst = true;
var $_genSeqSQL = "create table %s (seq_name char(30) not null unique , seq_value integer not null)";
var $_dropSeqSQL = "delete from adodb_seq where seq_name = '%s'";
var $_autocommit = true;
var $_bindInputArray = false;
var $_useUnicodeSQL = false;
var $_canPrepareSP = false;
function ADODB_odbtp()
{
}
function ServerInfo()
{
return array('description' => @odbtp_get_attr( ODB_ATTR_DBMSNAME, $this->_connectionID),
'version' => @odbtp_get_attr( ODB_ATTR_DBMSVER, $this->_connectionID));
}
function ErrorMsg()
{
if (empty($this->_connectionID)) return @odbtp_last_error();
return @odbtp_last_error($this->_connectionID);
}
function ErrorNo()
{
if (empty($this->_connectionID)) return @odbtp_last_error_state();
return @odbtp_last_error_state($this->_connectionID);
}
function _insertid()
{
// SCOPE_IDENTITY()
// Returns the last IDENTITY value inserted into an IDENTITY column in
// the same scope. A scope is a module -- a stored procedure, trigger,
// function, or batch. Thus, two statements are in the same scope if
// they are in the same stored procedure, function, or batch.
return $this->GetOne($this->identitySQL);
}
function _affectedrows()
{
if ($this->_queryID) {
return @odbtp_affected_rows ($this->_queryID);
} else
return 0;
}
function CreateSequence($seqname='adodbseq',$start=1)
{
//verify existence
$num = $this->GetOne("select seq_value from adodb_seq");
$seqtab='adodb_seq';
if( $this->odbc_driver == ODB_DRIVER_FOXPRO ) {
$path = @odbtp_get_attr( ODB_ATTR_DATABASENAME, $this->_connectionID );
//if using vfp dbc file
if( !strcasecmp(strrchr($path, '.'), '.dbc') )
$path = substr($path,0,strrpos($path,'\/'));
$seqtab = $path . '/' . $seqtab;
}
if($num == false) {
if (empty($this->_genSeqSQL)) return false;
$ok = $this->Execute(sprintf($this->_genSeqSQL ,$seqtab));
}
$num = $this->GetOne("select seq_value from adodb_seq where seq_name='$seqname'");
if ($num) {
return false;
}
$start -= 1;
return $this->Execute("insert into adodb_seq values('$seqname',$start)");
}
function DropSequence($seqname)
{
if (empty($this->_dropSeqSQL)) return false;
return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
}
function GenID($seq='adodbseq',$start=1)
{
$seqtab='adodb_seq';
if( $this->odbc_driver == ODB_DRIVER_FOXPRO ) {
$path = @odbtp_get_attr( ODB_ATTR_DATABASENAME, $this->_connectionID );
//if using vfp dbc file
if( !strcasecmp(strrchr($path, '.'), '.dbc') )
$path = substr($path,0,strrpos($path,'\/'));
$seqtab = $path . '/' . $seqtab;
}
$MAXLOOPS = 100;
while (--$MAXLOOPS>=0) {
$num = $this->GetOne("select seq_value from adodb_seq where seq_name='$seq'");
if ($num === false) {
//verify if abodb_seq table exist
$ok = $this->GetOne("select seq_value from adodb_seq ");
if(!$ok) {
//creating the sequence table adodb_seq
$this->Execute(sprintf($this->_genSeqSQL ,$seqtab));
}
$start -= 1;
$num = '0';
$ok = $this->Execute("insert into adodb_seq values('$seq',$start)");
if (!$ok) return false;
}
$ok = $this->Execute("update adodb_seq set seq_value=seq_value+1 where seq_name='$seq'");
if($ok) {
$num += 1;
$this->genID = $num;
return $num;
}
}
if ($fn = $this->raiseErrorFn) {
$fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
}
return false;
}
//example for $UserOrDSN
//for visual fox : DRIVER={Microsoft Visual FoxPro Driver};SOURCETYPE=DBF;SOURCEDB=c:\YourDbfFileDir;EXCLUSIVE=NO;
//for visual fox dbc: DRIVER={Microsoft Visual FoxPro Driver};SOURCETYPE=DBC;SOURCEDB=c:\YourDbcFileDir\mydb.dbc;EXCLUSIVE=NO;
//for access : DRIVER={Microsoft Access Driver (*.mdb)};DBQ=c:\path_to_access_db\base_test.mdb;UID=root;PWD=;
//for mssql : DRIVER={SQL Server};SERVER=myserver;UID=myuid;PWD=mypwd;DATABASE=OdbtpTest;
//if uid & pwd can be separate
function _connect($HostOrInterface, $UserOrDSN='', $argPassword='', $argDatabase='')
{
$this->_connectionID = @odbtp_connect($HostOrInterface,$UserOrDSN,$argPassword,$argDatabase);
if ($this->_connectionID === false)
{
$this->_errorMsg = $this->ErrorMsg() ;
return false;
}
$this->odbc_driver = @odbtp_get_attr(ODB_ATTR_DRIVER, $this->_connectionID);
// Set driver specific attributes
switch( $this->odbc_driver ) {
case ODB_DRIVER_MSSQL:
$this->fmtDate = "'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d h:i:sA'";
$this->sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
$this->sysTimeStamp = 'GetDate()';
$this->ansiOuter = true;
$this->leftOuter = '*=';
$this->rightOuter = '=*';
$this->hasTop = 'top';
$this->hasInsertID = true;
$this->hasTransactions = true;
$this->_bindInputArray = true;
$this->_canSelectDb = true;
$this->substr = "substring";
$this->length = 'len';
$this->identitySQL = 'select @@IDENTITY';
$this->metaDatabasesSQL = "select name from master..sysdatabases where name <> 'master'";
break;
case ODB_DRIVER_JET:
$this->fmtDate = "#Y-m-d#";
$this->fmtTimeStamp = "#Y-m-d h:i:sA#";
$this->sysDate = "FORMAT(NOW,'yyyy-mm-dd')";
$this->sysTimeStamp = 'NOW';
$this->hasTop = 'top';
$this->hasTransactions = false;
$this->_canPrepareSP = true; // For MS Access only.
// Can't rebind ODB_CHAR to ODB_WCHAR if row cache enabled.
if ($this->_useUnicodeSQL)
odbtp_use_row_cache($this->_connectionID, FALSE, 0);
break;
case ODB_DRIVER_FOXPRO:
$this->fmtDate = "{^Y-m-d}";
$this->fmtTimeStamp = "{^Y-m-d, h:i:sA}";
$this->sysDate = 'date()';
$this->sysTimeStamp = 'datetime()';
$this->ansiOuter = true;
$this->hasTop = 'top';
$this->hasTransactions = false;
$this->replaceQuote = "'+chr(39)+'";
$this->true = '.T.';
$this->false = '.F.';
break;
case ODB_DRIVER_ORACLE:
$this->fmtDate = "'Y-m-d 00:00:00'";
$this->fmtTimeStamp = "'Y-m-d h:i:sA'";
$this->sysDate = 'TRUNC(SYSDATE)';
$this->sysTimeStamp = 'SYSDATE';
$this->hasTransactions = true;
$this->_bindInputArray = true;
$this->concat_operator = '||';
break;
case ODB_DRIVER_SYBASE:
$this->fmtDate = "'Y-m-d'";
$this->fmtTimeStamp = "'Y-m-d H:i:s'";
$this->sysDate = 'GetDate()';
$this->sysTimeStamp = 'GetDate()';
$this->leftOuter = '*=';
$this->rightOuter = '=*';
$this->hasInsertID = true;
$this->hasTransactions = true;
$this->identitySQL = 'select @@IDENTITY';
break;
default:
if( @odbtp_get_attr(ODB_ATTR_TXNCAPABLE, $this->_connectionID) )
$this->hasTransactions = true;
else
$this->hasTransactions = false;
}
@odbtp_set_attr(ODB_ATTR_FULLCOLINFO, TRUE, $this->_connectionID );
if ($this->_useUnicodeSQL )
@odbtp_set_attr(ODB_ATTR_UNICODESQL, TRUE, $this->_connectionID);
return true;
}
function _pconnect($HostOrInterface, $UserOrDSN='', $argPassword='', $argDatabase='')
{
return $this->_connect($HostOrInterface, $UserOrDSN, $argPassword, $argDatabase);
}
function SelectDB($dbName)
{
if (!@odbtp_select_db($dbName, $this->_connectionID)) {
return false;
}
$this->databaseName = $dbName;
return true;
}
function &MetaTables($ttype='',$showSchema=false,$mask=false)
{
global $ADODB_FETCH_MODE;
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$arr =& $this->GetArray("||SQLTables||||$ttype");
$ADODB_FETCH_MODE = $savem;
$arr2 = array();
for ($i=0; $i < sizeof($arr); $i++) {
if ($arr[$i][3] == 'SYSTEM TABLE' ) continue;
if ($arr[$i][2])
$arr2[] = $showSchema ? $arr[$i][1].'.'.$arr[$i][2] : $arr[$i][2];
}
return $arr2;
}
function &MetaColumns($table,$upper=true)
{
global $ADODB_FETCH_MODE;
$schema = false;
$this->_findschema($table,$schema);
if ($upper) $table = strtoupper($table);
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->Execute( "||SQLColumns||$schema|$table" );
$ADODB_FETCH_MODE = $savem;
if (!$rs) return false;
while (!$rs->EOF) {
//print_r($rs->fields);
if (strtoupper($rs->fields[2]) == $table) {
$fld = new ADOFieldObject();
$fld->name = $rs->fields[3];
$fld->type = $rs->fields[5];
$fld->max_length = $rs->fields[6];
$fld->not_null = !empty($rs->fields[9]);
$fld->scale = $rs->fields[7];
if (!is_null($rs->fields[12])) {
$fld->has_default = true;
$fld->default_value = $rs->fields[12];
}
$retarr[strtoupper($fld->name)] = $fld;
} else if (sizeof($retarr)>0)
break;
$rs->MoveNext();
}
$rs->Close();
return $retarr;
}
function &MetaPrimaryKeys($table, $owner='')
{
global $ADODB_FETCH_MODE;
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$arr =& $this->GetArray("||SQLPrimaryKeys||$owner|$table");
$ADODB_FETCH_MODE = $savem;
//print_r($arr);
$arr2 = array();
for ($i=0; $i < sizeof($arr); $i++) {
if ($arr[$i][3]) $arr2[] = $arr[$i][3];
}
return $arr2;
}
function &MetaForeignKeys($table, $owner='', $upper=false)
{
global $ADODB_FETCH_MODE;
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$constraints =& $this->GetArray("||SQLForeignKeys|||||$owner|$table");
$ADODB_FETCH_MODE = $savem;
$arr = false;
foreach($constraints as $constr) {
//print_r($constr);
$arr[$constr[11]][$constr[2]][] = $constr[7].'='.$constr[3];
}
if (!$arr) return false;
$arr2 = array();
foreach($arr as $k => $v) {
foreach($v as $a => $b) {
if ($upper) $a = strtoupper($a);
$arr2[$a] = $b;
}
}
return $arr2;
}
function BeginTrans()
{
if (!$this->hasTransactions) return false;
if ($this->transOff) return true;
$this->transCnt += 1;
$this->_autocommit = false;
$rs = @odbtp_set_attr(ODB_ATTR_TRANSACTIONS,ODB_TXN_READUNCOMMITTED,$this->_connectionID);
if(!$rs) return false;
else return true;
}
function CommitTrans($ok=true)
{
if ($this->transOff) return true;
if (!$ok) return $this->RollbackTrans();
if ($this->transCnt) $this->transCnt -= 1;
$this->_autocommit = true;
if( ($ret = odbtp_commit($this->_connectionID)) )
$ret = @odbtp_set_attr(ODB_ATTR_TRANSACTIONS, ODB_TXN_NONE, $this->_connectionID);//set transaction off
return $ret;
}
function RollbackTrans()
{
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
$this->_autocommit = true;
if( ($ret = odbtp_rollback($this->_connectionID)) )
$ret = @odbtp_set_attr(ODB_ATTR_TRANSACTIONS, ODB_TXN_NONE, $this->_connectionID);//set transaction off
return $ret;
}
function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
{
// TOP requires ORDER BY for Visual FoxPro
if( $this->odbc_driver == ODB_DRIVER_FOXPRO ) {
if (!preg_match('/ORDER[ \t\r\n]+BY/is',$sql)) $sql .= ' ORDER BY 1';
}
return ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
}
function Prepare($sql)
{
if (! $this->_bindInputArray) return $sql; // no binding
$stmt = odbtp_prepare($sql,$this->_connectionID);
if (!$stmt) {
// print "Prepare Error for ($sql) ".$this->ErrorMsg()."<br>";
return $sql;
}
return array($sql,$stmt,false);
}
function PrepareSP($sql)
{
if (!$this->_canPrepareSP) return $sql; // Can't prepare procedures
$stmt = odbtp_prepare_proc($sql,$this->_connectionID);
if (!$stmt) return false;
return array($sql,$stmt);
}
/*
Usage:
$stmt = $db->PrepareSP('SP_RUNSOMETHING'); -- takes 2 params, @myid and @group
# note that the parameter does not have @ in front!
$db->Parameter($stmt,$id,'myid');
$db->Parameter($stmt,$group,'group',false,64);
$db->Parameter($stmt,$group,'photo',false,100000,ODB_BINARY);
$db->Execute($stmt);
@param $stmt Statement returned by Prepare() or PrepareSP().
@param $var PHP variable to bind to. Can set to null (for isNull support).
@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 odbtp.
@param [$maxLen] Holds an maximum length of the variable.
@param [$type] The data type of $var. Legal values depend on driver.
See odbtp_attach_param documentation at http://odbtp.sourceforge.net.
*/
function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=0, $type=0)
{
if ( $this->odbc_driver == ODB_DRIVER_JET ) {
$name = '['.$name.']';
if( !$type && $this->_useUnicodeSQL
&& @odbtp_param_bindtype($stmt[1], $name) == ODB_CHAR )
{
$type = ODB_WCHAR;
}
}
else {
$name = '@'.$name;
}
return odbtp_attach_param($stmt[1], $name, $var, $type, $maxLen);
}
/*
Insert a null into the blob field of the table first.
Then use UpdateBlob to store the blob.
Usage:
$conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
$conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
*/
function UpdateBlob($table,$column,$val,$where,$blobtype='image')
{
$sql = "UPDATE $table SET $column = ? WHERE $where";
if( !($stmt = odbtp_prepare($sql, $this->_connectionID)) )
return false;
if( !odbtp_input( $stmt, 1, ODB_BINARY, 1000000, $blobtype ) )
return false;
if( !odbtp_set( $stmt, 1, $val ) )
return false;
return odbtp_execute( $stmt ) != false;
}
function IfNull( $field, $ifNull )
{
switch( $this->odbc_driver ) {
case ODB_DRIVER_MSSQL:
return " ISNULL($field, $ifNull) ";
case ODB_DRIVER_JET:
return " IIF(IsNull($field), $ifNull, $field) ";
}
return " CASE WHEN $field is null THEN $ifNull ELSE $field END ";
}
function _query($sql,$inputarr=false)
{
if ($inputarr) {
if (is_array($sql)) {
$stmtid = $sql[1];
} else {
$stmtid = odbtp_prepare($sql,$this->_connectionID);
if ($stmtid == false) {
$this->_errorMsg = $php_errormsg;
return false;
}
}
$num_params = odbtp_num_params( $stmtid );
for( $param = 1; $param <= $num_params; $param++ ) {
@odbtp_input( $stmtid, $param );
@odbtp_set( $stmtid, $param, $inputarr[$param-1] );
}
if (! odbtp_execute($stmtid) ) {
return false;
}
} else if (is_array($sql)) {
$stmtid = $sql[1];
if (!odbtp_execute($stmtid)) {
return false;
}
} else {
$stmtid = @odbtp_query($sql,$this->_connectionID);
}
$this->_lastAffectedRows = 0;
if ($stmtid) {
$this->_lastAffectedRows = @odbtp_affected_rows($stmtid);
}
return $stmtid;
}
function _close()
{
$ret = @odbtp_close($this->_connectionID);
$this->_connectionID = false;
return $ret;
}
}
class ADORecordSet_odbtp extends ADORecordSet {
var $databaseType = 'odbtp';
var $canSeek = true;
function ADORecordSet_odbtp($queryID,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
$this->fetchMode = $mode;
$this->ADORecordSet($queryID);
}
function _initrs()
{
$this->_numOfFields = @odbtp_num_fields($this->_queryID);
if (!($this->_numOfRows = @odbtp_num_rows($this->_queryID)))
$this->_numOfRows = -1;
}
function &FetchField($fieldOffset = 0)
{
$off=$fieldOffset; // offsets begin at 0
$o= new ADOFieldObject();
$o->name = @odbtp_field_name($this->_queryID,$off);
$o->type = @odbtp_field_type($this->_queryID,$off);
$o->max_length = @odbtp_field_length($this->_queryID,$off);
if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
return $o;
}
function _seek($row)
{
return @odbtp_data_seek($this->_queryID, $row);
}
function fields($colname)
{
if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
if (!$this->bind) {
$this->bind = array();
for ($i=0; $i < $this->_numOfFields; $i++) {
$name = @odbtp_field_name( $this->_queryID, $i );
$this->bind[strtoupper($name)] = $i;
}
}
return $this->fields[$this->bind[strtoupper($colname)]];
}
function _fetch_odbtp($type=0)
{
switch ($this->fetchMode) {
case ADODB_FETCH_NUM:
$this->fields = @odbtp_fetch_row($this->_queryID, $type);
break;
case ADODB_FETCH_ASSOC:
$this->fields = @odbtp_fetch_assoc($this->_queryID, $type);
break;
default:
$this->fields = @odbtp_fetch_array($this->_queryID, $type);
}
return is_array($this->fields);
}
function _fetch()
{
return $this->_fetch_odbtp();
}
function MoveFirst()
{
if (!$this->_fetch_odbtp(ODB_FETCH_FIRST)) return false;
$this->EOF = false;
$this->_currentRow = 0;
return true;
}
function MoveLast()
{
if (!$this->_fetch_odbtp(ODB_FETCH_LAST)) return false;
$this->EOF = false;
$this->_currentRow = $this->_numOfRows - 1;
return true;
}
function NextRecordSet()
{
if (!@odbtp_next_result($this->_queryID)) return false;
$this->_inited = false;
$this->bind = false;
$this->_currentRow = -1;
$this->Init();
return true;
}
function _close()
{
return @odbtp_free_query($this->_queryID);
}
}
?>

View File

@ -0,0 +1,62 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
*/
// Code contributed by "Robert Twitty" <rtwitty#neutron.ushmm.org>
// security - hide paths
if (!defined('ADODB_DIR')) die();
/*
Because the ODBTP server sends and reads UNICODE text data using UTF-8
encoding, the following HTML meta tag must be included within the HTML
head section of every HTML form and script page:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Also, all SQL query strings must be submitted as UTF-8 encoded text.
*/
if (!defined('_ADODB_ODBTP_LAYER')) {
include(ADODB_DIR."/drivers/adodb-odbtp.inc.php");
}
class ADODB_odbtp_unicode extends ADODB_odbtp {
var $databaseType = "odbtp_unicode";
var $_useUnicodeSQL = true;
function ADODB_odbtp_unicode()
{
$this->ADODB_odbtp();
}
}
class ADORecordSet_odbtp_unicode extends ADORecordSet_odbtp {
var $databaseType = 'odbtp_unicode';
function ADORecordSet_odbtp_unicode($queryID,$mode=false)
{
$this->ADORecordSet_odbtp($queryID, $mode);
}
function _initrs()
{
$this->_numOfFields = @odbtp_num_fields($this->_queryID);
if (!($this->_numOfRows = @odbtp_num_rows($this->_queryID)))
$this->_numOfRows = -1;
if ($this->connection->odbc_driver == ODB_DRIVER_JET) {
for ($f = 0; $f < $this->_numOfFields; $f++) {
if (odbtp_field_bindtype($this->_queryID, $f) == ODB_CHAR)
odbtp_bind_field($this->_queryID, $f, ODB_WCHAR);
}
}
}
}
?>

View File

@ -0,0 +1,320 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Latest version is available at http://adodb.sourceforge.net
Oracle data driver. Requires Oracle client. Works on Windows and Unix and Oracle 7.
If you are using Oracle 8 or later, use the oci8 driver which is much better and more reliable.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB_oracle extends ADOConnection {
var $databaseType = "oracle";
var $replaceQuote = "''"; // string to use to replace quotes
var $concat_operator='||';
var $_curs;
var $_initdate = true; // init date to YYYY-MM-DD
var $metaTablesSQL = 'select table_name from cat';
var $metaColumnsSQL = "select cname,coltype,width from col where tname='%s' order by colno";
var $sysDate = "TO_DATE(TO_CHAR(SYSDATE,'YYYY-MM-DD'),'YYYY-MM-DD')";
var $sysTimeStamp = 'SYSDATE';
var $connectSID = true;
function ADODB_oracle()
{
}
// format and return date string in database date format
function DBDate($d)
{
if (is_string($d)) $d = ADORecordSet::UnixDate($d);
return 'TO_DATE('.adodb_date($this->fmtDate,$d).",'YYYY-MM-DD')";
}
// format and return date string in database timestamp format
function DBTimeStamp($ts)
{
if (is_string($ts)) $d = ADORecordSet::UnixTimeStamp($ts);
return 'TO_DATE('.adodb_date($this->fmtTimeStamp,$ts).",'RRRR-MM-DD, HH:MI:SS AM')";
}
function BeginTrans()
{
$this->autoCommit = false;
ora_commitoff($this->_connectionID);
return true;
}
function CommitTrans($ok=true)
{
if (!$ok) return $this->RollbackTrans();
$ret = ora_commit($this->_connectionID);
ora_commiton($this->_connectionID);
return $ret;
}
function RollbackTrans()
{
$ret = ora_rollback($this->_connectionID);
ora_commiton($this->_connectionID);
return $ret;
}
/* there seems to be a bug in the oracle extension -- always returns ORA-00000 - no error */
function ErrorMsg()
{
if ($this->_errorMsg !== false) return $this->_errorMsg;
if (is_resource($this->_curs)) $this->_errorMsg = @ora_error($this->_curs);
if (empty($this->_errorMsg)) $this->_errorMsg = @ora_error($this->_connectionID);
return $this->_errorMsg;
}
function ErrorNo()
{
if ($this->_errorCode !== false) return $this->_errorCode;
if (is_resource($this->_curs)) $this->_errorCode = @ora_errorcode($this->_curs);
if (empty($this->_errorCode)) $this->_errorCode = @ora_errorcode($this->_connectionID);
return $this->_errorCode;
}
// returns true or false
function _connect($argHostname, $argUsername, $argPassword, $argDatabasename, $mode=0)
{
if (!function_exists('ora_plogon')) return null;
// <G. Giunta 2003/03/03/> Reset error messages before connecting
$this->_errorMsg = false;
$this->_errorCode = false;
// G. Giunta 2003/08/13 - This looks danegrously suspicious: why should we want to set
// the oracle home to the host name of remote DB?
// if ($argHostname) putenv("ORACLE_HOME=$argHostname");
if($argHostname) { // code copied from version submitted for oci8 by Jorma Tuomainen <jorma.tuomainen@ppoy.fi>
if (empty($argDatabasename)) $argDatabasename = $argHostname;
else {
if(strpos($argHostname,":")) {
$argHostinfo=explode(":",$argHostname);
$argHostname=$argHostinfo[0];
$argHostport=$argHostinfo[1];
} else {
$argHostport="1521";
}
if ($this->connectSID) {
$argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
.")(PORT=$argHostport))(CONNECT_DATA=(SID=$argDatabasename)))";
} else
$argDatabasename="(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=".$argHostname
.")(PORT=$argHostport))(CONNECT_DATA=(SERVICE_NAME=$argDatabasename)))";
}
}
if ($argDatabasename) $argUsername .= "@$argDatabasename";
//if ($argHostname) print "<p>Connect: 1st argument should be left blank for $this->databaseType</p>";
if ($mode = 1)
$this->_connectionID = ora_plogon($argUsername,$argPassword);
else
$this->_connectionID = ora_logon($argUsername,$argPassword);
if ($this->_connectionID === false) return false;
if ($this->autoCommit) ora_commiton($this->_connectionID);
if ($this->_initdate) {
$rs = $this->_query("ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD'");
if ($rs) ora_close($rs);
}
return true;
}
// returns true or false
function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, 1);
}
// returns query ID if successful, otherwise false
function _query($sql,$inputarr=false)
{
// <G. Giunta 2003/03/03/> Reset error messages before executing
$this->_errorMsg = false;
$this->_errorCode = false;
$curs = ora_open($this->_connectionID);
if ($curs === false) return false;
$this->_curs = $curs;
if (!ora_parse($curs,$sql)) return false;
if (ora_exec($curs)) return $curs;
// <G. Giunta 2004/03/03> before we close the cursor, we have to store the error message
// that we can obtain ONLY from the cursor (and not from the connection)
$this->_errorCode = @ora_errorcode($curs);
$this->_errorMsg = @ora_error($curs);
// </G. Giunta 2004/03/03>
@ora_close($curs);
return false;
}
// returns true or false
function _close()
{
return @ora_logoff($this->_connectionID);
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordset_oracle extends ADORecordSet {
var $databaseType = "oracle";
var $bind = false;
function ADORecordset_oracle($queryID,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
$this->fetchMode = $mode;
$this->_queryID = $queryID;
$this->_inited = true;
$this->fields = array();
if ($queryID) {
$this->_currentRow = 0;
$this->EOF = !$this->_fetch();
@$this->_initrs();
} else {
$this->_numOfRows = 0;
$this->_numOfFields = 0;
$this->EOF = true;
}
return $this->_queryID;
}
/* Returns: an object containing field information.
Get column information in the Recordset object. fetchField() can be used in order to obtain information about
fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
fetchField() is retrieved. */
function FetchField($fieldOffset = -1)
{
$fld = new ADOFieldObject;
$fld->name = ora_columnname($this->_queryID, $fieldOffset);
$fld->type = ora_columntype($this->_queryID, $fieldOffset);
$fld->max_length = ora_columnsize($this->_queryID, $fieldOffset);
return $fld;
}
/* Use associative array to get fields array */
function Fields($colname)
{
if (!$this->bind) {
$this->bind = array();
for ($i=0; $i < $this->_numOfFields; $i++) {
$o = $this->FetchField($i);
$this->bind[strtoupper($o->name)] = $i;
}
}
return $this->fields[$this->bind[strtoupper($colname)]];
}
function _initrs()
{
$this->_numOfRows = -1;
$this->_numOfFields = @ora_numcols($this->_queryID);
}
function _seek($row)
{
return false;
}
function _fetch($ignore_fields=false) {
// should remove call by reference, but ora_fetch_into requires it in 4.0.3pl1
if ($this->fetchMode & ADODB_FETCH_ASSOC)
return @ora_fetch_into($this->_queryID,&$this->fields,ORA_FETCHINTO_NULLS|ORA_FETCHINTO_ASSOC);
else
return @ora_fetch_into($this->_queryID,&$this->fields,ORA_FETCHINTO_NULLS);
}
/* close() only needs to be called if you are worried about using too much memory while your script
is running. All associated result memory for the specified result identifier will automatically be freed. */
function _close()
{
return @ora_close($this->_queryID);
}
function MetaType($t,$len=-1)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
switch (strtoupper($t)) {
case 'VARCHAR':
case 'VARCHAR2':
case 'CHAR':
case 'VARBINARY':
case 'BINARY':
if ($len <= $this->blobSize) return 'C';
case 'LONG':
case 'LONG VARCHAR':
case 'CLOB':
return 'X';
case 'LONG RAW':
case 'LONG VARBINARY':
case 'BLOB':
return 'B';
case 'DATE': return 'D';
//case 'T': return 'T';
case 'BIT': return 'L';
case 'INT':
case 'SMALLINT':
case 'INTEGER': return 'I';
default: return 'N';
}
}
}
?>

View File

@ -0,0 +1,319 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim#natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Requires ODBC. Works on Windows and Unix.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
/*--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------*/
class ADODB_pdo extends ADOConnection {
var $databaseType = "pdo";
var $dataProvider = "pdo";
var $fmtDate = "'Y-m-d'";
var $fmtTimeStamp = "'Y-m-d, h:i:sA'";
var $replaceQuote = "''"; // string to use to replace quotes
var $hasAffectedRows = true;
var $_bindInputArray = true;
var $_genSeqSQL = "create table %s (id integer)";
var $_autocommit = true;
var $_haserrorfunctions = true;
var $_lastAffectedRows = 0;
var $stmt = false;
function ADODB_pdo()
{
}
// returns true or false
function _connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persist=false)
{
$this->_connectionID = new PDO($argDSN, $argUsername, $argPassword);
if ($this->_connectionID) {
switch(ADODB_ASSOC_CASE){
case 0: $m = PDO_CASE_LOWER; break;
case 1: $m = PDO_CASE_UPPER; break;
default:
case 2: $m = PDO_CASE_NATURAL; break;
}
//$this->_connectionID->setAttribute(PDO_ATTR_ERRMODE,PDO_ERRMODE_SILENT );
$this->_connectionID->setAttribute(PDO_ATTR_CASE,$m);
//$this->_connectionID->setAttribute(PDO_ATTR_AUTOCOMMIT,true);
return true;
}
return false;
}
// returns true or false
function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
{
return $this->_connect($argDSN, $argUsername, $argPassword, $argDatabasename, true);
}
function ErrorMsg()
{
if ($this->_stmt) $arr = $this->_stmt->errorInfo();
else $arr = $this->_connectionID->errorInfo();
if ($arr) {
if ($arr[0]) return $arr[2];
else return '';
} else return '-1';
}
function InParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false)
{
$obj = $stmt[1];
if ($type) $obj->bindParam($name,$var,$type,$maxLen);
else $obj->bindParam($name, $var);
}
function ErrorNo()
{
if ($this->_stmt) return $this->_stmt->errorCode();
else return $this->_connectionID->errorInfo();
}
function BeginTrans()
{
if (!$this->hasTransactions) return false;
if ($this->transOff) return true;
$this->transCnt += 1;
$this->_autocommit = false;
$this->_connectionID->setAttribute(PDO_ATTR_AUTOCOMMIT,false);
return $this->_connectionID->beginTransaction();
}
function CommitTrans($ok=true)
{
if ($this->transOff) return true;
if (!$ok) return $this->RollbackTrans();
if ($this->transCnt) $this->transCnt -= 1;
$this->_autocommit = true;
$ret = $this->_connectionID->commit();
$this->_connectionID->setAttribute(PDO_ATTR_AUTOCOMMIT,true);
return $ret;
}
function RollbackTrans()
{
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
$this->_autocommit = true;
$ret = $this->_connectionID->rollback();
$this->_connectionID->setAttribute(PDO_ATTR_AUTOCOMMIT,true);
return $ret;
}
function Prepare($sql)
{
$this->_stmt = $this->_connectionID->prepare($sql);
if ($this->_stmt) return array($sql,$this->_stmt);
return false;
}
function PrepareStmt($sql)
{
$stmt = $this->_connectionID->prepare($sql);
if (!$stmt) return false;
$obj = new ADOPDOStatement($stmt,$this);
return $obj;
}
/* returns queryID or false */
function _query($sql,$inputarr=false)
{
if (is_array($sql)) {
$stmt = $sql[1];
} else {
$stmt = $this->_connectionID->prepare($sql);
}
if ($stmt) {
if ($inputarr) $stmt->execute($inputarr);
else $stmt->execute();
}
$this->_stmt = $stmt;
return $stmt;
}
// returns true or false
function _close()
{
$this->_stmt = false;
return true;
}
function _affectedrows()
{
return ($this->_stmt) ? $this->_stmt->rowCount() : 0;
}
function _insertid()
{
return ($this->_connectionID) ? $this->_connectionID->lastInsertId() : 0;
}
}
class ADOPDOStatement {
var $databaseType = "pdo";
var $dataProvider = "pdo";
var $_stmt;
var $_connectionID;
function ADOPDOStatement($stmt,$connection)
{
$this->_stmt = $stmt;
$this->_connectionID = $connection;
}
function Execute($inputArr=false)
{
$savestmt = $this->_connectionID->_stmt;
$rs = $this->_connectionID->Execute(array(false,$this->_stmt),$inputArr);
$this->_connectionID->_stmt = $savestmt;
return $rs;
}
function InParameter(&$var,$name,$maxLen=4000,$type=false)
{
if ($type) $this->_stmt->bindParam($name,$var,$type,$maxLen);
else $this->_stmt->bindParam($name, $var);
}
function Affected_Rows()
{
return ($this->_stmt) ? $this->_stmt->rowCount() : 0;
}
function ErrorMsg()
{
if ($this->_stmt) $arr = $this->_stmt->errorInfo();
else $arr = $this->_connectionID->errorInfo();
print_r($arr);
if ($arr) {
if ($arr[0]) return $arr[2];
else return '';
} else return '-1';
}
function ErrorNo()
{
if ($this->_stmt) return $this->_stmt->errorCode();
else return $this->_connectionID->errorInfo();
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordSet_pdo extends ADORecordSet {
var $bind = false;
var $databaseType = "pdo";
var $dataProvider = "pdo";
function ADORecordSet_pdo($id,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
switch($mode) {
default:
case ADODB_FETCH_BOTH: $mode = PDO_FETCH_BOTH; break;
case ADODB_FETCH_NUM: $mode = PDO_FETCH_NUM; break;
case ADODB_FETCH_ASSOC: $mode = PDO_FETCH_ASSOC; break;
}
$this->fetchMode = $mode;
$this->_queryID = $id;
$this->ADORecordSet($id);
}
// returns the field object
function &FetchField($fieldOffset = -1)
{
$off=$fieldOffset+1; // offsets begin at 1
$o= new ADOFieldObject();
$o->name = @odbc_field_name($this->_queryID,$off);
$o->type = @odbc_field_type($this->_queryID,$off);
$o->max_length = @odbc_field_len($this->_queryID,$off);
if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
return $o;
}
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->_currentRow == -1) {
$this->_currentRow = 0;
if ($this->EOF = ($this->_fetch() === false)) {
$this->_numOfRows = 0; // _numOfRows could be -1
}
$this->_numOfFields = sizeof($this->fields);
} else {
$this->EOF = true;
}
}
function _initrs()
{
global $ADODB_COUNTRECS;
$this->_numOfRows = ($ADODB_COUNTRECS) ? @$this->_queryID->rowCount() : -1;
if (!$this->_numOfRows) $this->_numOfRows = -1;
$this->_numOfFields =0;
}
function _seek($row)
{
return false;
}
function _fetch()
{
$this->fields = $this->_queryID->fetch($this->fetchMode);
return !empty($this->fields);
}
function _close()
{
$this->_queryID = false;
}
}
?>

View File

@ -0,0 +1,14 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4.
NOTE: Since 3.31, this file is no longer used, and the "postgres" driver is
remapped to "postgres7". Maintaining multiple postgres drivers is no easy
job, so hopefully this will ensure greater consistency and fewer bugs.
*/
?>

View File

@ -0,0 +1,958 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 8.
Original version derived from Alberto Cerezal (acerezalp@dbnet.es) - DBNet Informatica & Comunicaciones.
08 Nov 2000 jlim - Minor corrections, removing mysql stuff
09 Nov 2000 jlim - added insertid support suggested by "Christopher Kings-Lynne" <chriskl@familyhealth.com.au>
jlim - changed concat operator to || and data types to MetaType to match documented pgsql types
see http://www.postgresql.org/devel-corner/docs/postgres/datatype.htm
22 Nov 2000 jlim - added changes to FetchField() and MetaTables() contributed by "raser" <raser@mail.zen.com.tw>
27 Nov 2000 jlim - added changes to _connect/_pconnect from ideas by "Lennie" <leen@wirehub.nl>
15 Dec 2000 jlim - added changes suggested by Additional code changes by "Eric G. Werk" egw@netguide.dk.
31 Jan 2002 jlim - finally installed postgresql. testing
01 Mar 2001 jlim - Freek Dijkstra changes, also support for text type
See http://www.varlena.com/varlena/GeneralBits/47.php
-- What indexes are on my table?
select * from pg_indexes where tablename = 'tablename';
-- What triggers are on my table?
select c.relname as "Table", t.tgname as "Trigger Name",
t.tgconstrname as "Constraint Name", t.tgenabled as "Enabled",
t.tgisconstraint as "Is Constraint", cc.relname as "Referenced Table",
p.proname as "Function Name"
from pg_trigger t, pg_class c, pg_class cc, pg_proc p
where t.tgfoid = p.oid and t.tgrelid = c.oid
and t.tgconstrrelid = cc.oid
and c.relname = 'tablename';
-- What constraints are on my table?
select r.relname as "Table", c.conname as "Constraint Name",
contype as "Constraint Type", conkey as "Key Columns",
confkey as "Foreign Columns", consrc as "Source"
from pg_class r, pg_constraint c
where r.oid = c.conrelid
and relname = 'tablename';
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
function adodb_addslashes($s)
{
$len = strlen($s);
if ($len == 0) return "''";
if (strncmp($s,"'",1) === 0 && substr(s,$len-1) == "'") return $s; // already quoted
return "'".addslashes($s)."'";
}
class ADODB_postgres64 extends ADOConnection{
var $databaseType = 'postgres64';
var $dataProvider = 'postgres';
var $hasInsertID = true;
var $_resultid = false;
var $concat_operator='||';
var $metaDatabasesSQL = "select datname from pg_database where datname not in ('template0','template1') order by 1";
var $metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
and tablename not in ('sql_features', 'sql_implementation_info', 'sql_languages',
'sql_packages', 'sql_sizing', 'sql_sizing_profiles')
union
select viewname,'V' from pg_views where viewname not like 'pg\_%'";
//"select tablename from pg_tables where tablename not like 'pg_%' order by 1";
var $isoDates = true; // accepts dates in ISO format
var $sysDate = "CURRENT_DATE";
var $sysTimeStamp = "CURRENT_TIMESTAMP";
var $blobEncodeType = 'C';
var $metaColumnsSQL = "SELECT a.attname,t.typname,a.attlen,a.atttypmod,a.attnotnull,a.atthasdef,a.attnum
FROM pg_class c, pg_attribute a,pg_type t
WHERE relkind = 'r' AND (c.relname='%s' or c.relname = lower('%s')) and a.attname not like '....%%'
AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
var $metaColumnsSQL1 = "SELECT a.attname, t.typname, a.attlen, a.atttypmod, a.attnotnull, a.atthasdef, a.attnum
FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n
WHERE relkind = 'r' AND (c.relname='%s' or c.relname = lower('%s'))
and c.relnamespace=n.oid and n.nspname='%s'
and a.attname not like '....%%' AND a.attnum > 0
AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
// get primary key etc -- from Freek Dijkstra
var $metaKeySQL = "SELECT ic.relname AS index_name, a.attname AS column_name,i.indisunique AS unique_key, i.indisprimary AS primary_key
FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a WHERE bc.oid = i.indrelid AND ic.oid = i.indexrelid AND (i.indkey[0] = a.attnum OR i.indkey[1] = a.attnum OR i.indkey[2] = a.attnum OR i.indkey[3] = a.attnum OR i.indkey[4] = a.attnum OR i.indkey[5] = a.attnum OR i.indkey[6] = a.attnum OR i.indkey[7] = a.attnum) AND a.attrelid = bc.oid AND bc.relname = '%s'";
var $hasAffectedRows = true;
var $hasLimit = false; // set to true for pgsql 7 only. support pgsql/mysql SELECT * FROM TABLE LIMIT 10
// below suggested by Freek Dijkstra
var $true = 't'; // string that represents TRUE for a database
var $false = 'f'; // string that represents FALSE for a database
var $fmtDate = "'Y-m-d'"; // used by DBDate() as the default date format used by the database
var $fmtTimeStamp = "'Y-m-d G:i:s'"; // used by DBTimeStamp as the default timestamp fmt.
var $hasMoveFirst = true;
var $hasGenID = true;
var $_genIDSQL = "SELECT NEXTVAL('%s')";
var $_genSeqSQL = "CREATE SEQUENCE %s START %s";
var $_dropSeqSQL = "DROP SEQUENCE %s";
var $metaDefaultsSQL = "SELECT d.adnum as num, d.adsrc as def from pg_attrdef d, pg_class c where d.adrelid=c.oid and c.relname='%s' order by d.adnum";
var $random = 'random()'; /// random function
var $autoRollback = true; // apparently pgsql does not autorollback properly before 4.3.4
// http://bugs.php.net/bug.php?id=25404
var $_bindInputArray = false; // requires postgresql 7.3+ and ability to modify database
// The last (fmtTimeStamp is not entirely correct:
// PostgreSQL also has support for time zones,
// and writes these time in this format: "2001-03-01 18:59:26+02".
// There is no code for the "+02" time zone information, so I just left that out.
// I'm not familiar enough with both ADODB as well as Postgres
// to know what the concequences are. The other values are correct (wheren't in 0.94)
// -- Freek Dijkstra
function ADODB_postgres64()
{
// changes the metaColumnsSQL, adds columns: attnum[6]
}
function ServerInfo()
{
if (isset($this->version)) return $this->version;
$arr['description'] = $this->GetOne("select version()");
$arr['version'] = ADOConnection::_findvers($arr['description']);
$this->version = $arr;
return $arr;
}
/*
function IfNull( $field, $ifNull )
{
return " NULLIF($field, $ifNull) "; // if PGSQL
}
*/
// get the last id - never tested
function pg_insert_id($tablename,$fieldname)
{
$result=pg_exec($this->_connectionID, "SELECT last_value FROM ${tablename}_${fieldname}_seq");
if ($result) {
$arr = @pg_fetch_row($result,0);
pg_freeresult($result);
if (isset($arr[0])) return $arr[0];
}
return false;
}
/* Warning from http://www.php.net/manual/function.pg-getlastoid.php:
Using a OID as a unique identifier is not generally wise.
Unless you are very careful, you might end up with a tuple having
a different OID if a database must be reloaded. */
function _insertid()
{
if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;
return pg_getlastoid($this->_resultid);
}
// I get this error with PHP before 4.0.6 - jlim
// Warning: This compilation does not support pg_cmdtuples() in d:/inetpub/wwwroot/php/adodb/adodb-postgres.inc.php on line 44
function _affectedrows()
{
if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;
return pg_cmdtuples($this->_resultid);
}
// returns true/false
function BeginTrans()
{
if ($this->transOff) return true;
$this->transCnt += 1;
return @pg_Exec($this->_connectionID, "begin");
}
function RowLock($tables,$where)
{
if (!$this->transCnt) $this->BeginTrans();
return $this->GetOne("select 1 as ignore from $tables where $where for update");
}
// returns true/false.
function CommitTrans($ok=true)
{
if ($this->transOff) return true;
if (!$ok) return $this->RollbackTrans();
$this->transCnt -= 1;
return @pg_Exec($this->_connectionID, "commit");
}
// returns true/false
function RollbackTrans()
{
if ($this->transOff) return true;
$this->transCnt -= 1;
return @pg_Exec($this->_connectionID, "rollback");
}
function &MetaTables($ttype=false,$showSchema=false,$mask=false)
{
if ($mask) {
$save = $this->metaTablesSQL;
$mask = $this->qstr(strtolower($mask));
$this->metaTablesSQL = "
select tablename,'T' from pg_tables where tablename like $mask union
select viewname,'V' from pg_views where viewname like $mask";
}
$ret =& ADOConnection::MetaTables($ttype,$showSchema);
if ($mask) {
$this->metaTablesSQL = $save;
}
return $ret;
}
/*
// if magic quotes disabled, use pg_escape_string()
function qstr($s,$magic_quotes=false)
{
if (!$magic_quotes) {
if (ADODB_PHPVER >= 0x4200) {
return "'".pg_escape_string($s)."'";
}
if ($this->replaceQuote[0] == '\\'){
$s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
}
return "'".str_replace("'",$this->replaceQuote,$s)."'";
}
// undo magic quotes for "
$s = str_replace('\\"','"',$s);
return "'$s'";
}
*/
// Format date column in sql string given an input format that understands Y M D
function SQLDate($fmt, $col=false)
{
if (!$col) $col = $this->sysTimeStamp;
$s = 'TO_CHAR('.$col.",'";
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
$ch = $fmt[$i];
switch($ch) {
case 'Y':
case 'y':
$s .= 'YYYY';
break;
case 'Q':
case 'q':
$s .= 'Q';
break;
case 'M':
$s .= 'Mon';
break;
case 'm':
$s .= 'MM';
break;
case 'D':
case 'd':
$s .= 'DD';
break;
case 'H':
$s.= 'HH24';
break;
case 'h':
$s .= 'HH';
break;
case 'i':
$s .= 'MI';
break;
case 's':
$s .= 'SS';
break;
case 'a':
case 'A':
$s .= 'AM';
break;
default:
// handle escape characters...
if ($ch == '\\') {
$i++;
$ch = substr($fmt,$i,1);
}
if (strpos('-/.:;, ',$ch) !== false) $s .= $ch;
else $s .= '"'.$ch.'"';
}
}
return $s. "')";
}
/*
* Load a Large Object from a file
* - the procedure stores the object id in the table and imports the object using
* postgres proprietary blob handling routines
*
* contributed by Mattia Rossi mattia@technologist.com
* modified for safe mode by juraj chlebec
*/
function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
{
pg_exec ($this->_connectionID, "begin");
$fd = fopen($path,'r');
$contents = fread($fd,filesize($path));
fclose($fd);
$oid = pg_lo_create($this->_connectionID);
$handle = pg_lo_open($this->_connectionID, $oid, 'w');
pg_lo_write($handle, $contents);
pg_lo_close($handle);
// $oid = pg_lo_import ($path);
pg_exec($this->_connectionID, "commit");
$rs = ADOConnection::UpdateBlob($table,$column,$oid,$where,$blobtype);
$rez = !empty($rs);
return $rez;
}
/*
* If an OID is detected, then we use pg_lo_* to open the oid file and read the
* real blob from the db using the oid supplied as a parameter. If you are storing
* blobs using bytea, we autodetect and process it so this function is not needed.
*
* contributed by Mattia Rossi mattia@technologist.com
*
* see http://www.postgresql.org/idocs/index.php?largeobjects.html
*/
function BlobDecode( $blob)
{
if (strlen($blob) > 24) return $blob;
@pg_exec($this->_connectionID,"begin");
$fd = @pg_lo_open($this->_connectionID,$blob,"r");
if ($fd === false) {
@pg_exec($this->_connectionID,"commit");
return $blob;
}
$realblob = @pg_loreadall($fd);
@pg_loclose($fd);
@pg_exec($this->_connectionID,"commit");
return $realblob;
}
/*
See http://www.postgresql.org/idocs/index.php?datatype-binary.html
NOTE: SQL string literals (input strings) must be preceded with two backslashes
due to the fact that they must pass through two parsers in the PostgreSQL
backend.
*/
function BlobEncode($blob)
{
if (ADODB_PHPVER >= 0x4200) return pg_escape_bytea($blob);
/*92=backslash, 0=null, 39=single-quote*/
$badch = array(chr(92),chr(0),chr(39)); # \ null '
$fixch = array('\\\\134','\\\\000','\\\\047');
return adodb_str_replace($badch,$fixch,$blob);
// note that there is a pg_escape_bytea function only for php 4.2.0 or later
}
function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
{
// do not use bind params which uses qstr(), as blobencode() already quotes data
return $this->Execute("UPDATE $table SET $column='".$this->BlobEncode($val)."'::bytea WHERE $where");
}
function OffsetDate($dayFraction,$date=false)
{
if (!$date) $date = $this->sysDate;
return "($date+interval'$dayFraction days')";
}
// for schema support, pass in the $table param "$schema.$tabname".
// converts field names to lowercase, $upper is ignored
function &MetaColumns($table,$normalize=true)
{
global $ADODB_FETCH_MODE;
$schema = false;
$this->_findschema($table,$schema);
if ($normalize) $table = strtolower($table);
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
if ($schema) $rs =& $this->Execute(sprintf($this->metaColumnsSQL1,$table,$table,$schema));
else $rs =& $this->Execute(sprintf($this->metaColumnsSQL,$table,$table));
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rs === false) return false;
if (!empty($this->metaKeySQL)) {
// If we want the primary keys, we have to issue a separate query
// Of course, a modified version of the metaColumnsSQL query using a
// LEFT JOIN would have been much more elegant, but postgres does
// not support OUTER JOINS. So here is the clumsy way.
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$rskey = $this->Execute(sprintf($this->metaKeySQL,($table)));
// fetch all result in once for performance.
$keys =& $rskey->GetArray();
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
$rskey->Close();
unset($rskey);
}
$rsdefa = array();
if (!empty($this->metaDefaultsSQL)) {
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$sql = sprintf($this->metaDefaultsSQL, ($table));
$rsdef = $this->Execute($sql);
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ($rsdef) {
while (!$rsdef->EOF) {
$num = $rsdef->fields['num'];
$s = $rsdef->fields['def'];
if (strpos($s,'::')===false && substr($s, 0, 1) == "'") { /* quoted strings hack... for now... fixme */
$s = substr($s, 1);
$s = substr($s, 0, strlen($s) - 1);
}
$rsdefa[$num] = $s;
$rsdef->MoveNext();
}
} else {
ADOConnection::outp( "==> SQL => " . $sql);
}
unset($rsdef);
}
$retarr = array();
while (!$rs->EOF) {
$fld = new ADOFieldObject();
$fld->name = $rs->fields[0];
$fld->type = $rs->fields[1];
$fld->max_length = $rs->fields[2];
if ($fld->max_length <= 0) $fld->max_length = $rs->fields[3]-4;
if ($fld->max_length <= 0) $fld->max_length = -1;
// dannym
// 5 hasdefault; 6 num-of-column
$fld->has_default = ($rs->fields[5] == 't');
if ($fld->has_default) {
$fld->default_value = $rsdefa[$rs->fields[6]];
}
//Freek
if ($rs->fields[4] == $this->true) {
$fld->not_null = true;
}
// Freek
if (is_array($keys)) {
foreach($keys as $key) {
if ($fld->name == $key['column_name'] AND $key['primary_key'] == $this->true)
$fld->primary_key = true;
if ($fld->name == $key['column_name'] AND $key['unique_key'] == $this->true)
$fld->unique = true; // What name is more compatible?
}
}
if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
else $retarr[($normalize) ? strtoupper($fld->name) : $fld->name] = $fld;
$rs->MoveNext();
}
$rs->Close();
return $retarr;
}
function &MetaIndexes ($table, $primary = FALSE)
{
global $ADODB_FETCH_MODE;
$schema = false;
$this->_findschema($table,$schema);
if ($schema) { // requires pgsql 7.3+ - pg_namespace used.
$sql = '
SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
,pg_namespace n
WHERE (c2.relname=\'%s\' or c2.relname=lower(\'%s\')) and c.relnamespace=c2.relnamespace and c.relnamespace=n.oid and n.nspname=\'%s\' AND i.indisprimary=false';
} else {
$sql = '
SELECT c.relname as "Name", i.indisunique as "Unique", i.indkey as "Columns"
FROM pg_catalog.pg_class c
JOIN pg_catalog.pg_index i ON i.indexrelid=c.oid
JOIN pg_catalog.pg_class c2 ON c2.oid=i.indrelid
WHERE c2.relname=\'%s\' or c2.relname=lower(\'%s\')';
}
if ($primary == FALSE) {
$sql .= ' AND i.indisprimary=false;';
}
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
$savem = $this->SetFetchMode(FALSE);
}
$rs = $this->Execute(sprintf($sql,$table,$table,$schema));
if (isset($savem)) {
$this->SetFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
if (!is_object($rs)) {
return FALSE;
}
$col_names = $this->MetaColumnNames($table,true);
$indexes = array();
while ($row = $rs->FetchRow()) {
$columns = array();
foreach (explode(' ', $row[2]) as $col) {
$columns[] = $col_names[$col - 1];
}
$indexes[$row[0]] = array(
'unique' => ($row[1] == 't'),
'columns' => $columns
);
}
return $indexes;
}
// returns true or false
//
// examples:
// $db->Connect("host=host1 user=user1 password=secret port=4341");
// $db->Connect('host1','user1','secret');
function _connect($str,$user='',$pwd='',$db='',$ctype=0)
{
if (!function_exists('pg_pconnect')) return null;
$this->_errorMsg = false;
if ($user || $pwd || $db) {
$user = adodb_addslashes($user);
$pwd = adodb_addslashes($pwd);
if (strlen($db) == 0) $db = 'template1';
$db = adodb_addslashes($db);
if ($str) {
$host = split(":", $str);
if ($host[0]) $str = "host=".adodb_addslashes($host[0]);
else $str = 'host=localhost';
if (isset($host[1])) $str .= " port=$host[1]";
}
if ($user) $str .= " user=".$user;
if ($pwd) $str .= " password=".$pwd;
if ($db) $str .= " dbname=".$db;
}
//if ($user) $linea = "user=$user host=$linea password=$pwd dbname=$db port=5432";
if ($ctype === 1) { // persistent
$this->_connectionID = pg_pconnect($str);
} else {
if ($ctype === -1) { // nconnect, we trick pgsql ext by changing the connection str
static $ncnt;
if (empty($ncnt)) $ncnt = 1;
else $ncnt += 1;
$str .= str_repeat(' ',$ncnt);
}
$this->_connectionID = pg_connect($str);
}
if ($this->_connectionID === false) return false;
$this->Execute("set datestyle='ISO'");
return true;
}
function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName)
{
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName,-1);
}
// returns true or false
//
// examples:
// $db->PConnect("host=host1 user=user1 password=secret port=4341");
// $db->PConnect('host1','user1','secret');
function _pconnect($str,$user='',$pwd='',$db='')
{
return $this->_connect($str,$user,$pwd,$db,1);
}
// returns queryID or false
function _query($sql,$inputarr)
{
if ($inputarr) {
/*
It appears that PREPARE/EXECUTE is slower for many queries.
For query executed 1000 times:
"select id,firstname,lastname from adoxyz
where firstname not like ? and lastname not like ? and id = ?"
with plan = 1.51861286163 secs
no plan = 1.26903700829 secs
*/
$plan = 'P'.md5($sql);
$execp = '';
foreach($inputarr as $v) {
if ($execp) $execp .= ',';
if (is_string($v)) {
if (strncmp($v,"'",1) !== 0) $execp .= $this->qstr($v);
} else {
$execp .= $v;
}
}
if ($execp) $exsql = "EXECUTE $plan ($execp)";
else $exsql = "EXECUTE $plan";
$rez = @pg_exec($this->_connectionID,$exsql);
if (!$rez) {
# Perhaps plan does not exist? Prepare/compile plan.
$params = '';
foreach($inputarr as $v) {
if ($params) $params .= ',';
if (is_string($v)) {
$params .= 'VARCHAR';
} else if (is_integer($v)) {
$params .= 'INTEGER';
} else {
$params .= "REAL";
}
}
$sqlarr = explode('?',$sql);
//print_r($sqlarr);
$sql = '';
$i = 1;
foreach($sqlarr as $v) {
$sql .= $v.' $'.$i;
$i++;
}
$s = "PREPARE $plan ($params) AS ".substr($sql,0,strlen($sql)-2);
//adodb_pr($s);
pg_exec($this->_connectionID,$s);
echo $this->ErrorMsg();
}
$rez = pg_exec($this->_connectionID,$exsql);
} else {
$this->_errorMsg = false;
//adodb_backtrace();
$rez = pg_exec($this->_connectionID,$sql);
}
// check if no data returned, then no need to create real recordset
if ($rez && pg_numfields($rez) <= 0) {
if (is_resource($this->_resultid) && get_resource_type($this->_resultid) === 'pgsql result') {
pg_freeresult($this->_resultid);
}
$this->_resultid = $rez;
return true;
}
return $rez;
}
/* Returns: the last error message from previous database operation */
function ErrorMsg()
{
if ($this->_errorMsg !== false) return $this->_errorMsg;
if (ADODB_PHPVER >= 0x4300) {
if (!empty($this->_resultid)) {
$this->_errorMsg = @pg_result_error($this->_resultid);
if ($this->_errorMsg) return $this->_errorMsg;
}
if (!empty($this->_connectionID)) {
$this->_errorMsg = @pg_last_error($this->_connectionID);
} else $this->_errorMsg = @pg_last_error();
} else {
if (empty($this->_connectionID)) $this->_errorMsg = @pg_errormessage();
else $this->_errorMsg = @pg_errormessage($this->_connectionID);
}
return $this->_errorMsg;
}
function ErrorNo()
{
$e = $this->ErrorMsg();
if (strlen($e)) {
return ADOConnection::MetaError($e);
}
return 0;
}
// returns true or false
function _close()
{
if ($this->transCnt) $this->RollbackTrans();
if ($this->_resultid) {
@pg_freeresult($this->_resultid);
$this->_resultid = false;
}
@pg_close($this->_connectionID);
$this->_connectionID = false;
return true;
}
/*
* Maximum size of C field
*/
function CharMax()
{
return 1000000000; // should be 1 Gb?
}
/*
* Maximum size of X field
*/
function TextMax()
{
return 1000000000; // should be 1 Gb?
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordSet_postgres64 extends ADORecordSet{
var $_blobArr;
var $databaseType = "postgres64";
var $canSeek = true;
function ADORecordSet_postgres64($queryID,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
switch ($mode)
{
case ADODB_FETCH_NUM: $this->fetchMode = PGSQL_NUM; break;
case ADODB_FETCH_ASSOC:$this->fetchMode = PGSQL_ASSOC; break;
default:
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:$this->fetchMode = PGSQL_BOTH; break;
}
$this->ADORecordSet($queryID);
}
function &GetRowAssoc($upper=true)
{
if ($this->fetchMode == PGSQL_ASSOC && !$upper) return $this->fields;
$row =& ADORecordSet::GetRowAssoc($upper);
return $row;
}
function _initrs()
{
global $ADODB_COUNTRECS;
$qid = $this->_queryID;
$this->_numOfRows = ($ADODB_COUNTRECS)? @pg_numrows($qid):-1;
$this->_numOfFields = @pg_numfields($qid);
// cache types for blob decode check
for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
if (pg_fieldtype($qid,$i) == 'bytea') {
$this->_blobArr[$i] = pg_fieldname($qid,$i);
}
}
}
/* Use associative array to get fields array */
function Fields($colname)
{
if ($this->fetchMode != PGSQL_NUM) return @$this->fields[$colname];
if (!$this->bind) {
$this->bind = array();
for ($i=0; $i < $this->_numOfFields; $i++) {
$o = $this->FetchField($i);
$this->bind[strtoupper($o->name)] = $i;
}
}
return $this->fields[$this->bind[strtoupper($colname)]];
}
function &FetchField($off = 0)
{
// offsets begin at 0
$o= new ADOFieldObject();
$o->name = @pg_fieldname($this->_queryID,$off);
$o->type = @pg_fieldtype($this->_queryID,$off);
$o->max_length = @pg_fieldsize($this->_queryID,$off);
return $o;
}
function _seek($row)
{
return @pg_fetch_row($this->_queryID,$row);
}
function _decode($blob)
{
eval('$realblob="'.adodb_str_replace(array('"','$'),array('\"','\$'),$blob).'";');
return $realblob;
}
function _fixblobs()
{
if ($this->fetchMode == PGSQL_NUM || $this->fetchMode == PGSQL_BOTH) {
foreach($this->_blobArr as $k => $v) {
$this->fields[$k] = ADORecordSet_postgres64::_decode($this->fields[$k]);
}
}
if ($this->fetchMode == PGSQL_ASSOC || $this->fetchMode == PGSQL_BOTH) {
foreach($this->_blobArr as $k => $v) {
$this->fields[$v] = ADORecordSet_postgres64::_decode($this->fields[$v]);
}
}
}
// 10% speedup to move MoveNext to child class
function MoveNext()
{
if (!$this->EOF) {
$this->_currentRow++;
if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) {
$this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
if (is_array($this->fields) && $this->fields) {
if (isset($this->_blobArr)) $this->_fixblobs();
return true;
}
}
$this->fields = false;
$this->EOF = true;
}
return false;
}
function _fetch()
{
if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0)
return false;
$this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
if ($this->fields && isset($this->_blobArr)) $this->_fixblobs();
return (is_array($this->fields));
}
function _close()
{
return @pg_freeresult($this->_queryID);
}
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
switch (strtoupper($t)) {
case 'MONEY': // stupid, postgres expects money to be a string
case 'INTERVAL':
case 'CHAR':
case 'CHARACTER':
case 'VARCHAR':
case 'NAME':
case 'BPCHAR':
case '_VARCHAR':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
return 'X';
case 'IMAGE': // user defined type
case 'BLOB': // user defined type
case 'BIT': // This is a bit string, not a single bit, so don't return 'L'
case 'VARBIT':
case 'BYTEA':
return 'B';
case 'BOOL':
case 'BOOLEAN':
return 'L';
case 'DATE':
return 'D';
case 'TIME':
case 'DATETIME':
case 'TIMESTAMP':
case 'TIMESTAMPTZ':
return 'T';
case 'SMALLINT':
case 'BIGINT':
case 'INTEGER':
case 'INT8':
case 'INT4':
case 'INT2':
if (isset($fieldobj) &&
empty($fieldobj->primary_key) && empty($fieldobj->unique)) return 'I';
case 'OID':
case 'SERIAL':
return 'R';
default:
return 'N';
}
}
}
?>

View File

@ -0,0 +1,192 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4.
Postgres7 support.
28 Feb 2001: Currently indicate that we support LIMIT
01 Dec 2001: dannym added support for default values
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
include_once(ADODB_DIR."/drivers/adodb-postgres64.inc.php");
class ADODB_postgres7 extends ADODB_postgres64 {
var $databaseType = 'postgres7';
var $hasLimit = true; // set to true for pgsql 6.5+ only. support pgsql/mysql SELECT * FROM TABLE LIMIT 10
var $ansiOuter = true;
var $charSet = true; //set to true for Postgres 7 and above - PG client supports encodings
function ADODB_postgres7()
{
$this->ADODB_postgres64();
}
// the following should be compat with postgresql 7.2,
// which makes obsolete the LIMIT limit,offset syntax
function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
{
$offsetStr = ($offset >= 0) ? " OFFSET $offset" : '';
$limitStr = ($nrows >= 0) ? " LIMIT $nrows" : '';
if ($secs2cache)
$rs =& $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr);
else
$rs =& $this->Execute($sql."$limitStr$offsetStr",$inputarr);
return $rs;
}
/*
function Prepare($sql)
{
$info = $this->ServerInfo();
if ($info['version']>=7.3) {
return array($sql,false);
}
return $sql;
}
*/
// from Edward Jaramilla, improved version - works on pg 7.4
function MetaForeignKeys($table, $owner=false, $upper=false)
{
$sql = 'SELECT t.tgargs as args
FROM
pg_trigger t,pg_class c,pg_proc p
WHERE
t.tgenabled AND
t.tgrelid = c.oid AND
t.tgfoid = p.oid AND
p.proname = \'RI_FKey_check_ins\' AND
c.relname = \''.strtolower($table).'\'
ORDER BY
t.tgrelid';
$rs = $this->Execute($sql);
if ($rs && !$rs->EOF) {
$arr =& $rs->GetArray();
$a = array();
foreach($arr as $v)
{
$data = explode(chr(0), $v['args']);
if ($upper) {
$a[strtoupper($data[2])][] = strtoupper($data[4].'='.$data[5]);
} else {
$a[$data[2]][] = $data[4].'='.$data[5];
}
}
return $a;
}
return false;
}
function xMetaForeignKeys($table, $owner=false, $upper=false)
{
$sql = '
SELECT t.tgargs as args
FROM pg_trigger t,
pg_class c,
pg_class c2,
pg_proc f
WHERE t.tgenabled
AND t.tgrelid=c.oid
AND t.tgconstrrelid=c2.oid
AND t.tgfoid=f.oid
AND f.proname ~ \'^RI_FKey_check_ins\'
AND t.tgargs like \'$1\\\000'.strtolower($table).'%\'
ORDER BY t.tgrelid';
$rs = $this->Execute($sql);
if ($rs && !$rs->EOF) {
$arr =& $rs->GetArray();
$a = array();
foreach($arr as $v) {
$data = explode(chr(0), $v['args']);
if ($upper) {
$a[] = array(strtoupper($data[2]) => strtoupper($data[4].'='.$data[5]));
} else {
$a[] = array($data[2] => $data[4].'='.$data[5]);
}
}
return $a;
}
else return false;
}
// this is a set of functions for managing client encoding - very important if the encodings
// of your database and your output target (i.e. HTML) don't match
//for instance, you may have UNICODE database and server it on-site as WIN1251 etc.
// GetCharSet - get the name of the character set the client is using now
// the functions should work with Postgres 7.0 and above, the set of charsets supported
// depends on compile flags of postgres distribution - if no charsets were compiled into the server
// it will return 'SQL_ANSI' always
function GetCharSet()
{
//we will use ADO's builtin property charSet
$this->charSet = @pg_client_encoding($this->_connectionID);
if (!$this->charSet) {
return false;
} else {
return $this->charSet;
}
}
// SetCharSet - switch the client encoding
function SetCharSet($charset_name)
{
$this->GetCharSet();
if ($this->charSet !== $charset_name) {
$if = pg_set_client_encoding($this->_connectionID, $charset_name);
if ($if == "0" & $this->GetCharSet() == $charset_name) {
return true;
} else return false;
} else return true;
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordSet_postgres7 extends ADORecordSet_postgres64{
var $databaseType = "postgres7";
function ADORecordSet_postgres7($queryID,$mode=false)
{
$this->ADORecordSet_postgres64($queryID,$mode);
}
// 10% speedup to move MoveNext to child class
function MoveNext()
{
if (!$this->EOF) {
$this->_currentRow++;
if ($this->_numOfRows < 0 || $this->_numOfRows > $this->_currentRow) {
$this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
if (is_array($this->fields)) {
if ($this->fields && isset($this->_blobArr)) $this->_fixblobs();
return true;
}
}
$this->fields = false;
$this->EOF = true;
}
return false;
}
}
?>

View File

@ -0,0 +1,33 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4.
Synonym for csv driver.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
if (! defined("_ADODB_PROXY_LAYER")) {
define("_ADODB_PROXY_LAYER", 1 );
include(ADODB_DIR."/drivers/adodb-csv.inc.php");
class ADODB_proxy extends ADODB_csv {
var $databaseType = 'proxy';
var $databaseProvider = 'csv';
}
class ADORecordset_proxy extends ADORecordset_csv {
var $databaseType = "proxy";
function ADORecordset_proxy($id,$mode=false)
{
$this->ADORecordset($id,$mode);
}
};
} // define
?>

View File

@ -0,0 +1,66 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
SAPDB data driver. Requires ODBC.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
if (!defined('_ADODB_ODBC_LAYER')) {
include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
}
if (!defined('ADODB_SAPDB')){
define('ADODB_SAPDB',1);
class ADODB_SAPDB extends ADODB_odbc {
var $databaseType = "sapdb";
var $concat_operator = '||';
var $sysDate = 'DATE';
var $sysTimeStamp = 'TIMESTAMP';
var $fmtDate = "\\D\\A\\T\\E('Y-m-d')"; /// used by DBDate() as the default date format used by the database
var $fmtTimeStamp = "\\T\\I\\M\\E\\S\\T\\A\\M\\P('Y-m-d','H:i:s')"; /// used by DBTimeStamp as the default timestamp fmt.
function ADODB_SAPDB()
{
//if (strncmp(PHP_OS,'WIN',3) === 0) $this->curmode = SQL_CUR_USE_ODBC;
$this->ADODB_odbc();
}
/*
SelectLimit implementation problems:
The following will return random 10 rows as order by performed after "WHERE rowno<10"
which is not ideal...
select * from table where rowno < 10 order by 1
This means that we have to use the adoconnection base class SelectLimit when
there is an "order by".
See http://listserv.sap.com/pipermail/sapdb.general/2002-January/010405.html
*/
};
class ADORecordSet_sapdb extends ADORecordSet_odbc {
var $databaseType = "sapdb";
function ADORecordSet_sapdb($id,$mode=false)
{
$this->ADORecordSet_odbc($id,$mode);
}
}
} //define
?>

View File

@ -0,0 +1,322 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Latest version is available at http://adodb.sourceforge.net
SQLite info: http://www.hwaci.com/sw/sqlite/
Install Instructions:
====================
1. Place this in adodb/drivers
2. Rename the file, remove the .txt prefix.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB_sqlite extends ADOConnection {
var $databaseType = "sqlite";
var $replaceQuote = "''"; // string to use to replace quotes
var $concat_operator='||';
var $_errorNo = 0;
var $hasLimit = true;
var $hasInsertID = true; /// supports autoincrement ID?
var $hasAffectedRows = true; /// supports affected rows for update/delete?
var $metaTablesSQL = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name";
var $sysDate = "adodb_date('Y-m-d')";
var $sysTimeStamp = "adodb_date('Y-m-d H:i:s')";
var $fmtTimeStamp = "'Y-m-d H:i:s'";
function ADODB_sqlite()
{
}
/*
function __get($name)
{
switch($name) {
case 'sysDate': return "'".date($this->fmtDate)."'";
case 'sysTimeStamp' : return "'".date($this->sysTimeStamp)."'";
}
}*/
function ServerInfo()
{
$arr['version'] = sqlite_libversion();
$arr['description'] = 'SQLite ';
$arr['encoding'] = sqlite_libencoding();
return $arr;
}
function BeginTrans()
{
if ($this->transOff) return true;
$ret = $this->Execute("BEGIN TRANSACTION");
$this->transCnt += 1;
return true;
}
function CommitTrans($ok=true)
{
if ($this->transOff) return true;
if (!$ok) return $this->RollbackTrans();
$ret = $this->Execute("COMMIT");
if ($this->transCnt>0)$this->transCnt -= 1;
return !empty($ret);
}
function RollbackTrans()
{
if ($this->transOff) return true;
$ret = $this->Execute("ROLLBACK");
if ($this->transCnt>0)$this->transCnt -= 1;
return !empty($ret);
}
function _insertid()
{
return sqlite_last_insert_rowid($this->_connectionID);
}
function _affectedrows()
{
return sqlite_changes($this->_connectionID);
}
function ErrorMsg()
{
if ($this->_logsql) return $this->_errorMsg;
return ($this->_errorNo) ? sqlite_error_string($this->_errorNo) : '';
}
function ErrorNo()
{
return $this->_errorNo;
}
function SQLDate($fmt, $col=false)
{
$fmt = $this->qstr($fmt);
return ($col) ? "adodb_date2($fmt,$col)" : "adodb_date($fmt)";
}
function &MetaColumns($tab)
{
global $ADODB_FETCH_MODE;
$rs = $this->Execute("select * from $tab limit 1");
if (!$rs) return false;
$arr = array();
for ($i=0,$max=$rs->_numOfFields; $i < $max; $i++) {
$fld =& $rs->FetchField($i);
if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] =& $fld;
else $arr[strtoupper($fld->name)] =& $fld;
}
$rs->Close();
return $arr;
}
function _createFunctions()
{
@sqlite_create_function($this->_connectionID, 'adodb_date', 'adodb_date', 1);
@sqlite_create_function($this->_connectionID, 'adodb_date2', 'adodb_date2', 2);
}
// returns true or false
function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (!function_exists('sqlite_open')) return null;
$this->_connectionID = sqlite_open($argHostname);
if ($this->_connectionID === false) return false;
$this->_createFunctions();
return true;
}
// returns true or false
function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (!function_exists('sqlite_open')) return null;
$this->_connectionID = sqlite_popen($argHostname);
if ($this->_connectionID === false) return false;
$this->_createFunctions();
return true;
}
// returns query ID if successful, otherwise false
function _query($sql,$inputarr=false)
{
$rez = sqlite_query($sql,$this->_connectionID);
if (!$rez) {
$this->_errorNo = sqlite_last_error($this->_connectionID);
}
return $rez;
}
function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
{
$offsetStr = ($offset >= 0) ? " OFFSET $offset" : '';
$limitStr = ($nrows >= 0) ? " LIMIT $nrows" : ($offset >= 0 ? ' LIMIT 999999999' : '');
if ($secs2cache)
$rs =& $this->CacheExecute($secs2cache,$sql."$limitStr$offsetStr",$inputarr);
else
$rs =& $this->Execute($sql."$limitStr$offsetStr",$inputarr);
return $rs;
}
/*
This algorithm is not very efficient, but works even if table locking
is not available.
Will return false if unable to generate an ID after $MAXLOOPS attempts.
*/
var $_genSeqSQL = "create table %s (id integer)";
function GenID($seq='adodbseq',$start=1)
{
// if you have to modify the parameter below, your database is overloaded,
// or you need to implement generation of id's yourself!
$MAXLOOPS = 100;
//$this->debug=1;
while (--$MAXLOOPS>=0) {
$num = $this->GetOne("select id from $seq");
if ($num === false) {
$this->Execute(sprintf($this->_genSeqSQL ,$seq));
$start -= 1;
$num = '0';
$ok = $this->Execute("insert into $seq values($start)");
if (!$ok) return false;
}
$this->Execute("update $seq set id=id+1 where id=$num");
if ($this->affected_rows() > 0) {
$num += 1;
$this->genID = $num;
return $num;
}
}
if ($fn = $this->raiseErrorFn) {
$fn($this->databaseType,'GENID',-32000,"Unable to generate unique id after $MAXLOOPS attempts",$seq,$num);
}
return false;
}
function CreateSequence($seqname='adodbseq',$start=1)
{
if (empty($this->_genSeqSQL)) return false;
$ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
if (!$ok) return false;
$start -= 1;
return $this->Execute("insert into $seqname values($start)");
}
var $_dropSeqSQL = 'drop table %s';
function DropSequence($seqname)
{
if (empty($this->_dropSeqSQL)) return false;
return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
}
// returns true or false
function _close()
{
return @sqlite_close($this->_connectionID);
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordset_sqlite extends ADORecordSet {
var $databaseType = "sqlite";
var $bind = false;
function ADORecordset_sqlite($queryID,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
switch($mode) {
case ADODB_FETCH_NUM: $this->fetchMode = SQLITE_NUM; break;
case ADODB_FETCH_ASSOC: $this->fetchMode = SQLITE_ASSOC; break;
default: $this->fetchMode = SQLITE_BOTH; break;
}
$this->_queryID = $queryID;
$this->_inited = true;
$this->fields = array();
if ($queryID) {
$this->_currentRow = 0;
$this->EOF = !$this->_fetch();
@$this->_initrs();
} else {
$this->_numOfRows = 0;
$this->_numOfFields = 0;
$this->EOF = true;
}
return $this->_queryID;
}
function &FetchField($fieldOffset = -1)
{
$fld = new ADOFieldObject;
$fld->name = sqlite_field_name($this->_queryID, $fieldOffset);
$fld->type = 'VARCHAR';
$fld->max_length = -1;
return $fld;
}
function _initrs()
{
$this->_numOfRows = @sqlite_num_rows($this->_queryID);
$this->_numOfFields = @sqlite_num_fields($this->_queryID);
}
function Fields($colname)
{
if ($this->fetchMode != SQLITE_NUM) return $this->fields[$colname];
if (!$this->bind) {
$this->bind = array();
for ($i=0; $i < $this->_numOfFields; $i++) {
$o = $this->FetchField($i);
$this->bind[strtoupper($o->name)] = $i;
}
}
return $this->fields[$this->bind[strtoupper($colname)]];
}
function _seek($row)
{
return sqlite_seek($this->_queryID, $row);
}
function _fetch($ignore_fields=false)
{
$this->fields = @sqlite_fetch_array($this->_queryID,$this->fetchMode);
return !empty($this->fields);
}
function _close()
{
}
}
?>

View File

@ -0,0 +1,62 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Portable version of sqlite driver, to make it more similar to other database drivers.
The main differences are
1. When selecting (joining) multiple tables, in assoc mode the table
names are included in the assoc keys in the "sqlite" driver.
In "sqlitepo" driver, the table names are stripped from the returned column names.
When this results in a conflict, the first field get preference.
Contributed by Herman Kuiper herman#ozuzo.net
*/
if (!defined('ADODB_DIR')) die();
include_once(ADODB_DIR.'/drivers/adodb-sqlite.inc.php');
class ADODB_sqlitepo extends ADODB_sqlite {
var $databaseType = 'sqlitepo';
function ADODB_sqlitepo()
{
$this->ADODB_sqlite();
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordset_sqlitepo extends ADORecordset_sqlite {
var $databaseType = 'sqlitepo';
function ADORecordset_sqlitepo($queryID,$mode=false)
{
$this->ADORecordset_sqlite($queryID,$mode);
}
// Modified to strip table names from returned fields
function _fetch($ignore_fields=false)
{
$this->fields = array();
$fields = @sqlite_fetch_array($this->_queryID,$this->fetchMode);
if(is_array($fields))
foreach($fields as $n => $v)
{
if(($p = strpos($n, ".")) !== false)
$n = substr($n, $p+1);
$this->fields[$n] = $v;
}
return !empty($this->fields);
}
}
?>

View File

@ -0,0 +1,408 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim. All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Sybase driver contributed by Toni (toni.tunkkari@finebyte.com)
- MSSQL date patch applied.
Date patch by Toni 15 Feb 2002
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB_sybase extends ADOConnection {
var $databaseType = "sybase";
//var $dataProvider = 'sybase';
var $replaceQuote = "''"; // string to use to replace quotes
var $fmtDate = "'Y-m-d'";
var $fmtTimeStamp = "'Y-m-d H:i:s'";
var $hasInsertID = true;
var $hasAffectedRows = true;
var $metaTablesSQL="select name from sysobjects where type='U' or type='V'";
// see http://sybooks.sybase.com/onlinebooks/group-aw/awg0800e/dbrfen8/@ebt-link;pt=5981;uf=0?target=0;window=new;showtoc=true;book=dbrfen8
var $metaColumnsSQL = "SELECT c.column_name, c.column_type, c.width FROM syscolumn c, systable t WHERE t.table_name='%s' AND c.table_id=t.table_id AND t.table_type='BASE'";
/*
"select c.name,t.name,c.length from
syscolumns c join systypes t on t.xusertype=c.xusertype join sysobjects o on o.id=c.id
where o.name='%s'";
*/
var $concat_operator = '+';
var $arrayClass = 'ADORecordSet_array_sybase';
var $sysDate = 'GetDate()';
var $leftOuter = '*=';
var $rightOuter = '=*';
function ADODB_sybase()
{
}
// might require begintrans -- committrans
function _insertid()
{
return $this->GetOne('select @@identity');
}
// might require begintrans -- committrans
function _affectedrows()
{
return $this->GetOne('select @@rowcount');
}
function BeginTrans()
{
if ($this->transOff) return true;
$this->transCnt += 1;
$this->Execute('BEGIN TRAN');
return true;
}
function CommitTrans($ok=true)
{
if ($this->transOff) return true;
if (!$ok) return $this->RollbackTrans();
$this->transCnt -= 1;
$this->Execute('COMMIT TRAN');
return true;
}
function RollbackTrans()
{
if ($this->transOff) return true;
$this->transCnt -= 1;
$this->Execute('ROLLBACK TRAN');
return true;
}
// http://www.isug.com/Sybase_FAQ/ASE/section6.1.html#6.1.4
function RowLock($tables,$where)
{
if (!$this->_hastrans) $this->BeginTrans();
$tables = str_replace(',',' HOLDLOCK,',$tables);
return $this->GetOne("select top 1 null as ignore from $tables HOLDLOCK where $where");
}
function SelectDB($dbName) {
$this->databaseName = $dbName;
if ($this->_connectionID) {
return @sybase_select_db($dbName);
}
else return false;
}
/* Returns: the last error message from previous database operation
Note: This function is NOT available for Microsoft SQL Server. */
function ErrorMsg()
{
if ($this->_logsql) return $this->_errorMsg;
$this->_errorMsg = sybase_get_last_message();
return $this->_errorMsg;
}
// returns true or false
function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (!function_exists('sybase_connect')) return null;
$this->_connectionID = sybase_connect($argHostname,$argUsername,$argPassword);
if ($this->_connectionID === false) return false;
if ($argDatabasename) return $this->SelectDB($argDatabasename);
return true;
}
// returns true or false
function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (!function_exists('sybase_connect')) return null;
$this->_connectionID = sybase_pconnect($argHostname,$argUsername,$argPassword);
if ($this->_connectionID === false) return false;
if ($argDatabasename) return $this->SelectDB($argDatabasename);
return true;
}
// returns query ID if successful, otherwise false
function _query($sql,$inputarr)
{
global $ADODB_COUNTRECS;
if ($ADODB_COUNTRECS == false && ADODB_PHPVER >= 0x4300)
return sybase_unbuffered_query($sql,$this->_connectionID);
else
return sybase_query($sql,$this->_connectionID);
}
// See http://www.isug.com/Sybase_FAQ/ASE/section6.2.html#6.2.12
function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs2cache=0)
{
if ($secs2cache > 0) {// we do not cache rowcount, so we have to load entire recordset
$rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
return $rs;
}
$cnt = ($nrows > 0) ? $nrows : 0;
if ($offset > 0 && $cnt) $cnt += $offset;
$this->Execute("set rowcount $cnt");
$rs =& ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,0);
$this->Execute("set rowcount 0");
return $rs;
}
// returns true or false
function _close()
{
return @sybase_close($this->_connectionID);
}
function UnixDate($v)
{
return ADORecordSet_array_sybase::UnixDate($v);
}
function UnixTimeStamp($v)
{
return ADORecordSet_array_sybase::UnixTimeStamp($v);
}
# Added 2003-10-05 by Chris Phillipson
# Used ASA SQL Reference Manual -- http://sybooks.sybase.com/onlinebooks/group-aw/awg0800e/dbrfen8/@ebt-link;pt=16756?target=%25N%15_12018_START_RESTART_N%25
# to convert similar Microsoft SQL*Server (mssql) API into Sybase compatible version
// Format date column in sql string given an input format that understands Y M D
function SQLDate($fmt, $col=false)
{
if (!$col) $col = $this->sysTimeStamp;
$s = '';
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
if ($s) $s .= '+';
$ch = $fmt[$i];
switch($ch) {
case 'Y':
case 'y':
$s .= "datename(yy,$col)";
break;
case 'M':
$s .= "convert(char(3),$col,0)";
break;
case 'm':
$s .= "replace(str(month($col),2),' ','0')";
break;
case 'Q':
case 'q':
$s .= "datename(qq,$col)";
break;
case 'D':
case 'd':
$s .= "replace(str(datepart(dd,$col),2),' ','0')";
break;
case 'h':
$s .= "substring(convert(char(14),$col,0),13,2)";
break;
case 'H':
$s .= "replace(str(datepart(hh,$col),2),' ','0')";
break;
case 'i':
$s .= "replace(str(datepart(mi,$col),2),' ','0')";
break;
case 's':
$s .= "replace(str(datepart(ss,$col),2),' ','0')";
break;
case 'a':
case 'A':
$s .= "substring(convert(char(19),$col,0),18,2)";
break;
default:
if ($ch == '\\') {
$i++;
$ch = substr($fmt,$i,1);
}
$s .= $this->qstr($ch);
break;
}
}
return $s;
}
# Added 2003-10-07 by Chris Phillipson
# Used ASA SQL Reference Manual -- http://sybooks.sybase.com/onlinebooks/group-aw/awg0800e/dbrfen8/@ebt-link;pt=5981;uf=0?target=0;window=new;showtoc=true;book=dbrfen8
# to convert similar Microsoft SQL*Server (mssql) API into Sybase compatible version
function MetaPrimaryKeys($table)
{
$sql = "SELECT c.column_name " .
"FROM syscolumn c, systable t " .
"WHERE t.table_name='$table' AND c.table_id=t.table_id " .
"AND t.table_type='BASE' " .
"AND c.pkey = 'Y' " .
"ORDER BY c.column_id";
$a = $this->GetCol($sql);
if ($a && sizeof($a)>0) return $a;
return false;
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
global $ADODB_sybase_mths;
$ADODB_sybase_mths = array(
'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,
'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
class ADORecordset_sybase extends ADORecordSet {
var $databaseType = "sybase";
var $canSeek = true;
// _mths works only in non-localised system
var $_mths = array('JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
function ADORecordset_sybase($id,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;
}
if (!$mode) $this->fetchMode = ADODB_FETCH_ASSOC;
else $this->fetchMode = $mode;
return $this->ADORecordSet($id,$mode);
}
/* Returns: an object containing field information.
Get column information in the Recordset object. fetchField() can be used in order to obtain information about
fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
fetchField() is retrieved. */
function &FetchField($fieldOffset = -1)
{
if ($fieldOffset != -1) {
$o = @sybase_fetch_field($this->_queryID, $fieldOffset);
}
else if ($fieldOffset == -1) { /* The $fieldOffset argument is not provided thus its -1 */
$o = @sybase_fetch_field($this->_queryID);
}
// older versions of PHP did not support type, only numeric
if ($o && !isset($o->type)) $o->type = ($o->numeric) ? 'float' : 'varchar';
return $o;
}
function _initrs()
{
global $ADODB_COUNTRECS;
$this->_numOfRows = ($ADODB_COUNTRECS)? @sybase_num_rows($this->_queryID):-1;
$this->_numOfFields = @sybase_num_fields($this->_queryID);
}
function _seek($row)
{
return @sybase_data_seek($this->_queryID, $row);
}
function _fetch($ignore_fields=false)
{
if ($this->fetchMode == ADODB_FETCH_NUM) {
$this->fields = @sybase_fetch_row($this->_queryID);
} else if ($this->fetchMode == ADODB_FETCH_ASSOC) {
$this->fields = @sybase_fetch_row($this->_queryID);
if (is_array($this->fields)) {
$this->fields = $this->GetRowAssoc(ADODB_ASSOC_CASE);
return true;
}
return false;
} else {
$this->fields = @sybase_fetch_array($this->_queryID);
}
if ( is_array($this->fields)) {
return true;
}
return false;
}
/* close() only needs to be called if you are worried about using too much memory while your script
is running. All associated result memory for the specified result identifier will automatically be freed. */
function _close() {
return @sybase_free_result($this->_queryID);
}
// sybase/mssql uses a default date like Dec 30 2000 12:00AM
function UnixDate($v)
{
return ADORecordSet_array_sybase::UnixDate($v);
}
function UnixTimeStamp($v)
{
return ADORecordSet_array_sybase::UnixTimeStamp($v);
}
}
class ADORecordSet_array_sybase extends ADORecordSet_array {
function ADORecordSet_array_sybase($id=-1)
{
$this->ADORecordSet_array($id);
}
// sybase/mssql uses a default date like Dec 30 2000 12:00AM
function UnixDate($v)
{
global $ADODB_sybase_mths;
//Dec 30 2000 12:00AM
if (!ereg( "([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})"
,$v, $rr)) return parent::UnixDate($v);
if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
$themth = substr(strtoupper($rr[1]),0,3);
$themth = $ADODB_sybase_mths[$themth];
if ($themth <= 0) return false;
// h-m-s-MM-DD-YY
return mktime(0,0,0,$themth,$rr[2],$rr[3]);
}
function UnixTimeStamp($v)
{
global $ADODB_sybase_mths;
//11.02.2001 Toni Tunkkari toni.tunkkari@finebyte.com
//Changed [0-9] to [0-9 ] in day conversion
if (!ereg( "([A-Za-z]{3})[-/\. ]([0-9 ]{1,2})[-/\. ]([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})"
,$v, $rr)) return parent::UnixTimeStamp($v);
if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
$themth = substr(strtoupper($rr[1]),0,3);
$themth = $ADODB_sybase_mths[$themth];
if ($themth <= 0) return false;
switch (strtoupper($rr[6])) {
case 'P':
if ($rr[4]<12) $rr[4] += 12;
break;
case 'A':
if ($rr[4]==12) $rr[4] = 0;
break;
default:
break;
}
// h-m-s-MM-DD-YY
return mktime($rr[4],$rr[5],0,$themth,$rr[2],$rr[3]);
}
}
?>

View File

@ -0,0 +1,106 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Microsoft Visual FoxPro data driver. Requires ODBC. Works only on MS Windows.
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
if (!defined('_ADODB_ODBC_LAYER')) {
include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
}
if (!defined('ADODB_VFP')){
define('ADODB_VFP',1);
class ADODB_vfp extends ADODB_odbc {
var $databaseType = "vfp";
var $fmtDate = "{^Y-m-d}";
var $fmtTimeStamp = "{^Y-m-d, h:i:sA}";
var $replaceQuote = "'+chr(39)+'" ;
var $true = '.T.';
var $false = '.F.';
var $hasTop = 'top'; // support mssql SELECT TOP 10 * FROM TABLE
var $_bindInputArray = false; // strangely enough, setting to true does not work reliably
var $sysTimeStamp = 'datetime()';
var $sysDate = 'date()';
var $ansiOuter = true;
var $hasTransactions = false;
var $curmode = SQL_CUR_USE_ODBC ; // See sqlext.h, SQL_CUR_DEFAULT == SQL_CUR_USE_DRIVER == 2L
function ADODB_vfp()
{
$this->ADODB_odbc();
}
function Time()
{
return time();
}
function BeginTrans() { return false;}
// quote string to be sent back to database
function qstr($s,$nofixquotes=false)
{
if (!$nofixquotes) return "'".str_replace("\r\n","'+chr(13)+'",str_replace("'",$this->replaceQuote,$s))."'";
return "'".$s."'";
}
// TOP requires ORDER BY for VFP
function &SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
{
$this->hasTop = preg_match('/ORDER[ \t\r\n]+BY/is',$sql) ? 'top' : false;
return ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
}
};
class ADORecordSet_vfp extends ADORecordSet_odbc {
var $databaseType = "vfp";
function ADORecordSet_vfp($id,$mode=false)
{
return $this->ADORecordSet_odbc($id,$mode);
}
function MetaType($t,$len=-1)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
switch (strtoupper($t)) {
case 'C':
if ($len <= $this->blobSize) return 'C';
case 'M':
return 'X';
case 'D': return 'D';
case 'T': return 'T';
case 'L': return 'L';
case 'I': return 'I';
default: return 'N';
}
}
}
} //define
?>

View File

@ -0,0 +1,436 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Martin Jansen <mj@php.net>
// | Richard Tango-Lowy <richtl@arscognita.com> |
// +----------------------------------------------------------------------+
//
// $Id$
//
require_once 'Auth/Container.php';
require_once 'adodb.inc.php';
require_once 'adodb-pear.inc.php';
require_once 'adodb-errorpear.inc.php';
/**
* Storage driver for fetching login data from a database using ADOdb-PHP.
*
* This storage driver can use all databases which are supported
* by the ADBdb DB abstraction layer to fetch login data.
* See http://php.weblogs.com/adodb for information on ADOdb.
* NOTE: The ADOdb directory MUST be in your PHP include_path!
*
* @author Richard Tango-Lowy <richtl@arscognita.com>
* @package Auth
* @version $Revision$
*/
class Auth_Container_ADOdb extends Auth_Container
{
/**
* Additional options for the storage container
* @var array
*/
var $options = array();
/**
* DB object
* @var object
*/
var $db = null;
var $dsn = '';
/**
* User that is currently selected from the DB.
* @var string
*/
var $activeUser = '';
// {{{ Constructor
/**
* Constructor of the container class
*
* Initate connection to the database via PEAR::ADOdb
*
* @param string Connection data or DB object
* @return object Returns an error object if something went wrong
*/
function Auth_Container_ADOdb($dsn)
{
$this->_setDefaults();
if (is_array($dsn)) {
$this->_parseOptions($dsn);
if (empty($this->options['dsn'])) {
PEAR::raiseError('No connection parameters specified!');
}
} else {
// Extract db_type from dsn string.
$this->options['dsn'] = $dsn;
$this->_parseDsn( $dsn );
}
}
// }}}
// {{{ _connect()
/**
* Connect to database by using the given DSN string
*
* @access private
* @param string DSN string
* @return mixed Object on error, otherwise bool
*/
function _connect($dsn)
{
if (is_string($dsn) || is_array($dsn)) {
if(!$this->db) {
$this->db = &ADONewConnection($this->options['db_type']);
if( $err = ADODB_Pear_error() ) {
return PEAR::raiseError($err);
}
}
$dbconnected = $this->db->Connect(
$this->options['db_host'],
$this->options['db_user'],
$this->options['db_pass'],
$this->options['db_name'] );
if( !$dbconnected ) {
PEAR::raiseError('Unable to connect to database' );
}
} else {
return PEAR::raiseError('The given dsn was not valid in file ' . __FILE__ . ' at line ' . __LINE__,
41,
PEAR_ERROR_RETURN,
null,
null
);
}
if(!$this->db) {
return PEAR::raiseError(ADODB_Pear_error());
} else {
return true;
}
}
// }}}
// {{{ _prepare()
/**
* Prepare database connection
*
* This function checks if we have already opened a connection to
* the database. If that's not the case, a new connection is opened.
*
* @access private
* @return mixed True or a DB error object.
*/
function _prepare()
{
if(!$this->db) {
$res = $this->_connect($this->options['dsn']);
}
return true;
}
// }}}
// {{{ query()
/**
* Prepare query to the database
*
* This function checks if we have already opened a connection to
* the database. If that's not the case, a new connection is opened.
* After that the query is passed to the database.
*
* @access public
* @param string Query string
* @return mixed a DB_result object or DB_OK on success, a DB
* or PEAR error on failure
*/
function query($query)
{
$err = $this->_prepare();
if ($err !== true) {
return $err;
}
return $this->db->query($query);
}
// }}}
// {{{ _setDefaults()
/**
* Set some default options
*
* @access private
* @return void
*/
function _setDefaults()
{
$this->options['db_type'] = 'mysql';
$this->options['table'] = 'auth';
$this->options['usernamecol'] = 'username';
$this->options['passwordcol'] = 'password';
$this->options['dsn'] = '';
$this->options['db_fields'] = '';
$this->options['cryptType'] = 'md5';
}
// }}}
// {{{ _parseOptions()
/**
* Parse options passed to the container class
*
* @access private
* @param array
*/
function _parseOptions($array)
{
foreach ($array as $key => $value) {
if (isset($this->options[$key])) {
$this->options[$key] = $value;
}
}
/* Include additional fields if they exist */
if(!empty($this->options['db_fields'])){
if(is_array($this->options['db_fields'])){
$this->options['db_fields'] = join($this->options['db_fields'], ', ');
}
$this->options['db_fields'] = ', '.$this->options['db_fields'];
}
}
// }}}
// {{{ fetchData()
/**
* Get user information from database
*
* This function uses the given username to fetch
* the corresponding login data from the database
* table. If an account that matches the passed username
* and password is found, the function returns true.
* Otherwise it returns false.
*
* @param string Username
* @param string Password
* @return mixed Error object or boolean
*/
function fetchData($username, $password)
{
// Prepare for a database query
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
// Find if db_fields contains a *, i so assume all col are selected
if(strstr($this->options['db_fields'], '*')){
$sql_from = "*";
}
else{
$sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields'];
}
$query = "SELECT ".$sql_from.
" FROM ".$this->options['table'].
" WHERE ".$this->options['usernamecol']." = " . $this->db->Quote($username);
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$rset = $this->db->Execute( $query );
$res = $rset->fetchRow();
if (DB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
}
if (!is_array($res)) {
$this->activeUser = '';
return false;
}
if ($this->verifyPassword(trim($password, "\r\n"),
trim($res[$this->options['passwordcol']], "\r\n"),
$this->options['cryptType'])) {
// Store additional field values in the session
foreach ($res as $key => $value) {
if ($key == $this->options['passwordcol'] ||
$key == $this->options['usernamecol']) {
continue;
}
// Use reference to the auth object if exists
// This is because the auth session variable can change so a static call to setAuthData does not make sence
if(is_object($this->_auth_obj)){
$this->_auth_obj->setAuthData($key, $value);
} else {
Auth::setAuthData($key, $value);
}
}
return true;
}
$this->activeUser = $res[$this->options['usernamecol']];
return false;
}
// }}}
// {{{ listUsers()
function listUsers()
{
$err = $this->_prepare();
if ($err !== true) {
return PEAR::raiseError($err->getMessage(), $err->getCode());
}
$retVal = array();
// Find if db_fileds contains a *, i so assume all col are selected
if(strstr($this->options['db_fields'], '*')){
$sql_from = "*";
}
else{
$sql_from = $this->options['usernamecol'] . ", ".$this->options['passwordcol'].$this->options['db_fields'];
}
$query = sprintf("SELECT %s FROM %s",
$sql_from,
$this->options['table']
);
$res = $this->db->getAll($query, null, DB_FETCHMODE_ASSOC);
if (DB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
} else {
foreach ($res as $user) {
$user['username'] = $user[$this->options['usernamecol']];
$retVal[] = $user;
}
}
return $retVal;
}
// }}}
// {{{ addUser()
/**
* Add user to the storage container
*
* @access public
* @param string Username
* @param string Password
* @param mixed Additional information that are stored in the DB
*
* @return mixed True on success, otherwise error object
*/
function addUser($username, $password, $additional = "")
{
if (function_exists($this->options['cryptType'])) {
$cryptFunction = $this->options['cryptType'];
} else {
$cryptFunction = 'md5';
}
$additional_key = '';
$additional_value = '';
if (is_array($additional)) {
foreach ($additional as $key => $value) {
$additional_key .= ', ' . $key;
$additional_value .= ", '" . $value . "'";
}
}
$query = sprintf("INSERT INTO %s (%s, %s%s) VALUES ('%s', '%s'%s)",
$this->options['table'],
$this->options['usernamecol'],
$this->options['passwordcol'],
$additional_key,
$username,
$cryptFunction($password),
$additional_value
);
$res = $this->query($query);
if (DB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
} else {
return true;
}
}
// }}}
// {{{ removeUser()
/**
* Remove user from the storage container
*
* @access public
* @param string Username
*
* @return mixed True on success, otherwise error object
*/
function removeUser($username)
{
$query = sprintf("DELETE FROM %s WHERE %s = '%s'",
$this->options['table'],
$this->options['usernamecol'],
$username
);
$res = $this->query($query);
if (DB::isError($res)) {
return PEAR::raiseError($res->getMessage(), $res->getCode());
} else {
return true;
}
}
// }}}
function _parseDsn( $dsn )
{
if( is_string( $dsn )) {
preg_match( '/^(\w*):\/\/(\w*)(:(\w*))?@(\w*)\/(\w*)$/', $dsn, $match );
$this->options['db_type'] = $match[1];
$this->options['db_user'] = $match[2];
$this->options['db_pass'] = $match[3];
$this->options['db_host'] = $match[5];
$this->options['db_name'] = $match[6];
}
}
}
function showDbg( $string ) {
print "<P>$string</P>";
}
function dump( $var, $str, $vardump = false ) {
print "<H4>$str</H4><pre>";
( !$vardump ) ? ( print_r( $var )) : ( var_dump( $var ));
print "</pre>";
}
?>

View File

@ -0,0 +1,102 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Library for basic performance monitoring and tuning
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
// Simple guide to configuring db2: so-so http://www.devx.com/gethelpon/10MinuteSolution/16575
// SELECT * FROM TABLE(SNAPSHOT_APPL('SAMPLE', -1)) as t
class perf_db2 extends adodb_perf{
var $createTableSQL = "CREATE TABLE adodb_logsql (
created TIMESTAMP NOT NULL,
sql0 varchar(250) NOT NULL,
sql1 varchar(4000) NOT NULL,
params varchar(3000) NOT NULL,
tracer varchar(500) NOT NULL,
timer decimal(16,6) NOT NULL
)";
var $settings = array(
'Ratios',
'data cache hit ratio' => array('RATIO',
"SELECT
case when sum(POOL_DATA_L_READS+POOL_INDEX_L_READS)=0 then 0
else 100*(1-sum(POOL_DATA_P_READS+POOL_INDEX_P_READS)/sum(POOL_DATA_L_READS+POOL_INDEX_L_READS)) end
FROM TABLE(SNAPSHOT_APPL('',-2)) as t",
'=WarnCacheRatio'),
'Data Cache',
'data cache buffers' => array('DATAC',
'select sum(npages) from SYSCAT.BUFFERPOOLS',
'See <a href=http://www7b.boulder.ibm.com/dmdd/library/techarticle/anshum/0107anshum.html#bufferpoolsize>tuning reference</a>.' ),
'cache blocksize' => array('DATAC',
'select avg(pagesize) from SYSCAT.BUFFERPOOLS',
'' ),
'data cache size' => array('DATAC',
'select sum(npages*pagesize) from SYSCAT.BUFFERPOOLS',
'' ),
'Connections',
'current connections' => array('SESS',
"SELECT count(*) FROM TABLE(SNAPSHOT_APPL_INFO('',-2)) as t",
''),
false
);
function perf_db2(&$conn)
{
$this->conn =& $conn;
}
function Explain($sql,$partial=false)
{
$save = $this->conn->LogSQL(false);
if ($partial) {
$sqlq = $this->conn->qstr($sql.'%');
$arr = $this->conn->GetArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq");
if ($arr) {
foreach($arr as $row) {
$sql = reset($row);
if (crc32($sql) == $partial) break;
}
}
}
$qno = rand();
$ok = $this->conn->Execute("EXPLAIN PLAN SET QUERYNO=$qno FOR $sql");
ob_start();
if (!$ok) echo "<p>Have EXPLAIN tables been created?</p>";
else {
$rs = $this->conn->Execute("select * from explain_statement where queryno=$qno");
if ($rs) rs2html($rs);
}
$s = ob_get_contents();
ob_end_clean();
$this->conn->LogSQL($save);
$s .= $this->Tracer($sql);
return $s;
}
function Tables()
{
$rs = $this->conn->Execute("select tabschema,tabname,card as rows,
npages pages_used,fpages pages_allocated, tbspace tablespace
from syscat.tables where tabschema not in ('SYSCAT','SYSIBM','SYSSTAT') order by 1,2");
return rs2html($rs,false,false,false,false);
}
}
?>

View File

@ -0,0 +1,70 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Library for basic performance monitoring and tuning
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
//
// Thx to Fernando Ortiz, mailto:fortiz#lacorona.com.mx
// With info taken from http://www.oninit.com/oninit/sysmaster/index.html
//
class perf_informix extends adodb_perf{
// Maximum size on varchar upto 9.30 255 chars
// better truncate varchar to 255 than char(4000) ?
var $createTableSQL = "CREATE TABLE adodb_logsql (
created datetime year to second NOT NULL,
sql0 varchar(250) NOT NULL,
sql1 varchar(255) NOT NULL,
params varchar(255) NOT NULL,
tracer varchar(255) NOT NULL,
timer decimal(16,6) NOT NULL
)";
var $tablesSQL = "select a.tabname tablename, ti_nptotal*2 size_in_k, ti_nextns extents, ti_nrows records from systables c, sysmaster:systabnames a, sysmaster:systabinfo b where c.tabname not matches 'sys*' and c.partnum = a.partnum and c.partnum = b.ti_partnum";
var $settings = array(
'Ratios',
'data cache hit ratio' => array('RATIOH',
"select round((1-(wt.value / (rd.value + wr.value)))*100,2)
from sysmaster:sysprofile wr, sysmaster:sysprofile rd, sysmaster:sysprofile wt
where rd.name = 'pagreads' and
wr.name = 'pagwrites' and
wt.name = 'buffwts'",
'=WarnCacheRatio'),
'IO',
'data reads' => array('IO',
"select value from sysmaster:sysprofile where name='pagreads'",
'Page reads'),
'data writes' => array('IO',
"select value from sysmaster:sysprofile where name='pagwrites'",
'Page writes'),
'Connections',
'current connections' => array('SESS',
'select count(*) from sysmaster:syssessions',
'Number of sessions'),
false
);
function perf_informix(&$conn)
{
$this->conn =& $conn;
}
}
?>

View File

@ -0,0 +1,164 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Library for basic performance monitoring and tuning
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
/*
MSSQL has moved most performance info to Performance Monitor
*/
class perf_mssql extends adodb_perf{
var $sql1 = 'cast(sql1 as text)';
var $createTableSQL = "CREATE TABLE adodb_logsql (
created datetime NOT NULL,
sql0 varchar(250) NOT NULL,
sql1 varchar(4000) NOT NULL,
params varchar(3000) NOT NULL,
tracer varchar(500) NOT NULL,
timer decimal(16,6) NOT NULL
)";
var $settings = array(
'Ratios',
'data cache hit ratio' => array('RATIO',
"select round((a.cntr_value*100.0)/b.cntr_value,2) from master.dbo.sysperfinfo a, master.dbo.sysperfinfo b where a.counter_name = 'Buffer cache hit ratio' and b.counter_name='Buffer cache hit ratio base'",
'=WarnCacheRatio'),
'prepared sql hit ratio' => array('RATIO',
array('dbcc cachestats','Prepared',1,100),
''),
'adhoc sql hit ratio' => array('RATIO',
array('dbcc cachestats','Adhoc',1,100),
''),
'IO',
'data reads' => array('IO',
"select cntr_value from master.dbo.sysperfinfo where counter_name = 'Page reads/sec'"),
'data writes' => array('IO',
"select cntr_value from master.dbo.sysperfinfo where counter_name = 'Page writes/sec'"),
'Data Cache',
'data cache size' => array('DATAC',
"select cntr_value*8192 from master.dbo.sysperfinfo where counter_name = 'Total Pages' and object_name='SQLServer:Buffer Manager'",
'' ),
'data cache blocksize' => array('DATAC',
"select 8192",'page size'),
'Connections',
'current connections' => array('SESS',
'=sp_who',
''),
'max connections' => array('SESS',
"SELECT @@MAX_CONNECTIONS",
''),
false
);
function perf_mssql(&$conn)
{
if ($conn->dataProvider == 'odbc') {
$this->sql1 = 'sql1';
//$this->explain = false;
}
$this->conn =& $conn;
}
function Explain($sql,$partial=false)
{
$save = $this->conn->LogSQL(false);
if ($partial) {
$sqlq = $this->conn->qstr($sql.'%');
$arr = $this->conn->GetArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq");
if ($arr) {
foreach($arr as $row) {
$sql = reset($row);
if (crc32($sql) == $partial) break;
}
}
}
$s = '<p><b>Explain</b>: '.htmlspecialchars($sql).'</p>';
$this->conn->Execute("SET SHOWPLAN_ALL ON;");
$sql = str_replace('?',"''",$sql);
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs =& $this->conn->Execute($sql);
//adodb_printr($rs);
$ADODB_FETCH_MODE = $save;
if ($rs) {
$rs->MoveNext();
$s .= '<table bgcolor=white border=0 cellpadding="1" callspacing=0><tr><td nowrap align=center> Rows<td nowrap align=center> IO<td nowrap align=center> CPU<td align=left> &nbsp; &nbsp; Plan</tr>';
while (!$rs->EOF) {
$s .= '<tr><td>'.round($rs->fields[8],1).'<td>'.round($rs->fields[9],3).'<td align=right>'.round($rs->fields[10],3).'<td nowrap><pre>'.htmlspecialchars($rs->fields[0])."</td></pre></tr>\n"; ## NOTE CORRUPT </td></pre> tag is intentional!!!!
$rs->MoveNext();
}
$s .= '</table>';
$rs->NextRecordSet();
}
$this->conn->Execute("SET SHOWPLAN_ALL OFF;");
$this->conn->LogSQL($save);
$s .= $this->Tracer($sql);
return $s;
}
function Tables()
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
//$this->conn->debug=1;
$s = '<table border=1 bgcolor=white><tr><td><b>tablename</b></td><td><b>size_in_k</b></td><td><b>index size</b></td><td><b>reserved size</b></td></tr>';
$rs1 = $this->conn->Execute("select distinct name from sysobjects where xtype='U'");
if ($rs1) {
while (!$rs1->EOF) {
$tab = $rs1->fields[0];
$tabq = $this->conn->qstr($tab);
$rs2 = $this->conn->Execute("sp_spaceused $tabq");
if ($rs2) {
$s .= '<tr><td>'.$tab.'</td><td align=right>'.$rs2->fields[3].'</td><td align=right>'.$rs2->fields[4].'</td><td align=right>'.$rs2->fields[2].'</td></tr>';
$rs2->Close();
}
$rs1->MoveNext();
}
$rs1->Close();
}
$ADODB_FETCH_MODE = $save;
return $s.'</table>';
}
function sp_who()
{
$arr = $this->conn->GetArray('sp_who');
return sizeof($arr);
}
function HealthCheck($cli=false)
{
$this->conn->Execute('dbcc traceon(3604)');
$html = adodb_perf::HealthCheck($cli);
$this->conn->Execute('dbcc traceoff(3604)');
return $html;
}
}
?>

View File

@ -0,0 +1,259 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Library for basic performance monitoring and tuning
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class perf_mysql extends adodb_perf{
var $tablesSQL = 'show table status';
var $createTableSQL = "CREATE TABLE adodb_logsql (
created datetime NOT NULL,
sql0 varchar(250) NOT NULL,
sql1 text NOT NULL,
params text NOT NULL,
tracer text NOT NULL,
timer decimal(16,6) NOT NULL
)";
var $settings = array(
'Ratios',
'MyISAM cache hit ratio' => array('RATIO',
'=GetKeyHitRatio',
'=WarnCacheRatio'),
'InnoDB cache hit ratio' => array('RATIO',
'=GetInnoDBHitRatio',
'=WarnCacheRatio'),
'data cache hit ratio' => array('HIDE', # only if called
'=FindDBHitRatio',
'=WarnCacheRatio'),
'sql cache hit ratio' => array('RATIO',
'=GetQHitRatio',
''),
'IO',
'data reads' => array('IO',
'=GetReads',
'Number of selects (Key_reads is not accurate)'),
'data writes' => array('IO',
'=GetWrites',
'Number of inserts/updates/deletes * coef (Key_writes is not accurate)'),
'Data Cache',
'MyISAM data cache size' => array('DATAC',
array("show variables", 'key_buffer_size'),
'' ),
'BDB data cache size' => array('DATAC',
array("show variables", 'bdb_cache_size'),
'' ),
'InnoDB data cache size' => array('DATAC',
array("show variables", 'innodb_buffer_pool_size'),
'' ),
'Memory Usage',
'read buffer size' => array('CACHE',
array("show variables", 'read_buffer_size'),
'(per session)'),
'sort buffer size' => array('CACHE',
array("show variables", 'sort_buffer_size'),
'Size of sort buffer (per session)' ),
'table cache' => array('CACHE',
array("show variables", 'table_cache'),
'Number of tables to keep open'),
'Connections',
'current connections' => array('SESS',
array('show status','Threads_connected'),
''),
'max connections' => array( 'SESS',
array("show variables",'max_connections'),
''),
false
);
function perf_mysql(&$conn)
{
$this->conn =& $conn;
}
function Explain($sql,$partial=false)
{
if (strtoupper(substr(trim($sql),0,6)) !== 'SELECT') return '<p>Unable to EXPLAIN non-select statement</p>';
$save = $this->conn->LogSQL(false);
if ($partial) {
$sqlq = $this->conn->qstr($sql.'%');
$arr = $this->conn->GetArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq");
if ($arr) {
foreach($arr as $row) {
$sql = reset($row);
if (crc32($sql) == $partial) break;
}
}
}
$sql = str_replace('?',"''",$sql);
if ($partial) {
$sqlq = $this->conn->qstr($sql.'%');
$sql = $this->conn->GetOne("select sql1 from adodb_logsql where sql1 like $sqlq");
}
$s = '<p><b>Explain</b>: '.htmlspecialchars($sql).'</p>';
$rs = $this->conn->Execute('EXPLAIN '.$sql);
$s .= rs2html($rs,false,false,false,false);
$this->conn->LogSQL($save);
$s .= $this->Tracer($sql);
return $s;
}
function Tables()
{
if (!$this->tablesSQL) return false;
$rs = $this->conn->Execute($this->tablesSQL);
if (!$rs) return false;
$html = rs2html($rs,false,false,false,false);
return $html;
}
function GetReads()
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->conn->Execute('show status');
$ADODB_FETCH_MODE = $save;
if (!$rs) return 0;
$val = 0;
while (!$rs->EOF) {
switch($rs->fields[0]) {
case 'Com_select':
$val = $rs->fields[1];
$rs->Close();
return $val;
}
$rs->MoveNext();
}
$rs->Close();
return $val;
}
function GetWrites()
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
$rs = $this->conn->Execute('show status');
$ADODB_FETCH_MODE = $save;
if (!$rs) return 0;
$val = 0.0;
while (!$rs->EOF) {
switch($rs->fields[0]) {
case 'Com_insert':
$val += $rs->fields[1]; break;
case 'Com_delete':
$val += $rs->fields[1]; break;
case 'Com_update':
$val += $rs->fields[1]/2;
$rs->Close();
return $val;
}
$rs->MoveNext();
}
$rs->Close();
return $val;
}
function FindDBHitRatio()
{
// first find out type of table
//$this->conn->debug=1;
$rs = $this->conn->Execute('show table status');
if (!$rs) return '';
$type = strtoupper($rs->fields[1]);
$rs->Close();
switch($type){
case 'MYISAM':
case 'ISAM':
return $this->DBParameter('MyISAM cache hit ratio').' (MyISAM)';
case 'INNODB':
return $this->DBParameter('InnoDB cache hit ratio').' (InnoDB)';
default:
return $type.' not supported';
}
}
function GetQHitRatio()
{
//Total number of queries = Qcache_inserts + Qcache_hits + Qcache_not_cached
$hits = $this->_DBParameter(array("show status","Qcache_hits"));
$total = $this->_DBParameter(array("show status","Qcache_inserts"));
$total += $this->_DBParameter(array("show status","Qcache_not_cached"));
$total += $hits;
if ($total) return ($hits*100)/$total;
return 0;
}
/*
Use session variable to store Hit percentage, because MySQL
does not remember last value of SHOW INNODB STATUS hit ratio
# 1st query to SHOW INNODB STATUS
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000
# 2nd query to SHOW INNODB STATUS
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool activity since the last printout
*/
function GetInnoDBHitRatio()
{
global $HTTP_SESSION_VARS;
$rs = $this->conn->Execute('show innodb status');
if (!$rs || $rs->EOF) return 0;
$stat = $rs->fields[0];
$rs->Close();
$at = strpos($stat,'Buffer pool hit rate');
$stat = substr($stat,$at,200);
if (preg_match('!Buffer pool hit rate\s*([0-9]*) / ([0-9]*)!',$stat,$arr)) {
$val = 100*$arr[1]/$arr[2];
$HTTP_SESSION_VARS['INNODB_HIT_PCT'] = $val;
return $val;
} else {
if (isset($HTTP_SESSION_VARS['INNODB_HIT_PCT'])) return $HTTP_SESSION_VARS['INNODB_HIT_PCT'];
return 0;
}
return 0;
}
function GetKeyHitRatio()
{
$hits = $this->_DBParameter(array("show status","Key_read_requests"));
$reqs = $this->_DBParameter(array("show status","Key_reads"));
if ($reqs == 0) return 0;
return ($hits/($reqs+$hits))*100;
}
}
?>

View File

@ -0,0 +1,499 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Library for basic performance monitoring and tuning
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
class perf_oci8 extends ADODB_perf{
var $tablesSQL = "select segment_name as \"tablename\", sum(bytes)/1024 as \"size_in_k\",tablespace_name as \"tablespace\",count(*) \"extents\" from sys.user_extents
group by segment_name,tablespace_name";
var $version;
var $createTableSQL = "CREATE TABLE adodb_logsql (
created date NOT NULL,
sql0 varchar(250) NOT NULL,
sql1 varchar(4000) NOT NULL,
params varchar(4000),
tracer varchar(4000),
timer decimal(16,6) NOT NULL
)";
var $settings = array(
'Ratios',
'data cache hit ratio' => array('RATIOH',
"select round((1-(phy.value / (cur.value + con.value)))*100,2)
from v\$sysstat cur, v\$sysstat con, v\$sysstat phy
where cur.name = 'db block gets' and
con.name = 'consistent gets' and
phy.name = 'physical reads'",
'=WarnCacheRatio'),
'sql cache hit ratio' => array( 'RATIOH',
'select round(100*(sum(pins)-sum(reloads))/sum(pins),2) from v$librarycache',
'increase <i>shared_pool_size</i> if too ratio low'),
'datadict cache hit ratio' => array('RATIOH',
"select
round((1 - (sum(getmisses) / (sum(gets) +
sum(getmisses))))*100,2)
from v\$rowcache",
'increase <i>shared_pool_size</i> if too ratio low'),
'memory sort ratio' => array('RATIOH',
"SELECT ROUND((100 * b.VALUE) /DECODE ((a.VALUE + b.VALUE),
0,1,(a.VALUE + b.VALUE)),2)
FROM v\$sysstat a,
v\$sysstat b
WHERE a.name = 'sorts (disk)'
AND b.name = 'sorts (memory)'",
"% of memory sorts compared to disk sorts - should be over 95%"),
'IO',
'data reads' => array('IO',
"select value from v\$sysstat where name='physical reads'"),
'data writes' => array('IO',
"select value from v\$sysstat where name='physical writes'"),
'Data Cache',
'data cache buffers' => array( 'DATAC',
"select a.value/b.value from v\$parameter a, v\$parameter b
where a.name = 'db_cache_size' and b.name= 'db_block_size'",
'Number of cache buffers. Tune <i>db_cache_size</i> if the <i>data cache hit ratio</i> is too low.'),
'data cache blocksize' => array('DATAC',
"select value from v\$parameter where name='db_block_size'",
'' ),
'Memory Pools',
'data cache size' => array('DATAC',
"select value from v\$parameter where name = 'db_cache_size'",
'db_cache_size' ),
'shared pool size' => array('DATAC',
"select value from v\$parameter where name = 'shared_pool_size'",
'shared_pool_size, which holds shared sql, stored procedures, dict cache and similar shared structs' ),
'java pool size' => array('DATAJ',
"select value from v\$parameter where name = 'java_pool_size'",
'java_pool_size' ),
'large pool buffer size' => array('CACHE',
"select value from v\$parameter where name='large_pool_size'",
'this pool is for large mem allocations (not because it is larger than shared pool), for MTS sessions, parallel queries, io buffers (large_pool_size) ' ),
'pga buffer size' => array('CACHE',
"select value from v\$parameter where name='pga_aggregate_target'",
'program global area is private memory for sorting, and hash and bitmap merges - since oracle 9i (pga_aggregate_target)' ),
'Connections',
'current connections' => array('SESS',
'select count(*) from sys.v_$session where username is not null',
''),
'max connections' => array( 'SESS',
"select value from v\$parameter where name='sessions'",
''),
'Memory Utilization',
'data cache utilization ratio' => array('RATIOU',
"select round((1-bytes/sgasize)*100, 2)
from (select sum(bytes) sgasize from sys.v_\$sgastat) s, sys.v_\$sgastat f
where name = 'free memory' and pool = 'shared pool'",
'Percentage of data cache actually in use - should be over 85%'),
'shared pool utilization ratio' => array('RATIOU',
'select round((sga.bytes/p.value)*100,2)
from v$sgastat sga, v$parameter p
where sga.name = \'free memory\' and sga.pool = \'shared pool\'
and p.name = \'shared_pool_size\'',
'Percentage of shared pool actually used - too low is bad, too high is worse'),
'large pool utilization ratio' => array('RATIOU',
"select round((1-bytes/sgasize)*100, 2)
from (select sum(bytes) sgasize from sys.v_\$sgastat) s, sys.v_\$sgastat f
where name = 'free memory' and pool = 'large pool'",
'Percentage of large_pool actually in use - too low is bad, too high is worse'),
'sort buffer size' => array('CACHE',
"select value from v\$parameter where name='sort_area_size'",
'max in-mem sort_area_size (per query), uses memory in pga' ),
'pga usage at peak' => array('RATIOU',
'=PGA','Mb utilization at peak transactions (requires Oracle 9i+)'),
'Transactions',
'rollback segments' => array('ROLLBACK',
"select count(*) from sys.v_\$rollstat",
''),
'peak transactions' => array('ROLLBACK',
"select max_utilization tx_hwm
from sys.v_\$resource_limit
where resource_name = 'transactions'",
'Taken from high-water-mark'),
'max transactions' => array('ROLLBACK',
"select value from v\$parameter where name = 'transactions'",
'max transactions / rollback segments < 3.5 (or transactions_per_rollback_segment)'),
'Parameters',
'cursor sharing' => array('CURSOR',
"select value from v\$parameter where name = 'cursor_sharing'",
'Cursor reuse strategy. Recommended is FORCE (8i+) or SIMILAR (9i+). See <a href=http://www.praetoriate.com/oracle_tips_cursor_sharing.htm>cursor_sharing</a>.'),
/*
'cursor reuse' => array('CURSOR',
"select count(*) from (select sql_text_wo_constants, count(*)
from t1
group by sql_text_wo_constants
having count(*) > 100)",'These are sql statements that should be using bind variables'),*/
'index cache cost' => array('COST',
"select value from v\$parameter where name = 'optimizer_index_caching'",
'=WarnIndexCost'),
'random page cost' => array('COST',
"select value from v\$parameter where name = 'optimizer_index_cost_adj'",
'=WarnPageCost'),
false
);
function perf_oci8(&$conn)
{
$savelog = $conn->LogSQL(false);
$this->version = $conn->ServerInfo();
$conn->LogSQL($savelog);
$this->conn =& $conn;
}
function WarnPageCost($val)
{
if ($val == 100) $s = '<font color=red><b>Too High</b>. </font>';
else $s = '';
return $s.'Recommended is 20-50 for TP, and 50 for data warehouses. Default is 100. See <a href=http://www.dba-oracle.com/oracle_tips_cost_adj.htm>optimizer_index_cost_adj</a>. ';
}
function WarnIndexCost($val)
{
if ($val == 0) $s = '<font color=red><b>Too Low</b>. </font>';
else $s = '';
return $s.'Percentage of indexed data blocks expected in the cache.
Recommended is 20 (fast disk array) to 50 (slower hard disks). Default is 0.
See <a href=http://www.dba-oracle.com/oracle_tips_cbo_part1.htm>optimizer_index_caching</a>.';
}
function PGA()
{
if ($this->version['version'] < 9) return 'Oracle 9i or later required';
$rs = $this->conn->Execute("select a.mb,a.targ as pga_size_pct,a.pct from
(select round(pga_target_for_estimate/1024.0/1024.0,0) Mb,
pga_target_factor targ,estd_pga_cache_hit_percentage pct,rownum as r
from v\$pga_target_advice) a left join
(select round(pga_target_for_estimate/1024.0/1024.0,0) Mb,
pga_target_factor targ,estd_pga_cache_hit_percentage pct,rownum as r
from v\$pga_target_advice) b on
a.r = b.r+1 where
b.pct < 100");
if (!$rs) return "Only in 9i or later";
$rs->Close();
if ($rs->EOF) return "PGA could be too big";
return reset($rs->fields);
}
function Explain($sql,$partial=false)
{
$savelog = $this->conn->LogSQL(false);
$rs =& $this->conn->SelectLimit("select ID FROM PLAN_TABLE");
if (!$rs) {
echo "<p><b>Missing PLAN_TABLE</b></p>
<pre>
CREATE TABLE PLAN_TABLE (
STATEMENT_ID VARCHAR2(30),
TIMESTAMP DATE,
REMARKS VARCHAR2(80),
OPERATION VARCHAR2(30),
OPTIONS VARCHAR2(30),
OBJECT_NODE VARCHAR2(128),
OBJECT_OWNER VARCHAR2(30),
OBJECT_NAME VARCHAR2(30),
OBJECT_INSTANCE NUMBER(38),
OBJECT_TYPE VARCHAR2(30),
OPTIMIZER VARCHAR2(255),
SEARCH_COLUMNS NUMBER,
ID NUMBER(38),
PARENT_ID NUMBER(38),
POSITION NUMBER(38),
COST NUMBER(38),
CARDINALITY NUMBER(38),
BYTES NUMBER(38),
OTHER_TAG VARCHAR2(255),
PARTITION_START VARCHAR2(255),
PARTITION_STOP VARCHAR2(255),
PARTITION_ID NUMBER(38),
OTHER LONG,
DISTRIBUTION VARCHAR2(30)
);
</pre>";
return false;
}
$rs->Close();
// $this->conn->debug=1;
if ($partial) {
$sqlq = $this->conn->qstr($sql.'%');
$arr = $this->conn->GetArray("select distinct distinct sql1 from adodb_logsql where sql1 like $sqlq");
if ($arr) {
foreach($arr as $row) {
$sql = reset($row);
if (crc32($sql) == $partial) break;
}
}
}
$s = "<p><b>Explain</b>: ".htmlspecialchars($sql)."</p>";
$this->conn->BeginTrans();
$id = "ADODB ".microtime();
$rs =& $this->conn->Execute("EXPLAIN PLAN SET STATEMENT_ID='$id' FOR $sql");
$m = $this->conn->ErrorMsg();
if ($m) {
$this->conn->RollbackTrans();
$this->conn->LogSQL($savelog);
$s .= "<p>$m</p>";
return $s;
}
$rs = $this->conn->Execute("
select
'<pre>'||lpad('--', (level-1)*2,'-') || trim(operation) || ' ' || trim(options)||'</pre>' as Operation,
object_name,COST,CARDINALITY,bytes
FROM plan_table
START WITH id = 0 and STATEMENT_ID='$id'
CONNECT BY prior id=parent_id and statement_id='$id'");
$s .= rs2html($rs,false,false,false,false);
$this->conn->RollbackTrans();
$this->conn->LogSQL($savelog);
$s .= $this->Tracer($sql,$partial);
return $s;
}
function CheckMemory()
{
if ($this->version['version'] < 9) return 'Oracle 9i or later required';
$rs =& $this->conn->Execute("
select a.size_for_estimate as cache_mb_estimate,
case when a.size_factor=1 then
'&lt;&lt;= current'
when a.estd_physical_read_factor-b.estd_physical_read_factor > 0 and a.estd_physical_read_factor<1 then
'- BETTER - '
else ' ' end as currsize,
a.estd_physical_read_factor-b.estd_physical_read_factor as best_when_0
from (select size_for_estimate,size_factor,estd_physical_read_factor,rownum r from v\$db_cache_advice) a ,
(select size_for_estimate,size_factor,estd_physical_read_factor,rownum r from v\$db_cache_advice) b where a.r = b.r-1");
if (!$rs) return false;
/*
The v$db_cache_advice utility show the marginal changes in physical data block reads for different sizes of db_cache_size
*/
$s = "<h3>Data Cache Estimate</h3>";
if ($rs->EOF) {
$s .= "<p>Cache that is 50% of current size is still too big</p>";
} else {
$s .= "Ideal size of Data Cache is when \"best_when_0\" changes from a positive number and becomes zero.";
$s .= rs2html($rs,false,false,false,false);
}
return $s;
}
/*
Generate html for suspicious/expensive sql
*/
function tohtml(&$rs,$type)
{
$o1 = $rs->FetchField(0);
$o2 = $rs->FetchField(1);
$o3 = $rs->FetchField(2);
if ($rs->EOF) return '<p>None found</p>';
$check = '';
$sql = '';
$s = "\n\n<table border=1 bgcolor=white><tr><td><b>".$o1->name.'</b></td><td><b>'.$o2->name.'</b></td><td><b>'.$o3->name.'</b></td></tr>';
while (!$rs->EOF) {
if ($check != $rs->fields[0].'::'.$rs->fields[1]) {
if ($check) {
$carr = explode('::',$check);
$prefix = "<a href=\"?$type=1&sql=".rawurlencode($sql).'&x#explain">';
$suffix = '</a>';
if (strlen($prefix)>2000) {
$prefix = '';
$suffix = '';
}
$s .= "\n<tr><td align=right>".$carr[0].'</td><td align=right>'.$carr[1].'</td><td>'.$prefix.$sql.$suffix.'</td></tr>';
}
$sql = $rs->fields[2];
$check = $rs->fields[0].'::'.$rs->fields[1];
} else
$sql .= $rs->fields[2];
$rs->MoveNext();
}
$rs->Close();
$carr = explode('::',$check);
$prefix = "<a target=".rand()." href=\"?&hidem=1&$type=1&sql=".rawurlencode($sql).'&x#explain">';
$suffix = '</a>';
if (strlen($prefix)>2000) {
$prefix = '';
$suffix = '';
}
$s .= "\n<tr><td align=right>".$carr[0].'</td><td align=right>'.$carr[1].'</td><td>'.$prefix.$sql.$suffix.'</td></tr>';
return $s."</table>\n\n";
}
// code thanks to Ixora.
// http://www.ixora.com.au/scripts/query_opt.htm
// requires oracle 8.1.7 or later
function SuspiciousSQL($numsql=10)
{
$sql = "
select
substr(to_char(s.pct, '99.00'), 2) || '%' load,
s.executions executes,
p.sql_text
from
(
select
address,
buffer_gets,
executions,
pct,
rank() over (order by buffer_gets desc) ranking
from
(
select
address,
buffer_gets,
executions,
100 * ratio_to_report(buffer_gets) over () pct
from
sys.v_\$sql
where
command_type != 47 and module != 'T.O.A.D.'
)
where
buffer_gets > 50 * executions
) s,
sys.v_\$sqltext p
where
s.ranking <= $numsql and
p.address = s.address
order by
1 desc, s.address, p.piece";
global $ADODB_CACHE_MODE,$HTTP_GET_VARS;
if (isset($HTTP_GET_VARS['expsixora']) && isset($HTTP_GET_VARS['sql'])) {
$partial = empty($HTTP_GET_VARS['part']);
echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'],$partial)."\n";
}
if (isset($HTTP_GET_VARS['sql'])) return $this->_SuspiciousSQL();
$save = $ADODB_CACHE_MODE;
$ADODB_CACHE_MODE = ADODB_FETCH_NUM;
$savelog = $this->conn->LogSQL(false);
$rs =& $this->conn->SelectLimit($sql);
$this->conn->LogSQL($savelog);
$ADODB_CACHE_MODE = $save;
if ($rs) {
$s = "\n<h3>Ixora Suspicious SQL</h3>";
$s .= $this->tohtml($rs,'expsixora');
} else
$s = '';
if ($s) $s .= '<p>';
$s .= $this->_SuspiciousSQL();
return $s;
}
// code thanks to Ixora.
// http://www.ixora.com.au/scripts/query_opt.htm
// requires oracle 8.1.7 or later
function ExpensiveSQL($numsql = 10)
{
$sql = "
select
substr(to_char(s.pct, '99.00'), 2) || '%' load,
s.executions executes,
p.sql_text
from
(
select
address,
disk_reads,
executions,
pct,
rank() over (order by disk_reads desc) ranking
from
(
select
address,
disk_reads,
executions,
100 * ratio_to_report(disk_reads) over () pct
from
sys.v_\$sql
where
command_type != 47 and module != 'T.O.A.D.'
)
where
disk_reads > 50 * executions
) s,
sys.v_\$sqltext p
where
s.ranking <= $numsql and
p.address = s.address
order by
1 desc, s.address, p.piece
";
global $ADODB_CACHE_MODE,$HTTP_GET_VARS;
if (isset($HTTP_GET_VARS['expeixora']) && isset($HTTP_GET_VARS['sql'])) {
$partial = empty($HTTP_GET_VARS['part']);
echo "<a name=explain></a>".$this->Explain($HTTP_GET_VARS['sql'],$partial)."\n";
}
if (isset($HTTP_GET_VARS['sql'])) {
$var =& $this->_ExpensiveSQL();
return $var;
}
$save = $ADODB_CACHE_MODE;
$ADODB_CACHE_MODE = ADODB_FETCH_NUM;
$savelog = $this->conn->LogSQL(false);
$rs =& $this->conn->Execute($sql);
$this->conn->LogSQL($savelog);
$ADODB_CACHE_MODE = $save;
if ($rs) {
$s = "\n<h3>Ixora Expensive SQL</h3>";
$s .= $this->tohtml($rs,'expeixora');
} else
$s = '';
if ($s) $s .= '<p>';
$s .= $this->_ExpensiveSQL();
return $s;
}
}
?>

View File

@ -0,0 +1,123 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
Library for basic performance monitoring and tuning
*/
// security - hide paths
if (!defined('ADODB_DIR')) die();
/*
Notice that PostgreSQL has no sql query cache
*/
class perf_postgres extends adodb_perf{
var $tablesSQL =
"select a.relname as tablename,(a.relpages+CASE WHEN b.relpages is null THEN 0 ELSE b.relpages END+CASE WHEN c.relpages is null THEN 0 ELSE c.relpages END)*8 as size_in_K,a.relfilenode as \"OID\" from pg_class a left join pg_class b
on b.relname = 'pg_toast_'||trim(a.relfilenode)
left join pg_class c on c.relname = 'pg_toast_'||trim(a.relfilenode)||'_index'
where a.relname in (select tablename from pg_tables where tablename not like 'pg_%')";
var $createTableSQL = "CREATE TABLE adodb_logsql (
created timestamp NOT NULL,
sql0 varchar(250) NOT NULL,
sql1 text NOT NULL,
params text NOT NULL,
tracer text NOT NULL,
timer decimal(16,6) NOT NULL
)";
var $settings = array(
'Ratios',
'statistics collector' => array('RATIO',
"select case when count(*)=3 then 'TRUE' else 'FALSE' end from pg_settings where (name='stats_block_level' or name='stats_row_level' or name='stats_start_collector') and setting='on' ",
'Value must be TRUE to enable hit ratio statistics (<i>stats_start_collector</i>,<i>stats_row_level</i> and <i>stats_block_level</i> must be set to true in postgresql.conf)'),
'data cache hit ratio' => array('RATIO',
"select case when blks_hit=0 then 0 else (1-blks_read::float/blks_hit)*100 end from pg_stat_database where datname='\$DATABASE'",
'=WarnCacheRatio'),
'IO',
'data reads' => array('IO',
'select sum(heap_blks_read+toast_blks_read) from pg_statio_user_tables',
),
'data writes' => array('IO',
'select sum(n_tup_ins/4.0+n_tup_upd/8.0+n_tup_del/4.0)/16 from pg_stat_user_tables',
'Count of inserts/updates/deletes * coef'),
'Data Cache',
'data cache buffers' => array('DATAC',
"select setting from pg_settings where name='shared_buffers'",
'Number of cache buffers. <a href=http://www.varlena.com/GeneralBits/Tidbits/perf.html#basic>Tuning</a>'),
'cache blocksize' => array('DATAC',
'select 8192',
'(estimate)' ),
'data cache size' => array( 'DATAC',
"select setting::integer*8192 from pg_settings where name='shared_buffers'",
'' ),
'operating system cache size' => array( 'DATA',
"select setting::integer*8192 from pg_settings where name='effective_cache_size'",
'(effective cache size)' ),
'Memory Usage',
'sort buffer size' => array('CACHE',
"select setting::integer*1024 from pg_settings where name='sort_mem'",
'Size of sort buffer (per query)' ),
'Connections',
'current connections' => array('SESS',
'select count(*) from pg_stat_activity',
''),
'max connections' => array('SESS',
"select setting from pg_settings where name='max_connections'",
''),
'Parameters',
'rollback buffers' => array('COST',
"select setting from pg_settings where name='wal_buffers'",
'WAL buffers'),
'random page cost' => array('COST',
"select setting from pg_settings where name='random_page_cost'",
'Cost of doing a seek (default=4). See <a href=http://www.varlena.com/GeneralBits/Tidbits/perf.html#less>random_page_cost</a>'),
false
);
function perf_postgres(&$conn)
{
$this->conn =& $conn;
}
function Explain($sql,$partial=false)
{
$save = $this->conn->LogSQL(false);
if ($partial) {
$sqlq = $this->conn->qstr($sql.'%');
$arr = $this->conn->GetArray("select distinct distinct sql1 from adodb_logsql where sql1 like $sqlq");
if ($arr) {
foreach($arr as $row) {
$sql = reset($row);
if (crc32($sql) == $partial) break;
}
}
}
$sql = str_replace('?',"''",$sql);
$s = '<p><b>Explain</b>: '.htmlspecialchars($sql).'</p>';
$rs = $this->conn->Execute('EXPLAIN '.$sql);
$this->conn->LogSQL($save);
$s .= '<pre>';
if ($rs)
while (!$rs->EOF) {
$s .= reset($rs->fields)."\n";
$rs->MoveNext();
}
$s .= '</pre>';
$s .= $this->Tracer($sql,$partial);
return $s;
}
}
?>

View File

@ -0,0 +1,118 @@
<?php
/*
V4.01 23 Oct 2003 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Contributed by Ross Smith (adodb@netebb.com).
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
if (!function_exists('bzcompress')) {
trigger_error('bzip2 functions are not available', E_USER_ERROR);
return 0;
}
/*
*/
class ADODB_Compress_Bzip2 {
/**
*/
var $_block_size = null;
/**
*/
var $_work_level = null;
/**
*/
var $_min_length = 1;
/**
*/
function getBlockSize() {
return $this->_block_size;
}
/**
*/
function setBlockSize($block_size) {
assert('$block_size >= 1');
assert('$block_size <= 9');
$this->_block_size = (int) $block_size;
}
/**
*/
function getWorkLevel() {
return $this->_work_level;
}
/**
*/
function setWorkLevel($work_level) {
assert('$work_level >= 0');
assert('$work_level <= 250');
$this->_work_level = (int) $work_level;
}
/**
*/
function getMinLength() {
return $this->_min_length;
}
/**
*/
function setMinLength($min_length) {
assert('$min_length >= 0');
$this->_min_length = (int) $min_length;
}
/**
*/
function ADODB_Compress_Bzip2($block_size = null, $work_level = null, $min_length = null) {
if (!is_null($block_size)) {
$this->setBlockSize($block_size);
}
if (!is_null($work_level)) {
$this->setWorkLevel($work_level);
}
if (!is_null($min_length)) {
$this->setMinLength($min_length);
}
}
/**
*/
function write($data, $key) {
if (strlen($data) < $this->_min_length) {
return $data;
}
if (!is_null($this->_block_size)) {
if (!is_null($this->_work_level)) {
return bzcompress($data, $this->_block_size, $this->_work_level);
} else {
return bzcompress($data, $this->_block_size);
}
}
return bzcompress($data);
}
/**
*/
function read($data, $key) {
return $data ? bzdecompress($data) : $data;
}
}
return 1;
?>

View File

@ -0,0 +1,93 @@
<?php
/*
V4.01 23 Oct 2003 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Contributed by Ross Smith (adodb@netebb.com).
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
if (!function_exists('gzcompress')) {
trigger_error('gzip functions are not available', E_USER_ERROR);
return 0;
}
/*
*/
class ADODB_Compress_Gzip {
/**
*/
var $_level = null;
/**
*/
var $_min_length = 1;
/**
*/
function getLevel() {
return $this->_level;
}
/**
*/
function setLevel($level) {
assert('$level >= 0');
assert('$level <= 9');
$this->_level = (int) $level;
}
/**
*/
function getMinLength() {
return $this->_min_length;
}
/**
*/
function setMinLength($min_length) {
assert('$min_length >= 0');
$this->_min_length = (int) $min_length;
}
/**
*/
function ADODB_Compress_Gzip($level = null, $min_length = null) {
if (!is_null($level)) {
$this->setLevel($level);
}
if (!is_null($min_length)) {
$this->setMinLength($min_length);
}
}
/**
*/
function write($data, $key) {
if (strlen($data) < $this->_min_length) {
return $data;
}
if (!is_null($this->_level)) {
return gzcompress($data, $this->_level);
} else {
return gzcompress($data);
}
}
/**
*/
function read($data, $key) {
return $data ? gzuncompress($data) : $data;
}
}
return 1;
?>

View File

@ -0,0 +1,24 @@
<?php
/*
V4.01 23 Oct 2003 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Contributed by Ross Smith (adodb@netebb.com).
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
/*
This file is provided for backwards compatibility purposes
*/
require_once dirname(__FILE__) . '/adodb-session.php';
require_once ADODB_SESSION . '/adodb-encrypt-md5.php';
ADODB_Session::filter(new ADODB_Encrypt_MD5());
?>

View File

@ -0,0 +1,109 @@
<?php
/*
V4.01 23 Oct 2003 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Contributed by Ross Smith (adodb@netebb.com).
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
if (!function_exists('mcrypt_encrypt')) {
trigger_error('Mcrypt functions are not available', E_USER_ERROR);
return 0;
}
/**
*/
class ADODB_Encrypt_MCrypt {
/**
*/
var $_cipher;
/**
*/
var $_mode;
/**
*/
var $_source;
/**
*/
function getCipher() {
return $this->_cipher;
}
/**
*/
function setCipher($cipher) {
$this->_cipher = $cipher;
}
/**
*/
function getMode() {
return $this->_mode;
}
/**
*/
function setMode($mode) {
$this->_mode = $mode;
}
/**
*/
function getSource() {
return $this->_source;
}
/**
*/
function setSource($source) {
$this->_source = $source;
}
/**
*/
function ADODB_Encrypt_MCrypt($cipher = null, $mode = null, $source = null) {
if (!$cipher) {
$cipher = MCRYPT_RIJNDAEL_256;
}
if (!$mode) {
$mode = MCRYPT_MODE_ECB;
}
if (!$source) {
$source = MCRYPT_RAND;
}
$this->_cipher = $cipher;
$this->_mode = $mode;
$this->_source = $source;
}
/**
*/
function write($data, $key) {
$iv_size = mcrypt_get_iv_size($this->_cipher, $this->_mode);
$iv = mcrypt_create_iv($iv_size, $this->_source);
return mcrypt_encrypt($this->_cipher, $key, $data, $this->_mode, $iv);
}
/**
*/
function read($data, $key) {
$iv_size = mcrypt_get_iv_size($this->_cipher, $this->_mode);
$iv = mcrypt_create_iv($iv_size, $this->_source);
$rv = mcrypt_decrypt($this->_cipher, $key, $data, $this->_mode, $iv);
return rtrim($rv, "\0");
}
}
return 1;
?>

View File

@ -0,0 +1,39 @@
<?php
/*
V4.01 23 Oct 2003 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Contributed by Ross Smith (adodb@netebb.com).
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
// security - hide paths
if (!defined('ADODB_SESSION')) die();
include_once ADODB_SESSION . '/crypt.inc.php';
/**
*/
class ADODB_Encrypt_MD5 {
/**
*/
function write($data, $key) {
$md5crypt =& new MD5Crypt();
return $md5crypt->encrypt($data, $key);
}
/**
*/
function read($data, $key) {
$md5crypt =& new MD5Crypt();
return $md5crypt->decrypt($data, $key);
}
}
return 1;
?>

View File

@ -0,0 +1,48 @@
<?php
/*
V4.01 23 Oct 2003 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Contributed by Ross Smith (adodb@netebb.com).
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
@define('HORDE_BASE', dirname(dirname(dirname(__FILE__))) . '/horde');
if (!is_dir(HORDE_BASE)) {
trigger_error(sprintf('Directory not found: \'%s\'', HORDE_BASE), E_USER_ERROR);
return 0;
}
include_once HORDE_BASE . '/lib/Horde.php';
include_once HORDE_BASE . '/lib/Secret.php';
/**
NOTE: On Windows 2000 SP4 with PHP 4.3.1, MCrypt 2.4.x, and Apache 1.3.28,
the session didn't work properly.
This may be resolved with 4.3.3.
*/
class ADODB_Encrypt_Secret {
/**
*/
function write($data, $key) {
return Secret::write($key, $data);
}
/**
*/
function read($data, $key) {
return Secret::read($key, $data);
}
}
return 1;
?>

View File

@ -0,0 +1,23 @@
<?php
/*
V4.01 23 Oct 2003 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Contributed by Ross Smith (adodb@netebb.com).
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
/*
This file is provided for backwards compatibility purposes
*/
require_once dirname(__FILE__) . '/adodb-session.php';
ADODB_Session::clob('CLOB');
?>

View File

@ -0,0 +1,817 @@
<?php
/*
V4.01 23 Oct 2003 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Contributed by Ross Smith (adodb@netebb.com).
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
/*
You may want to rename the 'data' field to 'session_data' as
'data' appears to be a reserved word for one or more of the following:
ANSI SQL
IBM DB2
MS SQL Server
Postgres
SAP
If you do, then execute:
ADODB_Session::dataFieldName('session_data');
*/
if (!defined('_ADODB_LAYER')) {
require_once realpath(dirname(__FILE__) . '/../adodb.inc.php');
}
if (defined('ADODB_SESSION')) return 1;
define('ADODB_SESSION', dirname(__FILE__));
/*!
\static
*/
class ADODB_Session {
/////////////////////
// getter/setter methods
/////////////////////
/*!
*/
function driver($driver = null) {
static $_driver = 'mysql';
static $set = false;
if (!is_null($driver)) {
$_driver = trim($driver);
$set = true;
} elseif (!$set) {
// backwards compatibility
if (isset($GLOBALS['ADODB_SESSION_DRIVER'])) {
return $GLOBALS['ADODB_SESSION_DRIVER'];
}
}
return $_driver;
}
/*!
*/
function host($host = null) {
static $_host = 'localhost';
static $set = false;
if (!is_null($host)) {
$_host = trim($host);
$set = true;
} elseif (!$set) {
// backwards compatibility
if (isset($GLOBALS['ADODB_SESSION_CONNECT'])) {
return $GLOBALS['ADODB_SESSION_CONNECT'];
}
}
return $_host;
}
/*!
*/
function user($user = null) {
static $_user = 'root';
static $set = false;
if (!is_null($user)) {
$_user = trim($user);
$set = true;
} elseif (!$set) {
// backwards compatibility
if (isset($GLOBALS['ADODB_SESSION_USER'])) {
return $GLOBALS['ADODB_SESSION_USER'];
}
}
return $_user;
}
/*!
*/
function password($password = null) {
static $_password = '';
static $set = false;
if (!is_null($password)) {
$_password = $password;
$set = true;
} elseif (!$set) {
// backwards compatibility
if (isset($GLOBALS['ADODB_SESSION_PWD'])) {
return $GLOBALS['ADODB_SESSION_PWD'];
}
}
return $_password;
}
/*!
*/
function database($database = null) {
static $_database = 'xphplens_2';
static $set = false;
if (!is_null($database)) {
$_database = trim($database);
$set = true;
} elseif (!$set) {
// backwards compatibility
if (isset($GLOBALS['ADODB_SESSION_DB'])) {
return $GLOBALS['ADODB_SESSION_DB'];
}
}
return $_database;
}
/*!
*/
function persist($persist = null) {
static $_persist = true;
if (!is_null($persist)) {
$_persist = trim($persist);
}
return $_persist;
}
/*!
*/
function lifetime($lifetime = null) {
static $_lifetime;
static $set = false;
if (!is_null($lifetime)) {
$_lifetime = (int) $lifetime;
$set = true;
} elseif (!$set) {
// backwards compatibility
if (isset($GLOBALS['ADODB_SESS_LIFE'])) {
return $GLOBALS['ADODB_SESS_LIFE'];
}
}
if (!$_lifetime) {
$_lifetime = ini_get('session.gc_maxlifetime');
if ($_lifetime <= 1) {
// bug in PHP 4.0.3 pl 1 -- how about other versions?
//print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $lifetime</h3>";
$_lifetime = 1440;
}
}
return $_lifetime;
}
/*!
*/
function debug($debug = null) {
static $_debug = false;
static $set = false;
if (!is_null($debug)) {
$_debug = (bool) $debug;
$conn = ADODB_Session::_conn();
if ($conn) {
$conn->debug = $_debug;
}
$set = true;
} elseif (!$set) {
// backwards compatibility
if (isset($GLOBALS['ADODB_SESS_DEBUG'])) {
return $GLOBALS['ADODB_SESS_DEBUG'];
}
}
return $_debug;
}
/*!
*/
function expireNotify($expire_notify = null) {
static $_expire_notify;
static $set = false;
if (!is_null($expire_notify)) {
$_expire_notify = $expire_notify;
$set = true;
} elseif (!$set) {
// backwards compatibility
if (isset($GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'])) {
return $GLOBALS['ADODB_SESSION_EXPIRE_NOTIFY'];
}
}
return $_expire_notify;
}
/*!
*/
function table($table = null) {
static $_table = 'sessions';
static $set = false;
if (!is_null($table)) {
$_table = trim($table);
$set = true;
} elseif (!$set) {
// backwards compatibility
if (isset($GLOBALS['ADODB_SESSION_TBL'])) {
return $GLOBALS['ADODB_SESSION_TBL'];
}
}
return $_table;
}
/*!
*/
function optimize($optimize = null) {
static $_optimize = false;
static $set = false;
if (!is_null($optimize)) {
$_optimize = (bool) $optimize;
$set = true;
} elseif (!$set) {
// backwards compatibility
if (defined('ADODB_SESSION_OPTIMIZE')) {
return true;
}
}
return $_optimize;
}
/*!
*/
function syncSeconds($sync_seconds = null) {
static $_sync_seconds = 60;
static $set = false;
if (!is_null($sync_seconds)) {
$_sync_seconds = (int) $sync_seconds;
$set = true;
} elseif (!$set) {
// backwards compatibility
if (defined('ADODB_SESSION_SYNCH_SECS')) {
return ADODB_SESSION_SYNCH_SECS;
}
}
return $_sync_seconds;
}
/*!
*/
function clob($clob = null) {
static $_clob = false;
static $set = false;
if (!is_null($clob)) {
$_clob = strtolower(trim($clob));
$set = true;
} elseif (!$set) {
// backwards compatibility
if (isset($GLOBALS['ADODB_SESSION_USE_LOBS'])) {
return $GLOBALS['ADODB_SESSION_USE_LOBS'];
}
}
return $_clob;
}
/*!
*/
function dataFieldName($data_field_name = null) {
static $_data_field_name = 'data';
if (!is_null($data_field_name)) {
$_data_field_name = trim($data_field_name);
}
return $_data_field_name;
}
/*!
*/
function filter($filter = null) {
static $_filter = array();
if (!is_null($filter)) {
if (!is_array($filter)) {
$filter = array($filter);
}
$_filter = $filter;
}
return $_filter;
}
/*!
*/
function encryptionKey($encryption_key = null) {
static $_encryption_key = 'CRYPTED ADODB SESSIONS ROCK!';
if (!is_null($encryption_key)) {
$_encryption_key = $encryption_key;
}
return $_encryption_key;
}
/////////////////////
// private methods
/////////////////////
/*!
*/
function &_conn($conn=null) {
return $GLOBALS['ADODB_SESS_CONN'];
}
/*!
*/
function _crc($crc = null) {
static $_crc = false;
if (!is_null($crc)) {
$_crc = $crc;
}
return $_crc;
}
/*!
*/
function _init() {
session_module_name('user');
session_set_save_handler(
array('ADODB_Session', 'open'),
array('ADODB_Session', 'close'),
array('ADODB_Session', 'read'),
array('ADODB_Session', 'write'),
array('ADODB_Session', 'destroy'),
array('ADODB_Session', 'gc')
);
}
/*!
*/
function _sessionKey() {
// use this function to create the encryption key for crypted sessions
// crypt the used key, ADODB_Session::encryptionKey() as key and session_id() as salt
return crypt(ADODB_Session::encryptionKey(), session_id());
}
/*!
*/
function _dumprs($rs) {
$conn =& ADODB_Session::_conn();
$debug = ADODB_Session::debug();
if (!$conn) {
return;
}
if (!$debug) {
return;
}
if (!$rs) {
echo "<br />\$rs is null or false<br />\n";
return;
}
//echo "<br />\nAffected_Rows=",$conn->Affected_Rows(),"<br />\n";
if (!is_object($rs)) {
return;
}
require_once ADODB_SESSION.'/../tohtml.inc.php';
rs2html($rs);
}
/////////////////////
// public methods
/////////////////////
/*!
Create the connection to the database.
If $conn already exists, reuse that connection
*/
function open($save_path, $session_name, $persist = null) {
$conn =& ADODB_Session::_conn();
if ($conn) {
return true;
}
$database = ADODB_Session::database();
$debug = ADODB_Session::debug();
$driver = ADODB_Session::driver();
$host = ADODB_Session::host();
$password = ADODB_Session::password();
$user = ADODB_Session::user();
if (!is_null($persist)) {
$persist = (bool) $persist;
ADODB_Session::persist($persist);
} else {
$persist = ADODB_Session::persist();
}
# these can all be defaulted to in php.ini
# assert('$database');
# assert('$driver');
# assert('$host');
// cannot use =& below - do not know why...
$conn = ADONewConnection($driver);
if ($debug) {
$conn->debug = true;
// ADOConnection::outp( " driver=$driver user=$user pwd=$password db=$database ");
}
if ($persist) {
$ok = $conn->PConnect($host, $user, $password, $database);
} else {
$ok = $conn->Connect($host, $user, $password, $database);
}
if ($ok) $GLOBALS['ADODB_SESS_CONN'] =& $conn;
else
ADOConnection::outp('<p>Session: connection failed</p>', false);
return $ok;
}
/*!
Close the connection
*/
function close() {
$conn =& ADODB_Session::_conn();
if ($conn) {
$conn->Close();
}
return true;
}
/*
Slurp in the session variables and return the serialized string
*/
function read($key) {
$conn =& ADODB_Session::_conn();
$data = ADODB_Session::dataFieldName();
$filter = ADODB_Session::filter();
$table = ADODB_Session::table();
if (!$conn) {
return '';
}
assert('$table');
$qkey = $conn->quote($key);
$binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';
$sql = "SELECT $data FROM $table WHERE $binary sesskey = $qkey AND expiry >= " . time();
$rs =& $conn->Execute($sql);
//ADODB_Session::_dumprs($rs);
if ($rs) {
if ($rs->EOF) {
$v = '';
} else {
$v = reset($rs->fields);
$filter = array_reverse($filter);
foreach ($filter as $f) {
if (is_object($f)) {
$v = $f->read($v, ADODB_Session::_sessionKey());
}
}
$v = rawurldecode($v);
}
$rs->Close();
ADODB_Session::_crc(strlen($v) . crc32($v));
return $v;
}
return '';
}
/*!
Write the serialized data to a database.
If the data has not been modified since the last read(), we do not write.
*/
function write($key, $val) {
$clob = ADODB_Session::clob();
$conn =& ADODB_Session::_conn();
$crc = ADODB_Session::_crc();
$data = ADODB_Session::dataFieldName();
$debug = ADODB_Session::debug();
$driver = ADODB_Session::driver();
$expire_notify = ADODB_Session::expireNotify();
$filter = ADODB_Session::filter();
$lifetime = ADODB_Session::lifetime();
$table = ADODB_Session::table();
if (!$conn) {
return false;
}
assert('$table');
$expiry = time() + $lifetime;
$qkey = $conn->quote($key);
$binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';
// crc32 optimization since adodb 2.1
// now we only update expiry date, thx to sebastian thom in adodb 2.32
if ($crc !== false && $crc == (strlen($val) . crc32($val))) {
if ($debug) {
echo '<p>Session: Only updating date - crc32 not changed</p>';
}
$sql = "UPDATE $table SET expiry = $expiry WHERE $binary sesskey = $qkey AND expiry >= " . time();
$rs =& $conn->Execute($sql);
ADODB_Session::_dumprs($rs);
if ($rs) {
$rs->Close();
}
return true;
}
$val = rawurlencode($val);
foreach ($filter as $f) {
if (is_object($f)) {
$val = $f->write($val, ADODB_Session::_sessionKey());
}
}
$arr = array('sesskey' => $key, 'expiry' => $expiry, $data => $val, 'expireref' => '');
if ($expire_notify) {
$var = reset($expire_notify);
global $$var;
if (isset($$var)) {
$arr['expireref'] = $$var;
}
}
if (!$clob) { // no lobs, simply use replace()
$arr[$data] = $conn->qstr($val);
$rs = $conn->Replace($table, $arr, 'sesskey', $autoQuote = true);
ADODB_Session::_dumprs($rs);
} else {
// what value shall we insert/update for lob row?
switch ($driver) {
// empty_clob or empty_lob for oracle dbs
case 'oracle':
case 'oci8':
case 'oci8po':
case 'oci805':
$lob_value = sprintf('empty_%s()', strtolower($clob));
break;
// null for all other
default:
$lob_value = 'null';
break;
}
// do we insert or update? => as for sesskey
$rs =& $conn->Execute("SELECT COUNT(*) AS cnt FROM $table WHERE $binary sesskey = $qkey");
ADODB_Session::_dumprs($rs);
if ($rs && reset($rs->fields) > 0) {
$sql = "UPDATE $table SET expiry = $expiry, $data = $lob_value WHERE sesskey = $qkey";
} else {
$sql = "INSERT INTO $table (expiry, $data, sesskey) VALUES ($expiry, $lob_value, $qkey)";
}
if ($rs) {
$rs->Close();
}
$err = '';
$rs1 =& $conn->Execute($sql);
ADODB_Session::_dumprs($rs1);
if (!$rs1) {
$err = $conn->ErrorMsg()."\n";
}
$rs2 =& $conn->UpdateBlob($table, $data, $val, " sesskey=$qkey", strtoupper($clob));
ADODB_Session::_dumprs($rs2);
if (!$rs2) {
$err .= $conn->ErrorMsg()."\n";
}
$rs = ($rs && $rs2) ? true : false;
if ($rs1) {
$rs1->Close();
}
if (is_object($rs2)) {
$rs2->Close();
}
}
if (!$rs) {
ADOConnection::outp('<p>Session Replace: ' . $conn->ErrorMsg() . '</p>', false);
return false;
} else {
// bug in access driver (could be odbc?) means that info is not committed
// properly unless select statement executed in Win2000
if ($conn->databaseType == 'access') {
$sql = "SELECT sesskey FROM $table WHERE $binary sesskey = $qkey";
$rs =& $conn->Execute($sql);
ADODB_Session::_dumprs($rs);
if ($rs) {
$rs->Close();
}
}
}
return $rs ? true : false;
}
/*!
*/
function destroy($key) {
$conn =& ADODB_Session::_conn();
$table = ADODB_Session::table();
$expire_notify = ADODB_Session::expireNotify();
if (!$conn) {
return false;
}
assert('$table');
$qkey = $conn->quote($key);
$binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';
if ($expire_notify) {
reset($expire_notify);
$fn = next($expire_notify);
$savem = $conn->SetFetchMode(ADODB_FETCH_NUM);
$sql = "SELECT expireref, sesskey FROM $table WHERE $binary sesskey = $qkey";
$rs =& $conn->Execute($sql);
ADODB_Session::_dumprs($rs);
$conn->SetFetchMode($savem);
if (!$rs) {
return false;
}
if (!$rs->EOF) {
$ref = $rs->fields[0];
$key = $rs->fields[1];
//assert('$ref');
//assert('$key');
$fn($ref, $key);
}
$rs->Close();
}
$sql = "DELETE FROM $table WHERE $binary sesskey = $qkey";
$rs =& $conn->Execute($sql);
ADODB_Session::_dumprs($rs);
if ($rs) {
$rs->Close();
}
return $rs ? true : false;
}
/*!
*/
function gc($maxlifetime) {
$conn =& ADODB_Session::_conn();
$debug = ADODB_Session::debug();
$expire_notify = ADODB_Session::expireNotify();
$optimize = ADODB_Session::optimize();
$sync_seconds = ADODB_Session::syncSeconds();
$table = ADODB_Session::table();
if (!$conn) {
return false;
}
assert('$table');
$time = time();
$binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';
if ($expire_notify) {
reset($expire_notify);
$fn = next($expire_notify);
$savem = $conn->SetFetchMode(ADODB_FETCH_NUM);
$sql = "SELECT expireref, sesskey FROM $table WHERE expiry < $time";
$rs =& $conn->Execute($sql);
ADODB_Session::_dumprs($rs);
$conn->SetFetchMode($savem);
if ($rs) {
$conn->BeginTrans();
$keys = array();
while (!$rs->EOF) {
$ref = $rs->fields[0];
$key = $rs->fields[1];
$fn($ref, $key);
$del = $conn->Execute("DELETE FROM $table WHERE sesskey='$key'");
$rs->MoveNext();
}
$rs->Close();
$conn->CommitTrans();
}
} else {
$sql = "DELETE FROM $table WHERE expiry < $time";
$rs =& $conn->Execute($sql);
ADODB_Session::_dumprs($rs);
if ($rs) {
$rs->Close();
}
if ($debug) {
ADOConnection::outp("<p><b>Garbage Collection</b>: $sql</p>");
}
}
// suggested by Cameron, "GaM3R" <gamr@outworld.cx>
if ($optimize) {
$driver = ADODB_Session::driver();
if (preg_match('/mysql/i', $driver)) {
$sql = "OPTIMIZE TABLE $table";
}
if (preg_match('/postgres/i', $driver)) {
$sql = "VACUUM $table";
}
if (!empty($sql)) {
$conn->Execute($sql);
}
}
if ($sync_seconds) {
$sql = 'SELECT ';
if ($conn->dataProvider === 'oci8') {
$sql .= "TO_CHAR({$conn->sysTimeStamp}, 'RRRR-MM-DD HH24:MI:SS')";
} else {
$sql .= $conn->sysTimeStamp;
}
$sql .= " FROM $table";
$rs =& $conn->SelectLimit($sql, 1);
if ($rs && !$rs->EOF) {
$dbts = reset($rs->fields);
$rs->Close();
$dbt = $conn->UnixTimeStamp($dbts);
$t = time();
if (abs($dbt - $t) >= $sync_seconds) {
global $HTTP_SERVER_VARS;
$msg = __FILE__ .
": Server time for webserver {$HTTP_SERVER_VARS['HTTP_HOST']} not in synch with database: " .
" database=$dbt ($dbts), webserver=$t (diff=". (abs($dbt - $t) / 3600) . ' hours)';
error_log($msg);
if ($debug) {
ADOConnection::outp("<p>$msg</p>");
}
}
}
}
return true;
}
}
ADODB_Session::_init();
// for backwards compatability only
function adodb_sess_open($save_path, $session_name, $persist = true) {
return ADODB_Session::open($save_path, $session_name, $persist);
}
// for backwards compatability only
function adodb_sess_gc($t)
{
return ADODB_Session::gc($t);
}
?>

View File

@ -0,0 +1,321 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Made table name configurable - by David Johnson djohnson@inpro.net
Encryption by Ari Kuorikoski <ari.kuorikoski@finebyte.com>
Set tabs to 4 for best viewing.
Latest version of ADODB is available at http://php.weblogs.com/adodb
======================================================================
This file provides PHP4 session management using the ADODB database
wrapper library.
Example
=======
GLOBAL $HTTP_SESSION_VARS;
include('adodb.inc.php');
#---------------------------------#
include('adodb-cryptsession.php');
#---------------------------------#
session_start();
session_register('AVAR');
$HTTP_SESSION_VARS['AVAR'] += 1;
print "<p>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</p>";
Installation
============
1. Create a new database in MySQL or Access "sessions" like
so:
create table sessions (
SESSKEY char(32) not null,
EXPIRY int(11) unsigned not null,
EXPIREREF varchar(64),
DATA CLOB,
primary key (sesskey)
);
2. Then define the following parameters. You can either modify
this file, or define them before this file is included:
$ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase';
$ADODB_SESSION_CONNECT='server to connect to';
$ADODB_SESSION_USER ='user';
$ADODB_SESSION_PWD ='password';
$ADODB_SESSION_DB ='database';
$ADODB_SESSION_TBL = 'sessions'
3. Recommended is PHP 4.0.2 or later. There are documented
session bugs in earlier versions of PHP.
*/
include_once('crypt.inc.php');
if (!defined('_ADODB_LAYER')) {
include (dirname(__FILE__).'/adodb.inc.php');
}
/* if database time and system time is difference is greater than this, then give warning */
define('ADODB_SESSION_SYNCH_SECS',60);
if (!defined('ADODB_SESSION')) {
define('ADODB_SESSION',1);
GLOBAL $ADODB_SESSION_CONNECT,
$ADODB_SESSION_DRIVER,
$ADODB_SESSION_USER,
$ADODB_SESSION_PWD,
$ADODB_SESSION_DB,
$ADODB_SESS_CONN,
$ADODB_SESS_LIFE,
$ADODB_SESS_DEBUG,
$ADODB_SESS_INSERT,
$ADODB_SESSION_EXPIRE_NOTIFY,
$ADODB_SESSION_TBL;
//$ADODB_SESS_DEBUG = true;
/* SET THE FOLLOWING PARAMETERS */
if (empty($ADODB_SESSION_DRIVER)) {
$ADODB_SESSION_DRIVER='mysql';
$ADODB_SESSION_CONNECT='localhost';
$ADODB_SESSION_USER ='root';
$ADODB_SESSION_PWD ='';
$ADODB_SESSION_DB ='xphplens_2';
}
if (empty($ADODB_SESSION_TBL)){
$ADODB_SESSION_TBL = 'sessions';
}
if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) {
$ADODB_SESSION_EXPIRE_NOTIFY = false;
}
function ADODB_Session_Key()
{
$ADODB_CRYPT_KEY = 'CRYPTED ADODB SESSIONS ROCK!';
/* USE THIS FUNCTION TO CREATE THE ENCRYPTION KEY FOR CRYPTED SESSIONS */
/* Crypt the used key, $ADODB_CRYPT_KEY as key and session_ID as SALT */
return crypt($ADODB_CRYPT_KEY, session_ID());
}
$ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime');
if ($ADODB_SESS_LIFE <= 1) {
// bug in PHP 4.0.3 pl 1 -- how about other versions?
//print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $ADODB_SESS_LIFE</h3>";
$ADODB_SESS_LIFE=1440;
}
function adodb_sess_open($save_path, $session_name)
{
GLOBAL $ADODB_SESSION_CONNECT,
$ADODB_SESSION_DRIVER,
$ADODB_SESSION_USER,
$ADODB_SESSION_PWD,
$ADODB_SESSION_DB,
$ADODB_SESS_CONN,
$ADODB_SESS_DEBUG;
$ADODB_SESS_INSERT = false;
if (isset($ADODB_SESS_CONN)) return true;
$ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER);
if (!empty($ADODB_SESS_DEBUG)) {
$ADODB_SESS_CONN->debug = true;
print" conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB ";
}
return $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT,
$ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
}
function adodb_sess_close()
{
global $ADODB_SESS_CONN;
if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close();
return true;
}
function adodb_sess_read($key)
{
$Crypt = new MD5Crypt;
global $ADODB_SESS_CONN,$ADODB_SESS_INSERT,$ADODB_SESSION_TBL;
$rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time());
if ($rs) {
if ($rs->EOF) {
$ADODB_SESS_INSERT = true;
$v = '';
} else {
// Decrypt session data
$v = rawurldecode($Crypt->Decrypt(reset($rs->fields), ADODB_Session_Key()));
}
$rs->Close();
return $v;
}
else $ADODB_SESS_INSERT = true;
return '';
}
function adodb_sess_write($key, $val)
{
$Crypt = new MD5Crypt;
global $ADODB_SESS_INSERT,$ADODB_SESS_CONN, $ADODB_SESS_LIFE, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
$expiry = time() + $ADODB_SESS_LIFE;
// encrypt session data..
$val = $Crypt->Encrypt(rawurlencode($val), ADODB_Session_Key());
$arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val);
if ($ADODB_SESSION_EXPIRE_NOTIFY) {
$var = reset($ADODB_SESSION_EXPIRE_NOTIFY);
global $$var;
$arr['expireref'] = $$var;
}
$rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,
$arr,
'sesskey',$autoQuote = true);
if (!$rs) {
ADOConnection::outp( '<p>Session Replace: '.$ADODB_SESS_CONN->ErrorMsg().'</p>',false);
} else {
// bug in access driver (could be odbc?) means that info is not commited
// properly unless select statement executed in Win2000
if ($ADODB_SESS_CONN->databaseType == 'access') $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'");
}
return isset($rs);
}
function adodb_sess_destroy($key)
{
global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
if ($ADODB_SESSION_EXPIRE_NOTIFY) {
reset($ADODB_SESSION_EXPIRE_NOTIFY);
$fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
$savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
$rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
$ADODB_SESS_CONN->SetFetchMode($savem);
if ($rs) {
$ADODB_SESS_CONN->BeginTrans();
while (!$rs->EOF) {
$ref = $rs->fields[0];
$key = $rs->fields[1];
$fn($ref,$key);
$del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
$rs->MoveNext();
}
$ADODB_SESS_CONN->CommitTrans();
}
} else {
$qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'";
$rs = $ADODB_SESS_CONN->Execute($qry);
}
return $rs ? true : false;
}
function adodb_sess_gc($maxlifetime) {
global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY,$ADODB_SESS_DEBUG;
if ($ADODB_SESSION_EXPIRE_NOTIFY) {
reset($ADODB_SESSION_EXPIRE_NOTIFY);
$fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
$savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
$t = time();
$rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t");
$ADODB_SESS_CONN->SetFetchMode($savem);
if ($rs) {
$ADODB_SESS_CONN->BeginTrans();
while (!$rs->EOF) {
$ref = $rs->fields[0];
$key = $rs->fields[1];
$fn($ref,$key);
//$del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
$rs->MoveNext();
}
$rs->Close();
$ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE expiry < $t");
$ADODB_SESS_CONN->CommitTrans();
}
} else {
$qry = "DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time();
$ADODB_SESS_CONN->Execute($qry);
}
// suggested by Cameron, "GaM3R" <gamr@outworld.cx>
if (defined('ADODB_SESSION_OPTIMIZE'))
{
switch( $ADODB_SESSION_DRIVER ) {
case 'mysql':
case 'mysqlt':
$opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL;
break;
case 'postgresql':
case 'postgresql7':
$opt_qry = 'VACUUM '.$ADODB_SESSION_TBL;
break;
}
}
if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL;
else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL;
$rs =& $ADODB_SESS_CONN->SelectLimit($sql,1);
if ($rs && !$rs->EOF) {
$dbts = reset($rs->fields);
$rs->Close();
$dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts);
$t = time();
if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) {
global $HTTP_SERVER_VARS;
$msg =
__FILE__.": Server time for webserver {$HTTP_SERVER_VARS['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)";
error_log($msg);
if ($ADODB_SESS_DEBUG) ADOConnection::outp("<p>$msg</p>");
}
}
return true;
}
session_module_name('user');
session_set_save_handler(
"adodb_sess_open",
"adodb_sess_close",
"adodb_sess_read",
"adodb_sess_write",
"adodb_sess_destroy",
"adodb_sess_gc");
}
/* TEST SCRIPT -- UNCOMMENT */
/*
if (0) {
GLOBAL $HTTP_SESSION_VARS;
session_start();
session_register('AVAR');
$HTTP_SESSION_VARS['AVAR'] += 1;
print "<p>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</p>";
}
*/
?>

View File

@ -0,0 +1,444 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version of ADODB is available at http://php.weblogs.com/adodb
======================================================================
This file provides PHP4 session management using the ADODB database
wrapper library, using Oracle CLOB's to store data. Contributed by achim.gosse@ddd.de.
Example
=======
GLOBAL $HTTP_SESSION_VARS;
include('adodb.inc.php');
include('adodb-session.php');
session_start();
session_register('AVAR');
$HTTP_SESSION_VARS['AVAR'] += 1;
print "<p>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</p>";
To force non-persistent connections, call adodb_session_open first before session_start():
GLOBAL $HTTP_SESSION_VARS;
include('adodb.inc.php');
include('adodb-session.php');
adodb_session_open(false,false,false);
session_start();
session_register('AVAR');
$HTTP_SESSION_VARS['AVAR'] += 1;
print "<p>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</p>";
Installation
============
1. Create this table in your database (syntax might vary depending on your db):
create table sessions (
SESSKEY char(32) not null,
EXPIRY int(11) unsigned not null,
EXPIREREF varchar(64),
DATA CLOB,
primary key (sesskey)
);
2. Then define the following parameters in this file:
$ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase';
$ADODB_SESSION_CONNECT='server to connect to';
$ADODB_SESSION_USER ='user';
$ADODB_SESSION_PWD ='password';
$ADODB_SESSION_DB ='database';
$ADODB_SESSION_TBL = 'sessions'
$ADODB_SESSION_USE_LOBS = false; (or, if you wanna use CLOBS (= 'CLOB') or ( = 'BLOB')
3. Recommended is PHP 4.0.6 or later. There are documented
session bugs in earlier versions of PHP.
4. If you want to receive notifications when a session expires, then
you can tag a session with an EXPIREREF, and before the session
record is deleted, we can call a function that will pass the EXPIREREF
as the first parameter, and the session key as the second parameter.
To do this, define a notification function, say NotifyFn:
function NotifyFn($expireref, $sesskey)
{
}
Then you need to define a global variable $ADODB_SESSION_EXPIRE_NOTIFY.
This is an array with 2 elements, the first being the name of the variable
you would like to store in the EXPIREREF field, and the 2nd is the
notification function's name.
In this example, we want to be notified when a user's session
has expired, so we store the user id in the global variable $USERID,
store this value in the EXPIREREF field:
$ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn');
Then when the NotifyFn is called, we are passed the $USERID as the first
parameter, eg. NotifyFn($userid, $sesskey).
*/
if (!defined('_ADODB_LAYER')) {
include (dirname(__FILE__).'/adodb.inc.php');
}
if (!defined('ADODB_SESSION')) {
define('ADODB_SESSION',1);
/* if database time and system time is difference is greater than this, then give warning */
define('ADODB_SESSION_SYNCH_SECS',60);
/****************************************************************************************\
Global definitions
\****************************************************************************************/
GLOBAL $ADODB_SESSION_CONNECT,
$ADODB_SESSION_DRIVER,
$ADODB_SESSION_USER,
$ADODB_SESSION_PWD,
$ADODB_SESSION_DB,
$ADODB_SESS_CONN,
$ADODB_SESS_LIFE,
$ADODB_SESS_DEBUG,
$ADODB_SESSION_EXPIRE_NOTIFY,
$ADODB_SESSION_CRC,
$ADODB_SESSION_USE_LOBS,
$ADODB_SESSION_TBL;
if (!isset($ADODB_SESSION_USE_LOBS)) $ADODB_SESSION_USE_LOBS = 'CLOB';
$ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime');
if ($ADODB_SESS_LIFE <= 1) {
// bug in PHP 4.0.3 pl 1 -- how about other versions?
//print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $ADODB_SESS_LIFE</h3>";
$ADODB_SESS_LIFE=1440;
}
$ADODB_SESSION_CRC = false;
//$ADODB_SESS_DEBUG = true;
//////////////////////////////////
/* SET THE FOLLOWING PARAMETERS */
//////////////////////////////////
if (empty($ADODB_SESSION_DRIVER)) {
$ADODB_SESSION_DRIVER='mysql';
$ADODB_SESSION_CONNECT='localhost';
$ADODB_SESSION_USER ='root';
$ADODB_SESSION_PWD ='';
$ADODB_SESSION_DB ='xphplens_2';
}
if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) {
$ADODB_SESSION_EXPIRE_NOTIFY = false;
}
// Made table name configurable - by David Johnson djohnson@inpro.net
if (empty($ADODB_SESSION_TBL)){
$ADODB_SESSION_TBL = 'sessions';
}
// defaulting $ADODB_SESSION_USE_LOBS
if (!isset($ADODB_SESSION_USE_LOBS) || empty($ADODB_SESSION_USE_LOBS)) {
$ADODB_SESSION_USE_LOBS = false;
}
/*
$ADODB_SESS['driver'] = $ADODB_SESSION_DRIVER;
$ADODB_SESS['connect'] = $ADODB_SESSION_CONNECT;
$ADODB_SESS['user'] = $ADODB_SESSION_USER;
$ADODB_SESS['pwd'] = $ADODB_SESSION_PWD;
$ADODB_SESS['db'] = $ADODB_SESSION_DB;
$ADODB_SESS['life'] = $ADODB_SESS_LIFE;
$ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
$ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
$ADODB_SESS['table'] = $ADODB_SESS_TBL;
*/
/****************************************************************************************\
Create the connection to the database.
If $ADODB_SESS_CONN already exists, reuse that connection
\****************************************************************************************/
function adodb_sess_open($save_path, $session_name,$persist=true)
{
GLOBAL $ADODB_SESS_CONN;
if (isset($ADODB_SESS_CONN)) return true;
GLOBAL $ADODB_SESSION_CONNECT,
$ADODB_SESSION_DRIVER,
$ADODB_SESSION_USER,
$ADODB_SESSION_PWD,
$ADODB_SESSION_DB,
$ADODB_SESS_DEBUG;
// cannot use & below - do not know why...
$ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER);
if (!empty($ADODB_SESS_DEBUG)) {
$ADODB_SESS_CONN->debug = true;
ADOConnection::outp( " conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB ");
}
if ($persist) $ok = $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT,
$ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
else $ok = $ADODB_SESS_CONN->Connect($ADODB_SESSION_CONNECT,
$ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
if (!$ok) ADOConnection::outp( "<p>Session: connection failed</p>",false);
}
/****************************************************************************************\
Close the connection
\****************************************************************************************/
function adodb_sess_close()
{
global $ADODB_SESS_CONN;
if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close();
return true;
}
/****************************************************************************************\
Slurp in the session variables and return the serialized string
\****************************************************************************************/
function adodb_sess_read($key)
{
global $ADODB_SESS_CONN,$ADODB_SESSION_TBL,$ADODB_SESSION_CRC;
$rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time());
if ($rs) {
if ($rs->EOF) {
$v = '';
} else
$v = rawurldecode(reset($rs->fields));
$rs->Close();
// new optimization adodb 2.1
$ADODB_SESSION_CRC = strlen($v).crc32($v);
return $v;
}
return ''; // thx to Jorma Tuomainen, webmaster#wizactive.com
}
/****************************************************************************************\
Write the serialized data to a database.
If the data has not been modified since adodb_sess_read(), we do not write.
\****************************************************************************************/
function adodb_sess_write($key, $val)
{
global
$ADODB_SESS_CONN,
$ADODB_SESS_LIFE,
$ADODB_SESSION_TBL,
$ADODB_SESS_DEBUG,
$ADODB_SESSION_CRC,
$ADODB_SESSION_EXPIRE_NOTIFY,
$ADODB_SESSION_DRIVER, // added
$ADODB_SESSION_USE_LOBS; // added
$expiry = time() + $ADODB_SESS_LIFE;
// crc32 optimization since adodb 2.1
// now we only update expiry date, thx to sebastian thom in adodb 2.32
if ($ADODB_SESSION_CRC !== false && $ADODB_SESSION_CRC == strlen($val).crc32($val)) {
if ($ADODB_SESS_DEBUG) echo "<p>Session: Only updating date - crc32 not changed</p>";
$qry = "UPDATE $ADODB_SESSION_TBL SET expiry=$expiry WHERE sesskey='$key' AND expiry >= " . time();
$rs = $ADODB_SESS_CONN->Execute($qry);
return true;
}
$val = rawurlencode($val);
$arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val);
if ($ADODB_SESSION_EXPIRE_NOTIFY) {
$var = reset($ADODB_SESSION_EXPIRE_NOTIFY);
global $$var;
$arr['expireref'] = $$var;
}
if ($ADODB_SESSION_USE_LOBS === false) { // no lobs, simply use replace()
$rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,$arr, 'sesskey',$autoQuote = true);
if (!$rs) {
$err = $ADODB_SESS_CONN->ErrorMsg();
}
} else {
// what value shall we insert/update for lob row?
switch ($ADODB_SESSION_DRIVER) {
// empty_clob or empty_lob for oracle dbs
case "oracle":
case "oci8":
case "oci8po":
case "oci805":
$lob_value = sprintf("empty_%s()", strtolower($ADODB_SESSION_USE_LOBS));
break;
// null for all other
default:
$lob_value = "null";
break;
}
// do we insert or update? => as for sesskey
$res = $ADODB_SESS_CONN->Execute("select count(*) as cnt from $ADODB_SESSION_TBL where sesskey = '$key'");
if ($res && reset($res->fields) > 0) {
$qry = sprintf("update %s set expiry = %d, data = %s where sesskey = '%s'", $ADODB_SESSION_TBL, $expiry, $lob_value, $key);
} else {
// insert
$qry = sprintf("insert into %s (sesskey, expiry, data) values ('%s', %d, %s)", $ADODB_SESSION_TBL, $key, $expiry, $lob_value);
}
$err = "";
$rs1 = $ADODB_SESS_CONN->Execute($qry);
if (!$rs1) {
$err .= $ADODB_SESS_CONN->ErrorMsg()."\n";
}
$rs2 = $ADODB_SESS_CONN->UpdateBlob($ADODB_SESSION_TBL, 'data', $val, "sesskey='$key'", strtoupper($ADODB_SESSION_USE_LOBS));
if (!$rs2) {
$err .= $ADODB_SESS_CONN->ErrorMsg()."\n";
}
$rs = ($rs1 && $rs2) ? true : false;
}
if (!$rs) {
ADOConnection::outp( '<p>Session Replace: '.nl2br($err).'</p>',false);
} else {
// bug in access driver (could be odbc?) means that info is not commited
// properly unless select statement executed in Win2000
if ($ADODB_SESS_CONN->databaseType == 'access')
$rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'");
}
return !empty($rs);
}
function adodb_sess_destroy($key)
{
global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
if ($ADODB_SESSION_EXPIRE_NOTIFY) {
reset($ADODB_SESSION_EXPIRE_NOTIFY);
$fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
$savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
$rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
$ADODB_SESS_CONN->SetFetchMode($savem);
if ($rs) {
$ADODB_SESS_CONN->BeginTrans();
while (!$rs->EOF) {
$ref = $rs->fields[0];
$key = $rs->fields[1];
$fn($ref,$key);
$del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
$rs->MoveNext();
}
$ADODB_SESS_CONN->CommitTrans();
}
} else {
$qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'";
$rs = $ADODB_SESS_CONN->Execute($qry);
}
return $rs ? true : false;
}
function adodb_sess_gc($maxlifetime)
{
global $ADODB_SESS_DEBUG, $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
if ($ADODB_SESSION_EXPIRE_NOTIFY) {
reset($ADODB_SESSION_EXPIRE_NOTIFY);
$fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
$savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
$t = time();
$rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t");
$ADODB_SESS_CONN->SetFetchMode($savem);
if ($rs) {
$ADODB_SESS_CONN->BeginTrans();
while (!$rs->EOF) {
$ref = $rs->fields[0];
$key = $rs->fields[1];
$fn($ref,$key);
$del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
$rs->MoveNext();
}
$rs->Close();
//$ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE expiry < $t");
$ADODB_SESS_CONN->CommitTrans();
}
} else {
$ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time());
if ($ADODB_SESS_DEBUG) ADOConnection::outp("<p><b>Garbage Collection</b>: $qry</p>");
}
// suggested by Cameron, "GaM3R" <gamr@outworld.cx>
if (defined('ADODB_SESSION_OPTIMIZE')) {
global $ADODB_SESSION_DRIVER;
switch( $ADODB_SESSION_DRIVER ) {
case 'mysql':
case 'mysqlt':
$opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL;
break;
case 'postgresql':
case 'postgresql7':
$opt_qry = 'VACUUM '.$ADODB_SESSION_TBL;
break;
}
if (!empty($opt_qry)) {
$ADODB_SESS_CONN->Execute($opt_qry);
}
}
if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL;
else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL;
$rs =& $ADODB_SESS_CONN->SelectLimit($sql,1);
if ($rs && !$rs->EOF) {
$dbts = reset($rs->fields);
$rs->Close();
$dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts);
$t = time();
if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) {
global $HTTP_SERVER_VARS;
$msg =
__FILE__.": Server time for webserver {$HTTP_SERVER_VARS['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)";
error_log($msg);
if ($ADODB_SESS_DEBUG) ADOConnection::outp("<p>$msg</p>");
}
}
return true;
}
session_module_name('user');
session_set_save_handler(
"adodb_sess_open",
"adodb_sess_close",
"adodb_sess_read",
"adodb_sess_write",
"adodb_sess_destroy",
"adodb_sess_gc");
}
/* TEST SCRIPT -- UNCOMMENT */
if (0) {
GLOBAL $HTTP_SESSION_VARS;
session_start();
session_register('AVAR');
$HTTP_SESSION_VARS['AVAR'] += 1;
ADOConnection::outp( "<p>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</p>",false);
}
?>

View File

@ -0,0 +1,403 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version of ADODB is available at http://php.weblogs.com/adodb
======================================================================
This file provides PHP4 session management using the ADODB database
wrapper library.
Example
=======
GLOBAL $HTTP_SESSION_VARS;
include('adodb.inc.php');
include('adodb-session.php');
session_start();
session_register('AVAR');
$HTTP_SESSION_VARS['AVAR'] += 1;
print "<p>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</p>";
To force non-persistent connections, call adodb_session_open first before session_start():
GLOBAL $HTTP_SESSION_VARS;
include('adodb.inc.php');
include('adodb-session.php');
adodb_sess_open(false,false,false);
session_start();
session_register('AVAR');
$HTTP_SESSION_VARS['AVAR'] += 1;
print "<p>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</p>";
Installation
============
1. Create this table in your database (syntax might vary depending on your db):
create table sessions (
SESSKEY char(32) not null,
EXPIRY int(11) unsigned not null,
EXPIREREF varchar(64),
DATA text not null,
primary key (sesskey)
);
For oracle:
create table sessions (
SESSKEY char(32) not null,
EXPIRY DECIMAL(16) not null,
EXPIREREF varchar(64),
DATA varchar(4000) not null,
primary key (sesskey)
);
2. Then define the following parameters. You can either modify
this file, or define them before this file is included:
$ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase';
$ADODB_SESSION_CONNECT='server to connect to';
$ADODB_SESSION_USER ='user';
$ADODB_SESSION_PWD ='password';
$ADODB_SESSION_DB ='database';
$ADODB_SESSION_TBL = 'sessions'
3. Recommended is PHP 4.0.6 or later. There are documented
session bugs in earlier versions of PHP.
4. If you want to receive notifications when a session expires, then
you can tag a session with an EXPIREREF, and before the session
record is deleted, we can call a function that will pass the EXPIREREF
as the first parameter, and the session key as the second parameter.
To do this, define a notification function, say NotifyFn:
function NotifyFn($expireref, $sesskey)
{
}
Then you need to define a global variable $ADODB_SESSION_EXPIRE_NOTIFY.
This is an array with 2 elements, the first being the name of the variable
you would like to store in the EXPIREREF field, and the 2nd is the
notification function's name.
In this example, we want to be notified when a user's session
has expired, so we store the user id in the global variable $USERID,
store this value in the EXPIREREF field:
$ADODB_SESSION_EXPIRE_NOTIFY = array('USERID','NotifyFn');
Then when the NotifyFn is called, we are passed the $USERID as the first
parameter, eg. NotifyFn($userid, $sesskey).
*/
if (!defined('_ADODB_LAYER')) {
include (dirname(__FILE__).'/adodb.inc.php');
}
if (!defined('ADODB_SESSION')) {
define('ADODB_SESSION',1);
/* if database time and system time is difference is greater than this, then give warning */
define('ADODB_SESSION_SYNCH_SECS',60);
/****************************************************************************************\
Global definitions
\****************************************************************************************/
GLOBAL $ADODB_SESSION_CONNECT,
$ADODB_SESSION_DRIVER,
$ADODB_SESSION_USER,
$ADODB_SESSION_PWD,
$ADODB_SESSION_DB,
$ADODB_SESS_CONN,
$ADODB_SESS_LIFE,
$ADODB_SESS_DEBUG,
$ADODB_SESSION_EXPIRE_NOTIFY,
$ADODB_SESSION_CRC,
$ADODB_SESSION_TBL;
$ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime');
if ($ADODB_SESS_LIFE <= 1) {
// bug in PHP 4.0.3 pl 1 -- how about other versions?
//print "<h3>Session Error: PHP.INI setting <i>session.gc_maxlifetime</i>not set: $ADODB_SESS_LIFE</h3>";
$ADODB_SESS_LIFE=1440;
}
$ADODB_SESSION_CRC = false;
//$ADODB_SESS_DEBUG = true;
//////////////////////////////////
/* SET THE FOLLOWING PARAMETERS */
//////////////////////////////////
if (empty($ADODB_SESSION_DRIVER)) {
$ADODB_SESSION_DRIVER='mysql';
$ADODB_SESSION_CONNECT='localhost';
$ADODB_SESSION_USER ='root';
$ADODB_SESSION_PWD ='';
$ADODB_SESSION_DB ='xphplens_2';
}
if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) {
$ADODB_SESSION_EXPIRE_NOTIFY = false;
}
// Made table name configurable - by David Johnson djohnson@inpro.net
if (empty($ADODB_SESSION_TBL)){
$ADODB_SESSION_TBL = 'sessions';
}
/*
$ADODB_SESS['driver'] = $ADODB_SESSION_DRIVER;
$ADODB_SESS['connect'] = $ADODB_SESSION_CONNECT;
$ADODB_SESS['user'] = $ADODB_SESSION_USER;
$ADODB_SESS['pwd'] = $ADODB_SESSION_PWD;
$ADODB_SESS['db'] = $ADODB_SESSION_DB;
$ADODB_SESS['life'] = $ADODB_SESS_LIFE;
$ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
$ADODB_SESS['debug'] = $ADODB_SESS_DEBUG;
$ADODB_SESS['table'] = $ADODB_SESS_TBL;
*/
/****************************************************************************************\
Create the connection to the database.
If $ADODB_SESS_CONN already exists, reuse that connection
\****************************************************************************************/
function adodb_sess_open($save_path, $session_name,$persist=true)
{
GLOBAL $ADODB_SESS_CONN;
if (isset($ADODB_SESS_CONN)) return true;
GLOBAL $ADODB_SESSION_CONNECT,
$ADODB_SESSION_DRIVER,
$ADODB_SESSION_USER,
$ADODB_SESSION_PWD,
$ADODB_SESSION_DB,
$ADODB_SESS_DEBUG;
// cannot use & below - do not know why...
$ADODB_SESS_CONN = ADONewConnection($ADODB_SESSION_DRIVER);
if (!empty($ADODB_SESS_DEBUG)) {
$ADODB_SESS_CONN->debug = true;
ADOConnection::outp( " conn=$ADODB_SESSION_CONNECT user=$ADODB_SESSION_USER pwd=$ADODB_SESSION_PWD db=$ADODB_SESSION_DB ");
}
if ($persist) $ok = $ADODB_SESS_CONN->PConnect($ADODB_SESSION_CONNECT,
$ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
else $ok = $ADODB_SESS_CONN->Connect($ADODB_SESSION_CONNECT,
$ADODB_SESSION_USER,$ADODB_SESSION_PWD,$ADODB_SESSION_DB);
if (!$ok) ADOConnection::outp( "<p>Session: connection failed</p>",false);
}
/****************************************************************************************\
Close the connection
\****************************************************************************************/
function adodb_sess_close()
{
global $ADODB_SESS_CONN;
if ($ADODB_SESS_CONN) $ADODB_SESS_CONN->Close();
return true;
}
/****************************************************************************************\
Slurp in the session variables and return the serialized string
\****************************************************************************************/
function adodb_sess_read($key)
{
global $ADODB_SESS_CONN,$ADODB_SESSION_TBL,$ADODB_SESSION_CRC;
$rs = $ADODB_SESS_CONN->Execute("SELECT data FROM $ADODB_SESSION_TBL WHERE sesskey = '$key' AND expiry >= " . time());
if ($rs) {
if ($rs->EOF) {
$v = '';
} else
$v = rawurldecode(reset($rs->fields));
$rs->Close();
// new optimization adodb 2.1
$ADODB_SESSION_CRC = strlen($v).crc32($v);
return $v;
}
return ''; // thx to Jorma Tuomainen, webmaster#wizactive.com
}
/****************************************************************************************\
Write the serialized data to a database.
If the data has not been modified since adodb_sess_read(), we do not write.
\****************************************************************************************/
function adodb_sess_write($key, $val)
{
global
$ADODB_SESS_CONN,
$ADODB_SESS_LIFE,
$ADODB_SESSION_TBL,
$ADODB_SESS_DEBUG,
$ADODB_SESSION_CRC,
$ADODB_SESSION_EXPIRE_NOTIFY;
$expiry = time() + $ADODB_SESS_LIFE;
// crc32 optimization since adodb 2.1
// now we only update expiry date, thx to sebastian thom in adodb 2.32
if ($ADODB_SESSION_CRC !== false && $ADODB_SESSION_CRC == strlen($val).crc32($val)) {
if ($ADODB_SESS_DEBUG) echo "<p>Session: Only updating date - crc32 not changed</p>";
$qry = "UPDATE $ADODB_SESSION_TBL SET expiry=$expiry WHERE sesskey='$key' AND expiry >= " . time();
$rs = $ADODB_SESS_CONN->Execute($qry);
return true;
}
$val = rawurlencode($val);
$arr = array('sesskey' => $key, 'expiry' => $expiry, 'data' => $val);
if ($ADODB_SESSION_EXPIRE_NOTIFY) {
$var = reset($ADODB_SESSION_EXPIRE_NOTIFY);
global $$var;
$arr['expireref'] = $$var;
}
$rs = $ADODB_SESS_CONN->Replace($ADODB_SESSION_TBL,$arr,
'sesskey',$autoQuote = true);
if (!$rs) {
ADOConnection::outp( '<p>Session Replace: '.$ADODB_SESS_CONN->ErrorMsg().'</p>',false);
} else {
// bug in access driver (could be odbc?) means that info is not commited
// properly unless select statement executed in Win2000
if ($ADODB_SESS_CONN->databaseType == 'access')
$rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'");
}
return !empty($rs);
}
function adodb_sess_destroy($key)
{
global $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
if ($ADODB_SESSION_EXPIRE_NOTIFY) {
reset($ADODB_SESSION_EXPIRE_NOTIFY);
$fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
$savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
$rs = $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
$ADODB_SESS_CONN->SetFetchMode($savem);
if ($rs) {
$ADODB_SESS_CONN->BeginTrans();
while (!$rs->EOF) {
$ref = $rs->fields[0];
$key = $rs->fields[1];
$fn($ref,$key);
$del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
$rs->MoveNext();
}
$ADODB_SESS_CONN->CommitTrans();
}
} else {
$qry = "DELETE FROM $ADODB_SESSION_TBL WHERE sesskey = '$key'";
$rs = $ADODB_SESS_CONN->Execute($qry);
}
return $rs ? true : false;
}
function adodb_sess_gc($maxlifetime)
{
global $ADODB_SESS_DEBUG, $ADODB_SESS_CONN, $ADODB_SESSION_TBL,$ADODB_SESSION_EXPIRE_NOTIFY;
if ($ADODB_SESSION_EXPIRE_NOTIFY) {
reset($ADODB_SESSION_EXPIRE_NOTIFY);
$fn = next($ADODB_SESSION_EXPIRE_NOTIFY);
$savem = $ADODB_SESS_CONN->SetFetchMode(ADODB_FETCH_NUM);
$t = time();
$rs =& $ADODB_SESS_CONN->Execute("SELECT expireref,sesskey FROM $ADODB_SESSION_TBL WHERE expiry < $t");
$ADODB_SESS_CONN->SetFetchMode($savem);
if ($rs) {
$ADODB_SESS_CONN->BeginTrans();
while (!$rs->EOF) {
$ref = $rs->fields[0];
$key = $rs->fields[1];
$fn($ref,$key);
$del = $ADODB_SESS_CONN->Execute("DELETE FROM $ADODB_SESSION_TBL WHERE sesskey='$key'");
$rs->MoveNext();
}
$rs->Close();
$ADODB_SESS_CONN->CommitTrans();
}
} else {
$qry = "DELETE FROM $ADODB_SESSION_TBL WHERE expiry < " . time();
$ADODB_SESS_CONN->Execute($qry);
if ($ADODB_SESS_DEBUG) ADOConnection::outp("<p><b>Garbage Collection</b>: $qry</p>");
}
// suggested by Cameron, "GaM3R" <gamr@outworld.cx>
if (defined('ADODB_SESSION_OPTIMIZE')) {
global $ADODB_SESSION_DRIVER;
switch( $ADODB_SESSION_DRIVER ) {
case 'mysql':
case 'mysqlt':
$opt_qry = 'OPTIMIZE TABLE '.$ADODB_SESSION_TBL;
break;
case 'postgresql':
case 'postgresql7':
$opt_qry = 'VACUUM '.$ADODB_SESSION_TBL;
break;
}
if (!empty($opt_qry)) {
$ADODB_SESS_CONN->Execute($opt_qry);
}
}
if ($ADODB_SESS_CONN->dataProvider === 'oci8') $sql = 'select TO_CHAR('.($ADODB_SESS_CONN->sysTimeStamp).', \'RRRR-MM-DD HH24:MI:SS\') from '. $ADODB_SESSION_TBL;
else $sql = 'select '.$ADODB_SESS_CONN->sysTimeStamp.' from '. $ADODB_SESSION_TBL;
$rs =& $ADODB_SESS_CONN->SelectLimit($sql,1);
if ($rs && !$rs->EOF) {
$dbts = reset($rs->fields);
$rs->Close();
$dbt = $ADODB_SESS_CONN->UnixTimeStamp($dbts);
$t = time();
if (abs($dbt - $t) >= ADODB_SESSION_SYNCH_SECS) {
global $HTTP_SERVER_VARS;
$msg =
__FILE__.": Server time for webserver {$HTTP_SERVER_VARS['HTTP_HOST']} not in synch with database: database=$dbt ($dbts), webserver=$t (diff=".(abs($dbt-$t)/3600)." hrs)";
error_log($msg);
if ($ADODB_SESS_DEBUG) ADOConnection::outp("<p>$msg</p>");
}
}
return true;
}
session_module_name('user');
session_set_save_handler(
"adodb_sess_open",
"adodb_sess_close",
"adodb_sess_read",
"adodb_sess_write",
"adodb_sess_destroy",
"adodb_sess_gc");
}
/* TEST SCRIPT -- UNCOMMENT */
if (0) {
GLOBAL $HTTP_SESSION_VARS;
session_start();
session_register('AVAR');
$HTTP_SESSION_VARS['AVAR'] += 1;
ADOConnection::outp( "<p>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</p>",false);
}
?>

View File

@ -0,0 +1,84 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>ADODB Benchmarks</title>
</head>
<body>
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Benchmark code to test the speed to the ADODB library with different databases.
This is a simplistic benchmark to be used as the basis for further testing.
It should not be used as proof of the superiority of one database over the other.
*/
$testmssql = true;
//$testvfp = true;
$testoracle = true;
$testado = true;
$testibase = true;
$testaccess = true;
$testmysql = true;
$testsqlite = true;;
set_time_limit(240); // increase timeout
include("../tohtml.inc.php");
include("../adodb.inc.php");
function testdb(&$db,$createtab="create table ADOXYZ (id int, firstname char(24), lastname char(24), created date)")
{
GLOBAL $ADODB_version,$ADODB_FETCH_MODE;
adodb_backtrace();
$max = 100;
$sql = 'select * from ADOXYZ';
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
//print "<h3>ADODB Version: $ADODB_version Host: <i>$db->host</i> &nbsp; Database: <i>$db->database</i></h3>";
// perform query once to cache results so we are only testing throughput
$rs = $db->Execute($sql);
if (!$rs){
print "Error in recordset<p>";
return;
}
$arr = $rs->GetArray();
//$db->debug = true;
global $ADODB_COUNTRECS;
$ADODB_COUNTRECS = false;
$start = microtime();
for ($i=0; $i < $max; $i++) {
$rs =& $db->Execute($sql);
$arr =& $rs->GetArray();
// print $arr[0][1];
}
$end = microtime();
$start = explode(' ',$start);
$end = explode(' ',$end);
//print_r($start);
//print_r($end);
// print_r($arr);
$total = $end[0]+trim($end[1]) - $start[0]-trim($start[1]);
printf ("<p>seconds = %8.2f for %d iterations each with %d records</p>",$total,$max, sizeof($arr));
flush();
//$db->Close();
}
include("testdatabases.inc.php");
?>
</body>
</html>

View File

@ -0,0 +1,233 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
*/
error_reporting(E_ALL);
include_once('../adodb.inc.php');
foreach(array('sybase','mysqlt','access','oci8','postgres','odbc_mssql','odbc','sybase','firebird','informix','db2') as $dbType) {
echo "<h3>$dbType</h3><p>";
$db = NewADOConnection($dbType);
$dict = NewDataDictionary($db);
if (!$dict) continue;
$dict->debug = 1;
$opts = array('REPLACE','mysql' => 'TYPE=INNODB', 'oci8' => 'TABLESPACE USERS');
/* $flds = array(
array('id', 'I',
'AUTO','KEY'),
array('name' => 'firstname', 'type' => 'varchar','size' => 30,
'DEFAULT'=>'Joan'),
array('lastname','varchar',28,
'DEFAULT'=>'Chen','key'),
array('averylonglongfieldname','X',1024,
'NOTNULL','default' => 'test'),
array('price','N','7.2',
'NOTNULL','default' => '0.00'),
array('MYDATE', 'D',
'DEFDATE'),
array('TS','T',
'DEFTIMESTAMP')
);*/
$flds = "
ID I AUTO KEY,
FIRSTNAME VARCHAR(30) DEFAULT 'Joan',
LASTNAME VARCHAR(28) DEFAULT 'Chen' key,
averylonglongfieldname X(1024) DEFAULT 'test',
price N(7.2) DEFAULT '0.00',
MYDATE D DEFDATE,
BIGFELLOW X NOTNULL,
TS T DEFTIMESTAMP";
$sqla = $dict->CreateDatabase('KUTU',array('postgres'=>"LOCATION='/u01/postdata'"));
$dict->SetSchema('KUTU');
$sqli = ($dict->CreateTableSQL('testtable',$flds, $opts));
$sqla =& array_merge($sqla,$sqli);
$sqli = $dict->CreateIndexSQL('idx','testtable','firstname,lastname',array('BITMAP','FULLTEXT','CLUSTERED','HASH'));
$sqla =& array_merge($sqla,$sqli);
$sqli = $dict->CreateIndexSQL('idx2','testtable','price,lastname');//,array('BITMAP','FULLTEXT','CLUSTERED'));
$sqla =& array_merge($sqla,$sqli);
$addflds = array(array('height', 'F'),array('weight','F'));
$sqli = $dict->AddColumnSQL('testtable',$addflds);
$sqla =& array_merge($sqla,$sqli);
$addflds = array(array('height', 'F','NOTNULL'),array('weight','F','NOTNULL'));
$sqli = $dict->AlterColumnSQL('testtable',$addflds);
$sqla =& array_merge($sqla,$sqli);
printsqla($dbType,$sqla);
if (file_exists('d:\inetpub\wwwroot\php\phplens\adodb\adodb.inc.php'))
if ($dbType == 'mysql') {
$db->Connect('localhost', "root", "", "test");
$dict->SetSchema('');
$sqla2 = $dict->ChangeTableSQL('adoxyz',$flds);
if ($sqla2) printsqla($dbType,$sqla2);
}
if ($dbType == 'postgres') {
$db->Connect('localhost', "tester", "test", "test");
$dict->SetSchema('');
$sqla2 = $dict->ChangeTableSQL('adoxyz',$flds);
if ($sqla2) printsqla($dbType,$sqla2);
}
}
function printsqla($dbType,$sqla)
{
print "<pre>";
//print_r($dict->MetaTables());
foreach($sqla as $s) {
$s = htmlspecialchars($s);
print "$s;\n";
if ($dbType == 'oci8') print "/\n";
}
print "</pre><hr>";
}
/***
Generated SQL:
mysql
CREATE DATABASE KUTU;
DROP TABLE KUTU.testtable;
CREATE TABLE KUTU.testtable (
id INTEGER NOT NULL AUTO_INCREMENT,
firstname VARCHAR(30) DEFAULT 'Joan',
lastname VARCHAR(28) NOT NULL DEFAULT 'Chen',
averylonglongfieldname LONGTEXT NOT NULL,
price NUMERIC(7,2) NOT NULL DEFAULT 0.00,
MYDATE DATE DEFAULT CURDATE(),
PRIMARY KEY (id, lastname)
)TYPE=ISAM;
CREATE FULLTEXT INDEX idx ON KUTU.testtable (firstname,lastname);
CREATE INDEX idx2 ON KUTU.testtable (price,lastname);
ALTER TABLE KUTU.testtable ADD height DOUBLE;
ALTER TABLE KUTU.testtable ADD weight DOUBLE;
ALTER TABLE KUTU.testtable MODIFY COLUMN height DOUBLE NOT NULL;
ALTER TABLE KUTU.testtable MODIFY COLUMN weight DOUBLE NOT NULL;
--------------------------------------------------------------------------------
oci8
CREATE USER KUTU IDENTIFIED BY tiger;
/
GRANT CREATE SESSION, CREATE TABLE,UNLIMITED TABLESPACE,CREATE SEQUENCE TO KUTU;
/
DROP TABLE KUTU.testtable CASCADE CONSTRAINTS;
/
CREATE TABLE KUTU.testtable (
id NUMBER(16) NOT NULL,
firstname VARCHAR(30) DEFAULT 'Joan',
lastname VARCHAR(28) DEFAULT 'Chen' NOT NULL,
averylonglongfieldname CLOB NOT NULL,
price NUMBER(7,2) DEFAULT 0.00 NOT NULL,
MYDATE DATE DEFAULT TRUNC(SYSDATE),
PRIMARY KEY (id, lastname)
)TABLESPACE USERS;
/
DROP SEQUENCE KUTU.SEQ_testtable;
/
CREATE SEQUENCE KUTU.SEQ_testtable;
/
CREATE OR REPLACE TRIGGER KUTU.TRIG_SEQ_testtable BEFORE insert ON KUTU.testtable
FOR EACH ROW
BEGIN
select KUTU.SEQ_testtable.nextval into :new.id from dual;
END;
/
CREATE BITMAP INDEX idx ON KUTU.testtable (firstname,lastname);
/
CREATE INDEX idx2 ON KUTU.testtable (price,lastname);
/
ALTER TABLE testtable ADD (
height NUMBER,
weight NUMBER);
/
ALTER TABLE testtable MODIFY(
height NUMBER NOT NULL,
weight NUMBER NOT NULL);
/
--------------------------------------------------------------------------------
postgres
AlterColumnSQL not supported for PostgreSQL
CREATE DATABASE KUTU LOCATION='/u01/postdata';
DROP TABLE KUTU.testtable;
CREATE TABLE KUTU.testtable (
id SERIAL,
firstname VARCHAR(30) DEFAULT 'Joan',
lastname VARCHAR(28) DEFAULT 'Chen' NOT NULL,
averylonglongfieldname TEXT NOT NULL,
price NUMERIC(7,2) DEFAULT 0.00 NOT NULL,
MYDATE DATE DEFAULT CURRENT_DATE,
PRIMARY KEY (id, lastname)
);
CREATE INDEX idx ON KUTU.testtable USING HASH (firstname,lastname);
CREATE INDEX idx2 ON KUTU.testtable (price,lastname);
ALTER TABLE KUTU.testtable ADD height FLOAT8;
ALTER TABLE KUTU.testtable ADD weight FLOAT8;
--------------------------------------------------------------------------------
odbc_mssql
CREATE DATABASE KUTU;
DROP TABLE KUTU.testtable;
CREATE TABLE KUTU.testtable (
id INT IDENTITY(1,1) NOT NULL,
firstname VARCHAR(30) DEFAULT 'Joan',
lastname VARCHAR(28) DEFAULT 'Chen' NOT NULL,
averylonglongfieldname TEXT NOT NULL,
price NUMERIC(7,2) DEFAULT 0.00 NOT NULL,
MYDATE DATETIME DEFAULT GetDate(),
PRIMARY KEY (id, lastname)
);
CREATE CLUSTERED INDEX idx ON KUTU.testtable (firstname,lastname);
CREATE INDEX idx2 ON KUTU.testtable (price,lastname);
ALTER TABLE KUTU.testtable ADD
height REAL,
weight REAL;
ALTER TABLE KUTU.testtable ALTER COLUMN height REAL NOT NULL;
ALTER TABLE KUTU.testtable ALTER COLUMN weight REAL NOT NULL;
--------------------------------------------------------------------------------
*/
echo "<h1>Test XML Schema</h1>";
$ff = file('xmlschema.xml');
echo "<pre>";
foreach($ff as $xml) echo htmlspecialchars($xml);
echo "</pre>";
include_once('test-xmlschema.php');
?>

View File

@ -0,0 +1,68 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 8.
*/
error_reporting(E_ALL);
$path = dirname(__FILE__);
include("$path/../adodb-exceptions.inc.php");
include("$path/../adodb.inc.php");
echo "<h3>PHP ".PHP_VERSION."</h3>\n";
try {
$dbt = 'oci8po';
switch($dbt) {
case 'oci8po':
$db = NewADOConnection("oci8po");
$db->Connect('','scott','natsoft');
break;
default:
case 'mysql':
$db = NewADOConnection("mysql");
$db->Connect('localhost','root','','test');
break;
case 'mysqli':
$db = NewADOConnection("mysqli://root:@localhost/test");
//$db->Connect('localhost','root','','test');
break;
}
$db->debug=1;
$cnt = $db->GetOne("select count(*) from adoxyz where ?<id and id<?",array(10,20));
$stmt = $db->Prepare("select * from adoxyz where ?<id and id<?");
if (!$stmt) echo $db->ErrorMsg(),"\n";
$rs = $db->Execute($stmt,array(10,20));
$i = 0;
foreach($rs as $v) {
$i += 1;
echo "rec $i: "; adodb_pr($v); adodb_pr($rs->fields);
flush();
}
if ($i != $cnt) die("actual cnt is $i, cnt should be $cnt\n");
$rs = $db->Execute("select bad from badder");
} catch (exception $e) {
adodb_pr($e);
echo "<h3>adodb_backtrace:</h3>\n";
$e = adodb_backtrace($e->gettrace());
}
$rs = $db->Execute("select distinct id, firstname,lastname from adoxyz order by id");
echo "Result=\n",$rs;
?>

View File

@ -0,0 +1,53 @@
<?PHP
// V4.50 6 July 2004
error_reporting(E_ALL);
require( "../adodb-xmlschema.inc.php" );
// To build the schema, start by creating a normal ADOdb connection:
$db = ADONewConnection( 'mysql' );
$db->Connect( 'localhost', 'root', '', 'schematest' );
// To create a schema object and build the query array.
$schema = new adoSchema( $db );
// To upgrade an existing schema object, use the following
// To upgrade an existing database to the provided schema,
// uncomment the following line:
#$schema->upgradeSchema();
print "<b>SQL to build xmlschema.xml</b>:\n<pre>";
// Build the SQL array
$sql = $schema->ParseSchema( "xmlschema.xml" );
print_r( $sql );
print "</pre>\n";
// Execute the SQL on the database
//$result = $schema->ExecuteSchema( $sql );
// Finally, clean up after the XML parser
// (PHP won't do this for you!)
//$schema->Destroy();
$db2 = ADONewConnection('mssql');
$db2->Connect('localhost','sa','natsoft','northwind') || die("Fail 2");
$db2->Execute("drop table simple_table");
print "<b>SQL to build xmlschema-mssql.xml</b>:\n<pre>";
$schema = new adoSchema( $db2 );
$sql = $schema->ParseSchema( "xmlschema-mssql.xml" );
print_r( $sql );
print "</pre>\n";
$db2->debug=1;
$db2->Execute($sql[0]);
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Untitled</title>
</head>
<body>
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 8.
*/
#
# test connecting to 2 MySQL databases simultaneously and ensure that each connection
# is independant.
#
include("../tohtml.inc.php");
include("../adodb.inc.php");
ADOLoadCode('mysql');
$c1 = ADONewConnection('oci8');
if (!$c1->PConnect('','scott','tiger'))
die("Cannot connect to server");
$c1->debug=1;
$rs = $c1->Execute('select rownum, p1.firstname,p2.lastname,p2.firstname,p1.lastname from adoxyz p1, adoxyz p2');
print "Records=".$rs->RecordCount()."<br><pre>";
//$rs->_array = false;
//$rs->connection = false;
//print_r($rs);
rs2html($rs);
?>
</body>
</html>

View File

@ -0,0 +1,44 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 8.
*/
error_reporting(E_ALL);
$path = dirname(__FILE__);
include("$path/../adodb-exceptions.inc.php");
include("$path/../adodb.inc.php");
try {
$db = NewADOConnection("oci8");
$db->Connect('','scott','natsoft');
$db->debug=1;
$cnt = $db->GetOne("select count(*) from adoxyz");
$rs = $db->Execute("select * from adoxyz order by id");
$i = 0;
foreach($rs as $k => $v) {
$i += 1;
echo $k; adodb_pr($v);
flush();
}
if ($i != $cnt) die("actual cnt is $i, cnt should be $cnt\n");
$rs = $db->Execute("select bad from badder");
} catch (exception $e) {
adodb_pr($e);
$e = adodb_backtrace($e->trace);
}
?>

View File

@ -0,0 +1,95 @@
<?php
/**
* @version V4.50 6 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
* Released under both BSD license and Lesser GPL library license.
* Whenever there is any discrepancy between the two licenses,
* the BSD license will take precedence.
*
* Set tabs to 4 for best viewing.
*
* Latest version is available at http://php.weblogs.com
*
* Test GetUpdateSQL and GetInsertSQL.
*/
error_reporting(E_ALL);
function testsql()
{
//define('ADODB_FORCE_NULLS',1);
include('../adodb.inc.php');
include('../tohtml.inc.php');
//==========================
// This code tests an insert
$sql = "
SELECT *
FROM ADOXYZ WHERE id = -1";
// Select an empty record from the database
$conn = &ADONewConnection("mysql"); // create a connection
$conn->PConnect("localhost", "root", "", "test"); // connect to MySQL, testdb
//$conn =& ADONewConnection('oci8');
//$conn->Connect('','scott','natsoft');
//$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
$conn->debug=1;
$conn->Execute("delete from adoxyz where lastname like 'Smith%'");
$rs = $conn->Execute($sql); // Execute the query and get the empty recordset
$record = array(); // Initialize an array to hold the record data to insert
// Set the values for the fields in the record
$record["firstname"] = 'null';
$record["lastname"] = "Smith\$@//";
$record["created"] = time();
//$record["id"] = -1;
// Pass the empty recordset and the array containing the data to insert
// into the GetInsertSQL function. The function will process the data and return
// a fully formatted insert sql statement.
$insertSQL = $conn->GetInsertSQL($rs, $record);
$conn->Execute($insertSQL); // Insert the record into the database
$insertSQL2 = $conn->GetInsertSQL($table='ADOXYZ', $record);
if ($insertSQL != $insertSQL2) echo "<p><b>Walt's new stuff failed</b>: $insertSQL2</p>";
//==========================
// This code tests an update
$sql = "
SELECT *
FROM ADOXYZ WHERE lastname=".$conn->qstr($record['lastname']). " ORDER BY 1";
// Select a record to update
$rs = $conn->Execute($sql); // Execute the query and get the existing record to update
if (!$rs) print "<p><b>No record found!</b></p>";
$record = array(); // Initialize an array to hold the record data to update
// Set the values for the fields in the record
$record["firstName"] = "Caroline".rand();
$record["lasTname"] = "Smithy Jones"; // Update Caroline's lastname from Miranda to Smith
$record["creAted"] = '2002-12-'.(rand()%30+1);
$record['num'] = 3921;
// Pass the single record recordset and the array containing the data to update
// into the GetUpdateSQL function. The function will process the data and return
// a fully formatted update sql statement.
// If the data has not changed, no recordset is returned
$updateSQL = $conn->GetUpdateSQL($rs, $record);
$conn->Execute($updateSQL); // Update the record in the database
if ($conn->Affected_Rows() != 1)print "<p><b>Error</b>: Rows Affected=".$conn->Affected_Rows().", should be 1</p>";
$rs = $conn->Execute("select * from adoxyz where lastname like 'Smith%'");
adodb_pr($rs);
rs2html($rs);
}
testsql();
?>

View File

@ -0,0 +1,47 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
*/
// Select an empty record from the database
include('../adodb.inc.php');
include('../tohtml.inc.php');
include('../adodb-errorpear.inc.php');
if (0) {
$conn = &ADONewConnection('mysql');
$conn->debug=1;
$conn->PConnect("localhost","root","","xphplens");
print $conn->databaseType.':'.$conn->GenID().'<br>';
}
if (0) {
$conn = &ADONewConnection("oci8"); // create a connection
$conn->debug=1;
$conn->PConnect("falcon", "scott", "tiger", "juris8.ecosystem.natsoft.com.my"); // connect to MySQL, testdb
print $conn->databaseType.':'.$conn->GenID();
}
if (0) {
$conn = &ADONewConnection("ibase"); // create a connection
$conn->debug=1;
$conn->Connect("localhost:c:\\Interbase\\Examples\\Database\\employee.gdb", "sysdba", "masterkey", ""); // connect to MySQL, testdb
print $conn->databaseType.':'.$conn->GenID().'<br>';
}
if (0) {
$conn = &ADONewConnection('postgres');
$conn->debug=1;
@$conn->PConnect("susetikus","tester","test","test");
print $conn->databaseType.':'.$conn->GenID().'<br>';
}
?>

View File

@ -0,0 +1,29 @@
<html>
<body>
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
*/
$ADODB_CACHE_DIR = dirname(tempnam('/tmp',''));
include("../adodb.inc.php");
if (isset($access)) {
$db=ADONewConnection('access');
$db->PConnect('nwind');
} else {
$db = ADONewConnection('mysql');
$db->PConnect('mangrove','root','','xphplens');
}
if (isset($cache)) $rs = $db->CacheExecute(120,'select * from products');
else $rs = $db->Execute('select * from products');
$arr = $rs->GetArray();
print sizeof($arr);
?>

View File

@ -0,0 +1,300 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
*/
/* this file is used by the ADODB test program: test.php */
?>
<table><tr valign=top><td>
<form method=get>
<input type=checkbox name="testaccess" value=1 <?php echo !empty($testaccess) ? 'checked' : '' ?>> <b>Access</b><br>
<input type=checkbox name="testibase" value=1 <?php echo !empty($testibase) ? 'checked' : '' ?>> <b>Interbase</b><br>
<input type=checkbox name="testmssql" value=1 <?php echo !empty($testmssql) ? 'checked' : '' ?>> <b>MSSQL</b><br>
<input type=checkbox name="testmysql" value=1 <?php echo !empty($testmysql) ? 'checked' : '' ?>> <b>MySQL</b><br>
<input type=checkbox name="testmysqlodbc" value=1 <?php echo !empty($testmysqlodbc) ? 'checked' : '' ?>> <b>MySQL ODBC</b><br>
<td><input type=checkbox name="testsqlite" value=1 <?php echo !empty($testsqlite) ? 'checked' : '' ?>> <b>SQLite</b><br>
<input type=checkbox name="testproxy" value=1 <?php echo !empty($testproxy) ? 'checked' : '' ?>> <b>MySQL Proxy</b><br>
<input type=checkbox name="testoracle" value=1 <?php echo !empty($testoracle) ? 'checked' : '' ?>> <b>Oracle (oci8)</b> <br>
<input type=checkbox name="testpostgres" value=1 <?php echo !empty($testpostgres) ? 'checked' : '' ?>> <b>PostgreSQL</b><br>
<input type=checkbox name="testpgodbc" value=1 <?php echo !empty($testpgodbc) ? 'checked' : '' ?>> <b>PostgreSQL ODBC</b><br>
<td><input type=checkbox name="testdb2" value=1 <?php echo !empty($testdb2) ? 'checked' : '' ?>> DB2<br>
<input type=checkbox name="testvfp" value=1 <?php echo !empty($testvfp) ? 'checked' : '' ?>> VFP<br>
<input type=checkbox name="testado" value=1 <?php echo !empty($testado) ? 'checked' : '' ?>> ADO (for mssql and access)<br>
<input type=checkbox name="nocountrecs" value=1 <?php echo !empty($nocountrecs) ? 'checked' : '' ?>> $ADODB_COUNTRECS=false<br>
<input type=checkbox name="nolog" value=1 <?php echo !empty($nolog) ? 'checked' : '' ?>> No SQL Logging<br>
<td><input type=submit>
</form>
</table>
<?php
if ($ADODB_FETCH_MODE != ADODB_FETCH_DEFAULT) print "<h3>FETCH MODE IS NOT ADODB_FETCH_DEFAULT</h3>";
if (isset($nocountrecs)) $ADODB_COUNTRECS = false;
// cannot test databases below, but we include them anyway to check
// if they parse ok...
if (!strpos(PHP_VERSION,'5') === 0) {
ADOLoadCode("sybase");
ADOLoadCode("postgres");
ADOLoadCode("postgres7");
ADOLoadCode("firebird");
ADOLoadCode("borland_ibase");
ADOLoadCode("informix");
ADOLoadCode("sqlanywhere");
// ADOLoadCode('mysqli');
}
flush();
if (!empty($testpostgres)) {
//ADOLoadCode("postgres");
$db = &ADONewConnection('postgres');
print "<h1>Connecting $db->databaseType...</h1>";
if ($db->Connect("localhost","tester","test","test")) {
testdb($db,"create table ADOXYZ (id integer, firstname char(24), lastname varchar,created date)");
}else
print "ERROR: PostgreSQL requires a database called test on server, user tester, password test.<BR>".$db->ErrorMsg();
}
if (!empty($testpgodbc)) {
$db = &ADONewConnection('odbc');
$db->hasTransactions = false;
print "<h1>Connecting $db->databaseType...</h1>";
if ($db->PConnect('Postgresql')) {
$db->hasTransactions = true;
testdb($db,
"create table ADOXYZ (id int, firstname char(24), lastname char(24), created date) type=innodb");
} else print "ERROR: PostgreSQL requires a database called test on server, user tester, password test.<BR>".$db->ErrorMsg();
}
if (!empty($testibase)) {
//$_GET['nolog'] = true;
$db = &ADONewConnection('firebird');
print "<h1>Connecting $db->databaseType...</h1>";
if ($db->PConnect("localhost:d:\\firebird\\10\\examples\\employee.gdb", "sysdba", "masterkey", ""))
testdb($db,"create table ADOXYZ (id integer, firstname char(24), lastname char(24),price numeric(12,2),created date)");
else print "ERROR: Interbase test requires a database called employee.gdb".'<BR>'.$db->ErrorMsg();
}
if (!empty($testsqlite)) {
$db = &ADONewConnection('sqlite');
print "<h1>Connecting $db->databaseType...</h1>";
if ($db->PConnect("d:\\inetpub\\adodb\\sqlite.db", "", "", ""))
testdb($db,"create table ADOXYZ (id int, firstname char(24), lastname char(24),created datetime)");
else print "ERROR: SQLite";
}
// REQUIRES ODBC DSN CALLED nwind
if (!empty($testaccess)) {
$db = &ADONewConnection('access');
print "<h1>Connecting $db->databaseType...</h1>";
$access = 'd:\inetpub\wwwroot\php\NWIND.MDB';
$dsn = "nwind";
$dsn = "Driver={Microsoft Access Driver (*.mdb)};Dbq=$access;Uid=Admin;Pwd=;";
//$dsn = 'Provider=Microsoft.Jet.OLEDB.4.0;DATA SOURCE=' . $access . ';';
if ($db->PConnect($dsn, "", "", ""))
testdb($db,"create table ADOXYZ (id int, firstname char(24), lastname char(24),created datetime)");
else print "ERROR: Access test requires a Windows ODBC DSN=nwind, Access driver";
}
if (!empty($testaccess) && !empty($testado)) { // ADO ACCESS
$db = &ADONewConnection("ado_access");
print "<h1>Connecting $db->databaseType...</h1>";
$access = 'd:\inetpub\wwwroot\php\NWIND.MDB';
$myDSN = 'PROVIDER=Microsoft.Jet.OLEDB.4.0;'
. 'DATA SOURCE=' . $access . ';';
//. 'USER ID=;PASSWORD=;';
if ($db->PConnect($myDSN, "", "", "")) {
print "ADO version=".$db->_connectionID->version."<br>";
testdb($db,"create table ADOXYZ (id int, firstname char(24), lastname char(24),created datetime)");
} else print "ERROR: Access test requires a Access database $access".'<BR>'.$db->ErrorMsg();
}
if (!empty($testvfp)) { // ODBC
$db = &ADONewConnection('vfp');
print "<h1>Connecting $db->databaseType...</h1>";flush();
if ( $db->PConnect("vfp-adoxyz")) {
testdb($db,"create table d:\\inetpub\\adodb\\ADOXYZ (id int, firstname char(24), lastname char(24),created date)");
} else print "ERROR: Visual FoxPro test requires a Windows ODBC DSN=vfp-adoxyz, VFP driver";
}
// REQUIRES MySQL server at localhost with database 'test'
if (!empty($testmysql)) { // MYSQL
if (PHP_VERSION >= 5 || $HTTP_SERVER_VARS['HTTP_HOST'] == 'localhost') $server = 'localhost';
else $server = "mangrove";
$user = 'root'; $password = ''; $database = 'northwind';
$db = &ADONewConnection("mysql://$user:$password@$server/$database?persist");
print "<h1>Connecting $db->databaseType...</h1>";
if (true || $db->PConnect($server, "root", "", "northwind")) {
//$db->debug=1;$db->Execute('drop table ADOXYZ');
testdb($db,
"create table ADOXYZ (id int, firstname char(24), lastname char(24), created date)");
} else print "ERROR: MySQL test requires a MySQL server on localhost, userid='admin', password='', database='test'".'<BR>'.$db->ErrorMsg();
}
// REQUIRES MySQL server at localhost with database 'test'
if (!empty($testmysqli)) { // MYSQL
$db = &ADONewConnection('mysqli');
print "<h1>Connecting $db->databaseType...</h1>";
if (PHP_VERSION >= 5 || $HTTP_SERVER_VARS['HTTP_HOST'] == 'localhost') $server = 'localhost';
else $server = "mangrove";
if ($db->PConnect($server, "root", "", "northwind")) {
//$db->debug=1;$db->Execute('drop table ADOXYZ');
testdb($db,
"create table ADOXYZ (id int, firstname char(24), lastname char(24), created date)");
} else print "ERROR: MySQL test requires a MySQL server on localhost, userid='admin', password='', database='test'".'<BR>'.$db->ErrorMsg();
}
// REQUIRES MySQL server at localhost with database 'test'
if (!empty($testmysqlodbc)) { // MYSQL
$db = &ADONewConnection('odbc');
$db->hasTransactions = false;
print "<h1>Connecting $db->databaseType...</h1>";
if ($HTTP_SERVER_VARS['HTTP_HOST'] == 'localhost') $server = 'localhost';
else $server = "mangrove";
if ($db->PConnect('mysql', "root", ""))
testdb($db,
"create table ADOXYZ (id int, firstname char(24), lastname char(24), created date) type=innodb");
else print "ERROR: MySQL test requires a MySQL server on localhost, userid='admin', password='', database='test'".'<BR>'.$db->ErrorMsg();
}
if (!empty($testproxy)){
$db = &ADONewConnection('proxy');
print "<h1>Connecting $db->databaseType...</h1>";
if ($HTTP_SERVER_VARS['HTTP_HOST'] == 'localhost') $server = 'localhost';
if ($db->PConnect('http://localhost/php/phplens/adodb/server.php'))
testdb($db,
"create table ADOXYZ (id int, firstname char(24), lastname char(24), created date) type=innodb");
else print "ERROR: MySQL test requires a MySQL server on localhost, userid='admin', password='', database='test'".'<BR>'.$db->ErrorMsg();
}
ADOLoadCode('oci805');
ADOLoadCode("oci8po");
if (!empty($testoracle)) {
$dsn = "oci8po://scott:natsoft@panther?persist";
$db = ADONewConnection($dsn);
print "<h1>Connecting $db->databaseType...</h1>";
if (true || $db->Connect('', "scott", "natsoft",''))
testdb($db,"create table ADOXYZ (id int, firstname varchar(24), lastname varchar(24),created date)");
else print "ERROR: Oracle test requires an Oracle server setup with scott/natsoft".'<BR>'.$db->ErrorMsg();
}
ADOLoadCode("oracle"); // no longer supported
if (false && !empty($testoracle)) {
$db = ADONewConnection();
print "<h1>Connecting $db->databaseType...</h1>";
if ($db->PConnect("", "scott", "tiger", "natsoft.domain"))
testdb($db,"create table ADOXYZ (id int, firstname varchar(24), lastname varchar(24),created date)");
else print "ERROR: Oracle test requires an Oracle server setup with scott/tiger".'<BR>'.$db->ErrorMsg();
}
ADOLoadCode("db2"); // no longer supported
if (!empty($testdb2)) {
$db = ADONewConnection();
print "<h1>Connecting $db->databaseType...</h1>";
if ($db->Connect("db2_sample", "root", "natsoft", ""))
testdb($db,"create table ADOXYZ (id int, firstname varchar(24), lastname varchar(24),created date)");
else print "ERROR: DB2 test requires an server setup with odbc data source db2_sample".'<BR>'.$db->ErrorMsg();
}
ADOLoadCode('odbc_mssql');
if (!empty($testmssql)) { // MS SQL Server via ODBC
$db = ADONewConnection();
print "<h1>Connecting $db->databaseType...</h1>";
$dsn = "PROVIDER=MSDASQL;Driver={SQL Server};Server=localhost;Database=northwind;";
if ($db->PConnect($dsn, "adodb", "natsoft", "")) {
testdb($db,"create table ADOXYZ (id int, firstname char(24) null, lastname char(24) null,created datetime null)");
}
else print "ERROR: MSSQL test 1 requires a MS SQL 7 server setup with DSN setup";
}
ADOLoadCode("ado_mssql");
if (!empty($testmssql) && !empty($testado) ) { // ADO ACCESS MSSQL -- thru ODBC -- DSN-less
$db = &ADONewConnection("ado_mssql");
//$db->debug=1;
print "<h1>Connecting DSN-less $db->databaseType...</h1>";
$myDSN="PROVIDER=MSDASQL;DRIVER={SQL Server};"
. "SERVER=tigress;DATABASE=NorthWind;UID=adodb;PWD=natsoft;Trusted_Connection=No" ;
if ($db->PConnect($myDSN, "", "", ""))
testdb($db,"create table ADOXYZ (id int, firstname char(24) null, lastname char(24) null,created datetime null)");
else print "ERROR: MSSQL test 2 requires MS SQL 7";
}
ADOLoadCode("mssqlpo");
if (!empty($testmssql)) { // MS SQL Server -- the extension is buggy -- probably better to use ODBC
$db = ADONewConnection("mssqlpo");
//$db->debug=1;
print "<h1>Connecting $db->databaseType...</h1>";
$ok = $db->PConnect('tigress','adodb','natsoft','northwind');
if ($ok or $db->PConnect("mangrove", "sa", "natsoft", "ai")) {
AutoDetect_MSSQL_Date_Order($db);
// $db->Execute('drop table adoxyz');
testdb($db,"create table ADOXYZ (id int, firstname char(24) null, lastname char(24) null,created datetime null)");
} else print "ERROR: MSSQL test 2 requires a MS SQL 7 on a server='192.168.0.1', userid='sa', password='natsoft', database='ai'".'<BR>'.$db->ErrorMsg();
}
if (!empty($testmssql) && !empty($testado)) { // ADO ACCESS MSSQL with OLEDB provider
$db = &ADONewConnection("ado_mssql");
print "<h1>Connecting DSN-less OLEDB Provider $db->databaseType...</h1>";
//$db->debug=1;
$myDSN="SERVER=tigress;DATABASE=northwind;Trusted_Connection=yes";
if ($db->PConnect($myDSN, "adodb", "natsoft", 'SQLOLEDB'))
testdb($db,"create table ADOXYZ (id int, firstname char(24), lastname char(24),created datetime)");
else print "ERROR: MSSQL test 2 requires a MS SQL 7 on a server='mangrove', userid='sa', password='', database='ai'";
}
print "<h3>Tests Completed</h3>";
?>

View File

@ -0,0 +1,83 @@
<html>
<body>
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
*/
error_reporting(63);
include("../adodb.inc.php");
include("../tohtml.inc.php");
if (0) {
$db = ADONewConnection('oci8po');
$db->PConnect('','scott','natsoft');
if (!empty($testblob)) {
$varHoldingBlob = 'ABC DEF GEF John TEST';
$num = time()%10240;
// create table atable (id integer, ablob blob);
$db->Execute('insert into ATABLE (id,ablob) values('.$num.',empty_blob())');
$db->UpdateBlob('ATABLE', 'ablob', $varHoldingBlob, 'id='.$num, 'BLOB');
$rs = &$db->Execute('select * from atable');
if (!$rs) die("Empty RS");
if ($rs->EOF) die("EOF RS");
rs2html($rs);
}
$stmt = $db->Prepare('select * from adoxyz where id=?');
for ($i = 1; $i <= 10; $i++) {
$rs = &$db->Execute(
$stmt,
array($i));
if (!$rs) die("Empty RS");
if ($rs->EOF) die("EOF RS");
rs2html($rs);
}
}
if (1) {
$db = ADONewConnection('oci8');
$db->PConnect('','scott','natsoft');
$db->debug = true;
$db->Execute("delete from emp where ename='John'");
print $db->Affected_Rows().'<BR>';
$stmt = &$db->Prepare('insert into emp (empno, ename) values (:empno, :ename)');
$rs = $db->Execute($stmt,array('empno'=>4321,'ename'=>'John'));
// prepare not quite ready for prime time
//$rs = $db->Execute($stmt,array('empno'=>3775,'ename'=>'John'));
if (!$rs) die("Empty RS");
$db->setfetchmode(ADODB_FETCH_NUM);
$vv = 'A%';
$stmt = $db->PrepareSP("BEGIN adodb.open_tab2(:rs,:tt); END;",true);
$db->OutParameter($stmt, $cur, 'rs', -1, OCI_B_CURSOR);
$db->OutParameter($stmt, $vv, 'tt');
$rs = $db->Execute($stmt);
while (!$rs->EOF) {
adodb_pr($rs->fields);
$rs->MoveNext();
}
echo " val = $vv";
}
if (0) {
$db = ADONewConnection('odbc_oracle');
if (!$db->PConnect('local_oracle','scott','tiger')) die('fail connect');
$db->debug = true;
$rs = &$db->Execute(
'select * from adoxyz where firstname=? and trim(lastname)=?',
array('first'=>'Caroline','last'=>'Miranda'));
if (!$rs) die("Empty RS");
if ($rs->EOF) die("EOF RS");
rs2html($rs);
}
?>

View File

@ -0,0 +1,111 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
*/
/*
Test for Oracle Variable Cursors, which are treated as ADOdb recordsets.
We have 2 examples. The first shows us using the Parameter statement.
The second shows us using the new ExecuteCursor($sql, $cursorName)
function.
------------------------------------------------------------------
-- TEST PACKAGE YOU NEED TO INSTALL ON ORACLE - run from sql*plus
------------------------------------------------------------------
-- TEST PACKAGE
CREATE OR REPLACE PACKAGE adodb AS
TYPE TabType IS REF CURSOR RETURN tab%ROWTYPE;
PROCEDURE open_tab (tabcursor IN OUT TabType,tablenames in varchar);
PROCEDURE data_out(input IN varchar, output OUT varchar);
procedure myproc (p1 in number, p2 out number);
END adodb;
/
CREATE OR REPLACE PACKAGE BODY adodb AS
PROCEDURE open_tab (tabcursor IN OUT TabType,tablenames in varchar) IS
BEGIN
OPEN tabcursor FOR SELECT * FROM tab where tname like tablenames;
END open_tab;
PROCEDURE data_out(input IN varchar, output OUT varchar) IS
BEGIN
output := 'Cinta Hati '||input;
END;
procedure myproc (p1 in number, p2 out number) as
begin
p2 := p1;
end;
END adodb;
/
------------------------------------------------------------------
-- END PACKAGE
------------------------------------------------------------------
*/
include('../adodb.inc.php');
include('../tohtml.inc.php');
error_reporting(E_ALL);
$db = ADONewConnection('oci8');
$db->PConnect('','scott','natsoft');
$db->debug = 99;
/*
*/
define('MYNUM',5);
$rs = $db->ExecuteCursor("BEGIN adodb.open_tab(:RS,'A%'); END;");
if ($rs && !$rs->EOF) {
print "Test 1 RowCount: ".$rs->RecordCount()."<p>";
} else {
print "<b>Error in using Cursor Variables 1</b><p>";
}
print "<h4>Testing Stored Procedures for oci8</h4>";
$stid = $db->PrepareSP('BEGIN adodb.myproc('.MYNUM.', :myov); END;');
$db->OutParameter($stid, $myov, 'myov');
$db->Execute($stid);
if ($myov != MYNUM) print "<p><b>Error with myproc</b></p>";
$stmt = $db->PrepareSP("BEGIN adodb.data_out(:a1, :a2); END;",true);
$a1 = 'Malaysia';
//$a2 = ''; # a2 doesn't even need to be defined!
$db->InParameter($stmt,$a1,'a1');
$db->OutParameter($stmt,$a2,'a2');
$rs = $db->Execute($stmt);
if ($rs) {
if ($a2 !== 'Cinta Hati Malaysia') print "<b>Stored Procedure Error: a2 = $a2</b><p>";
else echo "OK: a2=$a2<p>";
} else {
print "<b>Error in using Stored Procedure IN/Out Variables</b><p>";
}
$tname = 'A%';
$stmt = $db->PrepareSP('select * from tab where tname like :tablename');
$db->Parameter($stmt,$tname,'tablename');
$rs = $db->Execute($stmt);
rs2html($rs);
?>

View File

@ -0,0 +1,83 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
*/
error_reporting(E_ALL);
include_once('../adodb.inc.php');
include_once('../adodb-pager.inc.php');
$driver = 'oci8';
$sql = 'select ID, firstname as "First Name", lastname as "Last Name" from adoxyz order by id';
//$sql = 'select count(*),firstname from adoxyz group by firstname order by 2 ';
$sql = 'select distinct firstname, lastname from adoxyz order by firstname';
if ($driver == 'postgres') {
$db = NewADOConnection('postgres');
$db->PConnect('localhost','tester','test','test');
}
if ($driver == 'access') {
$db = NewADOConnection('access');
$db->PConnect("nwind", "", "", "");
}
if ($driver == 'ibase') {
$db = NewADOConnection('ibase');
$db->PConnect("localhost:e:\\firebird\\examples\\employee.gdb", "sysdba", "masterkey", "");
$sql = 'select distinct firstname, lastname from adoxyz order by firstname';
}
if ($driver == 'mssql') {
$db = NewADOConnection('mssql');
$db->Connect('JAGUAR\vsdotnet','adodb','natsoft','northwind');
}
if ($driver == 'oci8') {
$db = NewADOConnection('oci8');
$db->Connect('','scott','natsoft');
}
if ($driver == 'access') {
$db = NewADOConnection('access');
$db->Connect('nwind');
}
if (empty($driver) or $driver == 'mysql') {
$db = NewADOConnection('mysql');
$db->Connect('localhost','root','','xphplens');
}
//$db->pageExecuteCountRows = false;
$db->debug = true;
if (0) {
$rs = &$db->Execute($sql);
include_once('../toexport.inc.php');
print "<pre>";
print rs2csv($rs); # return a string
print '<hr>';
$rs->MoveFirst(); # note, some databases do not support MoveFirst
print rs2tab($rs); # return a string
print '<hr>';
$rs->MoveFirst();
rs2tabout($rs); # send to stdout directly
print "</pre>";
}
$pager = new ADODB_Pager($db,$sql);
$pager->showPageLinks = true;
$pager->linksPerPage = 3;
$pager->cache = 60;
$pager->Render($rows=7);
?>

View File

@ -0,0 +1,34 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
*/
error_reporting(E_ALL);
include_once('../adodb-pear.inc.php');
$username = 'root';
$password = '';
$hostname = 'localhost';
$databasename = 'xphplens';
$driver = 'mysql';
$dsn = "$driver://$username:$password@$hostname/$databasename";
$db = DB::Connect($dsn);
$db->setFetchMode(ADODB_FETCH_ASSOC);
$rs = $db->Query('select firstname,lastname from adoxyz');
$cnt = 0;
while ($arr = $rs->FetchRow()) {
print_r($arr);
print "<br>";
$cnt += 1;
}
if ($cnt != 50) print "<b>Error in \$cnt = $cnt</b>";
?>

View File

@ -0,0 +1,73 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Set tabs to 4 for best viewing.
Latest version is available at http://adodb.sourceforge.net
*/
function NotifyExpire($ref,$key)
{
print "<p><b>Notify Expiring=$ref, sessionkey=$key</b></p>";
}
//-------------------------------------------------------------------
#### CONNECTION
if (1) {
$ADODB_SESSION_DRIVER='oci8';
$ADODB_SESSION_CONNECT='';
$ADODB_SESSION_USER ='scott';
$ADODB_SESSION_PWD ='natsoft';
$ADODB_SESSION_DB ='';
} else {
$ADODB_SESSION_DRIVER='mysql';
$ADODB_SESSION_CONNECT='localhost';
$ADODB_SESSION_USER ='root';
$ADODB_SESSION_PWD ='';
$ADODB_SESSION_DB ='xphplens_2';
}
### TURN DEBUGGING ON
$ADODB_SESS_DEBUG = true;
#### SETUP NOTIFICATION
$USER = 'JLIM'.rand();
$ADODB_SESSION_EXPIRE_NOTIFY = array('USER','NotifyExpire');
#### INIT
ob_start();
error_reporting(E_ALL);
include('../session/adodb-cryptsession.php');
session_start();
### SETUP SESSION VARIABLES
$HTTP_SESSION_VARS['MONKEY'] = array('1','abc',44.41);
if (!isset($HTTP_GET_VARS['nochange'])) @$HTTP_SESSION_VARS['AVAR'] += 1;
### START DISPLAY
print "<h3>PHP ".PHP_VERSION."</h3>";
print "<p><b>\$HTTP_SESSION_VARS['AVAR']={$HTTP_SESSION_VARS['AVAR']}</b></p>";
print "<hr> <b>Cookies</b>: ";
print_r($HTTP_COOKIE_VARS);
### RANDOMLY PERFORM Garbage Collection
if (rand() % 10 == 0) {
print "<hr><p><b>Garbage Collection</b></p>";
adodb_sess_gc(10);
print "<p>Random session destroy</p>";
session_destroy();
}
?>

View File

@ -0,0 +1,181 @@
<?php
/*
V4.51 29 July 2004 (c) 2000-2004 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence.
Some pretty-printing by Chris Oxenreider <oxenreid@state.net>
*/
// specific code for tohtml
GLOBAL $gSQLMaxRows,$gSQLBlockRows;
$gSQLMaxRows = 1000; // max no of rows to download
$gSQLBlockRows=20; // max no of rows per table block
// RecordSet to HTML Table
//------------------------------------------------------------
// Convert a recordset to a html table. Multiple tables are generated
// if the number of rows is > $gSQLBlockRows. This is because
// web browsers normally require the whole table to be downloaded
// before it can be rendered, so we break the output into several
// smaller faster rendering tables.
//
// $rs: the recordset
// $ztabhtml: the table tag attributes (optional)
// $zheaderarray: contains the replacement strings for the headers (optional)
//
// USAGE:
// include('adodb.inc.php');
// $db = ADONewConnection('mysql');
// $db->Connect('mysql','userid','password','database');
// $rs = $db->Execute('select col1,col2,col3 from table');
// rs2html($rs, 'BORDER=2', array('Title1', 'Title2', 'Title3'));
// $rs->Close();
//
// RETURNS: number of rows displayed
function rs2html(&$rs,$ztabhtml=false,$zheaderarray=false,$htmlspecialchars=true,$echo = true)
{
$s ='';$rows=0;$docnt = false;
GLOBAL $gSQLMaxRows,$gSQLBlockRows;
if (!$rs) {
printf(ADODB_BAD_RS,'rs2html');
return false;
}
if (! $ztabhtml) $ztabhtml = "BORDER='1' WIDTH='98%'";
//else $docnt = true;
$typearr = array();
$ncols = $rs->FieldCount();
$hdr = "<TABLE COLS=$ncols $ztabhtml><tr>\n\n";
for ($i=0; $i < $ncols; $i++) {
$field = $rs->FetchField($i);
if ($zheaderarray) $fname = $zheaderarray[$i];
else $fname = htmlspecialchars($field->name);
$typearr[$i] = $rs->MetaType($field->type,$field->max_length);
//print " $field->name $field->type $typearr[$i] ";
if (strlen($fname)==0) $fname = '&nbsp;';
$hdr .= "<TH>$fname</TH>";
}
$hdr .= "\n</tr>";
if ($echo) print $hdr."\n\n";
else $html = $hdr;
// smart algorithm - handles ADODB_FETCH_MODE's correctly by probing...
$numoffset = isset($rs->fields[0]) ||isset($rs->fields[1]) || isset($rs->fields[2]);
while (!$rs->EOF) {
$s .= "<TR valign=top>\n";
for ($i=0; $i < $ncols; $i++) {
if ($i===0) $v=($numoffset) ? $rs->fields[0] : reset($rs->fields);
else $v = ($numoffset) ? $rs->fields[$i] : next($rs->fields);
$type = $typearr[$i];
switch($type) {
case 'D':
if (!strpos($v,':')) {
$s .= " <TD>".$rs->UserDate($v,"D d, M Y") ."&nbsp;</TD>\n";
break;
}
case 'T':
$s .= " <TD>".$rs->UserTimeStamp($v,"D d, M Y, h:i:s") ."&nbsp;</TD>\n";
break;
case 'I':
case 'N':
$s .= " <TD align=right>".stripslashes((trim($v))) ."&nbsp;</TD>\n";
break;
/*
case 'B':
if (substr($v,8,2)=="BM" ) $v = substr($v,8);
$mtime = substr(str_replace(' ','_',microtime()),2);
$tmpname = "tmp/".uniqid($mtime).getmypid();
$fd = @fopen($tmpname,'a');
@ftruncate($fd,0);
@fwrite($fd,$v);
@fclose($fd);
if (!function_exists ("mime_content_type")) {
function mime_content_type ($file) {
return exec("file -bi ".escapeshellarg($file));
}
}
$t = mime_content_type($tmpname);
$s .= (substr($t,0,5)=="image") ? " <td><img src='$tmpname' alt='$t'></td>\\n" : " <td><a
href='$tmpname'>$t</a></td>\\n";
break;
*/
default:
if ($htmlspecialchars) $v = htmlspecialchars(trim($v));
$v = trim($v);
if (strlen($v) == 0) $v = '&nbsp;';
$s .= " <TD>". str_replace("\n",'<br>',stripslashes($v)) ."</TD>\n";
}
} // for
$s .= "</TR>\n\n";
$rows += 1;
if ($rows >= $gSQLMaxRows) {
$rows = "<p>Truncated at $gSQLMaxRows</p>";
break;
} // switch
$rs->MoveNext();
// additional EOF check to prevent a widow header
if (!$rs->EOF && $rows % $gSQLBlockRows == 0) {
//if (connection_aborted()) break;// not needed as PHP aborts script, unlike ASP
if ($echo) print $s . "</TABLE>\n\n";
else $html .= $s ."</TABLE>\n\n";
$s = $hdr;
}
} // while
if ($echo) print $s."</TABLE>\n\n";
else $html .= $s."</TABLE>\n\n";
if ($docnt) if ($echo) print "<H2>".$rows." Rows</H2>";
return ($echo) ? $rows : $html;
}
// pass in 2 dimensional array
function arr2html(&$arr,$ztabhtml='',$zheaderarray='')
{
if (!$ztabhtml) $ztabhtml = 'BORDER=1';
$s = "<TABLE $ztabhtml>";//';print_r($arr);
if ($zheaderarray) {
$s .= '<TR>';
for ($i=0; $i<sizeof($zheaderarray); $i++) {
$s .= " <TH>{$zheaderarray[$i]}</TH>\n";
}
$s .= "\n</TR>";
}
for ($i=0; $i<sizeof($arr); $i++) {
$s .= '<TR>';
$a = &$arr[$i];
if (is_array($a))
for ($j=0; $j<sizeof($a); $j++) {
$val = $a[$j];
if (empty($val)) $val = '&nbsp;';
$s .= " <TD>$val</TD>\n";
}
else if ($a) {
$s .= ' <TD>'.$a."</TD>\n";
} else $s .= " <TD>&nbsp;</TD>\n";
$s .= "\n</TR>\n";
}
$s .= '</TABLE>';
print $s;
}
?>

View File

@ -0,0 +1,38 @@
<?xml version="1.0"?>
<!DOCTYPE adodb_schema [
<!ELEMENT schema (table*, sql*)>
<!ATTLIST schema version CDATA #REQUIRED>
<!ELEMENT table ((field+|DROP), constraint*, descr?, index*, data*)>
<!ELEMENT field ((NOTNULL|KEY|PRIMARY)?, (AUTO|AUTOINCREMENT)?, (DEFAULT|DEFDATE|DEFTIMESTAMP)?, NOQUOTE, constraint, descr?)>
<!ELEMENT data (row+)>
<!ELEMENT row (f+)>
<!ELEMENT f (#CDATA)>
<!ELEMENT descr (#CDATA)>
<!ELEMENT NOTNULL EMPTY>
<!ELEMENT KEY EMPTY>
<!ELEMENT PRIMARY EMPTY>
<!ELEMENT AUTO EMPTY>
<!ELEMENT AUTOINCREMENT EMPTY>
<!ELEMENT DEFAULT EMPTY>
<!ELEMENT DEFDATE EMPTY>
<!ELEMENT DEFTIMESTAMP EMPTY>
<!ELEMENT NOQUOTE EMPTY>
<!ELEMENT DROP EMPTY>
<!ELEMENT constraint (#CDATA)>
<!ATTLIST table name CDATA #REQUIRED platform CDATA #IMPLIED version CDATA #IMPLIED>
<!ATTLIST field name CDATA #REQUIRED type (C|C2|X|X2|B|D|T|L|I|F|N) #REQUIRED size CDATA #IMPLIED>
<!ATTLIST data platform CDATA #IMPLIED>
<!ATTLIST f name CDATA #IMPLIED>
<!ATTLIST DEFAULT value CDATA #REQUIRED>
<!ELEMENT index ((col+|DROP), CLUSTERED?, BITMAP?, UNIQUE?, FULLTEXT?, HASH?, descr?)>
<!ELEMENT col (#CDATA)>
<!ELEMENT CLUSTERED EMPTY>
<!ELEMENT BITMAP EMPTY>
<!ELEMENT UNIQUE EMPTY>
<!ELEMENT FULLTEXT EMPTY>
<!ELEMENT HASH EMPTY>
<!ATTLIST index name CDATA #REQUIRED platform CDATA #IMPLIED>
<!ELEMENT sql (query+, descr?)>
<!ELEMENT query (#CDATA)>
<!ATTLIST sql name CDATA #IMPLIED platform CDATA #IMPLIED, key CDATA, prefixmethod (AUTO|MANUAL|NONE) >
] >

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output method="xml" indent="yes" omit-xml-declaration="no" encoding="UTF-8"/>
<!-- Schema -->
<xsl:template match="/">
<xsl:comment>
ADODB XMLSchema
http://adodb-xmlschema.sourceforge.net
</xsl:comment>
<xsl:comment>
Uninstallation Schema
</xsl:comment>
<xsl:element name="schema">
<xsl:attribute name="version">0.2</xsl:attribute>
<xsl:apply-templates select="schema/table">
<xsl:sort select="position()" data-type="number" order="descending"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<!-- Table -->
<xsl:template match="table">
<xsl:if test="count(DROP) = 0">
<xsl:element name="table">
<xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute>
<xsl:if test="string-length(@platform) > 0">
<xsl:attribute name="platform"><xsl:value-of select="@platform"/></xsl:attribute>
</xsl:if>
<xsl:if test="string-length(@version) > 0">
<xsl:attribute name="version"><xsl:value-of select="@version"/></xsl:attribute>
</xsl:if>
<xsl:apply-templates select="descr[1]"/>
<xsl:element name="DROP"/>
</xsl:element>
</xsl:if>
</xsl:template>
<!-- Description -->
<xsl:template match="descr">
<xsl:element name="descr">
<xsl:value-of select="normalize-space(text())"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>