summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig22
-rw-r--r--README.md5
-rw-r--r--adodb-csvlib.inc.php26
-rw-r--r--adodb-datadict.inc.php36
-rw-r--r--adodb-memcache.lib.inc.php513
-rw-r--r--adodb-xmlschema.inc.php39
-rw-r--r--adodb-xmlschema03.inc.php40
-rw-r--r--adodb.inc.php642
-rw-r--r--datadict/datadict-access.inc.php20
-rw-r--r--datadict/datadict-db2.inc.php9
-rw-r--r--datadict/datadict-firebird.inc.php236
-rw-r--r--datadict/datadict-generic.inc.php11
-rw-r--r--datadict/datadict-ibase.inc.php9
-rw-r--r--datadict/datadict-informix.inc.php9
-rw-r--r--datadict/datadict-mssql.inc.php17
-rw-r--r--datadict/datadict-mssqlnative.inc.php18
-rw-r--r--datadict/datadict-mysql.inc.php31
-rw-r--r--datadict/datadict-oci8.inc.php17
-rw-r--r--datadict/datadict-postgres.inc.php22
-rw-r--r--datadict/datadict-sapdb.inc.php15
-rw-r--r--datadict/datadict-sqlite.inc.php10
-rw-r--r--datadict/datadict-sybase.inc.php18
-rw-r--r--docs/changelog.md34
-rw-r--r--drivers/adodb-ado.inc.php3
-rw-r--r--drivers/adodb-ado5.inc.php8
-rw-r--r--drivers/adodb-fbsql.inc.php9
-rw-r--r--drivers/adodb-firebird.inc.php1147
-rw-r--r--drivers/adodb-ibase.inc.php9
-rw-r--r--drivers/adodb-mssqlnative.inc.php31
-rw-r--r--drivers/adodb-mysql.inc.php8
-rw-r--r--drivers/adodb-mysqli.inc.php187
-rw-r--r--drivers/adodb-oci8.inc.php7
-rw-r--r--drivers/adodb-pdo.inc.php21
-rw-r--r--drivers/adodb-pdo_oci.inc.php41
-rw-r--r--drivers/adodb-pdo_pgsql.inc.php61
-rw-r--r--drivers/adodb-pdo_sqlite.inc.php91
-rw-r--r--drivers/adodb-postgres64.inc.php9
-rw-r--r--drivers/adodb-sqlite3.inc.php158
-rw-r--r--perf/perf-postgres.inc.php2
-rw-r--r--perf/perf-sqlite3.inc.php40
-rw-r--r--server.php103
-rw-r--r--session/session_schema2.xml30
-rw-r--r--tests/client.php208
-rw-r--r--tests/testdatabases.inc.php13
44 files changed, 2613 insertions, 1372 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..5dad2ea1
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,22 @@
+# EditorConfig file for ADOdb
+# https://editorconfig.org/
+
+root = true
+
+# Default file settings
+[*]
+indent_style = tab
+indent_size = 4
+end_of_line = lf
+trim_trailing_whitespace = true
+insert_final_newline = true
+charset = utf-8
+
+# Python build scripts
+[*.py]
+indent_style = space
+
+# Markdown files
+[*.md]
+indent_style = space
+trim_trailing_whitespace = false
diff --git a/README.md b/README.md
index e432b2fb..96ac67b2 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/adodb-csvlib.inc.php b/adodb-csvlib.inc.php
index c81254bf..6977c3dc 100644
--- a/adodb-csvlib.inc.php
+++ b/adodb-csvlib.inc.php
@@ -83,19 +83,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;
diff --git a/adodb-datadict.inc.php b/adodb-datadict.inc.php
index dbed95da..c73d5f2a 100644
--- a/adodb-datadict.inc.php
+++ b/adodb-datadict.inc.php
@@ -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;
}
@@ -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;
diff --git a/adodb-memcache.lib.inc.php b/adodb-memcache.lib.inc.php
index 7f110e74..16a0ba57 100644
--- a/adodb-memcache.lib.inc.php
+++ b/adodb-memcache.lib.inc.php
@@ -26,183 +26,416 @@ 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
+{
+ /*
+ * 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;
+ /*
+ * populated with the proper library on connect
+ * and is used later when there are differences in specific calls
+ * between memcache and memcached
+ */
+ private $memCacheLibrary = false;
+
+ /*
+ * array of hosts
+ */
+ private $hosts;
+
+ /*
+ * Connection Port, uses default
+ */
+ private $port = 11211;
+
+ /*
+ * memcache compression with zlib
+ */
+ private $compress = false;
- //-----------------------------
- // memcache specific variables
+ /*
+ * Array of options for memcached only
+ */
+ private $options = false;
+
+ /*
+ * Internal flag indicating successful connection
+ */
+ private $isConnected = false;
+
+ /*
+ * Handle for the Memcache library
+ */
+ private $memcacheLibrary = false;
+
+ /*
+ * New server feature controller lists available servers
+ */
+ private $serverControllers = array();
+
+ /*
+ * New server feature controller uses granular
+ * server controller
+ */
+ private $serverControllerTemplate = array(
+ 'host'=>'',
+ 'port'=>11211,
+ 'weight'=>0,
+ 'key'=>''
+ );
- var $hosts; // array of hosts
- var $port = 11211;
- var $compress = false; // memcache compression with zlib
-
- var $_connected = false;
- var $_memcache = false;
+
+ /*
+ * An integer index into the libraries
+ */
+ const MCLIB = 1;
+ const MCLIBD = 2;
+
+ /*
+ * Xrefs the library flag to the actual class name
+ */
+ private $libraries = array(
+ 1=>'Memcache',
+ 2=>'Memcached'
+ );
+
+ /*
+ * An indicator of which library we are using
+ */
+ private $libraryFlag;
+
+ /**
+ * constructor passes in a ADONewConnection Object
+ *
+ * @param $db ADONewConnection object
+ *
+ * @return obj
+ */
+ public function __construct(&$db)
+ {
+ $this->hosts = $db->memCacheHost;
+ $this->port = $db->memCachePort;
+ $this->compress = $db->memCacheCompress;
+ $this->options = $db->memCacheOptions;
+
+ }
- function __construct(&$obj)
+ /**
+ * implement as 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::MCLIB;
+ else
{
- $this->hosts = $obj->memCacheHost;
- $this->port = $obj->memCachePort;
- $this->compress = $obj->memCacheCompress;
+ $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)
+
+ $usedLibrary = $this->libraries[$this->libraryFlag];
+
+ $this->memCacheLibrary = new $usedLibrary;
+ if (!$this->memcacheLibrary)
+ {
+ $err = 'Memcache library failed to initialize';
+ return false;
+ }
+
+ /*
+ * Convert simple compression flag for memcached
+ */
+ if ($this->libraryFlag == self::MCLIBD && $this->compress)
+ {
+ /*
+ * Value of Memcached::OPT_COMPRESSION = 2;
+ */
+ $this->options[2] == 1;
+ }
+ /*
+ * Are there any options available for memcached
+ */
+ if ($this->libraryFlag == self::MCLIBD && count($this->options) > 0)
{
- // 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!';
+ $optionSuccess = $this->memCacheLibrary->setOptions($this->options);
+ if (!$optionSuccess)
+ {
+ $err = 'Invalid option parameters passed to Memecached';
return false;
}
-
- 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;
- }
+ }
+
+ /*
+ * Have we passed a controller array
+ */
+ if (!is_array($this->hosts))
+ $this->hosts = array($this->hosts);
+
+ if (array_values($this->hosts) == $this->hosts)
+ {
+ /*
+ * Old way, convert to controller
+ */
+ foreach ($this->hosts as $ipAddress)
+ {
+ $connector = $this->serverControllerTemplate;
+
+ $connector['host'] = $ipAddress;
+ $connector['port'] = $this->port;
+
+ $this->serverControllers[] = $connector;
}
- if ($failcnt == sizeof($this->hosts)) {
- $err = 'Can\'t connect to any memcache server';
- return false;
+ }
+ else
+ {
+ /*
+ * New way, must validate port, etc
+ */
+ foreach ($this->hosts as $controller)
+ {
+ $connector = array_merge($this->serverControllerTemplate,$controller);
+ if ($this->libraryFlag == self::MCLIB)
+ {
+ /*
+ * Cannot use a key or weight in memcache, simply discard
+ */
+ $connector['key'] = '';
+ $connector['weight'] = 0;
+
+ }
+ else
+ $connector['weight'] = $connector['weight'] ? (int)$connector['weight']:0;
+
+ $this->serverControllers[] = $connector;
}
- $this->_connected = true;
- $this->_memcache = $memcache;
- return true;
}
- // returns true or false. true if successful save
- function writecache($filename, $contents, $debug, $secs2cache)
+ /*
+ * Checks for existing connections ( but only for memcached )
+ */
+ if ($this->libraryFlag == self::MCLIBD)
{
- if (!$this->_connected) {
- $err = '';
- if (!$this->connect($err) && $debug) ADOConnection::outp($err);
+ $existingServers = $memCache->getServerList();
+ if (is_array($existingServers))
+ {
+ /*
+ * Use the existing configuration
+ */
+ $this->isConnected = true;
+ $this->memcacheLibrary = $memcache;
+ return true;
}
- if (!$this->_memcache) return false;
-
- $failed=false;
- switch ($this->library) {
- case 'Memcache':
- if (!$this->_memcache->set($filename, $contents, $this->compress ? MEMCACHE_COMPRESSED : 0, $secs2cache)) {
- $failed=true;
- }
- break;
- case 'Memcached':
- if (!$this->_memcache->set($filename, $contents, $secs2cache)) {
- $failed=true;
- }
- break;
+ }
+ $failcnt = 0;
+ foreach($this->serverControllers as $controller)
+ {
+ switch($this->libraryFlag)
+ {
+ case self::MCLIB:
+ if (!@$this->memcacheLibrary->addServer($controller['host'],$controller['port']))
+ $failcnt++;
+ break;
default:
- $failed=true;
- break;
- }
-
- if($failed) {
- if ($debug) ADOConnection::outp(" Failed to save data at the memcache server!<br>\n");
- return false;
+ if (!@$this->memcacheLibrary->addServer($controller['host'],$controller['port'],$controller['weight']))
+ $failcnt++;
}
-
- return true;
+
}
-
- // returns a recordset
- function readcache($filename, &$err, $secs2cache, $rsClass)
+ if ($failcnt == sizeof($this->serverControllers))
{
- $false = false;
- if (!$this->_connected) $this->connect($err);
- if (!$this->_memcache) return $false;
+ $err = 'Can\'t connect to any memcache server';
+ return false;
- $rs = $this->_memcache->get($filename);
- if (!$rs) {
- $err = 'Item with such key doesn\'t exist on the memcache server.';
- return $false;
- }
+ }
+
+ /*
+ * A valid memcache connection is available
+ */
+ $this->isConnected = true;
+ return true;
+ }
- // 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
+ /**
+ * 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;
- $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;
+ $failed=false;
+ switch ($this->libraryFlag)
+ {
+ case self::MCLIB:
+ if (!$this->memcacheLibrary->set($filename, $contents, $this->compress ? MEMCACHE_COMPRESSED : 0, $secs2cache)) {
+ $failed=true;
}
- }
- return $rs;
+ break;
+ case self::MCLIBD:
+ if (!$this->memcacheLibrary->set($filename, $contents, $secs2cache)) {
+ $failed=true;
+ }
+ break;
+ default:
+ $failed=true;
+ break;
}
- function flushall($debug=false)
- {
- if (!$this->_connected) {
- $err = '';
- if (!$this->connect($err) && $debug) ADOConnection::outp($err);
- }
- if (!$this->_memcache) return false;
+ if($failed) {
+ if ($debug) ADOConnection::outp(" Failed to save data at the memcache server!<br>\n");
+ return false;
+ }
- $del = $this->_memcache->flush();
+ return true;
+ }
+
+ /**
+ * Reads a cached query to the server
+ *
+ * @param string $filename The MD5 of the query to read
+ * @param string $err The query results
+ * @param int $secs2cache
+ * @param obj $rsClass **UNUSED**
+
+ * @return the record or false.
+ */
+ public function readCache($filename, &$err, $secs2cache, $rsClass)
+ {
+ if (!$this->isConnected) $this->connect($err);
+ if (!$this->memcacheLibrary)
+ return false;
- if ($debug)
- if (!$del) ADOConnection::outp("flushall: failed!<br>\n");
- else ADOConnection::outp("flushall: succeeded!<br>\n");
+ $rs = $this->memcacheLibrary->get($filename);
+ if (!$rs)
+ {
+ $err = 'Item with such key doesn\'t exist on the memcache server.';
+ return false;
+ }
- return $del;
+ // 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
- function flushcache($filename, $debug=false)
+ $tdiff = intval($rs->timeCreated+$secs2cache - time());
+ if ($tdiff <= 2)
{
- if (!$this->_connected) {
- $err = '';
- if (!$this->connect($err) && $debug) ADOConnection::outp($err);
+ 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;
}
- if (!$this->_memcache) return false;
+ }
+ return $rs;
+ }
- $del = $this->_memcache->delete($filename);
+ /**
+ * Flushes all of the stored memcache data
+ *
+ * @param bool $debug
+ *
+ * @return int 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;
- 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");
+ $del = $this->memcacheLibrary->flush();
- return $del;
- }
+ if ($debug)
+ if (!$del)
+ ADOConnection::outp("flushall: failed!<br>\n");
+ else
+ ADOConnection::outp("flushall: succeeded!<br>\n");
+
+ return $del;
+ }
- // not used for memcache
- function createdir($dir, $hash)
+ /**
+ * Flushes the contents of a specified query
+ *
+ * @param str $filname The MD5 of the query to flush
+ * @param bool $debug
+ *
+ * @return int The response from the memcache server
+ */
+ public function flushCache($filename, $debug=false)
+ {
+ if (!$this->isConnected)
{
- return true;
+ $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: $key entry doesn't exist on memcache server!<br>\n");
+ else ADOConnection::outp("flushcache: $key entry flushed from memcache server!<br>\n");
+
+ return $del;
}
+
+}
diff --git a/adodb-xmlschema.inc.php b/adodb-xmlschema.inc.php
index 58e3affd..7c4901df 100644
--- a/adodb-xmlschema.inc.php
+++ b/adodb-xmlschema.inc.php
@@ -26,20 +26,6 @@
* @author Dan Cech
*/
-function _file_get_contents($file)
-{
- if (function_exists('file_get_contents')) return file_get_contents($file);
-
- $f = fopen($file,'r');
- if (!$f) return '';
- $t = '';
-
- while ($s = fread($f,100000)) $t .= $s;
- fclose($f);
- return $t;
-}
-
-
/**
* Debug on or off
*/
@@ -126,7 +112,7 @@ class dbObject {
/**
* NOP
*/
- function __construct( &$parent, $attributes = NULL ) {
+ function __construct( $parent, $attributes = NULL ) {
$this->parent = $parent;
}
@@ -255,7 +241,7 @@ class dbTable extends dbObject {
* @param string $prefix DB Object prefix
* @param array $attributes Array of table attributes.
*/
- function __construct( &$parent, $attributes = NULL ) {
+ function __construct( $parent, $attributes = NULL ) {
$this->parent = $parent;
$this->name = $this->prefix($attributes['NAME']);
}
@@ -651,7 +637,7 @@ class dbIndex extends dbObject {
*
* @internal
*/
- function __construct( &$parent, $attributes = NULL ) {
+ function __construct( $parent, $attributes = NULL ) {
$this->parent = $parent;
$this->name = $this->prefix ($attributes['NAME']);
@@ -795,7 +781,7 @@ class dbData extends dbObject {
*
* @internal
*/
- function __construct( &$parent, $attributes = NULL ) {
+ function __construct( $parent, $attributes = NULL ) {
$this->parent = $parent;
}
@@ -994,7 +980,7 @@ class dbQuerySet extends dbObject {
* @param object $parent Parent object
* @param array $attributes Attributes
*/
- function __construct( &$parent, $attributes = NULL ) {
+ function __construct( $parent, $attributes = NULL ) {
$this->parent = $parent;
// Overrides the manual prefix key
@@ -1722,13 +1708,6 @@ class adoSchema {
return $result;
}
- // compat for pre-4.3 - jlim
- function _file_get_contents($path)
- {
- if (function_exists('file_get_contents')) return file_get_contents($path);
- return join('',file($path));
- }
-
/**
* Converts an XML schema file to the specified DTD version.
*
@@ -1757,7 +1736,7 @@ class adoSchema {
}
if( $version == $newVersion ) {
- $result = _file_get_contents( $filename );
+ $result = file_get_contents( $filename );
// remove unicode BOM if present
if( substr( $result, 0, 3 ) == sprintf( '%c%c%c', 239, 187, 191 ) ) {
@@ -1796,7 +1775,7 @@ class adoSchema {
return FALSE;
}
- $schema = _file_get_contents( $schema );
+ $schema = file_get_contents( $schema );
break;
case 'string':
default:
@@ -1807,14 +1786,14 @@ class adoSchema {
$arguments = array (
'/_xml' => $schema,
- '/_xsl' => _file_get_contents( $xsl_file )
+ '/_xsl' => file_get_contents( $xsl_file )
);
// create an XSLT processor
$xh = xslt_create ();
// set error handler
- xslt_set_error_handler ($xh, array (&$this, 'xslt_error_handler'));
+ xslt_set_error_handler ($xh, array ($this, 'xslt_error_handler'));
// process the schema
$result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
diff --git a/adodb-xmlschema03.inc.php b/adodb-xmlschema03.inc.php
index de1ea26c..4ab6f89b 100644
--- a/adodb-xmlschema03.inc.php
+++ b/adodb-xmlschema03.inc.php
@@ -26,20 +26,6 @@
* @author Dan Cech
*/
-function _file_get_contents($file)
-{
- if (function_exists('file_get_contents')) return file_get_contents($file);
-
- $f = fopen($file,'r');
- if (!$f) return '';
- $t = '';
-
- while ($s = fread($f,100000)) $t .= $s;
- fclose($f);
- return $t;
-}
-
-
/**
* Debug on or off
*/
@@ -144,7 +130,7 @@ class dbObject {
/**
* NOP
*/
- function __construct( &$parent, $attributes = NULL ) {
+ function __construct( $parent, $attributes = NULL ) {
$this->parent = $parent;
}
@@ -280,7 +266,7 @@ class dbTable extends dbObject {
* @param string $prefix DB Object prefix
* @param array $attributes Array of table attributes.
*/
- function __construct( &$parent, $attributes = NULL ) {
+ function __construct( $parent, $attributes = NULL ) {
$this->parent = $parent;
$this->name = $this->prefix($attributes['NAME']);
}
@@ -704,7 +690,7 @@ class dbIndex extends dbObject {
*
* @internal
*/
- function __construct( &$parent, $attributes = NULL ) {
+ function __construct( $parent, $attributes = NULL ) {
$this->parent = $parent;
$this->name = $this->prefix ($attributes['NAME']);
@@ -849,7 +835,7 @@ class dbData extends dbObject {
*
* @internal
*/
- function __construct( &$parent, $attributes = NULL ) {
+ function __construct( $parent, $attributes = NULL ) {
$this->parent = $parent;
}
@@ -1105,7 +1091,7 @@ class dbQuerySet extends dbObject {
* @param object $parent Parent object
* @param array $attributes Attributes
*/
- function __construct( &$parent, $attributes = NULL ) {
+ function __construct( $parent, $attributes = NULL ) {
$this->parent = $parent;
// Overrides the manual prefix key
@@ -1893,14 +1879,6 @@ class adoSchema {
return $result;
}
- /*
- // compat for pre-4.3 - jlim
- function _file_get_contents($path)
- {
- if (function_exists('file_get_contents')) return file_get_contents($path);
- return join('',file($path));
- }*/
-
/**
* Converts an XML schema file to the specified DTD version.
*
@@ -1929,7 +1907,7 @@ class adoSchema {
}
if( $version == $newVersion ) {
- $result = _file_get_contents( $filename );
+ $result = file_get_contents( $filename );
// remove unicode BOM if present
if( substr( $result, 0, 3 ) == sprintf( '%c%c%c', 239, 187, 191 ) ) {
@@ -1968,7 +1946,7 @@ class adoSchema {
return FALSE;
}
- $schema = _file_get_contents( $schema );
+ $schema = file_get_contents( $schema );
break;
case 'string':
default:
@@ -1979,14 +1957,14 @@ class adoSchema {
$arguments = array (
'/_xml' => $schema,
- '/_xsl' => _file_get_contents( $xsl_file )
+ '/_xsl' => file_get_contents( $xsl_file )
);
// create an XSLT processor
$xh = xslt_create ();
// set error handler
- xslt_set_error_handler ($xh, array (&$this, 'xslt_error_handler'));
+ xslt_set_error_handler ($xh, array ($this, 'xslt_error_handler'));
// process the schema
$result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments);
diff --git a/adodb.inc.php b/adodb.inc.php
index f15158f9..ea971b8a 100644
--- a/adodb.inc.php
+++ b/adodb.inc.php
@@ -198,7 +198,7 @@ if (!defined('_ADODB_LAYER')) {
/**
* ADODB version as a string.
*/
- $ADODB_vers = 'v5.21.2 2021-08-22';
+ $ADODB_vers = 'v5.22.0-dev Unreleased';
/**
* Determines whether recordset->RecordCount() is used.
@@ -240,12 +240,25 @@ if (!defined('_ADODB_LAYER')) {
}
+ /**
+ * Parse date string to prevent injection attack.
+ *
+ * @param string $s
+ *
+ * @return string
+ */
function _adodb_safedate($s) {
return str_replace(array("'", '\\'), '', $s);
}
- // parse date string to prevent injection attack
- // date string will have one quote at beginning e.g. '3434343'
+ /**
+ * Parse date string to prevent injection attack.
+ * Date string will have one quote at beginning e.g. '3434343'
+ *
+ * @param string $s
+ *
+ * @return string
+ */
function _adodb_safedateq($s) {
$len = strlen($s);
if ($s[0] !== "'") {
@@ -269,9 +282,17 @@ if (!defined('_ADODB_LAYER')) {
return strlen($s2) == 0 ? 'null' : $s2;
}
-
- // for transaction handling
-
+ /**
+ * For transaction handling.
+ *
+ * @param $dbms
+ * @param $fn
+ * @param $errno
+ * @param $errmsg
+ * @param $p1
+ * @param $p2
+ * @param $thisConnection
+ */
function ADODB_TransMonitor($dbms, $fn, $errno, $errmsg, $p1, $p2, &$thisConnection) {
//print "Errorno ($fn errno=$errno m=$errmsg) ";
$thisConnection->_transOK = false;
@@ -281,8 +302,9 @@ if (!defined('_ADODB_LAYER')) {
}
}
- //------------------
- // class for caching
+ /**
+ * Class ADODB_Cache_File
+ */
class ADODB_Cache_File {
var $createdir = true; // requires creation of temp dirs
@@ -294,18 +316,42 @@ if (!defined('_ADODB_LAYER')) {
}
}
- // write serialised recordset to cache item/file
- function writecache($filename, $contents, $debug, $secs2cache) {
+ /**
+ * Write serialised RecordSet to cache item/file.
+ *
+ * @param $filename
+ * @param $contents
+ * @param $debug
+ * @param $secs2cache
+ *
+ * @return bool|int
+ */
+ function writecache($filename, $contents, $debug, $secs2cache) {
return adodb_write_file($filename, $contents,$debug);
}
- // load serialised recordset and unserialise it
+ /**
+ * load serialised RecordSet and unserialise it
+ *
+ * @param $filename
+ * @param $err
+ * @param $secs2cache
+ * @param $rsClass
+ *
+ * @return ADORecordSet
+ */
function &readcache($filename, &$err, $secs2cache, $rsClass) {
$rs = csv2rs($filename,$err,$secs2cache,$rsClass);
return $rs;
}
- // flush all items in cache
+ /**
+ * Flush all items in cache.
+ *
+ * @param bool $debug
+ *
+ * @return bool|void
+ */
function flushall($debug=false) {
global $ADODB_CACHE_DIR;
@@ -320,7 +366,12 @@ if (!defined('_ADODB_LAYER')) {
return $rez;
}
- // flush one file in cache
+ /**
+ * Flush one file in cache.
+ *
+ * @param string $f
+ * @param bool $debug
+ */
function flushcache($f, $debug=false) {
if (!@unlink($f)) {
if ($debug) {
@@ -329,6 +380,11 @@ if (!defined('_ADODB_LAYER')) {
}
}
+ /**
+ * @param string $hash
+ *
+ * @return string
+ */
function getdirname($hash) {
global $ADODB_CACHE_DIR;
if (!isset($this->notSafeMode)) {
@@ -337,7 +393,14 @@ if (!defined('_ADODB_LAYER')) {
return ($this->notSafeMode) ? $ADODB_CACHE_DIR.'/'.substr($hash,0,2) : $ADODB_CACHE_DIR;
}
- // create temp directories
+ /**
+ * Create temp directories.
+ *
+ * @param string $hash
+ * @param bool $debug
+ *
+ * @return string
+ */
function createdir($hash, $debug) {
global $ADODB_CACHE_PERMS;
@@ -440,11 +503,38 @@ if (!defined('_ADODB_LAYER')) {
var $isoDates = false; /// accepts dates in ISO format
var $cacheSecs = 3600; /// cache for 1 hour
- // memcache
- var $memCache = false; /// should we use memCache instead of caching in files
- var $memCacheHost; /// memCache host
- var $memCachePort = 11211; /// memCache port
- var $memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib, not supported w/memcached library)
+ /*****************************************
+ * memcached server options
+ ******************************************/
+ /*
+ * Should we use memCache instead of caching in files
+ */
+ public $memCache = false;
+ /*
+ * A string, array of hosts or array of memcache connection
+ * options (see adodb.org)
+ */
+ public $memCacheHost;
+
+ /*
+ * Default port, may be ignored if connection object array
+ * is set
+ */
+ public $memCachePort = 11211;
+
+ /*
+ * Use 'true' to store the item compressed
+ * uses zlib, Direct option for memcache, else
+ * For memcached, use the memcacheOptions feature
+ */
+ public $memCacheCompress = false;
+
+ /*
+ * If using mecached, an array of options
+ * @link https://www.php.net/manual/en/memcached.constants.php
+ */
+ public $memCacheOptions = array();
+
var $sysDate = false; /// name of function that returns the current date
var $sysTimeStamp = false; /// name of function that returns the current timestamp
@@ -512,6 +602,24 @@ if (!defined('_ADODB_LAYER')) {
*/
protected $connectionParameters = array();
+ /*
+ * A simple associative array of user-defined custom actual/meta types
+ */
+ public $customActualTypes = array();
+
+ /*
+ * An array of user-defined custom meta/actual types
+ *
+ $this->customMetaTypes[$meta] = array(
+ 'actual'=>'',
+ 'dictionary'=>'',
+ 'handler'=>'',
+ 'callback'=>''
+ );
+ */
+ public $customMetaTypes = array();
+
+
/**
* Default Constructor.
* We define it even though it does not actually do anything. This avoids
@@ -573,10 +681,53 @@ if (!defined('_ADODB_LAYER')) {
}
/**
+ * Set a custom meta type with a corresponding actual
+ *
+ * @param string $metaType The Custom ADOdb metatype
+ * @param string $dictionaryType The database dictionary type
+ * @param string $actualType The database actual type
+ * @param bool $handleAsType handle like an existing Metatype
+ * @param mixed $callBack A pre-processing function
+ *
+ * @return bool success if the actual exists
+ */
+ final public function setCustomMetaType(
+ $metaType,
+ $dictionaryType,
+ $actualType,
+ $handleAsType=false,
+ $callback=false){
+
+ $this->customMetaTypes[strtoupper($metaType)] = array(
+ 'actual'=>$actualType,
+ 'dictionary'=>strtoupper($dictionaryType),
+ 'handler'=>$handleAsType,
+ 'callback'=>$callback
+ );
+
+ /*
+ * Create a reverse lookup for the actualType
+ */
+ $this->customActualTypes[$actualType] = $metaType;
+
+ return true;
+ }
+
+ /**
+ * Get a list of custom meta types.
+ *
+ * @return string[]
+ */
+ final public function getCustomMetaTypes()
+ {
+ return $this->customMetaTypes;
+ }
+
+
+ /**
* Get server version info.
*
- * @return string[] An array with 2 elements: $arr['string'] is the description string,
- * and $arr[version] is the version (also a string).
+ * @return string[] Array with 2 string elements: version and description
*/
function ServerInfo() {
return array('description' => '', 'version' => '');
@@ -591,6 +742,13 @@ if (!defined('_ADODB_LAYER')) {
return !empty($this->_connectionID);
}
+ /**
+ * Find version string.
+ *
+ * @param string $str
+ *
+ * @return string
+ */
function _findvers($str) {
if (preg_match('/([0-9]+\.([0-9\.])+)/',$str, $arr)) {
return $arr[1];
@@ -729,6 +887,16 @@ if (!defined('_ADODB_LAYER')) {
return false;
}
+ /**
+ * Always force a new connection to database.
+ *
+ * @param string $argHostname Host to connect to
+ * @param string $argUsername Userid to login
+ * @param string $argPassword Associated password
+ * @param string $argDatabaseName Database name
+ *
+ * @return bool
+ */
function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName) {
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName);
}
@@ -807,7 +975,13 @@ if (!defined('_ADODB_LAYER')) {
return $ret;
}
- function outp_throw($msg,$src='WARN',$sql='') {
+ /**
+ * Throw an exception if the handler is defined or prints the message if not.
+ * @param string $msg Message
+ * @param string $src the name of the calling function (in uppercase)
+ * @param string $sql Optional offending SQL statement
+ */
+ function outp_throw($msg, $src='WARN', $sql='') {
if (defined('ADODB_ERROR_HANDLER') && ADODB_ERROR_HANDLER == 'adodb_throw') {
adodb_throw($this->databaseType,$src,-9999,$msg,$sql,false,$this);
return;
@@ -897,6 +1071,12 @@ if (!defined('_ADODB_LAYER')) {
return $this->qstr($s);
}
+ /**
+ * Quotes a string so that all strings are escaped.
+ * Wrapper for qstr with magic_quotes = false.
+ *
+ * @param string &$s
+ */
function q(&$s) {
//if (!empty($this->qNull && $s == 'null') {
// return $s;
@@ -905,8 +1085,9 @@ if (!defined('_ADODB_LAYER')) {
}
/**
- * PEAR DB Compat - do not use internally.
- */
+ * PEAR DB Compat - do not use internally.
+ * @return int
+ */
function ErrorNative() {
return $this->ErrorNo();
}
@@ -914,18 +1095,23 @@ if (!defined('_ADODB_LAYER')) {
/**
* PEAR DB Compat - do not use internally.
+ * @param string $seq_name
+ * @return int
*/
function nextId($seq_name) {
return $this->GenID($seq_name);
}
/**
- * Lock a row, will escalate and lock the table if row locking not supported
- * will normally free the lock at the end of the transaction
+ * Lock a row.
+ * Will escalate and lock the table if row locking is not supported.
+ * Will normally free the lock at the end of the transaction.
*
- * @param string $table name of table to lock
- * @param string $where where clause to use, eg: "WHERE row=12". If left empty, will escalate to table lock
- * @param string $col
+ * @param string $table name of table to lock
+ * @param string $where where clause to use, eg: "WHERE row=12". If left empty, will escalate to table lock
+ * @param string $col
+ *
+ * @return bool
*/
function RowLock($table,$where,$col='1 as adodbignore') {
return false;
@@ -968,7 +1154,6 @@ if (!defined('_ADODB_LAYER')) {
return $old;
}
-
/**
* PEAR DB Compat - do not use internally.
*
@@ -985,7 +1170,6 @@ if (!defined('_ADODB_LAYER')) {
return $rs;
}
-
/**
* PEAR DB Compat - do not use internally
*/
@@ -1026,35 +1210,53 @@ if (!defined('_ADODB_LAYER')) {
return '?';
}
- /*
- InParameter and OutParameter are self-documenting versions of Parameter().
- */
- function InParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false) {
+ /**
+ * Self-documenting version of Parameter().
+ *
+ * @param $stmt
+ * @param &$var
+ * @param $name
+ * @param int $maxLen
+ * @param bool $type
+ *
+ * @return bool
+ */
+ function InParameter(&$stmt, &$var, $name, $maxLen=4000, $type=false) {
return $this->Parameter($stmt,$var,$name,false,$maxLen,$type);
}
- /*
- */
+ /**
+ * Self-documenting version of Parameter().
+ *
+ * @param $stmt
+ * @param $var
+ * @param $name
+ * @param int $maxLen
+ * @param bool $type
+ *
+ * @return bool
+ */
function OutParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false) {
return $this->Parameter($stmt,$var,$name,true,$maxLen,$type);
}
-
- /*
- Usage in oracle
- $stmt = $db->Prepare('select * from table where id =:myid and group=:group');
- $db->Parameter($stmt,$id,'myid');
- $db->Parameter($stmt,$group,'group',64);
- $db->Execute();
-
- @param $stmt Statement returned by Prepare() or PrepareSP().
- @param $var PHP variable to bind to
- @param $name Name of stored procedure variable name to bind to.
- @param [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8.
- @param [$maxLen] Holds an maximum length of the variable.
- @param [$type] The data type of $var. Legal values depend on driver.
-
+ /**
+ *
+ * Usage in oracle
+ * $stmt = $db->Prepare('select * from table where id =:myid and group=:group');
+ * $db->Parameter($stmt,$id,'myid');
+ * $db->Parameter($stmt,$group,'group',64);
+ * $db->Execute();
+ *
+ * @param mixed &$stmt Statement returned by Prepare() or PrepareSP().
+ * @param mixed &$var PHP variable to bind to
+ * @param string $name Name of stored procedure variable name to bind to.
+ * @param int|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.
+ *
+ * @return bool
*/
function Parameter(&$stmt,&$var,$name,$isOutput=false,$maxLen=4000,$type=false) {
return false;
@@ -1936,16 +2138,6 @@ if (!defined('_ADODB_LAYER')) {
return $rv;
}
- function Transpose(&$rs,$addfieldnames=true) {
- $rs2 = $this->_rs2rs($rs);
- if (!$rs2) {
- return false;
- }
-
- $rs2->_transpose($addfieldnames);
- return $rs2;
- }
-
/*
Calculate the offset of a date for a particular database and generate
appropriate SQL. Useful for calculating future/past dates and storing
@@ -2443,37 +2635,47 @@ if (!defined('_ADODB_LAYER')) {
/**
- * Update a blob column, given a where clause. There are more sophisticated
- * blob handling functions that we could have implemented, but all require
- * a very complex API. Instead we have chosen something that is extremely
- * simple to understand and use.
- *
- * Note: $blobtype supports 'BLOB' and 'CLOB', default is BLOB of course.
- *
- * Usage to update a $blobvalue which has a primary key blob_id=1 into a
- * field blobtable.blobcolumn:
- *
- * UpdateBlob('blobtable', 'blobcolumn', $blobvalue, 'blob_id=1');
- *
- * Insert example:
- *
- * $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
- * $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
- */
- function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB') {
+ * Update a BLOB column, given a where clause.
+ *
+ * There are more sophisticated blob handling functions that we could have
+ * implemented, but all require a very complex API. Instead we have chosen
+ * something that is extremely simple to understand and use.
+ *
+ * Sample usage:
+ * - update a BLOB in field table.blob_col with value $blobValue, for a
+ * record having primary key id=1
+ * $conn->updateBlob('table', 'blob_col', $blobValue, 'id=1');
+ * - insert example:
+ * $conn->execute('INSERT INTO table (id, blob_col) VALUES (1, null)');
+ * $conn->updateBlob('table', 'blob_col', $blobValue, 'id=1');
+ *
+ * @param string $table
+ * @param string $column
+ * @param string $val Filename containing blob data
+ * @param mixed $where {@see updateBlob()}
+ * @param string $blobtype supports 'BLOB' (default) and 'CLOB'
+ *
+ * @return bool success
+ */
+ function updateBlob($table, $column, $val, $where, $blobtype='BLOB') {
return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false;
}
/**
- * Usage:
- * UpdateBlob('TABLE', 'COLUMN', '/path/to/file', 'ID=1');
- *
- * $blobtype supports 'BLOB' and 'CLOB'
- *
- * $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
- * $conn->UpdateBlob('blobtable','blobcol',$blobpath,'id=1');
- */
- function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB') {
+ * Update a BLOB from a file.
+ *
+ * Usage example:
+ * $conn->updateBlobFile('table', 'blob_col', '/path/to/file', 'id=1');
+ *
+ * @param string $table
+ * @param string $column
+ * @param string $path Filename containing blob data
+ * @param mixed $where {@see updateBlob()}
+ * @param string $blobtype supports 'BLOB' and 'CLOB'
+ *
+ * @return bool success
+ */
+ function updateBlobFile($table, $column, $path, $where, $blobtype='BLOB') {
$fd = fopen($path,'rb');
if ($fd === false) {
return false;
@@ -2642,7 +2844,9 @@ if (!defined('_ADODB_LAYER')) {
}
/**
- * Begin a Transaction. Must be followed by CommitTrans() or RollbackTrans().
+ * Begin a Transaction.
+ *
+ * Must be followed by CommitTrans() or RollbackTrans().
*
* @return bool true if succeeded or false if database does not support transactions
*/
@@ -2704,11 +2908,14 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
/**
- * If database does not support transactions, always return true as data always committed
+ * Commits a transaction.
*
- * @param bool $ok set to false to rollback transaction, true to commit
+ * If database does not support transactions, return true as data is
+ * always committed.
*
- * @return true/false.
+ * @param bool $ok True to commit, false to rollback the transaction.
+ *
+ * @return bool true if successful
*/
function CommitTrans($ok=true) {
return true;
@@ -2716,9 +2923,12 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
- * If database does not support transactions, rollbacks always fail, so return false
+ * Rolls back a transaction.
*
- * @return bool
+ * If database does not support transactions, return false as rollbacks
+ * always fail.
+ *
+ * @return bool true if successful
*/
function RollbackTrans() {
return false;
@@ -3417,10 +3627,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
class ADOFetchObj {
};
- //==============================================================================================
- // CLASS ADORecordSet_empty
- //==============================================================================================
-
+ /**
+ * Class ADODB_Iterator_empty
+ */
class ADODB_Iterator_empty implements Iterator {
private $rs;
@@ -3543,10 +3752,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
include_once(ADODB_DIR.'/adodb-time.inc.php');
}
- //==============================================================================================
- // CLASS ADORecordSet
- //==============================================================================================
-
+ /**
+ * Class ADODB_Iterator
+ */
class ADODB_Iterator implements Iterator {
private $rs;
@@ -3586,13 +3794,14 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
- /**
- * RecordSet class that represents the dataset returned by the database.
- * To keep memory overhead low, this class holds only the current row in memory.
- * No prefetching of data is done, so the RecordCount() can return -1 ( which
- * means recordcount not known).
- */
- class ADORecordSet implements IteratorAggregate {
+/**
+ * RecordSet class that represents the dataset returned by the database.
+ *
+ * To keep memory overhead low, this class holds only the current row in memory.
+ * No prefetching of data is done, so the RecordCount() can return -1 (which
+ * means recordcount not known).
+ */
+class ADORecordSet implements IteratorAggregate {
/**
* public variables
@@ -3613,8 +3822,8 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
var $bind = false; /// used by Fields() to hold array - should be private?
var $fetchMode; /// default fetch mode
- var $connection = false; /// the parent connection
-
+ /** @var ADOConnection The parent connection */
+ var $connection = false;
/**
* private variables
*/
@@ -3635,6 +3844,10 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
var $_maxRecordCount = 0;
var $datetime = false;
+ public $customActualTypes;
+ public $customMetaTypes;
+
+
/**
* @var ADOFieldObject[] Field metadata cache
* @see fieldTypesArray()
@@ -3644,7 +3857,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Constructor
*
- * @param resource|int queryID this is the queryID returned by ADOConnection->_query()
+ * @param resource|int $queryID Query ID returned by ADOConnection->_query()
*
*/
function __construct($queryID) {
@@ -3671,7 +3884,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
$this->_inited = true;
if ($this->_queryID) {
- @$this->_initrs();
+ @$this->_initRS();
} else {
$this->_numOfRows = 0;
$this->_numOfFields = 0;
@@ -3686,6 +3899,16 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
}
+ /**
+ * Recordset initialization stub
+ */
+ protected function _initRS() {}
+
+ /**
+ * Row fetch stub
+ * @return bool
+ */
+ protected function _fetch() {}
/**
* Generate a SELECT tag from a recordset, and return the HTML markup.
@@ -3824,24 +4047,28 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
return $this->GetArray($nRows);
}
- /*
- * Some databases allow multiple recordsets to be returned. This function
- * will return true if there is a next recordset, or false if no more.
- */
+ /**
+ * Checks if there is another available recordset.
+ *
+ * Some databases allow multiple recordsets to be returned.
+ *
+ * @return boolean true if there is a next recordset, or false if no more
+ */
function NextRecordSet() {
return false;
}
/**
- * return recordset as a 2-dimensional array.
+ * Return recordset as a 2-dimensional array.
+ *
* Helper function for ADOConnection->SelectLimit()
*
- * @param offset is the row to start calculations from (1-based)
- * @param [nrows] is the number of rows to return
+ * @param int $nrows Number of rows to return
+ * @param int $offset Starting row (1-based)
*
* @return array an array indexed by the rows (0-based) from the recordset
*/
- function GetArrayLimit($nrows,$offset=-1) {
+ function getArrayLimit($nrows, $offset=-1) {
if ($offset <= 0) {
return $this->GetArray($nrows);
}
@@ -3862,11 +4089,11 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Synonym for GetArray() for compatibility with ADO.
*
- * @param [nRows] is the number of rows to return. -1 means every row.
+ * @param int $nRows Number of rows to return. -1 means every row.
*
* @return array an array indexed by the rows (0-based) from the recordset
*/
- function GetRows($nRows = -1) {
+ function getRows($nRows = -1) {
return $this->GetArray($nRows);
}
@@ -4079,8 +4306,8 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
- * PEAR DB Compat - do not use internally
- */
+ * PEAR DB Compat - do not use internally
+ */
function Free() {
return $this->Close();
}
@@ -4254,6 +4481,14 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
return false;
}
+ /**
+ * Adjusts the result pointer to an arbitrary row in the result.
+ *
+ * @param int $row The row to seek to.
+ *
+ * @return bool False if the recordset contains no rows, otherwise true.
+ */
+ function _seek($row) {}
/**
* Get the value of a field in the current row by column name.
@@ -4327,8 +4562,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* Use associative array to get fields array for databases that do not support
* associative arrays. Submitted by Paolo S. Asioli paolo.asioli#libero.it
*
- * @param int [$upper] Case for the array keys, defaults to uppercase
+ * @param int $upper Case for the array keys, defaults to uppercase
* (see ADODB_ASSOC_CASE_xxx constants)
+ * @return array
*/
function GetRowAssoc($upper = ADODB_ASSOC_CASE) {
$record = array();
@@ -4364,15 +4600,14 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
/**
- * Synonyms RecordCount and RowCount
+ * Number of rows in recordset.
*
* @return int Number of rows or -1 if this is not supported
*/
- function RecordCount() {
+ function recordCount() {
return $this->_numOfRows;
}
-
/**
* If we are using PageExecute(), this will return the maximum possible rows
* that can be returned when paging a recordset.
@@ -4380,26 +4615,32 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* @return int
*/
function MaxRecordCount() {
- return ($this->_maxRecordCount) ? $this->_maxRecordCount : $this->RecordCount();
+ return ($this->_maxRecordCount) ? $this->_maxRecordCount : $this->recordCount();
}
/**
- * synonyms RecordCount and RowCount
+ * Number of rows in recordset.
+ * Alias for {@see recordCount()}
*
- * @return the number of rows or -1 if this is not supported
+ * @return int Number of rows or -1 if this is not supported
*/
- function RowCount() {
- return $this->_numOfRows;
+ function rowCount() {
+ return $this->recordCount();
}
-
- /**
- * Portable RecordCount. Pablo Roca <pabloroca@mvps.org>
+ /**
+ * Portable RecordCount.
*
- * @return the number of records from a previous SELECT. All databases support this.
+ * Be aware of possible problems in multiuser environments.
+ * For better speed the table must be indexed by the condition.
+ * Heavy test this before deploying.
*
- * But aware possible problems in multiuser environments. For better speed the table
- * must be indexed by the condition. Heavy test this before deploying.
+ * @param string $table
+ * @param string $condition
+ *
+ * @return int Number of records from a previous SELECT. All databases support this.
+ *
+ * @author Pablo Roca <pabloroca@mvps.org>
*/
function PO_RecordCount($table="", $condition="") {
@@ -4486,11 +4727,11 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* Return the fields array of the current row as an object for convenience.
* The default case is uppercase.
*
- * @param $isupper to set the object property names to uppercase
+ * @param bool $isUpper to set the object property names to uppercase
*
- * @return the object with the properties set to the fields of the current row
+ * @return ADOFetchObj The object with properties set to the fields of the current row
*/
- function FetchObject($isupper=true) {
+ function FetchObject($isUpper=true) {
if (empty($this->_obj)) {
$this->_obj = new ADOFetchObj();
$this->_names = array();
@@ -4499,12 +4740,11 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
$this->_names[] = $f->name;
}
}
- $i = 0;
$o = clone($this->_obj);
for ($i=0; $i <$this->_numOfFields; $i++) {
$name = $this->_names[$i];
- if ($isupper) {
+ if ($isUpper) {
$n = strtoupper($name);
} else {
$n = $name;
@@ -4519,8 +4759,8 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* Return the fields array of the current row as an object for convenience.
* The default is lower-case field names.
*
- * @return the object with the properties set to the fields of the current row,
- * or false if EOF
+ * @return ADOFetchObj|false The object with properties set to the fields of the current row
+ * or false if EOF.
*
* Fixed bug reported by tim@orotech.net
*/
@@ -4533,17 +4773,17 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* Return the fields array of the current row as an object for convenience.
* The default is upper case field names.
*
- * @param $isupper to set the object property names to uppercase
+ * @param bool $isUpper to set the object property names to uppercase
*
- * @return the object with the properties set to the fields of the current row,
- * or false if EOF
+ * @return ADOFetchObj|false The object with properties set to the fields of the current row
+ * or false if EOF.
*
* Fixed bug reported by tim@orotech.net
*/
- function FetchNextObject($isupper=true) {
+ function FetchNextObject($isUpper=true) {
$o = false;
if ($this->_numOfRows != 0 && !$this->EOF) {
- $o = $this->FetchObject($isupper);
+ $o = $this->FetchObject($isUpper);
$this->_currentRow++;
if ($this->_fetch()) {
return $o;
@@ -4554,37 +4794,29 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
/**
- * Get the metatype of the column. This is used for formatting. This is because
- * many databases use different names for the same type, so we transform the original
- * type to our standardised version which uses 1 character codes:
+ * Get the ADOdb metatype.
*
- * @param t is the type passed in. Normally is ADOFieldObject->type.
- * @param len is the maximum length of that field. This is because we treat character
- * fields bigger than a certain size as a 'B' (blob).
- * @param fieldobj is the field object returned by the database driver. Can hold
- * additional info (eg. primary_key for mysql).
+ * Many databases use different names for the same type, so we transform
+ * the native type to our standardised one, which uses 1 character codes.
+ * @see https://adodb.org/dokuwiki/doku.php?id=v5:dictionary:dictionary_index#portable_data_types
*
- * @return the general type of the data:
- * C for character < 250 chars
- * X for teXt (>= 250 chars)
- * B for Binary
- * N for numeric or floating point
- * D for date
- * T for timestamp
- * L for logical/Boolean
- * I for integer
- * R for autoincrement counter/integer
+ * @param string|ADOFieldObject $t Native type (usually ADOFieldObject->type)
+ * It is also possible to provide an
+ * ADOFieldObject here.
+ * @param int $len The field's maximum length. This is because we treat
+ * character fields bigger than a certain size as a 'B' (blob).
+ * @param ADOFieldObject $fieldObj Field object returned by the database driver;
+ * can hold additional info (eg. primary_key for mysql).
*
- *
- */
- function MetaType($t,$len=-1,$fieldobj=false) {
- if (is_object($t)) {
- $fieldobj = $t;
- $t = $fieldobj->type;
- $len = $fieldobj->max_length;
+ * @return string The ADOdb Standard type
+ */
+ function metaType($t, $len = -1, $fieldObj = false) {
+ if ($t instanceof ADOFieldObject) {
+ $fieldObj = $t;
+ $t = $fieldObj->type;
+ $len = $fieldObj->max_length;
}
-
// changed in 2.32 to hashing instead of switch stmt for speed...
static $typeMap = array(
'VARCHAR' => 'C',
@@ -4691,8 +4923,6 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
"SQLBOOL" => 'L'
);
-
- $tmap = false;
$t = strtoupper($t);
$tmap = (isset($typeMap[$t])) ? $typeMap[$t] : ADODB_DEFAULT_METATYPE;
switch ($tmap) {
@@ -4708,7 +4938,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
return 'C';
case 'I':
- if (!empty($fieldobj->primary_key)) {
+ if (!empty($fieldObj->primary_key)) {
return 'R';
}
return 'I';
@@ -4717,8 +4947,8 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
return 'N';
case 'B':
- if (isset($fieldobj->binary)) {
- return ($fieldobj->binary) ? 'B' : 'X';
+ if (isset($fieldObj->binary)) {
+ return ($fieldObj->binary) ? 'B' : 'X';
}
return 'B';
@@ -4769,8 +4999,10 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* set/returns the current recordset page when paginating
+ * @param int $page
+ * @return int
*/
- function AbsolutePage($page=-1) {
+ function absolutePage($page=-1) {
if ($page != -1) {
$this->_currentPage = $page;
}
@@ -4779,6 +5011,8 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* set/returns the status of the atFirstPage flag when paginating
+ * @param bool $status
+ * @return bool
*/
function AtFirstPage($status=false) {
if ($status != false) {
@@ -4787,6 +5021,10 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
return $this->_atFirstPage;
}
+ /**
+ * @param bool $page
+ * @return bool
+ */
function LastPageNo($page = false) {
if ($page != false) {
$this->_lastPageNo = $page;
@@ -4796,6 +5034,8 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* set/returns the status of the atLastPage flag when paginating
+ * @param bool $status
+ * @return bool
*/
function AtLastPage($status=false) {
if ($status != false) {
@@ -4843,38 +5083,6 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
$this->fetchMode = $ADODB_FETCH_MODE;
}
- function _transpose($addfieldnames=true) {
- global $ADODB_INCLUDED_LIB;
-
- if (empty($ADODB_INCLUDED_LIB)) {
- include_once(ADODB_DIR.'/adodb-lib.inc.php');
- }
- $hdr = true;
-
- $fobjs = $addfieldnames ? $this->_fieldobjects : false;
- adodb_transpose($this->_array, $newarr, $hdr, $fobjs);
- //adodb_pr($newarr);
-
- $this->_skiprow1 = false;
- $this->_array = $newarr;
- $this->_colnames = $hdr;
-
- adodb_probetypes($newarr,$this->_types);
-
- $this->_fieldobjects = array();
-
- foreach($hdr as $k => $name) {
- $f = new ADOFieldObject();
- $f->name = $name;
- $f->type = $this->_types[$k];
- $f->max_length = -1;
- $this->_fieldobjects[] = $f;
- }
- $this->fields = reset($this->_array);
-
- $this->_initrs();
-
- }
/**
* Setup the array.
diff --git a/datadict/datadict-access.inc.php b/datadict/datadict-access.inc.php
index 7a7d4cbb..b3f9fad0 100644
--- a/datadict/datadict-access.inc.php
+++ b/datadict/datadict-access.inc.php
@@ -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;
}
diff --git a/datadict/datadict-db2.inc.php b/datadict/datadict-db2.inc.php
index c5dda09f..9ac106bb 100644
--- a/datadict/datadict-db2.inc.php
+++ b/datadict/datadict-db2.inc.php
@@ -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';
diff --git a/datadict/datadict-firebird.inc.php b/datadict/datadict-firebird.inc.php
index 0020a0ae..79d0a8f5 100644
--- a/datadict/datadict-firebird.inc.php
+++ b/datadict/datadict-firebird.inc.php
@@ -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);
}
diff --git a/datadict/datadict-generic.inc.php b/datadict/datadict-generic.inc.php
index c9c8dee8..1a60dbc2 100644
--- a/datadict/datadict-generic.inc.php
+++ b/datadict/datadict-generic.inc.php
@@ -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':
diff --git a/datadict/datadict-ibase.inc.php b/datadict/datadict-ibase.inc.php
index 5f58880f..4310ded4 100644
--- a/datadict/datadict-ibase.inc.php
+++ b/datadict/datadict-ibase.inc.php
@@ -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':
diff --git a/datadict/datadict-informix.inc.php b/datadict/datadict-informix.inc.php
index acb5ba74..9e151633 100644
--- a/datadict/datadict-informix.inc.php
+++ b/datadict/datadict-informix.inc.php
@@ -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':
diff --git a/datadict/datadict-mssql.inc.php b/datadict/datadict-mssql.inc.php
index 1bcb27da..17df9e39 100644
--- a/datadict/datadict-mssql.inc.php
+++ b/datadict/datadict-mssql.inc.php
@@ -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';
diff --git a/datadict/datadict-mssqlnative.inc.php b/datadict/datadict-mssqlnative.inc.php
index b53dcd97..59228cbe 100644
--- a/datadict/datadict-mssqlnative.inc.php
+++ b/datadict/datadict-mssqlnative.inc.php
@@ -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';
diff --git a/datadict/datadict-mysql.inc.php b/datadict/datadict-mysql.inc.php
index a1ee950a..9efbba1f 100644
--- a/datadict/datadict-mysql.inc.php
+++ b/datadict/datadict-mysql.inc.php
@@ -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;
}
}
diff --git a/datadict/datadict-oci8.inc.php b/datadict/datadict-oci8.inc.php
index 9a239095..6d2cd244 100644
--- a/datadict/datadict-oci8.inc.php
+++ b/datadict/datadict-oci8.inc.php
@@ -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;
diff --git a/datadict/datadict-postgres.inc.php b/datadict/datadict-postgres.inc.php
index 17627c44..219cc8a9 100644
--- a/datadict/datadict-postgres.inc.php
+++ b/datadict/datadict-postgres.inc.php
@@ -42,10 +42,17 @@ 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':
@@ -99,8 +106,17 @@ class ADODB2_postgres extends ADODB_DataDict
}
}
- 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;
diff --git a/datadict/datadict-sapdb.inc.php b/datadict/datadict-sapdb.inc.php
index 20c16aa6..c469800f 100644
--- a/datadict/datadict-sapdb.inc.php
+++ b/datadict/datadict-sapdb.inc.php
@@ -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',
diff --git a/datadict/datadict-sqlite.inc.php b/datadict/datadict-sqlite.inc.php
index 942927f8..d565f887 100644
--- a/datadict/datadict-sqlite.inc.php
+++ b/datadict/datadict-sqlite.inc.php
@@ -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
diff --git a/datadict/datadict-sybase.inc.php b/datadict/datadict-sybase.inc.php
index e565f8e2..d6573dfa 100644
--- a/datadict/datadict-sybase.inc.php
+++ b/datadict/datadict-sybase.inc.php
@@ -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':
diff --git a/docs/changelog.md b/docs/changelog.md
index 9af8d376..2f5e9ee4 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -16,6 +16,39 @@ Older changelogs:
## [Unreleased]
+### Added
+
+- Support for custom MetaTypes, e.g. JSON or GEOMETRY
+ [#602](https://github.com/ADOdb/ADOdb/issues/602)
+ [#626](https://github.com/ADOdb/ADOdb/issues/626)
+ [#649](https://github.com/ADOdb/ADOdb/issues/649)
+- sqlite3 performance monitor stub
+ [#661](https://github.com/ADOdb/ADOdb/issues/661)
+- Use of weighted server groups with Memcached
+ [#676](https://github.com/ADOdb/ADOdb/issues/676)
+
+### Changed
+
+- mysql: Support bound variable statements
+ [#655](https://github.com/ADOdb/ADOdb/issues/655)
+
+### Removed
+
+- Transpose() function and assorted sub-functions
+ [#586](https://github.com/ADOdb/ADOdb/issues/586)
+
+### Fixed
+
+- metaIndexes does not return primary key correctly
+ [#656](https://github.com/ADOdb/ADOdb/issues/656)
+- mysql: Update socket and client flags for ssl
+ [#622](https://github.com/ADOdb/ADOdb/issues/622)
+- pgsql: prevent AddColumnSQL() from updating existing values when default is changed
+ [#635](https://github.com/ADOdb/ADOdb/issues/635)
+
+
+## [5.21.3] - Unreleased
+
### Fixed
- mysqli: force error reporting mode to OFF (PHP 8.1 compatibility)
@@ -1129,6 +1162,7 @@ Released together with [v4.95](changelog_v4.x.md#495---17-may-2007)
[Unreleased]: https://github.com/adodb/adodb/compare/v5.21.2...master
+[5.21.3]: https://github.com/adodb/adodb/compare/v5.21.2...hotfix/5.21
[5.21.2]: https://github.com/adodb/adodb/compare/v5.21.1...v5.21.2
[5.21.1]: https://github.com/adodb/adodb/compare/v5.21.0...v5.21.1
[5.21.0]: https://github.com/adodb/adodb/compare/v5.21.0-rc.1...v5.21.0
diff --git a/drivers/adodb-ado.inc.php b/drivers/adodb-ado.inc.php
index 67a032d7..fc000cec 100644
--- a/drivers/adodb-ado.inc.php
+++ b/drivers/adodb-ado.inc.php
@@ -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;
diff --git a/drivers/adodb-ado5.inc.php b/drivers/adodb-ado5.inc.php
index f673d092..36f9c3b8 100644
--- a/drivers/adodb-ado5.inc.php
+++ b/drivers/adodb-ado5.inc.php
@@ -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:
diff --git a/drivers/adodb-fbsql.inc.php b/drivers/adodb-fbsql.inc.php
index 0fb895a1..a4255eb9 100644
--- a/drivers/adodb-fbsql.inc.php
+++ b/drivers/adodb-fbsql.inc.php
@@ -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':
diff --git a/drivers/adodb-firebird.inc.php b/drivers/adodb-firebird.inc.php
index 2fafbe4f..e479077f 100644
--- a/drivers/adodb-firebird.inc.php
+++ b/drivers/adodb-firebird.inc.php
@@ -35,39 +35,113 @@ class ADODB_firebird extends ADOConnection {
var $fmtTimeStamp = "'Y-m-d, H:i:s'";
var $concat_operator='||';
var $_transactionID;
- var $metaTablesSQL = "select lower(rdb\$relation_name) from rdb\$relations where rdb\$relation_name not like 'RDB\$%'";
+
+ public $metaTablesSQL = "SELECT LOWER(rdb\$relation_name) FROM rdb\$relations";
//OPN STUFF start
+
var $metaColumnsSQL = "select lower(a.rdb\$field_name), a.rdb\$null_flag, a.rdb\$default_source, b.rdb\$field_length, b.rdb\$field_scale, b.rdb\$field_sub_type, b.rdb\$field_precision, b.rdb\$field_type from rdb\$relation_fields a, rdb\$fields b where a.rdb\$field_source = b.rdb\$field_name and a.rdb\$relation_name = '%s' order by a.rdb\$field_position asc";
//OPN STUFF end
- var $ibasetrans;
+
+ public $_genSeqSQL = "CREATE SEQUENCE %s START WITH %s";
+
+ public $_dropSeqSQL = "DROP SEQUENCE %s";
+
var $hasGenID = true;
var $_bindInputArray = true;
- var $buffers = 0;
- var $dialect = 3;
var $sysDate = "cast('TODAY' as timestamp)";
var $sysTimeStamp = "CURRENT_TIMESTAMP"; //"cast('NOW' as timestamp)";
var $ansiOuter = true;
var $hasAffectedRows = true;
var $poorAffectedRows = false;
var $blobEncodeType = 'C';
- var $role = false;
+ /*
+ * firebird custom optionally specifies the user role
+ */
+ public $role = false;
+ /*
+ * firebird custom optionally specifies the connection buffers
+ */
+ public $buffers = 0;
+
+ /*
+ * firebird custom optionally specifies database dialect
+ */
+ public $dialect = 3;
+
var $nameQuote = ''; /// string to use to quote identifiers and names
function __construct()
{
- // Ignore IBASE_DEFAULT we want a more practical transaction!
- // if (defined('IBASE_DEFAULT')) $this->ibasetrans = IBASE_DEFAULT;
- // else
- $this->ibasetrans = IBASE_WAIT | IBASE_REC_VERSION | IBASE_COMMITTED;
+ parent::__construct();
+ $this->setTransactionMode('');
}
+ /**
+ * Sets the isolation level of a transaction.
+ *
+ * The default behavior is a more practical IBASE_WAIT | IBASE_REC_VERSION | IBASE_COMMITTED
+ * instead of IBASE_DEFAULT
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:settransactionmode
+ *
+ * @param string $transaction_mode The transaction mode to set.
+ *
+ * @return void
+ */
+ public function setTransactionMode($transaction_mode)
+ {
+ $this->_transmode = $transaction_mode;
+
+ if (empty($transaction_mode)) {
+ $this->_transmode = IBASE_WAIT | IBASE_REC_VERSION | IBASE_COMMITTED;
+ }
- // returns true or false
- function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$persist=false)
+ }
+
+ /**
+ * Connect to a database.
+ *
+ * @todo add: parameter int $port, parameter string $socket
+ *
+ * @param string|null $argHostname (Optional) The host to connect to.
+ * @param string|null $argUsername (Optional) The username to connect as.
+ * @param string|null $argPassword (Optional) The password to connect with.
+ * @param string|null $argDatabasename (Optional) The name of the database to start in when connected.
+ * @param bool $persist (Optional) Whether or not to use a persistent connection.
+ *
+ * @return bool|null True if connected successfully, false if connection failed, or null if the mysqli extension
+ * isn't currently loaded.
+ */
+ public function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$persist=false)
{
- if (!function_exists('fbird_pconnect')) return null;
- if ($argDatabasename) $argHostname .= ':'.$argDatabasename;
+ if (!function_exists('fbird_pconnect'))
+ return null;
+
+ if ($argDatabasename)
+ $argHostname .= ':'.$argDatabasename;
+
$fn = ($persist) ? 'fbird_pconnect':'fbird_connect';
+
+ /*
+ * Now merge in the standard connection parameters setting
+ */
+ foreach ($this->connectionParameters as $options)
+ {
+ foreach($options as $k=>$v)
+ {
+ switch($k){
+ case 'role':
+ $this->role = $v;
+ break;
+ case 'dialect':
+ $this->dialect = $v;
+ break;
+ case 'buffers':
+ $this->buffers = $v;
+ }
+ }
+ }
+
if ($this->role)
$this->_connectionID = $fn($argHostname,$argUsername,$argPassword,
$this->charSet,$this->buffers,$this->dialect,$this->role);
@@ -75,40 +149,39 @@ class ADODB_firebird extends ADOConnection {
$this->_connectionID = $fn($argHostname,$argUsername,$argPassword,
$this->charSet,$this->buffers,$this->dialect);
- if ($this->dialect != 1) { // http://www.ibphoenix.com/ibp_60_del_id_ds.html
- $this->replaceQuote = "''";
+ if ($this->dialect == 1) { // http://www.ibphoenix.com/ibp_60_del_id_ds.html
+ $this->replaceQuote = "";
}
if ($this->_connectionID === false) {
- $this->_handleerror();
+ $this->_handleError();
return false;
}
- // PHP5 change.
- if (function_exists('fbird_timefmt')) {
- fbird_timefmt($this->fbird_datefmt,fbird_DATE );
- if ($this->dialect == 1) {
- fbird_timefmt($this->fbird_datefmt,fbird_TIMESTAMP );
- } else {
- fbird_timefmt($this->fbird_timestampfmt,fbird_TIMESTAMP );
- }
- fbird_timefmt($this->fbird_timefmt,fbird_TIME );
+ ini_set("ibase.timestampformat", $this->fbird_timestampfmt);
+ ini_set("ibase.dateformat", $this->fbird_datefmt);
+ ini_set("ibase.timeformat", $this->fbird_timefmt);
- } else {
- ini_set("ibase.timestampformat", $this->fbird_timestampfmt);
- ini_set("ibase.dateformat", $this->fbird_datefmt);
- ini_set("ibase.timeformat", $this->fbird_timefmt);
- }
return true;
}
- // returns true or false
+ /**
+ * Connect to a database with a persistent connection.
+ *
+ * @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.
+ *
+ * @return bool|null True if connected successfully, false if connection failed, or null if the mysqli extension
+ * isn't currently loaded.
+ */
function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,true);
}
- function MetaPrimaryKeys($table,$owner_notused=false,$internalKey=false)
+ public function metaPrimaryKeys($table,$owner_notused=false,$internalKey=false)
{
if ($internalKey) {
return array('RDB$DB_KEY');
@@ -126,31 +199,58 @@ class ADODB_firebird extends ADOConnection {
return false;
}
- function ServerInfo()
+ /**
+ * Get information about the current Firebird server.
+ *
+ * @return array
+ */
+ public function serverInfo()
{
$arr['dialect'] = $this->dialect;
switch($arr['dialect']) {
- case '':
- case '1': $s = 'Firebird Dialect 1'; break;
- case '2': $s = 'Firebird Dialect 2'; break;
- default:
- case '3': $s = 'Firebird Dialect 3'; break;
+ case '':
+ case '1':
+ $s = 'Firebird Dialect 1';
+ break;
+ case '2':
+ $s = 'Firebird Dialect 2';
+ break;
+ default:
+ case '3':
+ $s = 'Firebird Dialect 3';
+ break;
}
$arr['version'] = ADOConnection::_findvers($s);
$arr['description'] = $s;
return $arr;
}
- function BeginTrans()
+ /**
+ * Begin a Transaction. Must be followed by CommitTrans() or RollbackTrans().
+ *
+ * @return bool true if succeeded or false if database does not support transactions
+ */
+ public function beginTrans()
{
if ($this->transOff) return true;
$this->transCnt += 1;
$this->autoCommit = false;
- $this->_transactionID = fbird_trans( $this->ibasetrans, $this->_connectionID );
+ /*
+ * We manage the transaction mode via fbird_trans
+ */
+ $this->_transactionID = fbird_trans( $this->_transmode, $this->_connectionID );
return $this->_transactionID;
}
- function CommitTrans($ok=true)
+
+ /**
+ * Commits a transaction
+ *
+ * @param bool $ok set to false to rollback transaction, true to commit
+ *
+ * @return true/false.
+ */
+ public function commitTrans($ok=true)
{
if (!$ok) {
return $this->RollbackTrans();
@@ -173,31 +273,26 @@ class ADODB_firebird extends ADOConnection {
function _affectedrows()
{
- return fbird_affected_rows( $this->_transactionID ? $this->_transactionID : $this->_connectionID );
+ return fbird_affected_rows( $this->_transactionID ? $this->_transactionID : $this->_connectionID );
}
- // there are some compat problems with ADODB_COUNTRECS=false and $this->_logsql currently.
- // it appears that ibase extension cannot support multiple concurrent queryid's
- function _Execute($sql,$inputarr=false) {
- global $ADODB_COUNTRECS;
-
- if ($this->_logsql) {
- $savecrecs = $ADODB_COUNTRECS;
- $ADODB_COUNTRECS = true; // force countrecs
- $ret =& ADOConnection::_Execute($sql,$inputarr);
- $ADODB_COUNTRECS = $savecrecs;
- } else {
- $ret = ADOConnection::_Execute($sql,$inputarr);
- }
- return $ret;
- }
-
- function RollbackTrans()
+ /**
+ * Rollback a smart transaction.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:rollbacktrans
+ *
+ * @return bool
+ */
+ public function rollbackTrans()
{
- if ($this->transOff) return true;
- if ($this->transCnt) $this->transCnt -= 1;
+ if ($this->transOff)
+ return true;
+ if ($this->transCnt)
+ $this->transCnt -= 1;
+
$ret = false;
$this->autoCommit = true;
+
if ($this->_transactionID) {
$ret = fbird_rollback($this->_transactionID);
}
@@ -206,16 +301,26 @@ class ADODB_firebird extends ADOConnection {
return $ret;
}
- function &MetaIndexes ($table, $primary = FALSE, $owner=false)
+ /**
+ * Get a list of indexes on the specified table.
+ *
+ * @param string $table The name of the table to get indexes for.
+ * @param bool $primary (Optional) Whether or not to include the primary key.
+ * @param bool $owner (Optional) Unused.
+ *
+ * @return array|bool An array of the indexes, or false if the query to get the indexes failed.
+ */
+ public 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);
}
+
$table = strtoupper($table);
$sql = "SELECT * FROM RDB\$INDICES WHERE RDB\$RELATION_NAME = '".$table."'";
if (!$primary) {
@@ -224,19 +329,19 @@ class ADODB_firebird extends ADOConnection {
$sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$FOREIGN%'";
}
// get index details
- $rs = $this->Execute($sql);
+ $rs = $this->execute($sql);
if (!is_object($rs)) {
// restore fetchmode
if (isset($savem)) {
$this->SetFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
- return $false;
+ return false;
}
-
$indexes = array();
while ($row = $rs->FetchRow()) {
- $index = $row[0];
+
+ $index = trim($row[0]);
if (!isset($indexes[$index])) {
if (is_null($row[3])) {
$row[3] = 0;
@@ -246,12 +351,13 @@ class ADODB_firebird extends ADOConnection {
'columns' => array()
);
}
- $sql = "SELECT * FROM RDB\$INDEX_SEGMENTS WHERE RDB\$INDEX_NAME = '".$index."' ORDER BY RDB\$FIELD_POSITION ASC";
- $rs1 = $this->Execute($sql);
+ $sql = sprintf("SELECT * FROM RDB\$INDEX_SEGMENTS WHERE RDB\$INDEX_NAME = '%s' ORDER BY RDB\$FIELD_POSITION ASC",$index);
+ $rs1 = $this->execute($sql);
while ($row1 = $rs1->FetchRow()) {
- $indexes[$index]['columns'][$row1[2]] = $row1[1];
+ $indexes[$index]['columns'][$row1[2]] = trim($row1[1]);
}
}
+
// restore fetchmode
if (isset($savem)) {
$this->SetFetchMode($savem);
@@ -261,38 +367,60 @@ class ADODB_firebird extends ADOConnection {
return $indexes;
}
-
- // See http://community.borland.com/article/0,1410,25844,00.html
- function RowLock($tables,$where,$col=false)
+ /**
+ * Lock a table row for a duration of a transaction.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:rowlock
+ * @link https://firebirdsql.org/refdocs/langrefupd21-notes-withlock.html
+ *
+ * @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.
+ */
+ public function rowLock($table,$where,$col=false)
{
- if ($this->autoCommit) {
- $this->BeginTrans();
- }
- $this->Execute("UPDATE $table SET $col=$col WHERE $where "); // is this correct - jlim?
- return 1;
- }
-
+ if ($this->transCnt==0)
+ $this->beginTrans();
- function CreateSequence($seqname = 'adodbseq', $startID = 1)
- {
- $ok = $this->Execute(("CREATE GENERATOR $seqname" ));
- if (!$ok) return false;
- return $this->Execute("SET GENERATOR $seqname TO ".($startID-1));
+ if ($where) $where = ' where '.$where;
+ $rs = $this->execute("SELECT $col FROM $table $where FOR UPDATE WITH LOCK");
+ return !empty($rs);
}
- function DropSequence($seqname = 'adodbseq')
+ /**
+ * Creates a sequence in the database.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:createsequence
+ *
+ * @param string $seqname The sequence name.
+ * @param int $startID The start id.
+ *
+ * @return ADORecordSet|bool A record set if executed successfully, otherwise false.
+ */
+ public function createSequence($seqname='adodbseq', $startID = 1)
{
- $seqname = strtoupper($seqname);
- return $this->Execute("DROP GENERATOR $seqname");
+ $sql = sprintf($this->_genSeqSQL,$seqname,$startID);
+ return $this->execute($sql);
}
- function GenID($seqname='adodbseq',$startID=1)
+ /**
+ * A portable method of creating sequence numbers.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:genid
+ *
+ * @param string $seqname (Optional) The name of the sequence to use.
+ * @param int $startID (Optional) The point to start at in the sequence.
+ *
+ * @return int
+ */
+ public function genID($seqname='adodbseq',$startID=1)
{
$getnext = ("SELECT Gen_ID($seqname,1) FROM RDB\$DATABASE");
$rs = @$this->Execute($getnext);
if (!$rs) {
- $this->Execute(("CREATE GENERATOR $seqname" ));
- $this->Execute("SET GENERATOR $seqname TO ".($startID-1).';');
+ $this->Execute("CREATE SEQUENCE $seqname START WITH $startID");
$rs = $this->Execute($getnext);
}
if ($rs && !$rs->EOF) {
@@ -309,36 +437,56 @@ class ADODB_firebird extends ADOConnection {
return $this->genID;
}
- function SelectDB($dbName)
+ function selectDB($dbName)
{
return false;
}
- function _handleerror()
+ function _handleError()
{
- $this->_errorMsg = fbird_errmsg();
+ $this->_errorCode = fbird_errcode();
+ $this->_errorMsg = fbird_errmsg();
}
- function ErrorNo()
+
+ public function errorNo()
{
- if (preg_match('/error code = ([\-0-9]*)/i', $this->_errorMsg,$arr)) return (integer) $arr[1];
- else return 0;
+ return (integer) $this->_errorCode;
}
- function ErrorMsg()
+ function errorMsg()
{
return $this->_errorMsg;
}
- function Prepare($sql)
+ /**
+ * 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
+ *
+ * @param string $sql The SQL to prepare.
+ *
+ * @return bool|array The SQL that was provided and the prepared parameters,
+ * or false if the preparation fails
+ */
+ public function prepare($sql)
{
$stmt = fbird_prepare($this->_connectionID,$sql);
- if (!$stmt) return false;
+ if (!$stmt)
+ return false;
return array($sql,$stmt);
}
- // returns query ID if successful, otherwise false
- // there have been reports of problems with nested queries - the code is probably not re-entrant?
+ /**
+ * Return the query id.
+ *
+ * @param string|array $sql
+ * @param array $iarr
+ *
+ * @return bool|object
+ */
function _query($sql,$iarr=false)
{
if ( !$this->isConnected() ) return false;
@@ -353,7 +501,7 @@ class ADODB_firebird extends ADOConnection {
$fn = 'fbird_execute';
$sql = $sql[1];
if (is_array($iarr)) {
- if ( !isset($iarr[0]) )
+ if ( !isset($iarr[0]) )
$iarr[0] = ''; // PHP5 compat hack
$fnarr = array_merge( array($sql) , $iarr);
$ret = call_user_func_array($fn,$fnarr);
@@ -363,9 +511,9 @@ class ADODB_firebird extends ADOConnection {
}
} else {
$fn = 'fbird_query';
- if (is_array($iarr))
+ if (is_array($iarr))
{
- if (sizeof($iarr) == 0)
+ if (sizeof($iarr) == 0)
$iarr[0] = ''; // PHP5 compat hack
$fnarr = array_merge( array($conn,$sql) , $iarr);
$ret = call_user_func_array($fn,$fnarr);
@@ -378,7 +526,7 @@ class ADODB_firebird extends ADOConnection {
fbird_commit($this->_connectionID);
}
- $this->_handleerror();
+ $this->_handleError();
return $ret;
}
@@ -398,122 +546,133 @@ class ADODB_firebird extends ADOConnection {
$fld->max_length = $flen;
$fld->scale = null;
switch($ftype){
- case 7:
- case 8:
- if ($dialect3) {
- switch($fsubtype){
- case 0:
- $fld->type = ($ftype == 7 ? 'smallint' : 'integer');
- break;
- case 1:
- $fld->type = 'numeric';
- $fld->max_length = $fprecision;
- $fld->scale = $fscale;
- break;
- case 2:
- $fld->type = 'decimal';
- $fld->max_length = $fprecision;
- $fld->scale = $fscale;
- break;
- } // switch
- } else {
- if ($fscale !=0) {
+ case 7:
+ case 8:
+ if ($dialect3) {
+ switch($fsubtype){
+ case 0:
+ $fld->type = ($ftype == 7 ? 'smallint' : 'integer');
+ break;
+ case 1:
+ $fld->type = 'numeric';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ case 2:
$fld->type = 'decimal';
+ $fld->max_length = $fprecision;
$fld->scale = $fscale;
- $fld->max_length = ($ftype == 7 ? 4 : 9);
- } else {
- $fld->type = ($ftype == 7 ? 'smallint' : 'integer');
- }
- }
- break;
- case 16:
- if ($dialect3) {
- switch($fsubtype){
- case 0:
- $fld->type = 'decimal';
- $fld->max_length = 18;
- $fld->scale = 0;
- break;
- case 1:
- $fld->type = 'numeric';
- $fld->max_length = $fprecision;
- $fld->scale = $fscale;
- break;
- case 2:
- $fld->type = 'decimal';
- $fld->max_length = $fprecision;
- $fld->scale = $fscale;
- break;
- } // switch
- }
- break;
- case 10:
- $fld->type = 'float';
- break;
- case 14:
- $fld->type = 'char';
- break;
- case 27:
+ break;
+ } // switch
+ } else {
if ($fscale !=0) {
$fld->type = 'decimal';
- $fld->max_length = 15;
- $fld->scale = 5;
- } else {
- $fld->type = 'double';
- }
- break;
- case 35:
- if ($dialect3) {
- $fld->type = 'timestamp';
+ $fld->scale = $fscale;
+ $fld->max_length = ($ftype == 7 ? 4 : 9);
} else {
- $fld->type = 'date';
+ $fld->type = ($ftype == 7 ? 'smallint' : 'integer');
}
- break;
- case 12:
+ }
+ break;
+ case 16:
+ if ($dialect3) {
+ switch($fsubtype){
+ case 0:
+ $fld->type = 'decimal';
+ $fld->max_length = 18;
+ $fld->scale = 0;
+ break;
+ case 1:
+ $fld->type = 'numeric';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ case 2:
+ $fld->type = 'decimal';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ } // switch
+ }
+ break;
+ case 10:
+ $fld->type = 'float';
+ break;
+ case 14:
+ $fld->type = 'char';
+ break;
+ case 27:
+ if ($fscale !=0) {
+ $fld->type = 'decimal';
+ $fld->max_length = 15;
+ $fld->scale = 5;
+ } else {
+ $fld->type = 'double';
+ }
+ break;
+ case 35:
+ if ($dialect3) {
+ $fld->type = 'timestamp';
+ } else {
$fld->type = 'date';
- break;
- case 13:
- $fld->type = 'time';
- break;
- case 37:
- $fld->type = 'varchar';
- break;
- case 40:
- $fld->type = 'cstring';
- break;
- case 261:
- $fld->type = 'blob';
- $fld->max_length = -1;
- break;
+ }
+ break;
+ case 12:
+ $fld->type = 'date';
+ break;
+ case 13:
+ $fld->type = 'time';
+ break;
+ case 37:
+ $fld->type = 'varchar';
+ break;
+ case 40:
+ $fld->type = 'cstring';
+ break;
+ case 261:
+ $fld->type = 'blob';
+ $fld->max_length = -1;
+ break;
} // switch
}
//OPN STUFF end
- // returns array of ADOFieldObjects for current table
- function MetaColumns($table, $normalize=true)
+ /**
+ * Return an array of information about a table's columns.
+ *
+ * @param string $table The name of the table to get the column info for.
+ * @param bool $normalize (Optional) Unused.
+ *
+ * @return ADOFieldObject[]|bool An array of info for each column,
+ * or false if it could not determine the info.
+ */
+ public function metaColumns($table, $normalize = true)
{
- global $ADODB_FETCH_MODE;
+
+ global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
- $rs = $this->Execute(sprintf($this->metaColumnsSQL,strtoupper($table)));
+ $rs = $this->execute(sprintf($this->metaColumnsSQL,strtoupper($table)));
$ADODB_FETCH_MODE = $save;
- $false = false;
+
if ($rs === false) {
- return $false;
+ return false;
}
$retarr = array();
//OPN STUFF start
- $dialect3 = ($this->dialect==3 ? true : false);
+ $dialect3 = $this->dialect == 3;
//OPN STUFF end
while (!$rs->EOF) { //print_r($rs->fields);
$fld = new ADOFieldObject();
$fld->name = trim($rs->fields[0]);
//OPN STUFF start
- $this->_ConvertFieldType($fld, $rs->fields[7], $rs->fields[3], $rs->fields[4], $rs->fields[5], $rs->fields[6], $dialect3);
+ //print_r($rs->fields);
+ $this->_ConvertFieldType(
+ $fld, $rs->fields[7], $rs->fields[3], $rs->fields[4], $rs->fields[5], $rs->fields[6], $dialect3);
if (isset($rs->fields[1]) && $rs->fields[1]) {
$fld->not_null = true;
}
@@ -521,17 +680,24 @@ class ADODB_firebird extends ADOConnection {
$fld->has_default = true;
$d = substr($rs->fields[2],strlen('default '));
- switch ($fld->type)
- {
- case 'smallint':
- case 'integer': $fld->default_value = (int) $d; break;
- case 'char':
- case 'blob':
- case 'text':
- case 'varchar': $fld->default_value = (string) substr($d,1,strlen($d)-2); break;
- case 'double':
- case 'float': $fld->default_value = (float) $d; break;
- default: $fld->default_value = $d; break;
+ switch ($fld->type) {
+ case 'smallint':
+ case 'integer':
+ $fld->default_value = (int)$d;
+ break;
+ case 'char':
+ case 'blob':
+ case 'text':
+ case 'varchar':
+ $fld->default_value = (string)substr($d, 1, strlen($d) - 2);
+ break;
+ case 'double':
+ case 'float':
+ $fld->default_value = (float)$d;
+ break;
+ default:
+ $fld->default_value = $d;
+ break;
}
// case 35:$tt = 'TIMESTAMP'; break;
}
@@ -547,40 +713,79 @@ class ADODB_firebird extends ADOConnection {
$rs->MoveNext();
}
$rs->Close();
- if ( empty($retarr)) return $false;
+ if ( empty($retarr))
+ return false;
else return $retarr;
}
- function BlobEncode( $blob )
+ /**
+ * Retrieves a list of tables based on given criteria
+ *
+ * @param string|bool $ttype (Optional) Table type = 'TABLE', 'VIEW' or false=both (default)
+ * @param string|bool $showSchema (Optional) schema name, false = current schema (default)
+ * @param string|bool $mask (Optional) filters the table by name
+ *
+ * @return array list of tables
+ */
+ public function metaTables($ttype = false, $showSchema = false, $mask = false)
+ {
+ $save = $this->metaTablesSQL;
+ if (!$showSchema) {
+ $this->metaTablesSQL .= " WHERE (rdb\$relation_name NOT LIKE 'RDB\$%' AND rdb\$relation_name NOT LIKE 'MON\$%' AND rdb\$relation_name NOT LIKE 'SEC\$%')";
+ } elseif (is_string($showSchema)) {
+ $this->metaTablesSQL .= $this->qstr($showSchema);
+ }
+
+ if ($mask) {
+ $mask = $this->qstr($mask);
+ $this->metaTablesSQL .= " AND table_name LIKE $mask";
+ }
+ $ret = ADOConnection::metaTables($ttype,$showSchema);
+
+ $this->metaTablesSQL = $save;
+ return $ret;
+ }
+
+ /**
+ * Encodes a blob, then assigns an id ready to be used
+ *
+ * @param string $blob The blob to be encoded
+ *
+ * @return bool success
+ */
+ public function blobEncode( $blob )
{
$blobid = fbird_blob_create( $this->_connectionID);
fbird_blob_add( $blobid, $blob );
return fbird_blob_close( $blobid );
}
- // since we auto-decode all blob's since 2.42,
- // BlobDecode should not do any transforms
- function BlobDecode($blob)
+ /**
+ * Manually decode a blob
+ *
+ * since we auto-decode all blob's since 2.42,
+ * BlobDecode should not do any transforms
+ *
+ * @param string $blob
+ *
+ * @return string the same blob
+ */
+ public function blobDecode($blob)
{
return $blob;
}
- // old blobdecode function
- // still used to auto-decode all blob's
- function _BlobDecode_old( $blob )
- {
- $blobid = fbird_blob_open($this->_connectionID, $blob );
- $realblob = fbird_blob_get( $blobid,$this->maxblobsize); // 2nd param is max size of blob -- Kevin Boillet <kevinboillet@yahoo.fr>
- while($string = fbird_blob_get($blobid, 8192)){
- $realblob .= $string;
- }
- fbird_blob_close( $blobid );
-
- return( $realblob );
- }
- function _BlobDecode( $blob )
+ /**
+ * Auto function called on read of blob to decode
+ *
+ * @param string $blob Value to decode
+ *
+ * @return string Decoded blob
+ */
+ public function _blobDecode( $blob )
{
+
$blob_data = fbird_blob_info($this->_connectionID, $blob );
$blobid = fbird_blob_open($this->_connectionID, $blob );
@@ -598,10 +803,24 @@ class ADODB_firebird extends ADOConnection {
return( $realblob );
}
- function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
+ /**
+ * Insert blob data into a database column directly
+ * from file
+ *
+ * @param string $table table to insert
+ * @param string $column column to insert
+ * @param string $path physical file name
+ * @param string $where string to find unique record
+ * @param string $blobtype BLOB or CLOB
+ *
+ * @return bool success
+ */
+ public function updateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
{
$fd = fopen($path,'rb');
- if ($fd === false) return false;
+ if ($fd === false)
+ return false;
+
$blob_id = fbird_blob_create($this->_connectionID);
/* fill with data */
@@ -617,105 +836,106 @@ class ADODB_firebird extends ADOConnection {
return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
}
- /*
- Insert a null into the blob field of the table first.
- Then use UpdateBlob to store the blob.
-
- Usage:
-
- $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
- $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
- */
- function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ /**
+ * Insert blob data into a database column
+ *
+ * @param string $table table to insert
+ * @param string $column column to insert
+ * @param string $val value to insert
+ * @param string $where string to find unique record
+ * @param string $blobtype BLOB or CLOB
+ *
+ * @return bool success
+ */
+ public function updateBlob($table,$column,$val,$where,$blobtype='BLOB')
{
- $blob_id = fbird_blob_create($this->_connectionID);
+ $blob_id = fbird_blob_create($this->_connectionID);
- // fbird_blob_add($blob_id, $val);
+ // fbird_blob_add($blob_id, $val);
- // replacement that solves the problem by which only the first modulus 64K /
- // of $val are stored at the blob field ////////////////////////////////////
- // Thx Abel Berenstein aberenstein#afip.gov.ar
- $len = strlen($val);
- $chunk_size = 32768;
- $tail_size = $len % $chunk_size;
- $n_chunks = ($len - $tail_size) / $chunk_size;
+ // replacement that solves the problem by which only the first modulus 64K /
+ // of $val are stored at the blob field ////////////////////////////////////
+ // Thx Abel Berenstein aberenstein#afip.gov.ar
+ $len = strlen($val);
+ $chunk_size = 32768;
+ $tail_size = $len % $chunk_size;
+ $n_chunks = ($len - $tail_size) / $chunk_size;
- for ($n = 0; $n < $n_chunks; $n++) {
- $start = $n * $chunk_size;
- $data = substr($val, $start, $chunk_size);
- fbird_blob_add($blob_id, $data);
- }
+ for ($n = 0; $n < $n_chunks; $n++) {
+ $start = $n * $chunk_size;
+ $data = substr($val, $start, $chunk_size);
+ fbird_blob_add($blob_id, $data);
+ }
- if ($tail_size) {
- $start = $n_chunks * $chunk_size;
- $data = substr($val, $start, $tail_size);
- fbird_blob_add($blob_id, $data);
- }
- // end replacement /////////////////////////////////////////////////////////
+ if ($tail_size) {
+ $start = $n_chunks * $chunk_size;
+ $data = substr($val, $start, $tail_size);
+ fbird_blob_add($blob_id, $data);
+ }
+ // end replacement /////////////////////////////////////////////////////////
- $blob_id_str = fbird_blob_close($blob_id);
+ $blob_id_str = fbird_blob_close($blob_id);
- return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
+ return $this->execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
}
- function OldUpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ /**
+ * Returns a portably-formatted date string from a timestamp database column.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:sqldate
+ *
+ * Firebird does not support an AM/PM format, so the A indicator always shows AM
+ *
+ * @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 string The SQL DATE_FORMAT() string, or empty if the provided date format was empty.
+ */
+ public function sqlDate($fmt, $col=false)
{
- $blob_id = fbird_blob_create($this->_connectionID);
- fbird_blob_add($blob_id, $val);
- $blob_id_str = fbird_blob_close($blob_id);
- return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
- }
+ if (!$col)
+ $col = 'CURRENT_TIMESTAMP';
- // Format date column in sql string given an input format that understands Y M D
- // Only since Interbase 6.0 - uses EXTRACT
- // problem - does not zero-fill the day and month yet
- function SQLDate($fmt, $col=false)
- {
- if (!$col) $col = $this->sysDate;
$s = '';
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
if ($s) $s .= '||';
$ch = $fmt[$i];
- switch($ch) {
+ $choice = strtoupper($ch);
+ switch($choice) {
case 'Y':
- case 'y':
- $s .= "extract(year from $col)";
+ $s .= "EXTRACT(YEAR FROM $col)";
break;
case 'M':
- case 'm':
- $s .= "extract(month from $col)";
+ $s .= "RIGHT('0' || TRIM(EXTRACT(MONTH FROM $col)),2)";
break;
case 'W':
- case 'w':
// The more accurate way of doing this is with a stored procedure
// See http://wiki.firebirdsql.org/wiki/index.php?page=DATE+Handling+Functions for details
- $s .= "((extract(yearday from $col) - extract(weekday from $col - 1) + 7) / 7)";
+ $s .= "((EXTRACT(YEARDAY FROM $col) - EXTRACT(WEEKDAY FROM $col - 1) + 7) / 7)";
break;
case 'Q':
- case 'q':
- $s .= "cast(((extract(month from $col)+2) / 3) as integer)";
+ $s .= "CAST(((EXTRACT(MONTH FROM $col)+2) / 3) AS INTEGER)";
break;
case 'D':
- case 'd':
- $s .= "(extract(day from $col))";
+ $s .= "RIGHT('0' || TRIM(EXTRACT(DAY FROM $col)),2)";
break;
case 'H':
- case 'h':
- $s .= "(extract(hour from $col))";
+ $s .= "RIGHT('0' || TRIM(EXTRACT(HOUR FROM $col)),2)";
break;
case 'I':
- case 'i':
- $s .= "(extract(minute from $col))";
+ $s .= "RIGHT('0' || TRIM(EXTRACT(MINUTE FROM $col)),2)";
break;
case 'S':
- case 's':
- $s .= "CAST((extract(second from $col)) AS INTEGER)";
+ //$s .= "CAST((EXTRACT(SECOND FROM $col)) AS INTEGER)";
+ $s .= "RIGHT('0' || TRIM(EXTRACT(SECOND FROM $col)),2)";
+ break;
+ case 'A':
+ $s .= $this->qstr('AM');
break;
-
default:
if ($ch == '\\') {
$i++;
@@ -728,10 +948,44 @@ class ADODB_firebird extends ADOConnection {
return $s;
}
+ /**
+ * Creates a portable date offset field, for use in SQL statements.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:offsetdate
+ *
+ * @param float $dayFraction A day in floating point
+ * @param string|bool $date (Optional) The date to offset. If false, uses CURDATE()
+ *
+ * @return string
+ */
+ public function offsetDate($dayFraction, $date=false)
+ {
+ if (!$date)
+ $date = $this->sysTimeStamp;
+
+ $fraction = $dayFraction * 24 * 3600;
+ return sprintf("DATEADD (second, %s, %s) FROM RDB\$DATABASE",$fraction,$date);
+ }
+
+
// Note that Interbase 6.5 uses this ROWS instead - don't you love forking wars!
// SELECT col1, col2 FROM table ROWS 5 -- get 5 rows
// SELECT col1, col2 FROM TABLE ORDER BY col1 ROWS 3 TO 7 -- first 5 skip 2
- function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false, $secs=0)
+ /**
+ * Executes a provided SQL statement and returns a handle to the result, with the ability to supply a starting
+ * offset and record count.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:selectlimit
+ *
+ * @param string $sql The SQL to execute.
+ * @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 $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.
+ */
+ public function selectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false, $secs2cache=0)
{
$nrows = (integer) $nrows;
$offset = (integer) $offset;
@@ -740,46 +994,89 @@ class ADODB_firebird extends ADOConnection {
$str .=($offset>=0) ? "SKIP $offset " : '';
$sql = preg_replace('/^[ \t]*select/i',$str,$sql);
- if ($secs)
- $rs = $this->CacheExecute($secs,$sql,$inputarr);
+ if ($secs2cache)
+ $rs = $this->cacheExecute($secs2cache,$sql,$inputarr);
else
- $rs = $this->Execute($sql,$inputarr);
+ $rs = $this->execute($sql,$inputarr);
return $rs;
}
}
-/*--------------------------------------------------------------------------------------
- Class Name: Recordset
---------------------------------------------------------------------------------------*/
-
-class ADORecordset_firebird extends ADORecordSet
+/**
+ * Class ADORecordset_firebird
+ */
+class ADORecordset_firebird extends ADORecordSet
{
-
var $databaseType = "firebird";
- var $bind=false;
- var $_cacheType;
+ var $bind = false;
+
+ /**
+ * @var ADOFieldObject[] Holds a cached version of the metadata
+ */
+ private $fieldObjects = false;
- function __construct($id,$mode=false)
+ /**
+ * @var bool Flags if we have retrieved the metadata
+ */
+ private $fieldObjectsRetrieved = false;
+
+ /**
+ * @var array Cross-reference the objects by name for easy access
+ */
+ private $fieldObjectsIndex = array();
+
+ /**
+ * @var bool Flag to indicate if the result has a blob
+ */
+ private $fieldObjectsHaveBlob = false;
+
+ function __construct($id, $mode = false)
{
- global $ADODB_FETCH_MODE;
+ global $ADODB_FETCH_MODE;
- $this->fetchMode = ($mode === false) ? $ADODB_FETCH_MODE : $mode;
- parent::__construct($id);
+ $this->fetchMode = ($mode === false) ? $ADODB_FETCH_MODE : $mode;
+ parent::__construct($id);
}
+
/**
- * Get column information in the Recordset object.
- * fetchField() can be used in order to obtain information about fields in
- * a certain query result. If the field offset isn't specified, the next
- * field that wasn't yet retrieved by fetchField() is retrieved.
- * @return object containing field information.
- */
- function FetchField($fieldOffset = -1)
+ * Returns: an object containing field information.
+ *
+ * Get column information in the Recordset object. fetchField()
+ * can be used in order to obtain information about fields in a
+ * certain query result. If the field offset isn't specified,
+ * the next field that wasn't yet retrieved by fetchField()
+ * is retrieved.
+ *
+ * $param int $fieldOffset (optional default=-1 for all
+ * @return mixed an ADOFieldObject, or array of objects
+ */
+ private function _fetchField($fieldOffset = -1)
{
+ if ($this->fieldObjectsRetrieved) {
+ if ($this->fieldObjects) {
+ // Already got the information
+ if ($fieldOffset == -1) {
+ return $this->fieldObjects;
+ } else {
+ return $this->fieldObjects[$fieldOffset];
+ }
+ } else {
+ // No metadata available
+ return false;
+ }
+ }
+
+ $this->fieldObjectsRetrieved = true;
+ $this->fieldObjectsHaveBlob = false;
+
+ $this->_numOfFields = fbird_num_fields($this->_queryID);
+ for ($fieldOffset = 0; $fieldOffset < $this->_numOfFields; $fieldOffset++) {
+
$fld = new ADOFieldObject;
- $ibf = fbird_field_info($this->_queryID,$fieldOffset);
+ $ibf = fbird_field_info($this->_queryID, $fieldOffset);
$name = empty($ibf['alias']) ? $ibf['name'] : $ibf['alias'];
@@ -799,23 +1096,55 @@ class ADORecordset_firebird extends ADORecordSet
$fld->type = $ibf['type'];
$fld->max_length = $ibf['length'];
- /* This needs to be populated from the metadata */
+ // This needs to be populated from the metadata
$fld->not_null = false;
$fld->has_default = false;
$fld->default_value = 'null';
- return $fld;
+
+ $this->fieldObjects[$fieldOffset] = $fld;
+
+ $this->fieldObjectsIndex[$fld->name] = $fieldOffset;
+
+ if ($fld->type == 'BLOB') {
+ $this->fieldObjectsHaveBlob = true;
+ }
+ }
+
+ if ($fieldOffset == -1) {
+ return $this->fieldObjects;
+ }
+
+ return $this->fieldObjects[$fieldOffset];
+ }
+
+ /**
+ * Fetchfield copies the oracle method, it loads the field information
+ * into the _fieldobjs array once, to save multiple calls to the
+ * fbird_ function
+ *
+ * @param int $fieldOffset (optional)
+ *
+ * @return adoFieldObject|false
+ */
+ public function fetchField($fieldOffset = -1)
+ {
+ if ($fieldOffset == -1) {
+ return $this->fieldObjects;
+ }
+
+ return $this->fieldObjects[$fieldOffset];
}
function _initrs()
{
$this->_numOfRows = -1;
- $this->_numOfFields = @fbird_num_fields($this->_queryID);
- // cache types for blob decode check
- for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
- $f1 = $this->FetchField($i);
- $this->_cacheType[] = $f1->type;
- }
+ /*
+ * Retrieve all of the column information first. We copy
+ * this method from oracle
+ */
+ $this->_fetchField();
+
}
function _seek($row)
@@ -823,9 +1152,30 @@ class ADORecordset_firebird extends ADORecordSet
return false;
}
- function _fetch()
+ public function _fetch()
{
- $f = @fbird_fetch_row($this->_queryID);
+ $localNumeric = true;
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ // Handle either associative or fetch both
+ $localNumeric = false;
+
+ $f = @fbird_fetch_assoc($this->_queryID);
+ if (is_array($f)) {
+ // Optimally do the case_upper or case_lower
+ if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_LOWER) {
+ $f = array_change_key_case($f, CASE_LOWER);
+ } else {
+ if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_UPPER) {
+ $f = array_change_key_case($f, CASE_UPPER);
+ }
+ }
+
+ }
+ } else {
+ // Numeric result
+ $f = @fbird_fetch_row($this->_queryID);
+ }
+
if ($f === false) {
$this->fields = false;
return false;
@@ -834,86 +1184,143 @@ class ADORecordset_firebird extends ADORecordSet
// fix missing nulls and decode blobs automatically
global $ADODB_ANSI_PADDING_OFF;
- //$ADODB_ANSI_PADDING_OFF=1;
$rtrim = !empty($ADODB_ANSI_PADDING_OFF);
- for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
- if ($this->_cacheType[$i]=="BLOB") {
- if (isset($f[$i])) {
- $f[$i] = $this->connection->_BlobDecode($f[$i]);
+ /*
+ * Fix missing nulls, not sure why they would be missing
+ *
+ *
+ $nullTemplate = array_fill(0,$this->_numOfFields,null);
+ */
+ /*
+ * Retrieved record is always numeric, use array_replace
+ * to inject missing keys
+ */
+ //$f = array_replace($nullTemplate,$f);
+
+ /*
+ * For optimal performance, only process if there
+ * is a possiblity of something to do
+ */
+ if ($this->fieldObjectsHaveBlob || $rtrim) {
+ /*
+ * Create a closure for an efficient method of
+ * iterating over the elements
+ */
+ $localFieldObjects = $this->fieldObjects;
+ $localFieldObjectIndex = $this->fieldObjectsIndex;
+ $localConnection = &$this->connection;
+
+ $rowTransform = function ($value, $key) use (
+ &$f,
+ $rtrim,
+ $localFieldObjects,
+ $localConnection,
+ $localNumeric,
+ $localFieldObjectIndex
+ ) {
+ if ($localNumeric) {
+ $localKey = $key;
} else {
- $f[$i] = null;
+ // Cross reference the associative key back to numeric
+ $localKey = $localFieldObjectIndex[strtolower($key)];
}
- } else {
- if (!isset($f[$i])) {
- $f[$i] = null;
- } else if ($rtrim && is_string($f[$i])) {
- $f[$i] = rtrim($f[$i]);
+
+ // As we iterate the elements check for blobs and padding
+ if ($localFieldObjects[$localKey]->type == 'BLOB') {
+ $f[$key] = $localConnection->_BlobDecode($value);
+ } else {
+ if ($rtrim && is_string($value)) {
+ $f[$key] = rtrim($value);
+ }
}
- }
+
+ };
+ // Walk the array, applying the above closure
+ array_walk($f, $rowTransform);
}
- // OPN stuff end
- $this->fields = $f;
- if ($this->fetchMode == ADODB_FETCH_ASSOC) {
- $this->fields = $this->GetRowAssoc();
- } else if ($this->fetchMode == ADODB_FETCH_BOTH) {
- $this->fields = array_merge($this->fields,$this->GetRowAssoc());
+ if (!$localNumeric && $this->fetchMode & ADODB_FETCH_NUM) {
+ // Creates a fetch both
+ $fNum = array_values($f);
+ $f = array_merge($f, $fNum);
}
+
+ $this->fields = $f;
+
return true;
}
- /* Use associative array to get fields array */
- function Fields($colname)
+ /**
+ * Get the value of a field in the current row by column name.
+ * Will not work if ADODB_FETCH_MODE is set to ADODB_FETCH_NUM.
+ *
+ * @param string $colname is the field to access
+ *
+ * @return mixed the value of $colname column
+ */
+ public function fields($colname)
{
- if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ return $this->fields[$colname];
+ }
+
if (!$this->bind) {
- $this->bind = array();
- for ($i=0; $i < $this->_numOfFields; $i++) {
- $o = $this->FetchField($i);
- $this->bind[strtoupper($o->name)] = $i;
- }
+ // fieldsObjectIndex populated by the recordset load
+ $this->bind = array_change_key_case($this->fieldObjectsIndex, CASE_UPPER);
}
return $this->fields[$this->bind[strtoupper($colname)]];
-
}
function _close()
{
- return @fbird_free_result($this->_queryID);
+ return @fbird_free_result($this->_queryID);
}
- function MetaType($t,$len=-1,$fieldobj=false)
+ public function metaType($t, $len = -1, $fieldobj = false)
{
if (is_object($t)) {
$fieldobj = $t;
$t = $fieldobj->type;
$len = $fieldobj->max_length;
}
- switch (strtoupper($t)) {
- case 'CHAR':
- return 'C';
- case 'TEXT':
- case 'VARCHAR':
- case 'VARYING':
- if ($len <= $this->blobSize) return 'C';
- return 'X';
- case 'BLOB':
- return 'B';
+ $t = strtoupper($t);
+
+ if (array_key_exists($t, $this->connection->customActualTypes)) {
+ return $this->connection->customActualTypes[$t];
+ }
- case 'TIMESTAMP':
- case 'DATE': return 'D';
- case 'TIME': return 'T';
- //case 'T': return 'T';
+ switch ($t) {
+ case 'CHAR':
+ return 'C';
- //case 'L': return 'L';
- case 'INT':
- case 'SHORT':
- case 'INTEGER': return 'I';
- default: return ADODB_DEFAULT_METATYPE;
+ case 'TEXT':
+ case 'VARCHAR':
+ case 'VARYING':
+ if ($len <= $this->blobSize) {
+ return 'C';
+ }
+ return 'X';
+ case 'BLOB':
+ return 'B';
+
+ case 'TIMESTAMP':
+ case 'DATE':
+ return 'D';
+ case 'TIME':
+ return 'T';
+ //case 'T': return 'T';
+
+ //case 'L': return 'L';
+ case 'INT':
+ case 'SHORT':
+ case 'INTEGER':
+ return 'I';
+ default:
+ return ADODB_DEFAULT_METATYPE;
}
}
diff --git a/drivers/adodb-ibase.inc.php b/drivers/adodb-ibase.inc.php
index 69de30dc..81ab29b5 100644
--- a/drivers/adodb-ibase.inc.php
+++ b/drivers/adodb-ibase.inc.php
@@ -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';
diff --git a/drivers/adodb-mssqlnative.inc.php b/drivers/adodb-mssqlnative.inc.php
index 36dc5433..6d6a0068 100644
--- a/drivers/adodb-mssqlnative.inc.php
+++ b/drivers/adodb-mssqlnative.inc.php
@@ -1008,6 +1008,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);
+
+ }
}
diff --git a/drivers/adodb-mysql.inc.php b/drivers/adodb-mysql.inc.php
index f07c081b..ed5570c9 100644
--- a/drivers/adodb-mysql.inc.php
+++ b/drivers/adodb-mysql.inc.php
@@ -869,9 +869,15 @@ class ADORecordSet_mysql 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; // mysql max_length is not accurate
- switch (strtoupper($t)) {
+
+ switch ($t) {
case 'STRING':
case 'CHAR':
case 'VARCHAR':
diff --git a/drivers/adodb-mysqli.inc.php b/drivers/adodb-mysqli.inc.php
index 160f5fa3..4364c9e2 100644
--- a/drivers/adodb-mysqli.inc.php
+++ b/drivers/adodb-mysqli.inc.php
@@ -81,6 +81,8 @@ class ADODB_mysqli extends ADOConnection {
*/
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,7 +125,7 @@ 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
@@ -202,6 +204,8 @@ 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;
@@ -574,7 +578,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)) {
@@ -856,7 +860,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);
@@ -1052,6 +1056,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 +1085,73 @@ 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) {
+ return $this->_execute($sql,false);
+ }
+
+ if (!is_array($inputarr)) {
+ $inputarr = array($inputarr);
+ }
+
+ if (!is_array($sql)) {
+ $typeString = '';
+ $typeArray = array(''); //placeholder for type list
+
+ foreach ($inputarr as $v) {
+ $typeArray[] = $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
+ $typeArray[0] = $typeString;
+
+ $ret = $this->_execute($sql,$typeArray);
+ if (!$ret) {
+ return $ret;
+ }
+ } else {
+ $ret = $this->_execute($sql,$inputarr);
+ }
+ return $ret;
+ }
+
+ /**
+ * Return the query id.
+ *
+ * @param string|array $sql
+ * @param array $inputarr
+ *
+ * @return bool|mysqli_result
+ */
function _query($sql, $inputarr)
{
global $ADODB_COUNTRECS;
@@ -1121,6 +1186,91 @@ class ADODB_mysqli extends ADOConnection {
$ret = mysqli_stmt_execute($stmt);
return $ret;
}
+ 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;
+
+ /*
+ * 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 != count($inputarr) - 1) {
+ $this->outp_throw(
+ "Input array has " . count($inputarr) .
+ " params, does not match query: '" . htmlspecialchars($sql) . "'",
+ 'Execute'
+ );
+ return false;
+ }
+
+ /*
+ * Must pass references into call_user_func_array
+ */
+ $paramsByReference = array();
+ foreach($inputarr as $key => $value) {
+ $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;
+
+ /*
+ * Is the statement a non-select
+ */
+ if ($stmt->affected_rows > -1)
+ {
+ $this->statementAffectedRows = $stmt->affected_rows;
+ return true;
+ }
+ /*
+ * Turn the statement into a result set
+ */
+ $result = $stmt->get_result();
+ /*
+ * Return the object for the select
+ */
+ return $result;
+
+ }
else
{
/*
@@ -1524,6 +1674,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 +1695,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 +1703,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 +1790,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 +1822,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':
diff --git a/drivers/adodb-oci8.inc.php b/drivers/adodb-oci8.inc.php
index e541b6b6..4dc93b1c 100644
--- a/drivers/adodb-oci8.inc.php
+++ b/drivers/adodb-oci8.inc.php
@@ -1809,8 +1809,13 @@ class ADORecordset_oci8 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];
- switch (strtoupper($t)) {
+ switch ($t) {
case 'VARCHAR':
case 'VARCHAR2':
case 'CHAR':
diff --git a/drivers/adodb-pdo.inc.php b/drivers/adodb-pdo.inc.php
index cf8e4e26..7b676d3b 100644
--- a/drivers/adodb-pdo.inc.php
+++ b/drivers/adodb-pdo.inc.php
@@ -238,6 +238,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)
{
@@ -565,6 +585,7 @@ class ADODB_pdo extends ADOConnection {
$this->_driver->debug = $this->debug;
}
if ($inputarr) {
+
/*
* inputarr must be numeric
*/
diff --git a/drivers/adodb-pdo_oci.inc.php b/drivers/adodb-pdo_oci.inc.php
index 9a05ee6a..20b47def 100644
--- a/drivers/adodb-pdo_oci.inc.php
+++ b/drivers/adodb-pdo_oci.inc.php
@@ -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);
+ }
}
diff --git a/drivers/adodb-pdo_pgsql.inc.php b/drivers/adodb-pdo_pgsql.inc.php
index 0212d4fd..6c06ac10 100644
--- a/drivers/adodb-pdo_pgsql.inc.php
+++ b/drivers/adodb-pdo_pgsql.inc.php
@@ -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);
+ }
}
diff --git a/drivers/adodb-pdo_sqlite.inc.php b/drivers/adodb-pdo_sqlite.inc.php
index b62ca35e..dab1de99 100644
--- a/drivers/adodb-pdo_sqlite.inc.php
+++ b/drivers/adodb-pdo_sqlite.inc.php
@@ -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);
+ }
}
diff --git a/drivers/adodb-postgres64.inc.php b/drivers/adodb-postgres64.inc.php
index 9128467b..851b8b0a 100644
--- a/drivers/adodb-postgres64.inc.php
+++ b/drivers/adodb-postgres64.inc.php
@@ -1069,7 +1069,14 @@ 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':
diff --git a/drivers/adodb-sqlite3.inc.php b/drivers/adodb-sqlite3.inc.php
index 548727d8..7f945620 100644
--- a/drivers/adodb-sqlite3.inc.php
+++ b/drivers/adodb-sqlite3.inc.php
@@ -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
@@ -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;
@@ -697,4 +807,4 @@ class ADORecordset_sqlite3 extends ADORecordSet {
{
}
-}
+} \ No newline at end of file
diff --git a/perf/perf-postgres.inc.php b/perf/perf-postgres.inc.php
index 315c17f5..5ca19449 100644
--- a/perf/perf-postgres.inc.php
+++ b/perf/perf-postgres.inc.php
@@ -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);
diff --git a/perf/perf-sqlite3.inc.php b/perf/perf-sqlite3.inc.php
new file mode 100644
index 00000000..19198d5b
--- /dev/null
+++ b/perf/perf-sqlite3.inc.php
@@ -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;
+ }
+}
diff --git a/server.php b/server.php
deleted file mode 100644
index 76e757fd..00000000
--- a/server.php
+++ /dev/null
@@ -1,103 +0,0 @@
-<?php
-/**
- * ADOdb Proxy Server.
- *
- * @deprecated 5.21.0
- *
- * Security warning - use with extreme caution !
- * Depending on how it is setup, this feature can potentially expose the
- * database to attacks, particularly if used with a privileged user account.
- *
- * 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
- */
-
-/* Documentation on usage is at https://adodb.org/dokuwiki/doku.php?id=v5:proxy:proxy_index
- *
- * Legal query string parameters:
- *
- * sql = holds sql string
- * nrows = number of rows to return
- * offset = skip offset rows of data
- * fetch = $ADODB_FETCH_MODE
- *
- * example:
- *
- * http://localhost/php/server.php?sql=select+*+from+table&nrows=10&offset=2
- */
-
-
-/*
- * Define the IP address you want to accept requests from
- * as a security measure. If blank we accept anyone promisciously!
- */
-$ACCEPTIP = '127.0.0.1';
-
-/*
- * Connection parameters
- */
-$driver = 'mysqli';
-$host = 'localhost'; // DSN for odbc
-$uid = 'root';
-$pwd = 'garbase-it-is';
-$database = 'test';
-
-/*============================ DO NOT MODIFY BELOW HERE =================================*/
-// $sep must match csv2rs() in adodb.inc.php
-$sep = ' :::: ';
-
-include('./adodb.inc.php');
-include_once(ADODB_DIR.'/adodb-csvlib.inc.php');
-
-function err($s)
-{
- die('**** '.$s.' ');
-}
-
-///////////////////////////////////////// DEFINITIONS
-
-
-$remote = $_SERVER["REMOTE_ADDR"];
-
-
-if (!empty($ACCEPTIP))
- if ($remote != '127.0.0.1' && $remote != $ACCEPTIP)
- err("Unauthorised client: '$remote'");
-
-
-if (empty($_REQUEST['sql'])) err('No SQL');
-
-
-$conn = ADONewConnection($driver);
-
-if (!$conn->connect($host,$uid,$pwd,$database)) err($conn->errorNo(). $sep . $conn->errorMsg());
-$sql = $_REQUEST['sql'];
-
-if (isset($_REQUEST['fetch']))
- $ADODB_FETCH_MODE = $_REQUEST['fetch'];
-
-if (isset($_REQUEST['nrows'])) {
- $nrows = $_REQUEST['nrows'];
- $offset = isset($_REQUEST['offset']) ? $_REQUEST['offset'] : -1;
- $rs = $conn->selectLimit($sql,$nrows,$offset);
-} else
- $rs = $conn->execute($sql);
-if ($rs){
- //$rs->timeToLive = 1;
- echo _rs2serialize($rs,$conn,$sql);
- $rs->close();
-} else
- err($conn->errorNo(). $sep .$conn->errorMsg());
diff --git a/session/session_schema2.xml b/session/session_schema2.xml
index 89cb4f28..a8a1b229 100644
--- a/session/session_schema2.xml
+++ b/session/session_schema2.xml
@@ -1,37 +1,33 @@
<?xml version="1.0"?>
<schema version="0.3">
<table name="sessions2">
- <descr>table for ADOdb session-management</descr>
-
+ <descr>Table for ADOdb session management</descr>
<field name="SESSKEY" type="C" size="64">
- <descr>session key</descr>
+ <descr>Session key to identify a user's browser session.</descr>
<KEY/>
<NOTNULL/>
</field>
-
-
-
<field name="EXPIRY" type="T">
- <descr></descr>
+ <descr>Slightly redundant as it can be dynamically calculated by NOW() and MODIFIED field,
+ but it enables forcing a fixed timeout for specific sessions.
+ </descr>
<NOTNULL/>
</field>
-
- <field name="CREATED" type="T">
- <descr></descr>
+ <field name="CREATED" type="T">
+ <descr>New session creation Timestamp.</descr>
<NOTNULL/>
</field>
-
- <field name="MODIFIED" type="T">
- <descr></descr>
+ <field name="MODIFIED" type="T">
+ <descr>Timestamp which is usually updated when the user interacts with a site, to extend the expire time.</descr>
<NOTNULL/>
</field>
-
<field name="EXPIREREF" type="C" size="250">
- <descr></descr>
+ <descr>Usually a User Id or unique username of your application.
+ The name EXPIREREF is a bit weird, it may be better to call it USERREF?
+ </descr>
</field>
-
<field name="SESSDATA" type="XL">
- <descr></descr>
+ <descr>PHP's serialized session data or encrypted serialized session data.</descr>
<NOTNULL/>
</field>
</table>
diff --git a/tests/client.php b/tests/client.php
deleted file mode 100644
index 8452da40..00000000
--- a/tests/client.php
+++ /dev/null
@@ -1,208 +0,0 @@
-<html>
-<body bgcolor=white>
-<?php
-/**
- * ADOdb tests - Proxy client
- *
- * @link https://adodb.org/dokuwiki/doku.php?id=v5:proxy:proxy_index
- *
- * 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
- */
-
- echo PHP_VERSION,'<br>';
- var_dump(parse_url('odbc_mssql://userserver/'));
- die();
-
-include('../adodb.inc.php');
-include('../tohtml.inc.php');
-
- function send2server($url,$sql)
- {
- $url .= '?sql='.urlencode($sql);
- print "<p>$url</p>";
- $rs = csv2rs($url,$err);
- if ($err) print $err;
- return $rs;
- }
-
- function print_pre($s)
- {
- print "<pre>";print_r($s);print "</pre>";
- }
-
-
-$serverURL = 'http://localhost/php/phplens/adodb/server.php';
-$testhttp = false;
-
-$sql1 = "insertz into products (productname) values ('testprod 1')";
-$sql2 = "insert into products (productname) values ('testprod 1')";
-$sql3 = "insert into products (productname) values ('testprod 2')";
-$sql4 = "delete from products where productid>80";
-$sql5 = 'select * from products';
-
-if ($testhttp) {
- print "<a href=#c>Client Driver Tests</a><p>";
- print "<h3>Test Error</h3>";
- $rs = send2server($serverURL,$sql1);
- print_pre($rs);
- print "<hr />";
-
- print "<h3>Test Insert</h3>";
-
- $rs = send2server($serverURL,$sql2);
- print_pre($rs);
- print "<hr />";
-
- print "<h3>Test Insert2</h3>";
-
- $rs = send2server($serverURL,$sql3);
- print_pre($rs);
- print "<hr />";
-
- print "<h3>Test Delete</h3>";
-
- $rs = send2server($serverURL,$sql4);
- print_pre($rs);
- print "<hr />";
-
-
- print "<h3>Test Select</h3>";
- $rs = send2server($serverURL,$sql5);
- if ($rs) rs2html($rs);
-
- print "<hr />";
-}
-
-
-print "<a name=c><h1>CLIENT Driver Tests</h1>";
-$conn = ADONewConnection('csv');
-$conn->Connect($serverURL);
-$conn->debug = true;
-
-print "<h3>Bad SQL</h3>";
-
-$rs = $conn->Execute($sql1);
-
-print "<h3>Insert SQL 1</h3>";
-$rs = $conn->Execute($sql2);
-
-print "<h3>Insert SQL 2</h3>";
-$rs = $conn->Execute($sql3);
-
-print "<h3>Select SQL</h3>";
-$rs = $conn->Execute($sql5);
-if ($rs) rs2html($rs);
-
-print "<h3>Delete SQL</h3>";
-$rs = $conn->Execute($sql4);
-
-print "<h3>Select SQL</h3>";
-$rs = $conn->Execute($sql5);
-if ($rs) rs2html($rs);
-
-
-/* EXPECTED RESULTS FOR HTTP TEST:
-
-Test Insert
-http://localhost/php/adodb/server.php?sql=insert+into+products+%28productname%29+values+%28%27testprod%27%29
-
-adorecordset Object
-(
- [dataProvider] => native
- [fields] =>
- [blobSize] => 64
- [canSeek] =>
- [EOF] => 1
- [emptyTimeStamp] =>
- [emptyDate] =>
- [debug] =>
- [timeToLive] => 0
- [bind] =>
- [_numOfRows] => -1
- [_numOfFields] => 0
- [_queryID] => 1
- [_currentRow] => -1
- [_closed] =>
- [_inited] =>
- [sql] => insert into products (productname) values ('testprod')
- [affectedrows] => 1
- [insertid] => 81
-)
-
-
---------------------------------------------------------------------------------
-
-Test Insert2
-http://localhost/php/adodb/server.php?sql=insert+into+products+%28productname%29+values+%28%27testprod%27%29
-
-adorecordset Object
-(
- [dataProvider] => native
- [fields] =>
- [blobSize] => 64
- [canSeek] =>
- [EOF] => 1
- [emptyTimeStamp] =>
- [emptyDate] =>
- [debug] =>
- [timeToLive] => 0
- [bind] =>
- [_numOfRows] => -1
- [_numOfFields] => 0
- [_queryID] => 1
- [_currentRow] => -1
- [_closed] =>
- [_inited] =>
- [sql] => insert into products (productname) values ('testprod')
- [affectedrows] => 1
- [insertid] => 82
-)
-
-
---------------------------------------------------------------------------------
-
-Test Delete
-http://localhost/php/adodb/server.php?sql=delete+from+products+where+productid%3E80
-
-adorecordset Object
-(
- [dataProvider] => native
- [fields] =>
- [blobSize] => 64
- [canSeek] =>
- [EOF] => 1
- [emptyTimeStamp] =>
- [emptyDate] =>
- [debug] =>
- [timeToLive] => 0
- [bind] =>
- [_numOfRows] => -1
- [_numOfFields] => 0
- [_queryID] => 1
- [_currentRow] => -1
- [_closed] =>
- [_inited] =>
- [sql] => delete from products where productid>80
- [affectedrows] => 2
- [insertid] => 0
-)
-
-[more stuff deleted]
- .
- .
- .
-*/
diff --git a/tests/testdatabases.inc.php b/tests/testdatabases.inc.php
index 8c6358a4..84f0a3ce 100644
--- a/tests/testdatabases.inc.php
+++ b/tests/testdatabases.inc.php
@@ -32,7 +32,6 @@
<input type=checkbox name="testmysqli" value=1 <?php echo !empty($testmysqli) ? 'checked' : '' ?>> <b>MySQLi</b>
<br>
<td><input type=checkbox name="testsqlite" value=1 <?php echo !empty($testsqlite) ? 'checked' : '' ?>> <b>SQLite</b><br>
-<input type=checkbox name="testproxy" value=1 <?php echo !empty($testproxy) ? 'checked' : '' ?>> <b>MySQL Proxy</b><br>
<input type=checkbox name="testoracle" value=1 <?php echo !empty($testoracle) ? 'checked' : '' ?>> <b>Oracle (oci8)</b> <br>
<input type=checkbox name="testpostgres" value=1 <?php echo !empty($testpostgres) ? 'checked' : '' ?>> <b>PostgreSQL</b><br>
<input type=checkbox name="testpostgres9" value=1 <?php echo !empty($testpostgres9) ? 'checked' : '' ?>> <b>PostgreSQL 9</b><br>
@@ -325,18 +324,6 @@ if (!empty($testmysqlodbc)) { // MYSQL
else print "ERROR: MySQL test requires a MySQL server on localhost, userid='admin', password='', database='test'".'<BR>'.$db->ErrorMsg();
}
-if (!empty($testproxy)){
- $db = ADONewConnection('proxy');
- print "<h1>Connecting $db->databaseType...</h1>";
- $server = 'localhost';
-
- if ($db->PConnect('http://localhost/php/phplens/adodb/server.php'))
- testdb($db,
- "create table ADOXYZ (id int, firstname char(24), lastname char(24), created date) type=innodb");
- else print "ERROR: MySQL test requires a MySQL server on localhost, userid='admin', password='', database='test'".'<BR>'.$db->ErrorMsg();
-
-}
-
ADOLoadCode('oci805');
ADOLoadCode("oci8po");