Merge branch 'MDL-74095_upgrade-adobb-to-5-22' of https://github.com/ziegenberg/moodle

This commit is contained in:
Sara Arjona 2022-06-08 18:46:33 +02:00
commit c46ab4ef04
54 changed files with 4529 additions and 4012 deletions

View File

@ -1,8 +1,9 @@
ADOdb Library for PHP
======================
[![Join chat on Gitter](https://img.shields.io/gitter/room/form-data/form-data.svg)](https://gitter.im/adodb/adodb?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Download ADOdb](https://img.shields.io/sourceforge/dm/adodb.svg)](https://sourceforge.net/projects/adodb/files/latest/download)
[![Join chat on Gitter](https://img.shields.io/gitter/room/adodb/adodb?logo=gitter)](https://gitter.im/adodb/adodb?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![SourceForge Downloads Shield](https://img.shields.io/sourceforge/dm/adodb?label=SourceForge&logo=sourceforge&color=informational)](https://sourceforge.net/projects/adodb/files/latest/download)
[![Packagist Downloads Shield](https://img.shields.io/packagist/dm/ADOdb/ADOdb-php?label=Packagist&logo=packagist&logoColor=white&color=informational)](https://packagist.org/packages/adodb/adodb-php)
(c) 2000-2013 John Lim (jlim@natsoft.com)
(c) 2014 Damien Regad, Mark Newnham and the

45
lib/adodb/SECURITY.md Normal file
View File

@ -0,0 +1,45 @@
# ADOdb Security Policy
## Supported Versions
The following releases of the library are currently being supported with
security updates. Please refer to the [project's home page](https://adodb.org)
for actual version numbers.
- Stable
- Legacy
- Development (Git *master* branch)
Older releases are no longer supported.
## Reporting a Vulnerability
If you discover a vulnerability in ADOdb, please contact
the [project's maintainer](https://github.com/dregad)
- by e-mail (look for it in the Git history)
- via private chat on [Gitter](https://gitter.im/dregad)
Kindly provide the following information in your report:
- Affected ADOdb version(s) or Git revision
- A clear and detailed description of the issue, including if possible a code
snippet to demonstrate or reproduce the vulnerability
- A patch for the issue if you have one, preferably in *Git diff* format
### CVE handling
To ensure a comprehensive and detailed declaration of the issue, we generally
prefer requesting CVE IDs ourselves, which usually happens after our analysis
confirms the vulnerability.
In case you have already obtained a CVE ID, do not forget to reference it in
your report.
### Credits
Let us know if and how you wish to be credited for the finding.
Your name, e-mail, company, etc. will be included as specified in the CVE
report, as well as in the Git commit message patching the issue.

View File

@ -281,7 +281,7 @@ class ADODB_Active_Record {
static function TableBelongsTo($table, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record')
{
$ar = new ADOdb_Active_Record($table);
$ar = new ADODB_Active_Record($table);
$ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass);
}
@ -290,7 +290,7 @@ class ADODB_Active_Record {
if (!is_array($tablePKey)) {
$tablePKey = array($tablePKey);
}
$ar = new ADOdb_Active_Record($table, $tablePKey);
$ar = new ADODB_Active_Record($table, $tablePKey);
$ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass);
}

View File

@ -29,11 +29,13 @@ global $ADODB_INCLUDED_CSV;
$ADODB_INCLUDED_CSV = 1;
/**
* convert a recordset into special format
* Convert a recordset into special format
*
* @param rs the recordset
* @param ADORecordSet $rs the recordset
* @param ADOConnection $conn
* @param string $sql
*
* @return the CSV formatted data
* @return string the CSV formatted data
*/
function _rs2serialize(&$rs,$conn=false,$sql='')
{
@ -74,7 +76,7 @@ $ADODB_INCLUDED_CSV = 1;
$savefetch = isset($rs->adodbFetchMode) ? $rs->adodbFetchMode : $rs->fetchMode;
$class = $rs->connection->arrayClass;
$rs2 = new $class();
$rs2 = new $class(-1); // Dummy query Id
$rs2->timeCreated = $rs->timeCreated; # memcache fix
$rs2->sql = $rs->sql;
$rs2->oldProvider = $rs->dataProvider;
@ -83,19 +85,19 @@ $ADODB_INCLUDED_CSV = 1;
return $line.serialize($rs2);
}
/**
* 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 occurred. If no
* error occurred in sql INSERT/UPDATE/DELETE,
* empty recordset is returned
*/
function csv2rs($url,&$err,$timeout=0, $rsclass='ADORecordSet_array')
/**
* Open CSV file and convert it into Data.
*
* @param string $url file/ftp/http url
* @param string &$err returns the error message
* @param int $timeout dispose if recordset has been alive for $timeout secs
* @param string $rsclass RecordSet class to return
*
* @return ADORecordSet|false recordset, or false if error occurred.
* If no error occurred in sql INSERT/UPDATE/DELETE,
* empty recordset is returned.
*/
function csv2rs($url, &$err, $timeout=0, $rsclass='ADORecordSet_array')
{
$false = false;
$err = false;

View File

@ -353,7 +353,7 @@ class ADODB_DataDict {
function nameQuote($name = NULL,$allowBrackets=false)
{
if (!is_string($name)) {
return FALSE;
return false;
}
$name = trim($name);
@ -427,6 +427,15 @@ class ADODB_DataDict {
function actualType($meta)
{
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
return $meta;
}
@ -498,7 +507,7 @@ class ADODB_DataDict {
* @param string $tabname table-name
* @param string $flds column-name and type for the changed column
* @param string $tableflds='' complete definition of the new table, eg. for postgres, default ''
* @param array/string $tableoptions='' options for the new table see createTableSQL, default ''
* @param array|string $tableoptions='' options for the new table see createTableSQL, default ''
* @return array with SQL strings
*/
function alterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
@ -553,7 +562,7 @@ class ADODB_DataDict {
* @param string $tabname table-name
* @param string $flds column-name and type for the changed column
* @param string $tableflds='' complete definition of the new table, eg. for postgres, default ''
* @param array/string $tableoptions='' options for the new table see createTableSQL, default ''
* @param array|string $tableoptions='' options for the new table see createTableSQL, default ''
* @return array with SQL strings
*/
function dropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
@ -695,16 +704,25 @@ class ADODB_DataDict {
case '0':
case 'NAME': $fname = $v; break;
case '1':
case 'TYPE': $ty = $v; $ftype = $this->actualType(strtoupper($v)); break;
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;
$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;

View File

@ -45,6 +45,9 @@ var $database = '';
$s = "$dbms error: [$errno: $errmsg] in $fn($p1, '$user', '****', $p2)";
break;
default:
//Prevent PHP warning if $p1 or $p2 are arrays.
$p1 = ( is_array($p1) ) ? 'Array' : $p1;
$p2 = ( is_array($p2) ) ? 'Array' : $p2;
$s = "$dbms error: [$errno: $errmsg] in $fn($p1, $p2)";
break;
}

View File

@ -174,7 +174,7 @@ class ADOdbLoadBalancer
* @param string $type Type of database connection, either: 'write' capable or 'readonly'
* @return bool|int|string
*/
private function getConnectionByWeight($type)
public function getConnectionByWeight($type)
{
if ($type == 'readonly') {
$total_weight = $this->total_connection_weights['all'];
@ -233,7 +233,7 @@ class ADOdbLoadBalancer
* @return bool|ADOConnection
* @throws Exception
*/
private function _getConnection($connection_id)
public function getConnectionById($connection_id)
{
if (isset($this->connections[$connection_id])) {
$connection_obj = $this->connections[$connection_id];
@ -261,6 +261,15 @@ class ADOdbLoadBalancer
throw $e; // No connections left, reThrow exception so application can catch it.
}
// Check to see if a connection test callback was defined, and if so execute it.
// This is useful for testing replication lag and such to ensure the connection is suitable to be used.
$test_connection_callback = $connection_obj->getConnectionTestCallback();
if (is_callable($test_connection_callback)
&& $test_connection_callback($connection_obj, $adodb_obj) !== TRUE
) {
return false;
}
if (is_array($this->user_defined_session_init_sql)) {
foreach ($this->user_defined_session_init_sql as $session_init_sql) {
$adodb_obj->Execute($session_init_sql);
@ -298,9 +307,12 @@ class ADOdbLoadBalancer
if ($connection_id !== false) {
try {
$adodb_obj = $this->_getConnection($connection_id);
// $connection_obj = $this->connections[$connection_id];
break;
$adodb_obj = $this->getConnectionById($connection_id);
if (is_object($adodb_obj)) {
break; //Found valid connection, continue with it.
} else {
throw new Exception('ADODB Connection Object does not exist. Perhaps LoadBalancer Database Connection Test Failed?');
}
} catch (Exception $e) {
// Connection error, see if there are other connections to try still.
$this->removeConnection($connection_id);
@ -315,6 +327,10 @@ class ADOdbLoadBalancer
}
}
if (!isset($connection_id)) {
throw new Exception('No connection available to use at this time! Type: ' . $type);
}
$this->last_connection_id[$type] = $connection_id;
if ($pin_connection === true) {
@ -432,7 +448,7 @@ class ADOdbLoadBalancer
&& $connection_obj->getADOdbObject()->_connectionID !== false
)
) {
$adodb_obj = $this->_getConnection($key);
$adodb_obj = $this->getConnectionById($key);
if (is_object($adodb_obj)) {
$result_arr[] = $adodb_obj->Execute($sql, $inputarr);
}
@ -595,6 +611,7 @@ class ADOdbLoadBalancer
case 'binddate':
case 'bindtimestamp':
case 'setfetchmode':
case 'setcustommetatype':
$type = false; // No connection necessary.
break;
@ -686,6 +703,11 @@ class ADOdbLoadBalancerConnection
*/
protected $adodb_obj = false;
/**
* @var callable Closure
*/
protected $connection_test_callback = NULL;
/**
* @var string Type of connection, either 'write' capable or 'readonly'
*/
@ -761,6 +783,24 @@ class ADOdbLoadBalancerConnection
return true;
}
/**
* Anonymous function that is called and must return TRUE for the connection to be usable.*
* The first argument is the type of connection to test.
* Useful to check things like replication lag.
* @param callable $callback
* @return void
*/
function setConnectionTestCallback($callback) {
$this->connection_test_callback = $callback;
}
/**
* @return callable|null
*/
function getConnectionTestCallback() {
return $this->connection_test_callback;
}
/**
* Returns the ADODB object for this connection.
*

View File

@ -17,6 +17,8 @@
*
* @copyright 2000-2013 John Lim
* @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
*
* @noinspection PhpUnused
*/
// security - hide paths
@ -26,183 +28,393 @@ global $ADODB_INCLUDED_MEMCACHE;
$ADODB_INCLUDED_MEMCACHE = 1;
global $ADODB_INCLUDED_CSV;
if (empty($ADODB_INCLUDED_CSV)) include_once(ADODB_DIR.'/adodb-csvlib.inc.php');
if (empty($ADODB_INCLUDED_CSV)) {
include_once(ADODB_DIR . '/adodb-csvlib.inc.php');
}
class ADODB_Cache_MemCache {
var $createdir = false; // create caching directory structure?
class ADODB_Cache_MemCache
{
/**
* @var bool Prevents parent class calling non-existant function
*/
public $createdir = false;
// $library will be populated with the proper library on connect
// and is used later when there are differences in specific calls
// between memcache and memcached
var $library = false;
/**
* @var array of hosts
*/
private $hosts;
//-----------------------------
// memcache specific variables
/**
* @var int Connection Port, uses default
*/
private $port;
var $hosts; // array of hosts
var $port = 11211;
var $compress = false; // memcache compression with zlib
/**
* @var bool memcache compression with zlib
*/
private $compress;
var $_connected = false;
var $_memcache = false;
/**
* @var array of options for memcached only
*/
private $options;
function __construct(&$obj)
{
$this->hosts = $obj->memCacheHost;
$this->port = $obj->memCachePort;
$this->compress = $obj->memCacheCompress;
/**
* @var bool Internal flag indicating successful connection
*/
private $isConnected = false;
/**
* @var Memcache|Memcached Handle for the Memcache library
*
* Populated with the proper library on connect, used later when
* there are differences in specific calls between memcache and memcached
*/
private $memcacheLibrary = false;
/**
* @var array New server feature controller lists available servers
*/
private $serverControllers = array();
/**
* @var array New server feature template uses granular server controller
*/
private $serverControllerTemplate = array(
'host' => '',
'port' => 11211,
'weight' => 0,
);
/**
* An integer index into the libraries
* @see $libraries
*/
const MCLIB = 1;
const MCLIBD = 2;
/**
* @var array Xrefs the library flag to the actual class name
*/
private $libraries = array(
self::MCLIB => 'Memcache',
self::MCLIBD => 'Memcached'
);
/**
* @var int An indicator of which library we are using
*/
private $libraryFlag;
/**
* Class Constructor.
*
* @param ADOConnection $db
*/
public function __construct($db)
{
$this->hosts = $db->memCacheHost;
$this->port = $this->serverControllerTemplate['port'] = $db->memCachePort;
$this->compress = $db->memCacheCompress;
$this->options = $db->memCacheOptions;
}
/**
* Return true if the current library is Memcached.
* @return bool
*/
public function isLibMemcached(): bool
{
return $this->libraryFlag == self::MCLIBD;
}
/**
* Lazy connection.
*
* The connection only occurs on CacheExecute call.
*
* @param string $err
*
* @return bool success of connecting to a server
*/
public function connect(&$err)
{
// do we have memcache or memcached? see the note at adodb.org on memcache
if (class_exists('Memcache')) {
$this->libraryFlag = self::MCLIB;
} elseif (class_exists('Memcached')) {
$this->libraryFlag = self::MCLIBD;
} else {
$err = 'Neither the Memcache nor Memcached PECL extensions were found!';
return false;
}
// implement as lazy connection. The connection only occurs on CacheExecute call
function connect(&$err)
{
// do we have memcache or memcached?
if (class_exists('Memcache')) {
$this->library='Memcache';
$memcache = new MemCache;
} elseif (class_exists('Memcached')) {
$this->library='Memcached';
$memcache = new MemCached;
} else {
$err = 'Neither the Memcache nor Memcached PECL extensions were found!';
$usedLibrary = $this->libraries[$this->libraryFlag];
/** @var Memcache|Memcached $memCache */
$memCache = new $usedLibrary;
if (!$memCache) {
$err = 'Memcache library failed to initialize';
return false;
}
// Convert simple compression flag for memcached
if ($this->isLibMemcached()) {
$this->options[Memcached::OPT_COMPRESSION] = $this->compress;
}
// Are there any options available for memcached
if ($this->isLibMemcached() && count($this->options) > 0) {
$optionSuccess = $memCache->setOptions($this->options);
if (!$optionSuccess) {
$err = 'Invalid option parameters passed to Memcached';
return false;
}
}
if (!is_array($this->hosts)) $this->hosts = array($this->hosts);
// Have we passed a controller array
if (!is_array($this->hosts)) {
$this->hosts = array($this->hosts);
}
$failcnt = 0;
foreach($this->hosts as $host) {
if (!@$memcache->addServer($host,$this->port)) {
$failcnt += 1;
if (!is_array($this->hosts[0])) {
// Old way, convert to controller
foreach ($this->hosts as $ipAddress) {
$connector = $this->serverControllerTemplate;
$connector['host'] = $ipAddress;
$connector['port'] = $this->port;
$this->serverControllers[] = $connector;
}
} else {
// New way, must validate port, etc
foreach ($this->hosts as $controller) {
$connector = array_merge($this->serverControllerTemplate, $controller);
if ($this->isLibMemcached()) {
$connector['weight'] = (int)$connector['weight'];
} else {
// Cannot use weight in memcache, simply discard
$connector['weight'] = 0;
}
$this->serverControllers[] = $connector;
}
if ($failcnt == sizeof($this->hosts)) {
$err = 'Can\'t connect to any memcache server';
return false;
}
$this->_connected = true;
$this->_memcache = $memcache;
}
// Checks for existing connections ( but only for memcached )
if ($this->isLibMemcached() && !empty($memCache->getServerList())) {
// Use the existing configuration
$this->isConnected = true;
$this->memcacheLibrary = $memCache;
return true;
}
// returns true or false. true if successful save
function writecache($filename, $contents, $debug, $secs2cache)
{
if (!$this->_connected) {
$err = '';
if (!$this->connect($err) && $debug) ADOConnection::outp($err);
$failcnt = 0;
foreach ($this->serverControllers as $controller) {
if ($this->isLibMemcached()) {
if (!@$memCache->addServer($controller['host'], $controller['port'], $controller['weight'])) {
$failcnt++;
}
} else {
if (!@$memCache->addServer($controller['host'], $controller['port'])) {
$failcnt++;
}
}
if (!$this->_memcache) return false;
}
if ($failcnt == sizeof($this->serverControllers)) {
$err = 'Can\'t connect to any memcache server';
return false;
}
$failed=false;
switch ($this->library) {
case 'Memcache':
if (!$this->_memcache->set($filename, $contents, $this->compress ? MEMCACHE_COMPRESSED : 0, $secs2cache)) {
$failed=true;
$this->memcacheLibrary = $memCache;
// A valid memcache connection is available
$this->isConnected = true;
return true;
}
/**
* Writes a cached query to the server
*
* @param string $filename The MD5 of the query to cache
* @param string $contents The query results
* @param bool $debug
* @param int $secs2cache
*
* @return bool true or false. true if successful save
*/
public function writeCache($filename, $contents, $debug, $secs2cache)
{
$err = '';
if (!$this->isConnected && $debug) {
// Call to writeCache() before connect(), try to connect
if (!$this->connect($err)) {
ADOConnection::outp($err);
}
} else {
if (!$this->isConnected) {
$this->connect($err);
}
}
if (!$this->memcacheLibrary) {
return false;
}
$failed = false;
switch ($this->libraryFlag) {
case self::MCLIB:
if (!$this->memcacheLibrary->set($filename, $contents, $this->compress ? MEMCACHE_COMPRESSED : 0,
$secs2cache)) {
$failed = true;
}
break;
case self::MCLIBD:
if (!$this->memcacheLibrary->set($filename, $contents, $secs2cache)) {
$failed = true;
}
break;
default:
$failed = true;
break;
}
if ($failed) {
if ($debug) {
ADOConnection::outp(" Failed to save data at the memcache server!<br>\n");
}
return false;
}
return true;
}
/**
* Reads a cached query from the server.
*
* @param string $filename The MD5 of the query to read
* @param string $err The query results
* @param int $secs2cache
* @param object $rsClass **UNUSED**
*
* @return object|bool record or false.
*
* @noinspection PhpUnusedParameterInspection
*/
public function readCache($filename, &$err, $secs2cache, $rsClass)
{
if (!$this->isConnected) {
$this->connect($err);
}
if (!$this->memcacheLibrary) {
return false;
}
$rs = $this->memcacheLibrary->get($filename);
if (!$rs) {
$err = 'Item with such key doesn\'t exist on the memcache server.';
return false;
}
// hack, should actually use _csv2rs
$rs = explode("\n", $rs);
unset($rs[0]);
$rs = join("\n", $rs);
$rs = unserialize($rs);
if (!is_object($rs)) {
$err = 'Unable to unserialize $rs';
return false;
}
if ($rs->timeCreated == 0) {
return $rs;
} // apparently have been reports that timeCreated was set to 0 somewhere
$tdiff = intval($rs->timeCreated + $secs2cache - time());
if ($tdiff <= 2) {
switch ($tdiff) {
case 2:
if ((rand() & 15) == 0) {
$err = "Timeout 2";
return false;
}
break;
case 'Memcached':
if (!$this->_memcache->set($filename, $contents, $secs2cache)) {
$failed=true;
case 1:
if ((rand() & 3) == 0) {
$err = "Timeout 1";
return false;
}
break;
default:
$failed=true;
break;
$err = "Timeout 0";
return false;
}
if($failed) {
if ($debug) ADOConnection::outp(" Failed to save data at the memcache server!<br>\n");
return false;
}
return true;
}
// returns a recordset
function readcache($filename, &$err, $secs2cache, $rsClass)
{
$false = false;
if (!$this->_connected) $this->connect($err);
if (!$this->_memcache) return $false;
$rs = $this->_memcache->get($filename);
if (!$rs) {
$err = 'Item with such key doesn\'t exist on the memcache server.';
return $false;
}
// hack, should actually use _csv2rs
$rs = explode("\n", $rs);
unset($rs[0]);
$rs = join("\n", $rs);
$rs = unserialize($rs);
if (! is_object($rs)) {
$err = 'Unable to unserialize $rs';
return $false;
}
if ($rs->timeCreated == 0) return $rs; // apparently have been reports that timeCreated was set to 0 somewhere
$tdiff = intval($rs->timeCreated+$secs2cache - time());
if ($tdiff <= 2) {
switch($tdiff) {
case 2:
if ((rand() & 15) == 0) {
$err = "Timeout 2";
return $false;
}
break;
case 1:
if ((rand() & 3) == 0) {
$err = "Timeout 1";
return $false;
}
break;
default:
$err = "Timeout 0";
return $false;
}
}
return $rs;
}
function flushall($debug=false)
{
if (!$this->_connected) {
$err = '';
if (!$this->connect($err) && $debug) ADOConnection::outp($err);
}
if (!$this->_memcache) return false;
$del = $this->_memcache->flush();
if ($debug)
if (!$del) ADOConnection::outp("flushall: failed!<br>\n");
else ADOConnection::outp("flushall: succeeded!<br>\n");
return $del;
}
function flushcache($filename, $debug=false)
{
if (!$this->_connected) {
$err = '';
if (!$this->connect($err) && $debug) ADOConnection::outp($err);
}
if (!$this->_memcache) return false;
$del = $this->_memcache->delete($filename);
if ($debug)
if (!$del) ADOConnection::outp("flushcache: $key entry doesn't exist on memcache server!<br>\n");
else ADOConnection::outp("flushcache: $key entry flushed from memcache server!<br>\n");
return $del;
}
// not used for memcache
function createdir($dir, $hash)
{
return true;
}
return $rs;
}
/**
* Flushes all of the stored memcache data
*
* @param bool $debug
*
* @return bool The response from the memcache server
*/
public function flushAll($debug = false)
{
if (!$this->isConnected) {
$err = '';
if (!$this->connect($err) && $debug) {
ADOConnection::outp($err);
}
}
if (!$this->memcacheLibrary) {
return false;
}
$del = $this->memcacheLibrary->flush();
if ($debug) {
if (!$del) {
ADOConnection::outp("flushall: failed!<br>\n");
} else {
ADOConnection::outp("flushall: succeeded!<br>\n");
}
}
return $del;
}
/**
* Flushes the contents of a specified query
*
* @param string $filename The MD5 of the query to flush
* @param bool $debug
*
* @return bool The response from the memcache server
*/
public function flushCache($filename, $debug = false)
{
if (!$this->isConnected) {
$err = '';
if (!$this->connect($err) && $debug) {
ADOConnection::outp($err);
}
}
if (!$this->memcacheLibrary) {
return false;
}
$del = $this->memcacheLibrary->delete($filename);
if ($debug) {
if (!$del) {
ADOConnection::outp("flushcache: $filename entry doesn't exist on memcache server!<br>\n");
} else {
ADOConnection::outp("flushcache: $filename entry flushed from memcache server!<br>\n");
}
}
return $del;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -30,6 +30,15 @@ class ADODB2_access extends ADODB_DataDict {
function ActualType($meta)
{
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
switch($meta) {
case 'C': return 'TEXT';
case 'XL':
@ -41,18 +50,19 @@ class ADODB2_access extends ADODB_DataDict {
case 'B': return 'BINARY';
case 'TS':
case 'D': return 'DATETIME';
case 'D':
return 'DATETIME';
case 'T': return 'DATETIME';
case 'L': return 'BYTE';
case 'I': return 'INTEGER';
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';
case 'F': return 'DOUBLE';
case 'N': return 'NUMERIC';
default:
return $meta;
}

View File

@ -34,6 +34,15 @@ class ADODB2_db2 extends ADODB_DataDict {
function ActualType($meta)
{
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL': return 'CLOB';

View File

@ -22,8 +22,8 @@
// security - hide paths
if (!defined('ADODB_DIR')) die();
class ADODB2_firebird extends ADODB_DataDict {
class ADODB2_firebird extends ADODB_DataDict
{
var $databaseType = 'firebird';
var $seqField = false;
var $seqPrefix = 's_';
@ -32,69 +32,92 @@ class ADODB2_firebird extends ADODB_DataDict {
var $alterCol = ' ALTER';
var $dropCol = ' DROP';
function ActualType($meta)
function actualType($meta)
{
$meta = strtoupper($meta);
// Add support for custom meta types.
// We do this first, that allows us to override existing types
if (isset($this->connection->customMetaTypes[$meta])) {
return $this->connection->customMetaTypes[$meta]['actual'];
}
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL':
case 'X': return 'BLOB SUB_TYPE TEXT';
case 'C':
return 'VARCHAR';
case 'XL':
return 'BLOB SUB_TYPE BINARY';
case 'X':
return 'BLOB SUB_TYPE TEXT';
case 'C2': return 'VARCHAR(32765)'; // up to 32K
case 'X2': return 'VARCHAR(4096)';
case 'C2':
return 'VARCHAR(32765)'; // up to 32K
case 'X2':
return 'VARCHAR(4096)';
case 'V': return 'CHAR';
case 'C1': return 'CHAR(1)';
case 'V':
return 'CHAR';
case 'C1':
return 'CHAR(1)';
case 'B': return 'BLOB';
case 'B':
return 'BLOB';
case 'D': return 'DATE';
case 'TS':
case 'T': return 'TIMESTAMP';
case 'D':
return 'DATE';
case 'TS':
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 'L':
case 'I1':
case 'I2':
return 'SMALLINT';
case 'I':
case 'I4':
return 'INTEGER';
case 'I8':
return 'BIGINT';
case 'F': return 'DOUBLE PRECISION';
case 'N': return 'DECIMAL';
default:
return $meta;
case 'F':
return 'DOUBLE PRECISION';
case 'N':
return 'DECIMAL';
default:
return $meta;
}
}
function NameQuote($name = NULL,$allowBrackets=false)
function nameQuote($name = null, $allowBrackets = false)
{
if (!is_string($name)) {
return FALSE;
return false;
}
$name = trim($name);
if ( !is_object($this->connection) ) {
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) ) {
if (preg_match('/^`(.+)`$/', $name, $matches)) {
return $quote . $matches[1] . $quote;
}
// if name contains special characters, quote it
if ( !preg_match('/^[' . $this->nameRegex . ']+$/', $name) ) {
if (!preg_match('/^[' . $this->nameRegex . ']+$/', $name)) {
return $quote . $name . $quote;
}
return $quote . $name . $quote;
}
function CreateDatabase($dbname, $options=false)
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'";
@ -102,50 +125,62 @@ class ADODB2_firebird extends ADODB_DataDict {
return $sql;
}
function _DropAutoIncrement($t)
function _dropAutoIncrement($tabname)
{
if (strpos($t,'.') !== false) {
$tarr = explode('.',$t);
return 'DROP GENERATOR '.$tarr[0].'."s_'.$tarr[1].'"';
if (strpos($tabname, '.') !== false) {
$tarr = explode('.', $tabname);
return 'DROP SEQUENCE ' . $tarr[0] . '."s_' . $tarr[1] . '"';
}
return 'DROP GENERATOR s_'.$t;
return 'DROP SEQUENCE s_' . $tabname;
}
function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned)
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 (strlen($fdefault)) {
$suffix .= " DEFAULT $fdefault";
}
if ($fnotnull) {
$suffix .= ' NOT NULL';
}
if ($fautoinc) {
$this->seqField = $fname;
}
$fconstraint = preg_replace("/``/", "\"", $fconstraint);
if ($fconstraint) $suffix .= ' '.$fconstraint;
if ($fconstraint) {
$suffix .= ' ' . $fconstraint;
}
return $suffix;
}
/**
Generate the SQL to create table. Returns an array of sql strings.
*/
function CreateTableSQL($tabname, $flds, $tableoptions=array())
* Generate the SQL to create table. Returns an array of sql strings.
*/
function createTableSQL($tabname, $flds, $tableoptions = array())
{
list($lines,$pkey,$idxs) = $this->_GenFields($flds, true);
list($lines, $pkey, $idxs) = $this->_GenFields($flds, true);
// genfields can return FALSE at times
if ($lines == null) $lines = array();
if ($lines == null) {
$lines = array();
}
$taboptions = $this->_Options($tableoptions);
$tabname = $this->TableName ($tabname);
$sql = $this->_TableSQL($tabname,$lines,$pkey,$taboptions);
$tabname = $this->TableName($tabname);
$sql = $this->_TableSQL($tabname, $lines, $pkey, $taboptions);
if ($this->autoIncrement && !isset($taboptions['DROP']))
{ $tsql = $this->_Triggers($tabname,$taboptions);
foreach($tsql as $s) $sql[] = $s;
if ($this->autoIncrement && !isset($taboptions['DROP'])) {
$tsql = $this->_Triggers($tabname, $taboptions);
foreach ($tsql as $s) {
$sql[] = $s;
}
}
if (is_array($idxs)) {
foreach($idxs as $idx => $idxdef) {
$sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
foreach ($idxs as $idx => $idxdef) {
$sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
$sql = array_merge($sql, $sql_idxs);
}
}
@ -154,44 +189,47 @@ class ADODB2_firebird extends ADODB_DataDict {
}
/*
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)
/*
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, $taboptions)
{
if (!$this->seqField) return array();
if (!$this->seqField) {
return array();
}
$tab1 = preg_replace( '/"/', '', $tabname );
$tab1 = preg_replace('/"/', '', $tabname);
if ($this->schema) {
$t = strpos($tab1,'.');
if ($t !== false) $tab = substr($tab1,$t+1);
else $tab = $tab1;
$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.'.t_'.$this->seqPrefix.$tab;
$seqname = $this->schema . '.' . $this->seqPrefix . $tab;
$trigname = $this->schema . '.t_' . $this->seqPrefix . $tab;
} else {
$seqField = $this->seqField;
$seqname = $this->seqPrefix.$tab1;
$trigname = 't_'.$seqname;
$seqname = $this->seqPrefix . $tab1;
$trigname = 't_' . $seqname;
}
if (isset($tableoptions['DROP']))
{ $sql[] = "DROP GENERATOR $seqname";
}
elseif (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";
if (isset($taboptions['DROP'])) {
$sql[] = "DROP SEQUENCE $seqname";
} elseif (isset($taboptions['REPLACE'])) {
$sql[] = "DROP SEQUENCE \"$seqname\"";
$sql[] = "CREATE SEQUENCE \"$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 SEQUENCE $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;
@ -201,27 +239,39 @@ end;
/**
* Change the definition of one column
*
* As some DBM's can't do that on there own, you need to supply the complete definition of the new table,
* to allow, recreating the table and copying the content over to the new table
* @param string $tabname table-name
* @param string $flds column-name and type for the changed column
* @param string $tableflds='' complete definition of the new table, eg. for postgres, default ''
* @param array/string $tableoptions='' options for the new table see CreateTableSQL, default ''
* @param string $tableflds Unused
* @param array|string $tableoptions Unused
*
* @return array with SQL strings
*/
function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
public function alterColumnSQL($tabname, $flds, $tableflds = '', $tableoptions = '')
{
$tabname = $this->TableName ($tabname);
$tabname = $this->TableName($tabname);
$sql = array();
list($lines,$pkey,$idxs) = $this->_GenFields($flds);
list($lines, , $idxs) = $this->_GenFields($flds);
// genfields can return FALSE at times
if ($lines == null) $lines = array();
if ($lines == null) {
$lines = array();
}
$alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' ';
foreach($lines as $v) {
foreach ($lines as $v) {
/*
* The type must be preceded by the keyword 'TYPE'
*/
$vExplode = explode(' ', $v);
$vExplode = array_filter($vExplode);
array_splice($vExplode, 1, 0, array('TYPE'));
$v = implode(' ', $vExplode);
$sql[] = $alter . $v;
}
if (is_array($idxs)) {
foreach($idxs as $idx => $idxdef) {
foreach ($idxs as $idx => $idxdef) {
$sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
$sql = array_merge($sql, $sql_idxs);
}

View File

@ -28,8 +28,19 @@ class ADODB2_generic extends ADODB_DataDict {
var $seqField = false;
function ActualType($meta)
{
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL':

View File

@ -30,6 +30,15 @@ class ADODB2_ibase extends ADODB_DataDict {
function ActualType($meta)
{
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL':

View File

@ -30,6 +30,15 @@ class ADODB2_informix extends ADODB_DataDict {
function ActualType($meta)
{
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
switch($meta) {
case 'C': return 'VARCHAR';// 255
case 'XL':

View File

@ -68,9 +68,14 @@ class ADODB2_mssql extends ADODB_DataDict {
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$t = strtoupper($t);
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
switch ($t) {
case 'R':
case 'INT':
case 'INTEGER': return 'I';
@ -87,6 +92,16 @@ class ADODB2_mssql extends ADODB_DataDict {
function ActualType($meta)
{
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
switch(strtoupper($meta)) {
case 'C': return 'VARCHAR';

View File

@ -71,7 +71,13 @@ class ADODB2_mssqlnative extends ADODB_DataDict {
$fieldobj = $t;
$t = $fieldobj->type;
}
$t = strtoupper($t);
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
$_typeConversion = array(
-155 => 'D',
93 => 'D',
@ -115,7 +121,15 @@ class ADODB2_mssqlnative extends ADODB_DataDict {
function ActualType($meta)
{
$DATE_TYPE = 'DATETIME';
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
switch(strtoupper($meta)) {
case 'C': return 'VARCHAR';

View File

@ -33,7 +33,7 @@ class ADODB2_mysql extends ADODB_DataDict {
public $blobAllowsNotNull = true;
function MetaType($t,$len=-1,$fieldobj=false)
function metaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
@ -44,7 +44,14 @@ class ADODB2_mysql extends ADODB_DataDict {
$is_serial = is_object($fieldobj) && $fieldobj->primary_key && $fieldobj->auto_increment;
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
$t = strtoupper($t);
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
switch ($t) {
case 'STRING':
case 'CHAR':
case 'VARCHAR':
@ -84,13 +91,27 @@ class ADODB2_mysql extends ADODB_DataDict {
case 'SMALLINT': return $is_serial ? 'R' : 'I2';
case 'MEDIUMINT': return $is_serial ? 'R' : 'I4';
case 'BIGINT': return $is_serial ? 'R' : 'I8';
default: return ADODB_DEFAULT_METATYPE;
default:
return ADODB_DEFAULT_METATYPE;
}
}
function ActualType($meta)
{
switch(strtoupper($meta)) {
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
switch($meta)
{
case 'C': return 'VARCHAR';
case 'XL':return 'LONGTEXT';
case 'X': return 'TEXT';
@ -114,7 +135,9 @@ class ADODB2_mysql extends ADODB_DataDict {
case 'F': return 'DOUBLE';
case 'N': return 'NUMERIC';
default:
return $meta;
}
}

View File

@ -50,7 +50,13 @@ class ADODB2_oci8 extends ADODB_DataDict {
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
switch (strtoupper($t)) {
$t = strtoupper($t);
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
switch ($t) {
case 'VARCHAR':
case 'VARCHAR2':
case 'CHAR':
@ -92,6 +98,15 @@ class ADODB2_oci8 extends ADODB_DataDict {
function ActualType($meta)
{
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
switch($meta) {
case 'C': return 'VARCHAR';
case 'X': return $this->typeX;

View File

@ -34,7 +34,7 @@ class ADODB2_postgres extends ADODB_DataDict
public $blobAllowsDefaultValue = true;
public $blobAllowsNotNull = true;
function metaType($t, $len=-1, $fieldobj=false)
{
if (is_object($t)) {
@ -42,16 +42,23 @@ class ADODB2_postgres extends ADODB_DataDict
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$t = strtoupper($t);
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
$is_serial = is_object($fieldobj) && !empty($fieldobj->primary_key) && !empty($fieldobj->unique) &&
!empty($fieldobj->has_default) && substr($fieldobj->default_value,0,8) == 'nextval(';
switch (strtoupper($t)) {
switch ($t) {
case 'INTERVAL':
case 'CHAR':
case 'CHARACTER':
case 'VARCHAR':
case 'NAME':
case 'BPCHAR':
case 'BPCHAR':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
@ -94,13 +101,22 @@ class ADODB2_postgres extends ADODB_DataDict
case 'REAL':
return 'F';
default:
return ADODB_DEFAULT_METATYPE;
default:
return ADODB_DEFAULT_METATYPE;
}
}
function actualType($meta)
function actualType($meta)
{
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
switch ($meta) {
case 'C': return 'VARCHAR';
case 'XL':
@ -152,7 +168,7 @@ class ADODB2_postgres extends ADODB_DataDict
if (preg_match('/^([^ ]+) .*DEFAULT (\'[^\']+\'|\"[^\"]+\"|[^ ]+)/',$v,$matches)) {
list(,$colname,$default) = $matches;
$sql[] = $alter . str_replace('DEFAULT '.$default,'',$v);
$sql[] = 'UPDATE '.$tabname.' SET '.$colname.'='.$default;
$sql[] = 'UPDATE '.$tabname.' SET '.$colname.'='.$default.' WHERE '.$colname.' IS NULL ';
$sql[] = 'ALTER TABLE '.$tabname.' ALTER COLUMN '.$colname.' SET DEFAULT ' . $default;
} else {
$sql[] = $alter . $v;
@ -168,18 +184,21 @@ class ADODB2_postgres extends ADODB_DataDict
function dropIndexSQL($idxname, $tabname = NULL)
{
return array(sprintf($this->dropIndex, $this->tableName($idxname), $this->tableName($tabname)));
return array(sprintf($this->dropIndex, $this->tableName($idxname), $this->tableName($tabname)));
}
/**
* Change the definition of one column
*
* Postgres can't do that on it's own, you need to supply the complete definition of the new table,
* to allow, recreating the table and copying the content over to the new table
* @param string $tabname table-name
* @param string $flds column-name and type for the changed column
* @param string $tableflds complete definition of the new table, eg. for postgres, default ''
* @param array/ $tableoptions options for the new table see CreateTableSQL, default ''
* Postgres can't do that on its own, you need to supply the complete
* definition of the new table, to allow recreating the table and copying
* the content over to the new table.
*
* @param string $tabname table-name
* @param string $flds column-name and type for the changed column
* @param string $tableflds complete definition of the new table, e.g. for postgres, default ''
* @param array $tableoptions options for the new table {@see CreateTableSQL()}, default ''
*
* @return array with SQL strings
*/
function alterColumnSQL($tabname, $flds, $tableflds='', $tableoptions='')
@ -197,9 +216,9 @@ class ADODB2_postgres extends ADODB_DataDict
if ($not_null = preg_match('/NOT NULL/i',$v)) {
$v = preg_replace('/NOT NULL/i','',$v);
}
// this next block doesn't work - there is no way that I can see to
// explicitly ask a column to be null using $flds
else if ($set_null = preg_match('/NULL/i',$v)) {
// this next block doesn't work - there is no way that I can see to
// explicitly ask a column to be null using $flds
elseif ($set_null = preg_match('/NULL/i',$v)) {
// if they didn't specify not null, see if they explicitly asked for null
// Lookbehind pattern covers the case 'fieldname NULL datatype DEFAULT NULL'
// only the first NULL should be removed, not the one specifying
@ -278,7 +297,7 @@ class ADODB2_postgres extends ADODB_DataDict
* @param string $tabname table-name
* @param string $flds column-name and type for the changed column
* @param string $tableflds complete definition of the new table, eg. for postgres, default ''
* @param array/ $tableoptions options for the new table see CreateTableSQL, default ''
* @param array $tableoptions options for the new table {@see CreateTableSQL}, default []
* @return array with SQL strings
*/
function dropColumnSQL($tabname, $flds, $tableflds='', $tableoptions='')
@ -305,7 +324,7 @@ class ADODB2_postgres extends ADODB_DataDict
* @param string $tabname table-name
* @param string $dropflds column-names to drop
* @param string $tableflds complete definition of the new table, eg. for postgres
* @param array/string $tableoptions options for the new table see CreateTableSQL, default ''
* @param array|string $tableoptions options for the new table see CreateTableSQL, default ''
* @return array with SQL strings
*/
function _recreate_copy_table($tabname, $dropflds, $tableflds, $tableoptions='')
@ -477,11 +496,11 @@ CREATE [ UNIQUE ] INDEX index_name ON table
if (isset($idxoptions['HASH'])) {
$s .= 'USING HASH ';
}
if (isset($idxoptions[$this->upperName])) {
$s .= $idxoptions[$this->upperName];
}
if (is_array($flds)) {
$flds = implode(', ', $flds);
}
@ -514,7 +533,7 @@ CREATE [ UNIQUE ] INDEX index_name ON table
}
return $ftype;
}
function changeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=false)
{
global $ADODB_FETCH_MODE;
@ -524,18 +543,18 @@ CREATE [ UNIQUE ] INDEX index_name ON table
if ($this->connection->fetchMode !== false) {
$savem = $this->connection->setFetchMode(false);
}
// check table exists
$save_handler = $this->connection->raiseErrorFn;
$this->connection->raiseErrorFn = '';
$cols = $this->metaColumns($tablename);
$this->connection->raiseErrorFn = $save_handler;
if (isset($savem)) {
$this->connection->setFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
$sqlResult=array();
if ( empty($cols)) {
$sqlResult=$this->createTableSQL($tablename, $flds, $tableoptions);
@ -543,7 +562,7 @@ CREATE [ UNIQUE ] INDEX index_name ON table
$sqlResultAdd = $this->addColumnSQL($tablename, $flds);
$sqlResultAlter = $this->alterColumnSQL($tablename, $flds, '', $tableoptions);
$sqlResult = array_merge((array)$sqlResultAdd, (array)$sqlResultAlter);
if ($dropOldFlds) {
// already exists, alter table instead
list($lines,$pkey,$idxs) = $this->_genFields($flds);
@ -558,7 +577,7 @@ CREATE [ UNIQUE ] INDEX index_name ON table
}
}
}
}
return $sqlResult;
}

View File

@ -30,6 +30,15 @@ class ADODB2_sapdb extends ADODB_DataDict {
function ActualType($meta)
{
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
switch($meta) {
case 'C': return 'VARCHAR';
case 'XL':
@ -65,6 +74,12 @@ class ADODB2_sapdb extends ADODB_DataDict {
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$t = strtoupper($t);
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
static $maxdb_type2adodb = array(
'VARCHAR' => 'C',
'CHARACTER' => 'C',

View File

@ -35,6 +35,16 @@ class ADODB2_sqlite extends ADODB_DataDict {
function ActualType($meta)
{
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
switch(strtoupper($meta)) {
case 'C': return 'VARCHAR'; // TEXT , TEXT affinity
case 'XL':return 'LONGTEXT'; // TEXT , TEXT affinity

View File

@ -35,8 +35,15 @@ class ADODB2_sybase extends ADODB_DataDict {
$len = $fieldobj->max_length;
}
$t = strtoupper($t);
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
switch ($t) {
case 'INT':
case 'INTEGER': return 'I';
@ -53,6 +60,15 @@ class ADODB2_sybase extends ADODB_DataDict {
function ActualType($meta)
{
$meta = strtoupper($meta);
/*
* Add support for custom meta types. We do this
* first, that allows us to override existing types
*/
if (isset($this->connection->customMetaTypes[$meta]))
return $this->connection->customMetaTypes[$meta]['actual'];
switch(strtoupper($meta)) {
case 'C': return 'VARCHAR';
case 'XL':

View File

@ -504,6 +504,9 @@ class ADORecordSet_ado extends ADORecordSet {
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
if (!is_numeric($t)) return $t;

View File

@ -545,8 +545,14 @@ class ADORecordSet_ado extends ADORecordSet {
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$t = strtoupper($t);
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
if (!is_numeric($t)) return $t;
if (!is_numeric($t))
return $t;
switch ($t) {
case 0:

View File

@ -113,7 +113,7 @@ class ADODB_db2 extends ADOConnection {
private function doDB2Connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persistent=false)
{
if (!function_exists('db2_connect')) {
ADOConnection::outp("DB2 extension not installed.");
return null;
@ -184,6 +184,7 @@ class ADODB_db2 extends ADOConnection {
null,
$db2Options);
$this->_errorMsg = @db2_conn_errormsg();
if ($this->_connectionID && $this->connectStmt)
@ -206,6 +207,7 @@ class ADODB_db2 extends ADOConnection {
private function unpackParameters($argDSN, $argUsername, $argPassword, $argDatabasename)
{
$connectionParameters = array('dsn'=>'',
'uid'=>'',
'pwd'=>'',
@ -255,6 +257,7 @@ class ADODB_db2 extends ADOConnection {
$errorMessage = 'Supply uncatalogued connection parameters ';
$errorMessage.= 'in either the database or DSN arguments, ';
$errorMessage.= 'but not both';
if ($this->debug)
ADOConnection::outp($errorMessage);
return null;
@ -279,6 +282,7 @@ class ADODB_db2 extends ADOConnection {
{
$errorMessage = 'For uncatalogued connections, provide ';
$errorMessage.= 'both UID and PWD in the connection string';
if ($this->debug)
ADOConnection::outp($errorMessage);
return null;
@ -313,6 +317,7 @@ class ADODB_db2 extends ADOConnection {
{
$errorMessage = 'Uncatalogued connection parameters ';
$errorMessage.= 'must contain a database= argument';
if ($this->debug)
ADOConnection::outp($errorMessage);
return null;
@ -676,16 +681,17 @@ class ADODB_db2 extends ADOConnection {
}
/**
* returns assoc array where keys are tables, and values are foreign keys
* Returns a list of Foreign Keys associated with a specific table.
*
* @param string $table
* @param string $owner [optional][discarded]
* @param bool $upper [optional][discarded]
* @param bool $associative[optional][discarded]
* @param string $table
* @param string $owner discarded
* @param bool $upper discarded
* @param bool $associative discarded
*
* @return mixed[] Array of foreign key information
* @return string[]|false An array where keys are tables, and values are foreign keys;
* false if no foreign keys could be found.
*/
public function metaForeignKeys($table, $owner = FALSE, $upper = FALSE, $asociative = FALSE )
public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false)
{
global $ADODB_FETCH_MODE;
@ -1610,12 +1616,12 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2
if ($stmtid == false)
{
$this->_errorMsg = @db2_stmt_errormsg();
$this->_errorCode = @db2_stmt_error();
if ($this->debug)
ADOConnection::outp($this->_errorMsg);
$this->_errorMsg = @db2_stmt_errormsg();
$this->_errorCode = @db2_stmt_error();
if ($this->debug)
ADOConnection::outp($this->_errorMsg);
return false;
}
}

View File

@ -232,8 +232,15 @@ class ADORecordSet_fbsql extends ADORecordSet{
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
$t = strtoupper($t);
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
$len = -1; // fbsql max_length is not accurate
switch (strtoupper($t)) {
switch ($t) {
case 'CHARACTER':
case 'CHARACTER VARYING':
case 'BLOB':

File diff suppressed because it is too large Load Diff

View File

@ -860,7 +860,14 @@ class ADORecordset_ibase extends ADORecordSet
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
switch (strtoupper($t)) {
$t = strtoupper($t);
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
switch ($t) {
case 'CHAR':
return 'C';

View File

@ -253,12 +253,12 @@ class ADODB_informix72 extends ADOConnection {
return $false;
}
function xMetaColumns($table)
{
function xMetaColumns($table)
{
return ADOConnection::MetaColumns($table,false);
}
}
function MetaForeignKeys($table, $owner=false, $upper=false) //!Eos
public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false)
{
$sql = "
select tr.tabname,updrule,delrule,

View File

@ -429,7 +429,7 @@ class ADODB_mssql extends ADOConnection {
return $indexes;
}
function MetaForeignKeys($table, $owner=false, $upper=false)
public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false)
{
global $ADODB_FETCH_MODE;

View File

@ -151,6 +151,8 @@ class ADODB_mssqlnative extends ADOConnection {
$arrServerInfo = sqlsrv_server_info($this->_connectionID);
$ADODB_FETCH_MODE = $savem;
$arr = array();
$arr['description'] = $arrServerInfo['SQLServerName'].' connected to '.$arrServerInfo['CurrentDatabase'];
$arr['version'] = $arrServerInfo['SQLServerVersion'];//ADOConnection::_findvers($arr['description']);
return $arr;
@ -719,7 +721,7 @@ class ADODB_mssqlnative extends ADOConnection {
return $indexes;
}
function MetaForeignKeys($table, $owner=false, $upper=false)
public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false)
{
global $ADODB_FETCH_MODE;
@ -1009,6 +1011,37 @@ class ADODB_mssqlnative extends ADOConnection {
return $metaProcedures;
}
/**
* An SQL Statement that adds a specific number of
* days or part to local datetime
*
* @param float $dayFraction
* @param string $date
*
* @return string
*/
public function offsetDate($dayFraction, $date = false)
{
if (!$date)
/*
* Use GETDATE() via systTimestamp;
*/
$date = $this->sysTimeStamp;
/*
* seconds, number of seconds, date base
*/
$dateFormat = "DATEADD(s, %s, %s)";
/*
* Adjust the offset back to seconds
*/
$fraction = $dayFraction * 24 * 3600;
return sprintf($dateFormat,$fraction,$date);
}
}
/*--------------------------------------------------------------------------------------

View File

@ -1,932 +0,0 @@
<?php
/**
* MySQL driver
*
* @deprecated
*
* This driver only supports the original non-transactional MySQL driver,
* which was deprecated in PHP version 5.5 and removed in PHP version 7.
* It is deprecated as of ADOdb version 5.20.0, use the mysqli driver
* instead, which supports both transactional and non-transactional updates.
*
* This file is part of ADOdb, a Database Abstraction Layer library for PHP.
*
* @package ADOdb
* @link https://adodb.org Project's web site and documentation
* @link https://github.com/ADOdb/ADOdb Source code and issue tracker
*
* The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
* and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
* any later version. This means you can use it in proprietary products.
* See the LICENSE.md file distributed with this source code for details.
* @license BSD-3-Clause
* @license LGPL-2.1-or-later
*
* @copyright 2000-2013 John Lim
* @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
*/
// 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 = "SELECT
TABLE_NAME,
CASE WHEN TABLE_TYPE = 'VIEW' THEN 'V' ELSE 'T' END
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA=";
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 $charSet = '';
var $substr = "substring";
var $nameQuote = '`'; /// string to use to quote identifiers and names
var $compat323 = false; // true if compat with mysql 3.23
/**
* ADODB_mysql constructor.
*/
public function __construct() {
if(version_compare(PHP_VERSION, '7.0.0', '>=')) {
$this->outp_throw(
'mysql extension is not supported since PHP 7.0.0, use mysqli instead',
__METHOD__
);
die(1); // Stop execution even if not using Exceptions
} elseif(version_compare(PHP_VERSION, '5.5.0', '>=')) {
// If mysql extension is available just print a warning,
// otherwise die with an error message
if(function_exists('mysql_connect')) {
$this->outp('mysql extension is deprecated since PHP 5.5.0, consider using mysqli');
} else {
$this->outp_throw(
'mysql extension is not available, use mysqli instead',
__METHOD__
);
die(1); // Stop execution even if not using Exceptions
}
}
}
function setCharSet($charset)
{
if (!function_exists('mysql_set_charset')) {
return false;
}
if ($this->charSet !== $charset) {
$ok = @mysql_set_charset($charset,$this->_connectionID);
if ($ok) {
$this->charSet = $charset;
return true;
}
return false;
}
return true;
}
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 metaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null)
{
// save old fetch mode
global $ADODB_FETCH_MODE;
$false = false;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
$savem = $this->SetFetchMode(FALSE);
}
$procedures = array ();
// get index details
$likepattern = '';
if ($NamePattern) {
$likepattern = " LIKE '".$NamePattern."'";
}
$rs = $this->Execute('SHOW PROCEDURE STATUS'.$likepattern);
if (is_object($rs)) {
// parse index data into array
while ($row = $rs->FetchRow()) {
$procedures[$row[1]] = array(
'type' => 'PROCEDURE',
'catalog' => '',
'schema' => '',
'remarks' => $row[7],
);
}
}
$rs = $this->Execute('SHOW FUNCTION STATUS'.$likepattern);
if (is_object($rs)) {
// parse index data into array
while ($row = $rs->FetchRow()) {
$procedures[$row[1]] = array(
'type' => 'FUNCTION',
'catalog' => '',
'schema' => '',
'remarks' => $row[7]
);
}
}
// restore fetchmode
if (isset($savem)) {
$this->SetFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
return $procedures;
}
/**
* Retrieves a list of tables based on given criteria
*
* @param string $ttype Table type = 'TABLE', 'VIEW' or false=both (default)
* @param string $showSchema schema name, false = current schema (default)
* @param string $mask filters the table by name
*
* @return array list of tables
*/
function metaTables($ttype=false,$showSchema=false,$mask=false)
{
$save = $this->metaTablesSQL;
if ($showSchema && is_string($showSchema)) {
$this->metaTablesSQL .= $this->qstr($showSchema);
} else {
$this->metaTablesSQL .= "schema()";
}
if ($mask) {
$mask = $this->qstr($mask);
$this->metaTablesSQL .= " AND table_name 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;
$false = false;
$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;
}
/**
* Appropriately quotes strings with ' characters for insertion into the database.
*
* Relies on mysql_real_escape_string()
* @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:qstr
*
* @param string $s The string to quote
* @param bool $magic_quotes This param is not used since 5.21.0.
* It remains for backwards compatibility.
*
* @return string Quoted string
*/
function qStr($s, $magic_quotes=false)
{
if (is_null($s)) {
return 'NULL';
}
if (is_resource($this->_connectionID)) {
return "'" . mysql_real_escape_string($s, $this->_connectionID) . "'";
}
if ($this->replaceQuote[0] == '\\') {
$s = str_replace(array('\\', "\0"), array('\\\\', "\\\0"), $s);
}
return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
}
protected function _insertID($table = '', $column = '')
{
return ADOConnection::GetOne('SELECT LAST_INSERT_ID()');
//return mysql_insert_id($this->_connectionID);
}
function getOne($sql,$inputarr=false)
{
global $ADODB_GETONE_EOF;
if ($this->compat323 == false && strncasecmp($sql,'sele',4) == 0) {
$rs = $this->SelectLimit($sql,1,-1,$inputarr);
if ($rs) {
$rs->Close();
if ($rs->EOF) return $ADODB_GETONE_EOF;
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 if not exists %s (id int not null)";
var $_genSeqCountSQL = "select count(*) from %s";
var $_genSeq2SQL = "insert into %s values (%s)";
var $_dropSeqSQL = "drop table if exists %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));
$cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname));
if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
$rs = $this->Execute($getnext);
}
if ($rs) {
$this->genID = mysql_insert_id($this->_connectionID);
$rs->Close();
} else
$this->genID = 0;
$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;
case 'w':
$s .= '%w';
break;
case 'W':
$s .= '%U';
break;
case 'l':
$s .= '%W';
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;
$fraction = $dayFraction * 24 * 3600;
return '('. $date . ' + INTERVAL ' . $fraction.' SECOND)';
// return "from_unixtime(unix_timestamp($date)+$fraction)";
}
// returns true or false
function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (!empty($this->port))
$argHostname .= ":".$this->port;
$this->_connectionID =
mysql_connect($argHostname,
$argUsername,
$argPassword,
$this->forceNewConnect,
$this->clientFlags
);
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 (!empty($this->port)) $argHostname .= ":".$this->port;
$this->_connectionID =
mysql_pconnect($argHostname,
$argUsername,
$argPassword,
$this->clientFlags);
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, $normalize=true)
{
$this->_findschema($table,$schema);
if ($schema) {
$dbName = $this->database;
$this->SelectDB($schema);
}
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 ($schema) {
$this->SelectDB($dbName);
}
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if (!is_object($rs)) {
$false = 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 (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;
} elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
$fld->type = $query_array[1];
$arr = explode(",",$query_array[2]);
$fld->enums = $arr;
$zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
$fld->max_length = ($zlen > 0) ? $zlen : 1;
} else {
$fld->type = $type;
$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($type,'blob') !== false || strpos($type,'binary') !== false);
$fld->unsigned = (strpos($type,'unsigned') !== false);
$fld->zerofill = (strpos($type,'zerofill') !== 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;
}
// returns true or false
function selectDB($dbName)
{
$this->database = $dbName;
$this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
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)
{
$nrows = (int) $nrows;
$offset = (int) $offset;
$offsetStr =($offset>=0) ? ((integer)$offset)."," : '';
// jason judge, see PHPLens Issue No: 9220
if ($nrows < 0) $nrows = '18446744073709551615';
if ($secs)
$rs = $this->CacheExecute($secs,$sql." LIMIT $offsetStr".((integer)$nrows),$inputarr);
else
$rs = $this->Execute($sql." LIMIT $offsetStr".((integer)$nrows),$inputarr);
return $rs;
}
// returns queryID or false
function _query($sql,$inputarr=false)
{
return mysql_query($sql,$this->_connectionID);
/*
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->charSet = '';
$this->_connectionID = false;
}
/*
* Maximum size of C field
*/
function charMax()
{
return 255;
}
/*
* Maximum size of X field
*/
function textMax()
{
return 4294967295;
}
// "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx>
function metaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
{
global $ADODB_FETCH_MODE;
if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true;
if ( !empty($owner) ) {
$table = "$owner.$table";
}
$a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
if ($associative) {
$create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"];
} else {
$create_sql = $a_create_table[1];
}
$matches = array();
if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
$foreign_keys = array();
$num_keys = count($matches[0]);
for ( $i = 0; $i < $num_keys; $i ++ ) {
$my_field = explode('`, `', $matches[1][$i]);
$ref_table = $matches[2][$i];
$ref_field = explode('`, `', $matches[3][$i]);
if ( $upper ) {
$ref_table = strtoupper($ref_table);
}
// see https://sourceforge.net/p/adodb/bugs/100/
if (!isset($foreign_keys[$ref_table])) {
$foreign_keys[$ref_table] = array();
}
$num_fields = count($my_field);
for ( $j = 0; $j < $num_fields; $j ++ ) {
if ( $associative ) {
$foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
} else {
$foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
}
}
}
return $foreign_keys;
}
}
/*--------------------------------------------------------------------------------------
Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordSet_mysql extends ADORecordSet{
var $databaseType = "mysql";
var $canSeek = true;
function __construct($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;
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:
default:
$this->fetchMode = MYSQL_BOTH; break;
}
$this->adodbFetchMode = $mode;
parent::__construct($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);
if ($o) $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
if ($o) $o->binary = (strpos($f,'binary')!== false);
}
else { /* The $fieldOffset argument is not provided thus its -1 */
$o = @mysql_fetch_field($this->_queryID);
//if ($o) $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 = ADODB_ASSOC_CASE)
{
if ($this->fetchMode == MYSQL_ASSOC && $upper == ADODB_ASSOC_CASE_LOWER) {
$row = $this->fields;
}
else {
$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()
{
if (@$this->fields = mysql_fetch_array($this->_queryID,$this->fetchMode)) {
$this->_updatefields();
$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);
$this->_updatefields();
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':
case 'BINARY':
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 ADODB_DEFAULT_METATYPE;
}
}
}
/**
* Class ADORecordSet_ext_mysql
*/
class ADORecordSet_ext_mysql extends ADORecordSet_mysql {
function moveNext()
{
return @adodb_movenext($this);
}
}
}

View File

@ -75,12 +75,17 @@ class ADODB_mysqli extends ADOConnection {
var $ssl_capath = null;
var $ssl_cipher = null;
/** @var mysqli Identifier for the native database connection */
var $_connectionID = false;
/**
* Tells the insert_id method how to obtain the last value, depending on whether
* we are using a stored procedure or not
*/
private $usePreparedStatement = false;
private $useLastInsertStatement = false;
private $usingBoundVariables = false;
private $statementAffectedRows = -1;
/**
* @var bool True if the last executed statement is a SELECT {@see _query()}
@ -123,13 +128,12 @@ class ADODB_mysqli extends ADOConnection {
/**
* Adds a parameter to the connection string.
*
* Parameter must be one of the the constants listed in mysqli_options().
* Parameter must be one of the constants listed in mysqli_options().
* @see https://www.php.net/manual/en/mysqli.options.php
*
* @param int $parameter The parameter to set
* @param string $value The value of the parameter
* @param int $parameter The parameter to set
* @param string $value The value of the parameter
*
* @example, for mssqlnative driver ('CharacterSet','UTF-8')
* @return bool
*/
public function setConnectionParameter($parameter, $value) {
@ -137,8 +141,7 @@ class ADODB_mysqli extends ADOConnection {
$this->outp_throw("Invalid connection parameter '$parameter'", __METHOD__);
return false;
}
$this->connectionParameters[$parameter] = $value;
return true;
return parent::setConnectionParameter($parameter, $value);
}
/**
@ -184,13 +187,15 @@ class ADODB_mysqli extends ADOConnection {
}
// Now merge in the standard connection parameters setting
foreach ($this->connectionParameters as $parameter => $value) {
// Make sure parameter is numeric before calling mysqli_options()
// that to avoid Warning (or TypeError exception on PHP 8).
if (!is_numeric($parameter)
|| !mysqli_options($this->_connectionID, $parameter, $value)
) {
$this->outp_throw("Invalid connection parameter '$parameter'", __METHOD__);
foreach ($this->connectionParameters as $options) {
foreach ($options as $parameter => $value) {
// Make sure parameter is numeric before calling mysqli_options()
// to avoid Warning (or TypeError exception on PHP 8).
if (!is_numeric($parameter)
|| !mysqli_options($this->_connectionID, $parameter, $value)
) {
$this->outp_throw("Invalid connection parameter '$parameter'", __METHOD__);
}
}
}
@ -202,9 +207,12 @@ class ADODB_mysqli extends ADOConnection {
// SSL Connections for MySQLI
if ($this->ssl_key || $this->ssl_cert || $this->ssl_ca || $this->ssl_capath || $this->ssl_cipher) {
mysqli_ssl_set($this->_connectionID, $this->ssl_key, $this->ssl_cert, $this->ssl_ca, $this->ssl_capath, $this->ssl_cipher);
$this->socket = MYSQLI_CLIENT_SSL;
$this->clientFlags = MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT;
}
#if (!empty($this->port)) $argHostname .= ":".$this->port;
/** @noinspection PhpCastIsUnnecessaryInspection */
$ok = @mysqli_real_connect($this->_connectionID,
$argHostname,
$argUsername,
@ -252,15 +260,15 @@ class ADODB_mysqli extends ADOConnection {
* @param string|null $argHostname The host to connect to.
* @param string|null $argUsername The username to connect as.
* @param string|null $argPassword The password to connect with.
* @param string|null $argDatabasename The name of the database to start in when connected.
* @param string|null $argDatabaseName The name of the database to start in when connected.
*
* @return bool|null True if connected successfully, false if connection failed, or null if the mysqli extension
* isn't currently loaded.
*/
function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName)
{
$this->forceNewConnect = true;
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName);
}
/**
@ -376,17 +384,17 @@ class ADODB_mysqli extends ADOConnection {
*
* @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:rowlock
*
* @param string $tables The table(s) to lock rows for.
* @param string $table The table(s) to lock rows for.
* @param string $where (Optional) The WHERE clause to use to determine which rows to lock.
* @param string $col (Optional) The columns to select.
*
* @return bool True if the locking SQL statement executed successfully, otherwise false.
*/
function RowLock($tables, $where = '', $col = '1 as adodbignore')
function RowLock($table, $where = '', $col = '1 as adodbignore')
{
if ($this->transCnt==0) $this->beginTrans();
if ($where) $where = ' where '.$where;
$rs = $this->execute("select $col from $tables $where for update");
$rs = $this->execute("select $col from $table $where for update");
return !empty($rs);
}
@ -457,10 +465,17 @@ class ADODB_mysqli extends ADOConnection {
// the rowcount, but ADOdb does not do that.
return false;
}
$result = @mysqli_affected_rows($this->_connectionID);
if ($result == -1) {
if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : " . $this->errorMsg());
else if ($this->statementAffectedRows >= 0)
{
$result = $this->statementAffectedRows;
$this->statementAffectedRows = -1;
}
else
{
$result = @mysqli_affected_rows($this->_connectionID);
if ($result == -1) {
if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : " . $this->errorMsg());
}
}
return $result;
}
@ -566,7 +581,6 @@ class ADODB_mysqli extends ADOConnection {
// save old fetch mode
global $ADODB_FETCH_MODE;
$false = false;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
@ -574,7 +588,7 @@ class ADODB_mysqli extends ADOConnection {
}
// get index details
$rs = $this->execute(sprintf('SHOW INDEXES FROM %s',$table));
$rs = $this->Execute(sprintf('SHOW INDEXES FROM `%s`',$table));
// restore fetchmode
if (isset($savem)) {
@ -583,7 +597,7 @@ class ADODB_mysqli extends ADOConnection {
$ADODB_FETCH_MODE = $save;
if (!is_object($rs)) {
return $false;
return false;
}
$indexes = array ();
@ -621,7 +635,7 @@ class ADODB_mysqli extends ADOConnection {
* @param string $fmt The date format to use.
* @param string|bool $col (Optional) The table column to date format, or if false, use NOW().
*
* @return bool|string The SQL DATE_FORMAT() string, or false if the provided date format was empty.
* @return string The SQL DATE_FORMAT() string, or false if the provided date format was empty.
*/
function SQLDate($fmt, $col = false)
{
@ -740,13 +754,13 @@ class ADODB_mysqli extends ADOConnection {
/**
* Returns information about stored procedures and stored functions.
*
* @param string|bool $NamePattern (Optional) Only look for procedures/functions with a name matching this pattern.
* @param string|bool $procedureNamePattern (Optional) Only look for procedures/functions with a name matching this pattern.
* @param null $catalog (Optional) Unused.
* @param null $schemaPattern (Optional) Unused.
*
* @return array
*/
function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null)
function MetaProcedures($procedureNamePattern = false, $catalog = null, $schemaPattern = null)
{
// save old fetch mode
global $ADODB_FETCH_MODE;
@ -763,8 +777,8 @@ class ADODB_mysqli extends ADOConnection {
// get index details
$likepattern = '';
if ($NamePattern) {
$likepattern = " LIKE '".$NamePattern."'";
if ($procedureNamePattern) {
$likepattern = " LIKE '".$procedureNamePattern."'";
}
$rs = $this->execute('SHOW PROCEDURE STATUS'.$likepattern);
if (is_object($rs)) {
@ -840,9 +854,8 @@ class ADODB_mysqli extends ADOConnection {
*
* @return array|bool An array of foreign keys, or false no foreign keys could be found.
*/
function MetaForeignKeys($table, $owner = false, $upper = false, $associative = false)
public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false)
{
global $ADODB_FETCH_MODE;
if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC
@ -856,7 +869,7 @@ class ADODB_mysqli extends ADOConnection {
$table = "$owner.$table";
}
$a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
$a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE `%s`', $table));
$this->setFetchMode($savem);
@ -935,7 +948,6 @@ class ADODB_mysqli extends ADOConnection {
while (!$rs->EOF) {
$fld = new ADOFieldObject();
$fld->name = $rs->fields[0];
$type = $rs->fields[1];
/*
* Type from information_schema returns
@ -1027,7 +1039,7 @@ class ADODB_mysqli extends ADOConnection {
* @param int $nrows (Optional) The limit for the number of records you want returned. By default, all results.
* @param int $offset (Optional) The offset to use when selecting the results. By default, no offset.
* @param array|bool $inputarr (Optional) Any parameter values required by the SQL statement, or false if none.
* @param int $secs (Optional) If greater than 0, perform a cached execute. By default, normal execution.
* @param int $secs2cache (Optional) If greater than 0, perform a cached execute. By default, normal execution.
*
* @return ADORecordSet|false The query results, or false if the query failed to execute.
*/
@ -1035,15 +1047,15 @@ class ADODB_mysqli extends ADOConnection {
$nrows = -1,
$offset = -1,
$inputarr = false,
$secs = 0)
$secs2cache = 0)
{
$nrows = (int) $nrows;
$offset = (int) $offset;
$offsetStr = ($offset >= 0) ? "$offset," : '';
if ($nrows < 0) $nrows = '18446744073709551615';
if ($secs)
$rs = $this->cacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr );
if ($secs2cache)
$rs = $this->cacheExecute($secs2cache, $sql . " LIMIT $offsetStr$nrows" , $inputarr );
else
$rs = $this->execute($sql . " LIMIT $offsetStr$nrows" , $inputarr );
@ -1052,6 +1064,7 @@ class ADODB_mysqli extends ADOConnection {
/**
* Prepares an SQL statement and returns a handle to use.
* This is not used by bound parameters anymore
*
* @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:prepare
* @todo update this function to handle prepared statements correctly
@ -1080,13 +1093,106 @@ class ADODB_mysqli extends ADOConnection {
}
/**
* Return the query id.
* Execute SQL
*
* @param string|array $sql
* @param array $inputarr
* @param string $sql SQL statement to execute, or possibly an array
* holding prepared statement ($sql[0] will hold sql text)
* @param array|bool $inputarr holds the input data to bind to.
* Null elements will be set to null.
*
* @return bool|mysqli_result
* @return ADORecordSet|bool
*/
public function execute($sql, $inputarr = false)
{
if ($this->fnExecute) {
$fn = $this->fnExecute;
$ret = $fn($this, $sql, $inputarr);
if (isset($ret)) {
return $ret;
}
}
if ($inputarr === false || $inputarr === []) {
return $this->_execute($sql);
}
if (!is_array($inputarr)) {
$inputarr = array($inputarr);
}
if (!is_array($sql)) {
// Check if we are bulkbinding. If so, $inputarr is a 2d array,
// and we make a gross assumption that all rows have the same number
// of columns of the same type, and use the elements of the first row
// to determine the MySQL bind param types.
if (is_array($inputarr[0])) {
if (!$this->bulkBind) {
$this->outp_throw(
"2D Array of values sent to execute and 'ADOdb_mysqli::bulkBind' not set",
'Execute'
);
return false;
}
$bulkTypeArray = [];
foreach ($inputarr as $v) {
if (is_string($this->bulkBind)) {
$typeArray = array_merge((array)$this->bulkBind, $v);
} else {
$typeArray = $this->getBindParamWithType($v);
}
$bulkTypeArray[] = $typeArray;
}
$this->bulkBind = false;
$ret = $this->_execute($sql, $bulkTypeArray);
} else {
$typeArray = $this->getBindParamWithType($inputarr);
$ret = $this->_execute($sql, $typeArray);
}
} else {
$ret = $this->_execute($sql, $inputarr);
}
return $ret;
}
/**
* Inserts the bind param type string at the front of the parameter array.
*
* @see https://www.php.net/manual/en/mysqli-stmt.bind-param.php
*
* @param array $inputArr
* @return array
*/
private function getBindParamWithType($inputArr): array
{
$typeString = '';
foreach ($inputArr as $v) {
if (is_integer($v) || is_bool($v)) {
$typeString .= 'i';
} elseif (is_float($v)) {
$typeString .= 'd';
} elseif (is_object($v)) {
// Assume a blob
$typeString .= 'b';
} else {
$typeString .= 's';
}
}
// Place the field type list at the front of the parameter array.
// This is the mysql specific format
array_unshift($inputArr, $typeString);
return $inputArr;
}
/**
* Return the query id.
*
* @param string|array $sql
* @param array $inputarr
*
* @return bool|mysqli_result
*/
function _query($sql, $inputarr)
{
global $ADODB_COUNTRECS;
@ -1104,7 +1210,7 @@ class ADODB_mysqli extends ADOConnection {
$stmt = $sql[1];
$a = '';
foreach($inputarr as $k => $v) {
foreach($inputarr as $v) {
if (is_string($v)) $a .= 's';
else if (is_integer($v)) $a .= 'i';
else $a .= 'd';
@ -1118,8 +1224,105 @@ class ADODB_mysqli extends ADOConnection {
$fnarr = array_merge( array($stmt,$a) , $inputarr);
call_user_func_array('mysqli_stmt_bind_param',$fnarr);
$ret = mysqli_stmt_execute($stmt);
return $ret;
return mysqli_stmt_execute($stmt);
}
else if (is_string($sql) && is_array($inputarr))
{
/*
* This is support for true prepared queries
* with bound parameters
*
* set prepared statement flags
*/
$this->usePreparedStatement = true;
$this->usingBoundVariables = true;
$bulkBindArray = array();
if (is_array($inputarr[0]))
{
$bulkBindArray = $inputarr;
$inputArrayCount = count($inputarr[0]) - 1;
}
else
{
$bulkBindArray[] = $inputarr;
$inputArrayCount = count($inputarr) - 1;
}
/*
* Prepare the statement with the placeholders,
* prepare will fail if the statement is invalid
* so we trap and error if necessary. Note that we
* are calling MySQL prepare here, not ADOdb
*/
$stmt = $this->_connectionID->prepare($sql);
if ($stmt === false)
{
$this->outp_throw(
"SQL Statement failed on preparation: " . htmlspecialchars($sql) . "'",
'Execute'
);
return false;
}
/*
* Make sure the number of parameters provided in the input
* array matches what the query expects. We must discount
* the first parameter which contains the data types in
* our inbound parameters
*/
$nparams = $stmt->param_count;
if ($nparams != $inputArrayCount)
{
$this->outp_throw(
"Input array has " . $inputArrayCount .
" params, does not match query: '" . htmlspecialchars($sql) . "'",
'Execute'
);
return false;
}
foreach ($bulkBindArray as $inputarr)
{
/*
* Must pass references into call_user_func_array
*/
$paramsByReference = array();
foreach($inputarr as $key => $value) {
/** @noinspection PhpArrayAccessCanBeReplacedWithForeachValueInspection */
$paramsByReference[$key] = &$inputarr[$key];
}
/*
* Bind the params
*/
call_user_func_array(array($stmt, 'bind_param'), $paramsByReference);
/*
* Execute
*/
$ret = mysqli_stmt_execute($stmt);
/*
* Did we throw an error?
*/
if ($ret == false)
return false;
}
// Tells affected_rows to be compliant
$this->isSelectStatement = $stmt->affected_rows == -1;
if (!$this->isSelectStatement) {
$this->statementAffectedRows = $stmt->affected_rows;
return true;
}
// Turn the statement into a result set and return it
return $stmt->get_result();
}
else
{
@ -1144,7 +1347,7 @@ class ADODB_mysqli extends ADOConnection {
$rs = mysqli_multi_query($this->_connectionID, $sql.';');
if ($rs) {
$rs = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->_connectionID ) : @mysqli_use_result( $this->_connectionID );
return $rs ? $rs : true; // mysqli_more_results( $this->_connectionID )
return $rs ?: true; // mysqli_more_results( $this->_connectionID )
}
} else {
$rs = mysqli_query($this->_connectionID, $sql, $ADODB_COUNTRECS ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT);
@ -1262,6 +1465,12 @@ class ADORecordSet_mysqli extends ADORecordSet{
var $databaseType = "mysqli";
var $canSeek = true;
/** @var ADODB_mysqli The parent connection */
var $connection = false;
/** @var mysqli_result result link identifier */
var $_queryID;
function __construct($queryID, $mode = false)
{
if ($mode === false) {
@ -1368,8 +1577,7 @@ class ADORecordSet_mysqli extends ADORecordSet{
if ($this->fetchMode == MYSQLI_ASSOC && $upper == ADODB_ASSOC_CASE_LOWER) {
return $this->fields;
}
$row = ADORecordSet::getRowAssoc($upper);
return $row;
return ADORecordSet::getRowAssoc($upper);
}
/**
@ -1524,6 +1732,7 @@ class ADORecordSet_mysqli extends ADORecordSet{
12 = MYSQLI_TYPE_DATETIME
13 = MYSQLI_TYPE_YEAR
14 = MYSQLI_TYPE_NEWDATE
245 = MYSQLI_TYPE_JSON
247 = MYSQLI_TYPE_ENUM
248 = MYSQLI_TYPE_SET
249 = MYSQLI_TYPE_TINY_BLOB
@ -1544,7 +1753,7 @@ class ADORecordSet_mysqli extends ADORecordSet{
*
* @return string The MetaType
*/
function MetaType($t, $len = -1, $fieldobj = false)
function metaType($t, $len = -1, $fieldobj = false)
{
if (is_object($t)) {
$fieldobj = $t;
@ -1552,8 +1761,16 @@ class ADORecordSet_mysqli extends ADORecordSet{
$len = $fieldobj->max_length;
}
$t = strtoupper($t);
/*
* Add support for custom actual types. We do this
* first, that allows us to override existing types
*/
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
switch ($t) {
case 'STRING':
case 'CHAR':
case 'VARCHAR':
@ -1631,6 +1848,8 @@ class ADORecordSet_mysqli extends ADORecordSet{
case 'DEC':
case 'FIXED':
default:
//if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>";
return 'N';
}
@ -1661,8 +1880,14 @@ class ADORecordSet_array_mysqli extends ADORecordSet_array
$len = $fieldobj->max_length;
}
$t = strtoupper($t);
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
switch ($t) {
case 'STRING':
case 'CHAR':
case 'VARCHAR':

View File

@ -1,124 +0,0 @@
<?php
/**
* Portable MySQL driver
*
* @deprecated
*
* Extends the deprecated mysql driver, and was originally designed to be a
* portable driver in the same manner as oci8po and mssqlpo. Its functionality
* is exactly duplicated in the mysqlt driver, which is itself deprecated.
* This driver will be removed in ADOdb version 6.0.0.
*
* This file is part of ADOdb, a Database Abstraction Layer library for PHP.
*
* @package ADOdb
* @link https://adodb.org Project's web site and documentation
* @link https://github.com/ADOdb/ADOdb Source code and issue tracker
*
* The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
* and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
* any later version. This means you can use it in proprietary products.
* See the LICENSE.md file distributed with this source code for details.
* @license BSD-3-Clause
* @license LGPL-2.1-or-later
*
* @copyright 2000-2013 John Lim
* @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
*/
// 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 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;
}
function RowLock($tables,$where='',$col='1 as adodbignore')
{
if ($this->transCnt==0) $this->BeginTrans();
if ($where) $where = ' where '.$where;
$rs = $this->Execute("select $col from $tables $where for update");
return !empty($rs);
}
}
class ADORecordSet_mysqlt extends ADORecordSet_mysql{
var $databaseType = "mysqlt";
function __construct($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;
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:
default: $this->fetchMode = MYSQL_BOTH; break;
}
$this->adodbFetchMode = $mode;
parent::__construct($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 MoveNext()
{
return adodb_movenext($this);
}
}

View File

@ -1,141 +0,0 @@
<?php
/**
* MySQL driver in transactional mode
*
* @deprecated
*
* This driver only supports the original MySQL driver in transactional mode. It
* is deprecated in PHP version 5.5 and removed in PHP version 7. It is deprecated
* as of ADOdb version 5.20.0. Use the mysqli driver instead, which supports both
* transactional and non-transactional updates
*
* This file is part of ADOdb, a Database Abstraction Layer library for PHP.
*
* @package ADOdb
* @link https://adodb.org Project's web site and documentation
* @link https://github.com/ADOdb/ADOdb Source code and issue tracker
*
* The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
* and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
* any later version. This means you can use it in proprietary products.
* See the LICENSE.md file distributed with this source code for details.
* @license BSD-3-Clause
* @license LGPL-2.1-or-later
*
* @copyright 2000-2013 John Lim
* @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
*/
// 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
/* set transaction mode
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }
*/
function SetTransactionMode( $transaction_mode )
{
$this->_transmode = $transaction_mode;
if (empty($transaction_mode)) {
$this->Execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ');
return;
}
if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
$this->Execute("SET SESSION TRANSACTION ".$transaction_mode);
}
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;
$ok = $this->Execute('COMMIT');
$this->Execute('SET AUTOCOMMIT=1');
return $ok ? true : false;
}
function RollbackTrans()
{
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
$ok = $this->Execute('ROLLBACK');
$this->Execute('SET AUTOCOMMIT=1');
return $ok ? true : false;
}
function RowLock($tables,$where='',$col='1 as adodbignore')
{
if ($this->transCnt==0) $this->BeginTrans();
if ($where) $where = ' where '.$where;
$rs = $this->Execute("select $col from $tables $where for update");
return !empty($rs);
}
}
class ADORecordSet_mysqlt extends ADORecordSet_mysql{
var $databaseType = "mysqlt";
function __construct($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;
case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH:
default: $this->fetchMode = MYSQL_BOTH; break;
}
$this->adodbFetchMode = $mode;
parent::__construct($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 MoveNext()
{
return adodb_movenext($this);
}
}

View File

@ -791,6 +791,11 @@ END;
$nrows += $offset;
}
$sql = "select * from (".$sql.") where rownum <= :adodb_offset";
// If non-bound statement, $inputarr is false
if (!$inputarr) {
$inputarr = array();
}
$inputarr['adodb_offset'] = $nrows;
$nrows = -1;
}
@ -973,9 +978,12 @@ END;
/**
* Execute SQL
*
* @param sql SQL statement to execute, or possibly an array holding prepared statement ($sql[0] will hold sql text)
* @param [inputarr] holds the input data to bind to. Null elements will be set to null.
* @return RecordSet or false
* @param string|array $sql SQL statement to execute, or possibly an array holding
* prepared statement ($sql[0] will hold sql text).
* @param array|false $inputarr holds the input data to bind to.
* Null elements will be set to null.
*
* @return ADORecordSet|false
*/
function Execute($sql,$inputarr=false)
{
@ -1094,6 +1102,22 @@ END;
return array($sql,$stmt,0,$BINDNUM);
}
function releaseStatement(&$stmt)
{
if (is_array($stmt)
&& isset($stmt[1])
&& is_resource($stmt[1])
&& oci_free_statement($stmt[1])
) {
// Clearing the resource to avoid it being of type Unknown
$stmt[1] = null;
return true;
}
// Not a valid prepared statement
return false;
}
/*
Call an oracle stored procedure and returns a cursor variable as a recordset.
Concept by Robert Tuttle robert@ud.com
@ -1241,12 +1265,12 @@ END;
* $db->Parameter($stmt,$group,'group');
* $db->Execute($stmt);
*
* @param $stmt Statement returned by Prepare() or PrepareSP().
* @param $stmt Statement returned by {@see Prepare()} or {@see PrepareSP()}.
* @param $var PHP variable to bind to
* @param $name Name of stored procedure variable name to bind to.
* @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8.
* @param [$maxLen] Holds an maximum length of the variable.
* @param [$type] The data type of $var. Legal values depend on driver.
* @param bool $isOutput Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8.
* @param int $maxLen Holds an maximum length of the variable.
* @param mixed $type The data type of $var. Legal values depend on driver.
*
* @link http://php.net/oci_bind_by_name
*/
@ -1484,16 +1508,17 @@ SELECT /*+ RULE */ distinct b.column_name
}
/**
* returns assoc array where keys are tables, and values are foreign keys
* Returns a list of Foreign Keys associated with a specific table.
*
* @param str $table
* @param str $owner [optional][default=NULL]
* @param bool $upper [optional][discarded]
* @return mixed[] Array of foreign key information
* @param string $table
* @param string $owner
* @param bool $upper discarded
* @param bool $associative discarded
*
* @link http://gis.mit.edu/classes/11.521/sqlnotes/referential_integrity.html
* @return string[]|false An array where keys are tables, and values are foreign keys;
* false if no foreign keys could be found.
*/
function MetaForeignKeys($table, $owner=false, $upper=false)
public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false)
{
global $ADODB_FETCH_MODE;
@ -1810,7 +1835,12 @@ class ADORecordset_oci8 extends ADORecordSet {
$len = $fieldobj->max_length;
}
switch (strtoupper($t)) {
$t = strtoupper($t);
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
switch ($t) {
case 'VARCHAR':
case 'VARCHAR2':
case 'CHAR':

View File

@ -81,8 +81,7 @@ class ADODB_odbc_mssql extends ADODB_odbc {
return $this->GetOne($this->identitySQL);
}
function MetaForeignKeys($table, $owner=false, $upper=false)
public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false)
{
global $ADODB_FETCH_MODE;

View File

@ -393,7 +393,7 @@ class ADODB_odbtp extends ADOConnection{
return $arr2;
}
function MetaForeignKeys($table, $owner='', $upper=false)
public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false)
{
global $ADODB_FETCH_MODE;

View File

@ -82,7 +82,6 @@ class ADODB_pdo extends ADOConnection {
var $_errormsg = false;
var $_errorno = false;
var $dsnType = '';
var $stmt = false;
var $_driver;
@ -238,6 +237,26 @@ class ADODB_pdo extends ADOConnection {
return call_user_func_array('parent::Concat', $args);
}
/**
* Triggers a driver-specific request for a bind parameter
*
* @param string $name
* @param string $type
*
* @return string
*/
public function param($name,$type='C') {
$args = func_get_args();
if(method_exists($this->_driver, 'param')) {
// Return the driver specific entry, that mimics the native driver
return call_user_func_array(array($this->_driver, 'param'), $args);
}
// No driver specific method defined, use mysql format '?'
return call_user_func_array('parent::param', $args);
}
// returns true or false
function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
{
@ -294,18 +313,19 @@ class ADODB_pdo extends ADOConnection {
}
/**
* Returns a list of Foreign Keys for a specified table.
* Returns a list of Foreign Keys associated with a specific table.
*
* @param string $table
* @param bool $owner (optional) not used in this driver
* @param string $owner (optional) not used in this driver
* @param bool $upper
* @param bool $associative
*
* @return string[] where keys are tables, and values are foreign keys
* @return string[]|false An array where keys are tables, and values are foreign keys;
* false if no foreign keys could be found.
*/
public function metaForeignKeys($table, $owner=false, $upper=false,$associative=false) {
public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false) {
if (method_exists($this->_driver,'metaForeignKeys'))
return $this->_driver->metaForeignKeys($table,$owner,$upper,$associative);
return $this->_driver->metaForeignKeys($table, $owner, $upper, $associative);
}
/**
@ -565,6 +585,7 @@ class ADODB_pdo extends ADOConnection {
$this->_driver->debug = $this->debug;
}
if ($inputarr) {
/*
* inputarr must be numeric
*/

View File

@ -75,15 +75,15 @@ class ADODB_pdo_oci extends ADODB_pdo_base {
$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];
$fld->name = $rs->fields[0];
$fld->type = $rs->fields[1];
$fld->max_length = $rs->fields[2];
$fld->scale = $rs->fields[3];
if ($rs->fields[1] == 'NUMBER' && $rs->fields[3] == 0) {
$fld->type ='INT';
$fld->max_length = $rs->fields[4];
}
$fld->not_null = (strncmp($rs->fields[5], 'NOT',3) === 0);
$fld->max_length = $rs->fields[4];
}
$fld->not_null = (strncmp($rs->fields[5], 'NOT',3) === 0);
$fld->binary = (strpos($fld->type,'BLOB') !== false);
$fld->default_value = $rs->fields[6];
@ -98,12 +98,25 @@ class ADODB_pdo_oci extends ADODB_pdo_base {
return $retarr;
}
/**
* @param bool $auto_commit
* @return void
*/
function SetAutoCommit($auto_commit)
{
$this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT, $auto_commit);
}
/**
* @param bool $auto_commit
* @return void
*/
function SetAutoCommit($auto_commit)
{
$this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT, $auto_commit);
}
/**
* Returns a driver-specific format for a bind parameter
*
* @param string $name
* @param string $type (ignored in driver)
*
* @return string
*/
public function param($name,$type='C')
{
return sprintf(':%s', $name);
}
}

View File

@ -21,11 +21,11 @@
class ADODB_pdo_pgsql extends ADODB_pdo {
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\_%'";
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";
@ -34,15 +34,15 @@ class ADODB_pdo_pgsql extends ADODB_pdo {
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 in ('r','v') 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";
AND a.attnum > 0 AND a.atttypid = t.oid AND a.attrelid = c.oid ORDER BY a.attnum";
// used when schema defined
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 in ('r','v') 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";
FROM pg_class c, pg_attribute a, pg_type t, pg_namespace n
WHERE relkind in ('r','v') 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
@ -97,23 +97,27 @@ WHERE relkind in ('r','v') AND (c.relname='%s' or c.relname = lower('%s'))
{
$info = $this->ServerInfo();
if ($info['version'] >= 7.3) {
$this->metaTablesSQL = "select tablename,'T' from pg_tables where tablename not like 'pg\_%'
and schemaname not in ( 'pg_catalog','information_schema')
union
select viewname,'V' from pg_views where viewname not like 'pg\_%' and schemaname not in ( 'pg_catalog','information_schema') ";
$this->metaTablesSQL = "
select tablename,'T' from pg_tables
where tablename not like 'pg\_%' and schemaname not in ( 'pg_catalog','information_schema')
union
select viewname,'V' from pg_views
where viewname not like 'pg\_%' and schemaname not in ( 'pg_catalog','information_schema')";
}
if ($mask) {
$save = $this->metaTablesSQL;
$mask = $this->qstr(strtolower($mask));
if ($info['version']>=7.3)
$this->metaTablesSQL = "
select tablename,'T' from pg_tables where tablename like $mask and schemaname not in ( 'pg_catalog','information_schema')
union
select viewname,'V' from pg_views where viewname like $mask and schemaname not in ( 'pg_catalog','information_schema') ";
select tablename,'T' from pg_tables
where tablename like $mask and schemaname not in ( 'pg_catalog','information_schema')
union
select viewname,'V' from pg_views
where viewname like $mask and schemaname not in ( 'pg_catalog','information_schema')";
else
$this->metaTablesSQL = "
select tablename,'T' from pg_tables where tablename like $mask
union
union
select viewname,'V' from pg_views where viewname like $mask";
}
$ret = ADOConnection::MetaTables($ttype,$showSchema);
@ -297,4 +301,23 @@ select viewname,'V' from pg_views where viewname like $mask";
if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
$this->_connectionID->query("SET TRANSACTION ".$transaction_mode);
}
/**
* Returns a driver-specific format for a bind parameter
*
* Unlike the native driver, we use :name parameters
* instead of offsets
*
* @param string $name
* @param string $type (ignored in driver)
*
* @return string
*/
public function param($name,$type='C') {
if (!$name) {
return '';
}
return sprintf(':%s', $name);
}
}

View File

@ -34,7 +34,7 @@ class ADODB_pdo_sqlite extends ADODB_pdo {
var $_genSeq2SQL = 'INSERT INTO %s VALUES(%s)';
var $_dropSeqSQL = 'DROP TABLE %s';
var $concat_operator = '||';
var $pdoDriver = false;
var $pdoDriver = false;
var $random='abs(random())';
function _init($parentDriver)
@ -156,40 +156,48 @@ class ADODB_pdo_sqlite extends ADODB_pdo {
// mark newnham
function MetaColumns($tab,$normalize=true)
{
global $ADODB_FETCH_MODE;
global $ADODB_FETCH_MODE;
$parent = $this->pdoDriver;
$false = false;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
if ($parent->fetchMode !== false) $savem = $parent->SetFetchMode(false);
$rs = $parent->Execute("PRAGMA table_info('$tab')");
if (isset($savem)) $parent->SetFetchMode($savem);
if (!$rs) {
$ADODB_FETCH_MODE = $save;
return $false;
}
$arr = array();
while ($r = $rs->FetchRow()) {
$type = explode('(',$r['type']);
$size = '';
if (sizeof($type)==2)
$size = trim($type[1],')');
$fn = strtoupper($r['name']);
$fld = new ADOFieldObject;
$fld->name = $r['name'];
$fld->type = $type[0];
$fld->max_length = $size;
$fld->not_null = $r['notnull'];
$fld->primary_key = $r['pk'];
$fld->default_value = $r['dflt_value'];
$fld->scale = 0;
if ($save == ADODB_FETCH_NUM) $arr[] = $fld;
else $arr[strtoupper($fld->name)] = $fld;
}
$rs->Close();
$ADODB_FETCH_MODE = $save;
return $arr;
$parent = $this->pdoDriver;
$false = false;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
if ($parent->fetchMode !== false) {
$savem = $parent->SetFetchMode(false);
}
$rs = $parent->Execute("PRAGMA table_info('$tab')");
if (isset($savem)) {
$parent->SetFetchMode($savem);
}
if (!$rs) {
$ADODB_FETCH_MODE = $save;
return $false;
}
$arr = array();
while ($r = $rs->FetchRow()) {
$type = explode('(', $r['type']);
$size = '';
if (sizeof($type) == 2) {
$size = trim($type[1], ')');
}
$fn = strtoupper($r['name']);
$fld = new ADOFieldObject;
$fld->name = $r['name'];
$fld->type = $type[0];
$fld->max_length = $size;
$fld->not_null = $r['notnull'];
$fld->primary_key = $r['pk'];
$fld->default_value = $r['dflt_value'];
$fld->scale = 0;
if ($save == ADODB_FETCH_NUM) {
$arr[] = $fld;
} else {
$arr[strtoupper($fld->name)] = $fld;
}
}
$rs->Close();
$ADODB_FETCH_MODE = $save;
return $arr;
}
function MetaTables($ttype=false,$showSchema=false,$mask=false)
@ -208,5 +216,18 @@ class ADODB_pdo_sqlite extends ADODB_pdo {
$this->metaTablesSQL = $save;
}
return $ret;
}
}
/**
* Returns a driver-specific format for a bind parameter
*
* @param string $name
* @param string $type (ignored in driver)
*
* @return string
*/
public function param($name,$type='C')
{
return sprintf(':%s', $name);
}
}

View File

@ -26,6 +26,7 @@ class ADODB_postgres64 extends ADOConnection{
var $databaseType = 'postgres64';
var $dataProvider = 'postgres';
var $hasInsertID = true;
/** @var PgSql\Connection|resource|false */
var $_resultid = false;
var $concat_operator='||';
var $metaDatabasesSQL = "select datname from pg_database where datname not in ('template0','template1') order by 1";
@ -154,7 +155,7 @@ class ADODB_postgres64 extends ADOConnection{
*/
protected function _insertID($table = '', $column = '')
{
if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;
if ($this->_resultid === false) return false;
$oid = pg_last_oid($this->_resultid);
// to really return the id, we need the table and column-name, else we can only return the oid != id
return empty($table) || empty($column) ? $oid : $this->GetOne("SELECT $column FROM $table WHERE oid=".(int)$oid);
@ -162,13 +163,13 @@ class ADODB_postgres64 extends ADOConnection{
function _affectedrows()
{
if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;
if ($this->_resultid === false) return false;
return pg_affected_rows($this->_resultid);
}
/**
* @return true/false
* @return bool
*/
function BeginTrans()
{
@ -378,7 +379,7 @@ class ADODB_postgres64 extends ADOConnection{
function BlobDelete( $blob )
{
pg_query($this->_connectionID, 'begin');
$result = @pg_lo_unlink($blob);
$result = @pg_lo_unlink($this->_connectionID, $blob);
pg_query($this->_connectionID, 'commit');
return( $result );
}
@ -808,8 +809,7 @@ class ADODB_postgres64 extends ADOConnection{
if ($execp) $exsql = "EXECUTE $plan ($execp)";
else $exsql = "EXECUTE $plan";
$rez = @pg_execute($this->_connectionID,$exsql);
$rez = @pg_query($this->_connectionID, $exsql);
if (!$rez) {
# Perhaps plan does not exist? Prepare/compile plan.
$params = '';
@ -833,18 +833,18 @@ class ADODB_postgres64 extends ADOConnection{
}
$s = "PREPARE $plan ($params) AS ".substr($sql,0,strlen($sql)-2);
//adodb_pr($s);
$rez = pg_execute($this->_connectionID,$s);
$rez = pg_query($this->_connectionID, $s);
//echo $this->ErrorMsg();
}
if ($rez)
$rez = pg_execute($this->_connectionID,$exsql);
$rez = pg_query($this->_connectionID, $exsql);
} else {
//adodb_backtrace();
$rez = pg_query($this->_connectionID,$sql);
$rez = pg_query($this->_connectionID, $sql);
}
// check if no data returned, then no need to create real recordset
if ($rez && pg_num_fields($rez) <= 0) {
if (is_resource($this->_resultid) && get_resource_type($this->_resultid) === 'pgsql result') {
if ($this->_resultid !== false) {
pg_free_result($this->_resultid);
}
$this->_resultid = $rez;
@ -1020,8 +1020,20 @@ class ADORecordSet_postgres64 extends ADORecordSet{
return pg_unescape_bytea($blob);
}
function _fixblobs()
/**
* Fetches and prepares the RecordSet's fields.
*
* Fixes the blobs if there are any.
*/
protected function _prepFields()
{
$this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
// Check prerequisites and bail early if we do not have what we need.
if (!isset($this->_blobArr) || $this->fields === false) {
return;
}
if ($this->fetchMode == PGSQL_NUM || $this->fetchMode == PGSQL_BOTH) {
foreach($this->_blobArr as $k => $v) {
$this->fields[$k] = ADORecordSet_postgres64::_decode($this->fields[$k]);
@ -1040,9 +1052,8 @@ class ADORecordSet_postgres64 extends ADORecordSet{
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();
$this->_prepfields();
if ($this->fields !== false) {
return true;
}
}
@ -1054,22 +1065,17 @@ class ADORecordSet_postgres64 extends ADORecordSet{
function _fetch()
{
if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0)
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));
$this->_prepfields();
return $this->fields !== false;
}
function _close()
{
if (!is_resource($this->_queryID)
|| get_resource_type($this->_queryID) != 'pgsql result'
) {
if ($this->_queryID === false) {
return true;
}
return pg_free_result($this->_queryID);
@ -1082,7 +1088,13 @@ class ADORecordSet_postgres64 extends ADORecordSet{
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
switch (strtoupper($t)) {
$t = strtoupper($t);
if (array_key_exists($t,$this->connection->customActualTypes))
return $this->connection->customActualTypes[$t];
switch ($t) {
case 'MONEY': // stupid, postgres expects money to be a string
case 'INTERVAL':
case 'CHAR':
@ -1094,6 +1106,7 @@ class ADORecordSet_postgres64 extends ADORecordSet{
case 'CIDR':
case 'INET':
case 'MACADDR':
case 'UUID':
if ($len <= $this->blobSize) return 'C';
case 'TEXT':
@ -1134,6 +1147,12 @@ class ADORecordSet_postgres64 extends ADORecordSet{
case 'SERIAL':
return 'R';
case 'NUMERIC':
case 'DECIMAL':
case 'FLOAT4':
case 'FLOAT8':
return 'N';
default:
return ADODB_DEFAULT_METATYPE;
}

View File

@ -154,10 +154,7 @@ class ADODB_postgres7 extends ADODB_postgres64 {
}
}
/**
* @returns assoc array where keys are tables, and values are foreign keys
*/
function MetaForeignKeys($table, $owner=false, $upper=false)
public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false)
{
# Regex isolates the 2 terms between parenthesis using subexpressions
$regex = '^.*\((.*)\).*\((.*)\).*$';
@ -193,50 +190,18 @@ class ADODB_postgres7 extends ADODB_postgres64 {
$a = array();
while (!$rs->EOF) {
$lookup_table = $rs->fields('lookup_table');
$fields = $rs->fields('dep_field') . '=' . $rs->fields('lookup_field');
if ($upper) {
$a[strtoupper($rs->Fields('lookup_table'))][] = strtoupper(str_replace('"','',$rs->Fields('dep_field').'='.$rs->Fields('lookup_field')));
} else {
$a[$rs->Fields('lookup_table')][] = str_replace('"','',$rs->Fields('dep_field').'='.$rs->Fields('lookup_field'));
$lookup_table = strtoupper($lookup_table);
$fields = strtoupper($fields);
}
$a[$lookup_table][] = str_replace('"','', $fields);
$rs->MoveNext();
}
return $a;
}
// from Edward Jaramilla, improved version - works on pg 7.4
function _old_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) return false;
$arr = $rs->GetArray();
$a = array();
foreach($arr as $v) {
$data = explode(chr(0), $v['args']);
$size = count($data)-1; //-1 because the last node is empty
for($i = 4; $i < $size; $i++) {
if ($upper)
$a[strtoupper($data[2])][] = strtoupper($data[$i].'='.$data[++$i]);
else
$a[$data[2]][] = $data[$i].'='.$data[++$i];
}
}
return $a;
}
function _query($sql,$inputarr=false)
@ -266,7 +231,7 @@ class ADODB_postgres7 extends ADODB_postgres64 {
}
// check if no data returned, then no need to create real recordset
if ($rez && pg_num_fields($rez) <= 0) {
if (is_resource($this->_resultid) && get_resource_type($this->_resultid) === 'pgsql result') {
if ($this->_resultid !== false) {
pg_free_result($this->_resultid);
}
$this->_resultid = $rez;
@ -334,10 +299,8 @@ class ADORecordSet_postgres7 extends ADORecordSet_postgres64{
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();
$this->_prepfields();
if ($this->fields !== false) {
return true;
}
}
@ -360,14 +323,13 @@ class ADORecordSet_assoc_postgres7 extends ADORecordSet_postgres64{
return false;
}
$this->fields = @pg_fetch_array($this->_queryID,$this->_currentRow,$this->fetchMode);
if ($this->fields) {
if (isset($this->_blobArr)) $this->_fixblobs();
$this->_prepfields();
if ($this->fields !== false) {
$this->_updatefields();
return true;
}
return (is_array($this->fields));
return false;
}
function MoveNext()
@ -375,19 +337,13 @@ class ADORecordSet_assoc_postgres7 extends ADORecordSet_postgres64{
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) {
if (isset($this->_blobArr)) $this->_fixblobs();
$this->_updatefields();
}
$this->_prepfields();
if ($this->fields !== false) {
$this->_updatefields();
return true;
}
}
$this->fields = false;
$this->EOF = true;
}

View File

@ -24,6 +24,9 @@
// security - hide paths
if (!defined('ADODB_DIR')) die();
/**
* Class ADODB_sqlite3
*/
class ADODB_sqlite3 extends ADOConnection {
var $databaseType = "sqlite3";
var $dataProvider = "sqlite";
@ -34,10 +37,13 @@ class ADODB_sqlite3 extends ADOConnection {
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 $sysDate = "DATE('now','localtime')";
var $sysTimeStamp = "DATETIME('now','localtime')";
var $fmtTimeStamp = "'Y-m-d H:i:s'";
/** @var SQLite3 */
var $_connectionID;
function ServerInfo()
{
$version = SQLite3::version();
@ -51,7 +57,7 @@ class ADODB_sqlite3 extends ADOConnection {
if ($this->transOff) {
return true;
}
$ret = $this->Execute("BEGIN TRANSACTION");
$this->Execute("BEGIN TRANSACTION");
$this->transCnt += 1;
return true;
}
@ -95,6 +101,9 @@ class ADODB_sqlite3 extends ADOConnection {
$t = strtoupper($t);
if (array_key_exists($t,$this->customActualTypes))
return $this->customActualTypes[$t];
/*
* We are using the Sqlite affinity method here
* @link https://www.sqlite.org/datatype3.html
@ -197,7 +206,7 @@ class ADODB_sqlite3 extends ADOConnection {
return $arr;
}
function metaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
public function metaForeignKeys($table, $owner = '', $upper = false, $associative = false)
{
global $ADODB_FETCH_MODE;
if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC
@ -214,7 +223,7 @@ class ADODB_sqlite3 extends ADOConnection {
)
WHERE type != 'meta'
AND sql NOTNULL
AND LOWER(name) ='" . strtolower($table) . "'";
AND LOWER(name) ='" . strtolower($table) . "'";
$tableSql = $this->getOne($sql);
@ -304,8 +313,7 @@ class ADODB_sqlite3 extends ADOConnection {
$this->_connectionID->createFunction('adodb_date2', 'adodb_date2', 2);
}
// returns true or false
/** @noinspection PhpUnusedParameterInspection */
function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (empty($argHostname) && $argDatabasename) {
@ -317,7 +325,6 @@ class ADODB_sqlite3 extends ADOConnection {
return true;
}
// returns true or false
function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
// There's no permanent connect in SQLite3
@ -394,7 +401,7 @@ class ADODB_sqlite3 extends ADOConnection {
return false;
}
function CreateSequence($seqname='adodbseq',$start=1)
function createSequence($seqname='adodbseq', $startID=1)
{
if (empty($this->_genSeqSQL)) {
return false;
@ -403,8 +410,8 @@ class ADODB_sqlite3 extends ADOConnection {
if (!$ok) {
return false;
}
$start -= 1;
return $this->Execute("insert into $seqname values($start)");
$startID -= 1;
return $this->Execute("insert into $seqname values($startID)");
}
var $_dropSeqSQL = 'drop table %s';
@ -559,14 +566,13 @@ class ADODB_sqlite3 extends ADOConnection {
*
* This uses the more efficient strftime native function to process
*
* @param str $fld The name of the field to process
* @param string $fld The name of the field to process
*
* @return str The SQL Statement
* @return string The SQL Statement
*/
function month($fld)
{
$x = "strftime('%m',$fld)";
return $x;
return "strftime('%m',$fld)";
}
/**
@ -574,13 +580,12 @@ class ADODB_sqlite3 extends ADOConnection {
*
* This uses the more efficient strftime native function to process
*
* @param str $fld The name of the field to process
* @param string $fld The name of the field to process
*
* @return str The SQL Statement
* @return string The SQL Statement
*/
function day($fld) {
$x = "strftime('%d',$fld)";
return $x;
return "strftime('%d',$fld)";
}
/**
@ -588,14 +593,116 @@ class ADODB_sqlite3 extends ADOConnection {
*
* This uses the more efficient strftime native function to process
*
* @param str $fld The name of the field to process
* @param string $fld The name of the field to process
*
* @return str The SQL Statement
* @return string The SQL Statement
*/
function year($fld)
{
$x = "strftime('%Y',$fld)";
return $x;
return "strftime('%Y',$fld)";
}
/**
* SQLite update for blob
*
* SQLite must be a fully prepared statement (all variables must be bound),
* so $where can either be an array (array params) or a string that we will
* do our best to unpack and turn into a prepared statement.
*
* @param string $table
* @param string $column
* @param string $val Blob value to set
* @param mixed $where An array of parameters (key => value pairs),
* or a string (where clause).
* @param string $blobtype ignored
*
* @return bool success
*/
function updateBlob($table, $column, $val, $where, $blobtype = 'BLOB')
{
if (is_array($where)) {
// We were passed a set of key=>value pairs
$params = $where;
} else {
// Given a where clause string, we have to disassemble the
// statements into keys and values
$params = array();
$temp = preg_split('/(where|and)/i', $where);
$where = array_filter($temp);
foreach ($where as $wValue) {
$wTemp = preg_split('/[= \']+/', $wValue);
$wTemp = array_filter($wTemp);
$wTemp = array_values($wTemp);
$params[$wTemp[0]] = $wTemp[1];
}
}
$paramWhere = array();
foreach ($params as $bindKey => $bindValue) {
$paramWhere[] = $bindKey . '=?';
}
$sql = "UPDATE $table SET $column=? WHERE "
. implode(' AND ', $paramWhere);
// Prepare the statement
$stmt = $this->_connectionID->prepare($sql);
// Set the first bind value equal to value we want to update
if (!$stmt->bindValue(1, $val, SQLITE3_BLOB)) {
return false;
}
// Build as many keys as available
$bindIndex = 2;
foreach ($params as $bindValue) {
if (is_integer($bindValue) || is_bool($bindValue) || is_float($bindValue)) {
$type = SQLITE3_NUM;
} elseif (is_object($bindValue)) {
// Assume a blob, this should never appear in
// the binding for a where statement anyway
$type = SQLITE3_BLOB;
} else {
$type = SQLITE3_TEXT;
}
if (!$stmt->bindValue($bindIndex, $bindValue, $type)) {
return false;
}
$bindIndex++;
}
// Now execute the update. NB this is SQLite execute, not ADOdb
$ok = $stmt->execute();
return is_object($ok);
}
/**
* SQLite update for blob from a file
*
* @param string $table
* @param string $column
* @param string $path Filename containing blob data
* @param mixed $where {@see updateBlob()}
* @param string $blobtype ignored
*
* @return bool success
*/
function updateBlobFile($table, $column, $path, $where, $blobtype = 'BLOB')
{
if (!file_exists($path)) {
return false;
}
// Read file information
$fileContents = file_get_contents($path);
if ($fileContents === false)
// Distinguish between an empty file and failure
return false;
return $this->updateBlob($table, $column, $fileContents, $where, $blobtype);
}
}
@ -609,9 +716,12 @@ class ADORecordset_sqlite3 extends ADORecordSet {
var $databaseType = "sqlite3";
var $bind = false;
/** @var SQLite3Result */
var $_queryID;
/** @noinspection PhpMissingParentConstructorInspection */
function __construct($queryID,$mode=false)
{
if ($mode === false) {
global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE;

View File

@ -125,7 +125,7 @@ class perf_mysql extends adodb_perf{
/**
* Returns a list of table statuses.
*
*
* @param string $orderby Unused (compatibility with parent method)
* @return string A formatted set of recordsets
*/
@ -299,7 +299,7 @@ class perf_mysql extends adodb_perf{
var $optimizeTableHigh = 'OPTIMIZE TABLE %s';
/**
* @see adodb_perf#optimizeTable
* @see adodb_perf::optimizeTable()
*/
function optimizeTable( $table, $mode = ADODB_OPT_LOW)
{

View File

@ -102,7 +102,7 @@ class perf_postgres extends adodb_perf{
var $optimizeTableHigh = 'VACUUM ANALYZE %s';
/**
* @see adodb_perf#optimizeTable
* @see adodb_perf::optimizeTable()
*/
function optimizeTable($table, $mode = ADODB_OPT_LOW)
@ -131,7 +131,7 @@ class perf_postgres extends adodb_perf{
if ($partial) {
$sqlq = $this->conn->qstr($sql.'%');
$arr = $this->conn->GetArray("select distinct distinct sql1 from adodb_logsql where sql1 like $sqlq");
$arr = $this->conn->getArray("select distinct sql1 from adodb_logsql where sql1 like $sqlq");
if ($arr) {
foreach($arr as $row) {
$sql = reset($row);

View File

@ -0,0 +1,40 @@
<?php
// security - hide paths
if (!defined('ADODB_DIR')) die();
class perf_sqlite3 extends adodb_perf{
var $tablesSQL = "SELECT * FROM sqlite_master WHERE type='table'";
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();
function __construct(&$conn)
{
$this->conn = $conn;
}
function tables($orderby='1')
{
if (!$this->tablesSQL){
return false;
}
$rs = $this->conn->execute($this->tablesSQL);
if (!$rs) {
return false;
}
$html = rs2html($rs, false, false, false, false);
return $html;
}
}

24
lib/adodb/phpdoc.dist.xml Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<phpdocumentor
configVersion="3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://www.phpdoc.org"
xsi:noNamespaceSchemaLocation="https://docs.phpdoc.org/latest/phpdoc.xsd"
>
<paths>
<output>docs/api</output>
<cache>docs/cache</cache>
</paths>
<version number="latest">
<api>
<source dsn=".">
</source>
<ignore>
<path>scripts</path>
<path>tests</path>
<path>vendor/**/*</path>
<path>xsl</path>
</ignore>
</api>
</version>
</phpdocumentor>

View File

@ -1,4 +1,4 @@
Description of ADOdb v5.21.4 library import into Moodle 4.0 and up
Description of ADOdb library import into Moodle
Source: https://github.com/ADOdb/ADOdb
@ -16,13 +16,10 @@ Removed:
* pear/
* replicate/ (if present)
* scripts/ (if present)
* server.php
* server.php (if present)
* session/
* tests/ (if present)
Added:
* index.html - prevent directory browsing on misconfigured servers
* readme_moodle.txt - this file ;-)
Our changes (to be checked on next update if they are already applied upstream):
* https://github.com/ADOdb/ADOdb/issues/791

View File

@ -4,7 +4,7 @@
<location>adodb</location>
<name>AdoDB</name>
<license>BSD/LGPL</license>
<version>5.21.4</version>
<version>5.22.2</version>
<licenseversion>3-Clause/2.1+</licenseversion>
</library>
<library>