📄 adodb.inc.php
字号:
$ADODB_COUNTRECS = $crecs;
if ($rs) {
$arr = array();
if (!$rs->EOF) $arr = $rs->fields;
$rs->Close();
return $arr;
}
return false;
}
function &CacheGetRow($secs2cache,$sql=false,$inputarr=false)
{
$rs =& $this->CacheExecute($secs2cache,$sql,$inputarr);
if ($rs) {
$arr = false;
if (!$rs->EOF) $arr = $rs->fields;
$rs->Close();
return $arr;
}
return false;
}
/**
* Insert or replace a single record. Note: this is not the same as MySQL's replace.
* ADOdb's Replace() uses update-insert semantics, not insert-delete-duplicates of MySQL.
* Also note that no table locking is done currently, so it is possible that the
* record be inserted twice by two programs...
*
* $this->Replace('products', array('prodname' =>"'Nails'","price" => 3.99), 'prodname');
*
* $table table name
* $fieldArray associative array of data (you must quote strings yourself).
* $keyCol the primary key field name or if compound key, array of field names
* autoQuote set to true to use a hueristic to quote strings. Works with nulls and numbers
* but does not work with dates nor SQL functions.
* has_autoinc the primary key is an auto-inc field, so skip in insert.
*
* Currently blob replace not supported
*
* returns 0 = fail, 1 = update, 2 = insert
*/
function Replace($table, $fieldArray, $keyCol, $autoQuote=false, $has_autoinc=false)
{
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 = $this->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";
}
$first = true;
foreach ($keyCol as $v) {
if ($first) {
$first = false;
$where = "$v=$fieldArray[$v]";
} else {
$where .= " and $v=$fieldArray[$v]";
}
}
if ($uSet) {
$update = "UPDATE $table SET $uSet WHERE $where";
$rs = $this->Execute($update);
if ($rs) {
if ($this->poorAffectedRows) {
/*
The Select count(*) wipes out any errors that the update would have returned.
http://phplens.com/lens/lensforum/msgs.php?id=5696
*/
if ($this->ErrorNo()<>0) return 0;
# affected_rows == 0 if update field values identical to old values
# for mysql - which is silly.
$cnt = $this->GetOne("select count(*) from $table where $where");
if ($cnt > 0) return 1; // record already exists
} else
if (($this->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 = $this->Execute($insert);
return ($rs) ? 2 : 0;
}
/**
* Will select, getting rows from $offset (1-based), for $nrows.
* This simulates the MySQL "select * from table limit $offset,$nrows" , and
* the PostgreSQL "select * from table limit $nrows offset $offset". Note that
* MySQL and PostgreSQL parameter ordering is the opposite of the other.
* eg.
* CacheSelectLimit(15,'select * from table',3); will return rows 1 to 3 (1-based)
* CacheSelectLimit(15,'select * from table',3,2); will return rows 3 to 5 (1-based)
*
* BUG: Currently CacheSelectLimit fails with $sql with LIMIT or TOP clause already set
*
* @param [secs2cache] seconds to cache data, set to 0 to force query. This is optional
* @param sql
* @param [offset] is the row to start calculations from (1-based)
* @param [nrows] is the number of rows to get
* @param [inputarr] array of bind variables
* @return the recordset ($rs->databaseType == 'array')
*/
function &CacheSelectLimit($secs2cache,$sql,$nrows=-1,$offset=-1,$inputarr=false)
{
if (!is_numeric($secs2cache)) {
if ($sql === false) $sql = -1;
if ($offset == -1) $offset = false;
// sql, nrows, offset,inputarr
$rs =& $this->SelectLimit($secs2cache,$sql,$nrows,$offset,$inputarr,$this->cacheSecs);
} else {
if ($sql === false) ADOConnection::outp( "Warning: \$sql missing from CacheSelectLimit()");
$rs =& $this->SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
}
return $rs;
}
/**
* Flush cached recordsets that match a particular $sql statement.
* If $sql == false, then we purge all files in the cache.
*/
function CacheFlush($sql=false,$inputarr=false)
{
global $ADODB_CACHE_DIR;
if (strlen($ADODB_CACHE_DIR) > 1 && !$sql) {
if (strncmp(PHP_OS,'WIN',3) === 0) {
$cmd = 'del /s '.str_replace('/','\\',$ADODB_CACHE_DIR).'\adodb_*.cache';
} else {
$cmd = 'rm -rf '.$ADODB_CACHE_DIR.'/??/adodb_*.cache';
// old version 'rm -f `find '.$ADODB_CACHE_DIR.' -name adodb_*.cache`';
}
if ($this->debug) {
ADOConnection::outp( "CacheFlush: $cmd<br><pre>\n", system($cmd),"</pre>");
} else {
exec($cmd);
}
return;
}
$f = $this->_gencachename($sql.serialize($inputarr),false);
adodb_write_file($f,''); // is adodb_write_file needed?
if (!@unlink($f)) {
if ($this->debug) ADOConnection::outp( "CacheFlush: failed for $f");
}
}
/**
* Private function to generate filename for caching.
* Filename is generated based on:
*
* - sql statement
* - database type (oci8, ibase, ifx, etc)
* - database name
* - userid
*
* We create 256 sub-directories in the cache directory ($ADODB_CACHE_DIR).
* Assuming that we can have 50,000 files per directory with good performance,
* then we can scale to 12.8 million unique cached recordsets. Wow!
*/
function _gencachename($sql,$createdir)
{
global $ADODB_CACHE_DIR;
$m = md5($sql.$this->databaseType.$this->database.$this->user);
$dir = $ADODB_CACHE_DIR.'/'.substr($m,0,2);
if ($createdir && !file_exists($dir)) {
$oldu = umask(0);
if (!mkdir($dir,0771))
if ($this->debug) ADOConnection::outp( "Unable to mkdir $dir for $sql");
umask($oldu);
}
return $dir.'/adodb_'.$m.'.cache';
}
/**
* Execute SQL, caching recordsets.
*
* @param [secs2cache] seconds to cache data, set to 0 to force query.
* This is an optional parameter.
* @param sql SQL statement to execute
* @param [inputarr] holds the input data to bind to
* @return RecordSet or false
*/
function &CacheExecute($secs2cache,$sql=false,$inputarr=false)
{
if (!is_numeric($secs2cache)) {
$inputarr = $sql;
$sql = $secs2cache;
$secs2cache = $this->cacheSecs;
}
global $ADODB_INCLUDED_CSV;
if (empty($ADODB_INCLUDED_CSV)) include_once(ADODB_DIR.'/adodb-csvlib.inc.php');
if (is_array($sql)) $sql = $sql[0];
$md5file = $this->_gencachename($sql.serialize($inputarr),true);
$err = '';
if ($secs2cache > 0){
$rs = &csv2rs($md5file,$err,$secs2cache);
$this->numCacheHits += 1;
} else {
$err='Timeout 1';
$rs = false;
$this->numCacheMisses += 1;
}
if (!$rs) {
// no cached rs found
if ($this->debug) {
if (get_magic_quotes_runtime()) {
ADOConnection::outp("Please disable magic_quotes_runtime - it corrupts cache files :(");
}
if ($this->debug !== -1) ADOConnection::outp( " $md5file cache failure: $err (see sql below)");
}
$rs = &$this->Execute($sql,$inputarr);
if ($rs) {
$eof = $rs->EOF;
$rs = &$this->_rs2rs($rs); // read entire recordset into memory immediately
$txt = _rs2serialize($rs,false,$sql); // serialize
if (!adodb_write_file($md5file,$txt,$this->debug)) {
if ($fn = $this->raiseErrorFn) {
$fn($this->databaseType,'CacheExecute',-32000,"Cache write error",$md5file,$sql,$this);
}
if ($this->debug) ADOConnection::outp( " Cache write error");
}
if ($rs->EOF && !$eof) {
$rs->MoveFirst();
//$rs = &csv2rs($md5file,$err);
$rs->connection = &$this; // Pablo suggestion
}
} else
@unlink($md5file);
} else {
$this->_errorMsg = '';
$this->_errorCode = 0;
if ($this->fnCacheExecute) {
$fn = $this->fnCacheExecute;
$fn($this, $secs2cache, $sql, $inputarr);
}
// ok, set cached object found
$rs->connection = &$this; // Pablo suggestion
if ($this->debug){
global $HTTP_SERVER_VARS;
$inBrowser = isset($HTTP_SERVER_VARS['HTTP_USER_AGENT']);
$ttl = $rs->timeCreated + $secs2cache - time();
$s = is_array($sql) ? $sql[0] : $sql;
if ($inBrowser) $s = '<i>'.htmlspecialchars($s).'</i>';
ADOConnection::outp( " $md5file reloaded, ttl=$ttl [ $s ]");
}
}
return $rs;
}
/**
* Generates an Update Query based on an existing recordset.
* $arrFields is an associative array of fields with the value
* that should be assigned.
*
* Note: This function should only be used on a recordset
* that is run against a single table and sql should only
* be a simple select stmt with no groupby/orderby/limit
*
* "Jonathan Younger" <jyounger@unilab.com>
*/
function GetUpdateSQL(&$rs, $arrFields,$forceUpdate=false,$magicq=false)
{
global $ADODB_INCLUDED_LIB;
if (empty($ADODB_INCLUDED_LIB)) include_once(ADODB_DIR.'/adodb-lib.inc.php');
return _adodb_getupdatesql($this,$rs,$arrFields,$forceUpdate,$magicq);
}
/**
* Generates an Insert Query based on an existing recordset.
* $arrFields is an associative array of fields with the value
* that should be assigned.
*
* Note: This function should only be used on a recordset
* that is run against a single table.
*/
function GetInsertSQL(&$rs, $arrFields,$magicq=false)
{
global $ADODB_INCLUDED_LIB;
if (empty($ADODB_INCLUDED_LIB)) include_once(ADODB_DIR.'/adodb-lib.inc.php');
return _adodb_getinsertsql($this,$rs,$arrFields,$magicq);
}
/**
* Update a blob column, given a where clause. There are more sophisticated
* blob handling functions that we could have implemented, but all require
* a very complex API. Instead we have chosen something that is extremely
* simple to understand and use.
*
* Note: $blobtype supports 'BLOB' and 'CLOB', default is BLOB of course.
*
* Usage to update a $blobvalue which has a primary key blob_id=1 into a
* field blobtable.blobcolumn:
*
* UpdateBlob('blobtable', 'blobcolumn', $blobvalue, 'blob_id=1');
*
* Insert example:
*
* $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
* $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
*/
function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
{
return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false;
}
/**
* Usage:
* UpdateBlob('TABLE', 'COLUMN', '/path/to/file', 'ID=1');
*
* $blobtype supports 'BLOB' and 'CLOB'
*
* $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
* $conn->UpdateBlob('blobtable','blobcol',$blobpath,'id=1');
*/
function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
{
$fd = fopen($path,'rb');
if ($fd === false) return false;
$val = fread($fd,filesize($path));
fclose($fd);
return $this->UpdateBlob($table,$column,$val,$where,$blobtype);
}
function BlobDecode($blob)
{
return $blob;
}
function BlobEncode($blob)
{
return $blob;
}
function SetCharSet($charset)
{
return false;
}
function IfNull( $field, $ifNull )
{
return " CASE WHEN $field is null THEN $ifNull ELSE $field END ";
}
function LogSQL($enable=true)
{
include_once(ADODB_DIR.'/adodb-perf.inc.php');
if ($enable) $this->fnExecute = 'adodb_log_sql';
else $this->fnExecute = false;
$old = $this->_logsql;
$this->_logsql = $enable;
if ($enable && !$old) $this->_affected = false;
return $old;
}
function GetCharSet()
{
return false;
}
/**
* Usage:
* UpdateClob('TABLE', 'COLUMN', $var, 'ID=1', 'CLOB');
*
* $conn->Execute('INSERT INTO clobtable (id, clobcol) VALUES (1, null)');
* $conn->UpdateClob('clobtable','clobcol',$clob,'id=1');
*/
function UpdateClob($table,$column,$val,$where)
{
return $this->UpdateBlob($table,$column,$val,$where,'CLOB');
}
/**
* Change the SQL connection locale to a specified locale.
* This is used to get the date formats written depending on the client locale.
*/
function SetDateLocale($locale = 'En')
{
$this->locale = $locale;
switch ($locale)
{
default:
case 'En':
$this->fmtDate="Y-m-d";
$this->fmtTimeStamp = "Y-m-d H:i:s";
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -