";
+
+
+ Installation
+ ============
+ 1. Create a new database in MySQL or Access "sessions" like
+so:
+
+ create table sessions (
+ SESSKEY char(32) not null,
+ EXPIRY int(11) unsigned not null,
+ EXPIREREF varchar(64),
+ DATA CLOB,
+ primary key (sesskey)
+ );
+
+ 2. Then define the following parameters. You can either modify
+ this file, or define them before this file is included:
+
+ $ADODB_SESSION_DRIVER='database driver, eg. mysql or ibase';
+ $ADODB_SESSION_CONNECT='server to connect to';
+ $ADODB_SESSION_USER ='user';
+ $ADODB_SESSION_PWD ='password';
+ $ADODB_SESSION_DB ='database';
+ $ADODB_SESSION_TBL = 'sessions'
+
+ 3. Recommended is PHP 4.0.2 or later. There are documented
+session bugs in earlier versions of PHP.
+
+*/
+
+
+include_once('crypt.inc.php');
+
+if (!defined('_ADODB_LAYER')) {
+ include (dirname(__FILE__).'/adodb.inc.php');
+}
+
+ /* if database time and system time is difference is greater than this, then give warning */
+ define('ADODB_SESSION_SYNCH_SECS',60);
+
+if (!defined('ADODB_SESSION')) {
+
+ define('ADODB_SESSION',1);
+
+GLOBAL $ADODB_SESSION_CONNECT,
+ $ADODB_SESSION_DRIVER,
+ $ADODB_SESSION_USER,
+ $ADODB_SESSION_PWD,
+ $ADODB_SESSION_DB,
+ $ADODB_SESS_CONN,
+ $ADODB_SESS_LIFE,
+ $ADODB_SESS_DEBUG,
+ $ADODB_SESS_INSERT,
+ $ADODB_SESSION_EXPIRE_NOTIFY,
+ $ADODB_SESSION_TBL;
+
+ //$ADODB_SESS_DEBUG = true;
+
+ /* SET THE FOLLOWING PARAMETERS */
+if (empty($ADODB_SESSION_DRIVER)) {
+ $ADODB_SESSION_DRIVER='mysql';
+ $ADODB_SESSION_CONNECT='localhost';
+ $ADODB_SESSION_USER ='root';
+ $ADODB_SESSION_PWD ='';
+ $ADODB_SESSION_DB ='xphplens_2';
+}
+
+if (empty($ADODB_SESSION_TBL)){
+ $ADODB_SESSION_TBL = 'sessions';
+}
+
+if (empty($ADODB_SESSION_EXPIRE_NOTIFY)) {
+ $ADODB_SESSION_EXPIRE_NOTIFY = false;
+}
+
+function ADODB_Session_Key()
+{
+$ADODB_CRYPT_KEY = 'CRYPTED ADODB SESSIONS ROCK!';
+
+ /* USE THIS FUNCTION TO CREATE THE ENCRYPTION KEY FOR CRYPTED SESSIONS */
+ /* Crypt the used key, $ADODB_CRYPT_KEY as key and session_ID as SALT */
+ return crypt($ADODB_CRYPT_KEY, session_ID());
+}
+
+$ADODB_SESS_LIFE = ini_get('session.gc_maxlifetime');
+if ($ADODB_SESS_LIFE <= 1) {
+ // bug in PHP 4.0.3 pl 1 -- how about other versions?
+ //print "
";
```
@@ -61,14 +61,14 @@ print "";
Documentation and Examples
==========================
-Refer to the [ADOdb website](http://adodb.org/) for library documentation and examples. The documentation can also be [downloaded for offline viewing](https://sourceforge.net/projects/adodb/files/Documentation/).
+Refer to the [ADOdb website](https://adodb.org/) for library documentation and examples. The documentation can also be [downloaded for offline viewing](https://sourceforge.net/projects/adodb/files/Documentation/).
-- [Main documentation](http://adodb.org/dokuwiki/doku.php?id=v5:userguide:userguide_index): Query, update and insert records using a portable API.
-- [Data dictionary](http://adodb.org/dokuwiki/doku.php?id=v5:dictionary:dictionary_index) describes how to create database tables and indexes in a portable manner.
-- [Database performance monitoring](http://adodb.org/dokuwiki/doku.php?id=v5:performance:performance_index) allows you to perform health checks, tune and monitor your database.
-- [Database-backed sessions](http://adodb.org/dokuwiki/doku.php?id=v5:session:session_index).
+- [Main documentation](https://adodb.org/dokuwiki/doku.php?id=v5:userguide:userguide_index): Query, update and insert records using a portable API.
+- [Data dictionary](https://adodb.org/dokuwiki/doku.php?id=v5:dictionary:dictionary_index) describes how to create database tables and indexes in a portable manner.
+- [Database performance monitoring](https://adodb.org/dokuwiki/doku.php?id=v5:performance:performance_index) allows you to perform health checks, tune and monitor your database.
+- [Database-backed sessions](https://adodb.org/dokuwiki/doku.php?id=v5:session:session_index).
-There is also a [tutorial](http://adodb.org/dokuwiki/doku.php?id=v5:userguide:mysql_tutorial) that contrasts ADOdb code with PHP native MySQL code.
+There is also a [tutorial](https://adodb.org/dokuwiki/doku.php?id=v5:userguide:mysql_tutorial) that contrasts ADOdb code with PHP native MySQL code.
Files
diff --git a/adodb/adodb-active-record.inc.php b/adodb/adodb-active-record.inc.php
index 6b5df9c..8f3b005 100644
--- a/adodb/adodb-active-record.inc.php
+++ b/adodb/adodb-active-record.inc.php
@@ -1,23 +1,25 @@
$d) {
- if (PHP_VERSION >= 5) {
- if ($d->db === $db) {
- return $k;
- }
- } else {
- if ($d->db->_connectionID === $db->_connectionID && $db->database == $d->db->database) {
- return $k;
- }
- }
+ foreach($_ADODB_ACTIVE_DBS as $k => $d) {
+ if($d->db === $db) {
+ return $k;
}
+ }
- $obj = new ADODB_Active_DB();
- $obj->db = $db;
- $obj->tables = array();
+ $obj = new ADODB_Active_DB();
+ $obj->db = $db;
+ $obj->tables = array();
- if ($index == false) {
- $index = sizeof($_ADODB_ACTIVE_DBS);
- }
+ if ($index == false) {
+ $index = sizeof($_ADODB_ACTIVE_DBS);
+ }
- $_ADODB_ACTIVE_DBS[$index] = $obj;
+ $_ADODB_ACTIVE_DBS[$index] = $obj;
- return sizeof($_ADODB_ACTIVE_DBS)-1;
+ return sizeof($_ADODB_ACTIVE_DBS)-1;
}
class ADODB_Active_Record {
static $_changeNames = true; // dynamically pluralize table names
- static $_quoteNames = false;
+
+ /** @var bool|string Allows override of global $ADODB_QUOTE_FIELDNAMES */
+ public $_quoteNames;
static $_foreignSuffix = '_id'; //
var $_dbat; // associative index pointing to ADODB_Active_DB eg. $ADODB_Active_DBS[_dbat]
@@ -120,7 +118,12 @@ public function __set($name, $value)
// php5 constructor
function __construct($table = false, $pkeyarr=false, $db=false)
{
- global $_ADODB_ACTIVE_DBS;
+ global $_ADODB_ACTIVE_DBS, $ADODB_QUOTE_FIELDNAMES;
+
+ // Set the local override for field quoting, only if not defined yet
+ if (!isset($this->_quoteNames)) {
+ $this->_quoteNames = $ADODB_QUOTE_FIELDNAMES;
+ }
if ($db == false && is_object($pkeyarr)) {
$db = $pkeyarr;
@@ -499,7 +502,6 @@ function UpdateActiveTable($pkeys=false,$forceUpdate=false)
break;
default:
foreach($cols as $name => $fldobj) {
- $name = ($fldobj->name);
if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value)) {
$this->$name = $fldobj->default_value;
@@ -522,7 +524,7 @@ function UpdateActiveTable($pkeys=false,$forceUpdate=false)
$activetab->_created = time();
$s = serialize($activetab);
if (!function_exists('adodb_write_file')) {
- include(ADODB_DIR.'/adodb-csvlib.inc.php');
+ include_once(ADODB_DIR.'/adodb-csvlib.inc.php');
}
adodb_write_file($fname,$s);
}
@@ -700,9 +702,14 @@ function LastInsertID(&$db,$fieldname)
$val = false;
}
- if (is_null($val) || $val === false) {
+ if (is_null($val) || $val === false)
+ {
+ $SQL = sprintf("SELECT MAX(%s) FROM %s",
+ $this->nameQuoter($db,$fieldname),
+ $this->nameQuoter($db,$this->_table)
+ );
// this might not work reliably in multi-user environment
- return $db->GetOne("select max(".$fieldname.") from ".$this->_table);
+ return $db->GetOne($SQL);
}
return $val;
}
@@ -749,10 +756,11 @@ function GenWhere(&$db, &$table)
foreach($keys as $k) {
$f = $table->flds[$k];
if ($f) {
- $parr[] = $k.' = '.$this->doquote($db,$this->$k,$db->MetaType($f->type));
+ $columnName = $this->nameQuoter($db,$k);
+ $parr[] = $columnName.' = '.$this->doquote($db,$this->$k,$db->MetaType($f->type));
}
}
- return implode(' and ', $parr);
+ return implode(' AND ', $parr);
}
@@ -774,7 +782,7 @@ function _QName($n,$db=false)
function Load($where=null,$bindarr=false, $lock = false)
{
- global $ADODB_FETCH_MODE;
+ global $ADODB_FETCH_MODE;
$db = $this->DB();
if (!$db) {
@@ -788,7 +796,9 @@ function Load($where=null,$bindarr=false, $lock = false)
$savem = $db->SetFetchMode(false);
}
- $qry = "select * from ".$this->_table;
+ $qry = sprintf("SELECT * FROM %s",
+ $this->nameQuoter($db,$this->_table)
+ );
if($where) {
$qry .= ' WHERE '.$where;
@@ -862,7 +872,7 @@ function Insert()
$val = $this->$name;
if(!is_array($val) || !is_null($val) || !array_key_exists($name, $table->keys)) {
$valarr[] = $val;
- $names[] = $this->_QName($name,$db);
+ $names[] = $this->nameQuoter($db,$name);
$valstr[] = $db->Param($cnt);
$cnt += 1;
}
@@ -871,12 +881,18 @@ function Insert()
if (empty($names)){
foreach($table->flds as $name=>$fld) {
$valarr[] = null;
- $names[] = $name;
+ $names[] = $this->nameQuoter($db,$name);
$valstr[] = $db->Param($cnt);
$cnt += 1;
}
}
- $sql = 'INSERT INTO '.$this->_table."(".implode(',',$names).') VALUES ('.implode(',',$valstr).')';
+
+ $tableName = $this->nameQuoter($db,$this->_table);
+ $sql = sprintf('INSERT INTO %s (%s) VALUES (%s)',
+ $tableName,
+ implode(',',$names),
+ implode(',',$valstr)
+ );
$ok = $db->Execute($sql,$valarr);
if ($ok) {
@@ -907,7 +923,14 @@ function Delete()
$table = $this->TableInfo();
$where = $this->GenWhere($db,$table);
- $sql = 'DELETE FROM '.$this->_table.' WHERE '.$where;
+
+ $tableName = $this->nameQuoter($db,$this->_table);
+
+ $sql = sprintf('DELETE FROM %s WHERE %s',
+ $tableName,
+ $where
+ );
+
$ok = $db->Execute($sql);
return $ok ? true : false;
@@ -979,7 +1002,19 @@ function Replace()
break;
}
- $ok = $db->Replace($this->_table,$arr,$pkey);
+ $newArr = array();
+ foreach($arr as $k=>$v)
+ $newArr[$this->nameQuoter($db,$k)] = $v;
+ $arr = $newArr;
+
+ $newPkey = array();
+ foreach($pkey as $k=>$v)
+ $newPkey[$k] = $this->nameQuoter($db,$v);
+ $pkey = $newPkey;
+
+ $tableName = $this->nameQuoter($db,$this->_table);
+
+ $ok = $db->Replace($tableName,$arr,$pkey);
if ($ok) {
$this->_saved = true; // 1= update 2=insert
if ($ok == 2) {
@@ -1051,7 +1086,7 @@ function Update()
}
$valarr[] = $val;
- $pairs[] = $this->_QName($name,$db).'='.$db->Param($cnt);
+ $pairs[] = $this->nameQuoter($db,$name).'='.$db->Param($cnt);
$cnt += 1;
}
@@ -1060,7 +1095,13 @@ function Update()
return -1;
}
- $sql = 'UPDATE '.$this->_table." SET ".implode(",",$pairs)." WHERE ".$where;
+ $tableName = $this->nameQuoter($db,$this->_table);
+
+ $sql = sprintf('UPDATE %s SET %s WHERE %s',
+ $tableName,
+ implode(',',$pairs),
+ $where);
+
$ok = $db->Execute($sql,$valarr);
if ($ok) {
$this->_original = $neworig;
@@ -1078,6 +1119,31 @@ function GetAttributeNames()
return array_keys($table->flds);
}
+ /**
+ * Quotes the table, column and field names.
+ *
+ * This honours the internal {@see $_quoteNames} property, which overrides
+ * the global $ADODB_QUOTE_FIELDNAMES directive.
+ *
+ * @param ADOConnection $db The database connection
+ * @param string $name The table or column name to quote
+ *
+ * @return string The quoted name
+ */
+ private function nameQuoter($db, $name)
+ {
+ global $ADODB_QUOTE_FIELDNAMES;
+
+ $save = $ADODB_QUOTE_FIELDNAMES;
+ $ADODB_QUOTE_FIELDNAMES = $this->_quoteNames;
+
+ $string = _adodb_quote_fieldname($db, $name);
+
+ $ADODB_QUOTE_FIELDNAMES = $save;
+
+ return $string;
+ }
+
};
function adodb_GetActiveRecordsClass(&$db, $class, $table,$whereOrderBy,$bindarr, $primkeyArr,
@@ -1087,6 +1153,7 @@ function adodb_GetActiveRecordsClass(&$db, $class, $table,$whereOrderBy,$bindarr
$save = $db->SetFetchMode(ADODB_FETCH_NUM);
+
$qry = "select * from ".$table;
if (!empty($whereOrderBy)) {
@@ -1125,7 +1192,7 @@ function adodb_GetActiveRecordsClass(&$db, $class, $table,$whereOrderBy,$bindarr
// arrRef will be the structure that knows about our objects.
// It is an associative array.
// We will, however, return arr, preserving regular 0.. order so that
- // obj[0] can be used by app developpers.
+ // obj[0] can be used by app developers.
$arrRef = array();
$bTos = array(); // Will store belongTo's indices if any
foreach($rows as $row) {
diff --git a/adodb/adodb-active-recordx.inc.php b/adodb/adodb-active-recordx.inc.php
index 1f17206..5de5b13 100644
--- a/adodb/adodb-active-recordx.inc.php
+++ b/adodb/adodb-active-recordx.inc.php
@@ -1,27 +1,27 @@
$d) {
- if (PHP_VERSION >= 5) {
- if ($d->db === $db) {
- return $k;
- }
- } else {
- if ($d->db->_connectionID === $db->_connectionID && $db->database == $d->db->database) {
- return $k;
- }
- }
+ foreach($_ADODB_ACTIVE_DBS as $k => $d) {
+ if ($d->db === $db) {
+ return $k;
}
+ }
- $obj = new ADODB_Active_DB();
- $obj->db = $db;
- $obj->tables = array();
+ $obj = new ADODB_Active_DB();
+ $obj->db = $db;
+ $obj->tables = array();
- $_ADODB_ACTIVE_DBS[] = $obj;
+ $_ADODB_ACTIVE_DBS[] = $obj;
- return sizeof($_ADODB_ACTIVE_DBS)-1;
+ return sizeof($_ADODB_ACTIVE_DBS)-1;
}
@@ -551,7 +545,7 @@ function UpdateActiveTable($pkeys=false,$forceUpdate=false)
$activetab->_created = time();
$s = serialize($activetab);
if (!function_exists('adodb_write_file')) {
- include(ADODB_DIR.'/adodb-csvlib.inc.php');
+ include_once(ADODB_DIR.'/adodb-csvlib.inc.php');
}
adodb_write_file($fname,$s);
}
@@ -1298,7 +1292,7 @@ function adodb_GetActiveRecordsClass(&$db, $class, $tableObj,$whereOrderBy,$bind
if (!isset($_ADODB_ACTIVE_DBS)) {
- include(ADODB_DIR.'/adodb-active-record.inc.php');
+ include_once(ADODB_DIR.'/adodb-active-record.inc.php');
}
if (!class_exists($class)) {
$db->outp_throw("Unknown class $class in GetActiveRecordsClass()",'GetActiveRecordsClass');
@@ -1309,7 +1303,7 @@ function adodb_GetActiveRecordsClass(&$db, $class, $tableObj,$whereOrderBy,$bind
// arrRef will be the structure that knows about our objects.
// It is an associative array.
// We will, however, return arr, preserving regular 0.. order so that
- // obj[0] can be used by app developpers.
+ // obj[0] can be used by app developers.
$arrRef = array();
$bTos = array(); // Will store belongTo's indices if any
foreach($rows as $row) {
diff --git a/adodb/adodb-csvlib.inc.php b/adodb/adodb-csvlib.inc.php
index 356ff15..c81254b 100644
--- a/adodb/adodb-csvlib.inc.php
+++ b/adodb/adodb-csvlib.inc.php
@@ -1,4 +1,26 @@
$str";
-$a= Lens_ParseArgs($str);
+$a= lens_ParseArgs($str);
print "
";
print_r($a);
print "
";
@@ -53,7 +56,7 @@ function ctype_alnum($text) {
@param tokenchars Include the following characters in tokens apart from A-Z and 0-9
@returns 2 dimensional array containing parsed tokens.
*/
-function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-')
+function lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-')
{
$pos = 0;
$intoken = false;
@@ -164,6 +167,7 @@ function Lens_ParseArgs($args,$endstmtchar=',',$tokenchars='_.-')
class ADODB_DataDict {
+ /** @var ADOConnection */
var $connection;
var $debug = false;
var $dropTable = 'DROP TABLE %s';
@@ -179,45 +183,60 @@ class ADODB_DataDict {
var $serverInfo = array();
var $autoIncrement = false;
var $dataProvider;
- var $invalidResizeTypes4 = array('CLOB','BLOB','TEXT','DATE','TIME'); // for changetablesql
+ var $invalidResizeTypes4 = array('CLOB','BLOB','TEXT','DATE','TIME'); // for changeTableSQL
var $blobSize = 100; /// any varchar/char field this size or greater is treated as a blob
- /// in other words, we use a text area for editting.
+ /// in other words, we use a text area for editing.
+ /** @var string Uppercase driver name */
+ var $upperName;
+
+ /*
+ * Indicates whether a BLOB/CLOB field will allow a NOT NULL setting
+ * The type is whatever is matched to an X or X2 or B type. We must
+ * explicitly set the value in the driver to switch the behaviour on
+ */
+ public $blobAllowsNotNull;
+ /*
+ * Indicates whether a BLOB/CLOB field will allow a DEFAULT set
+ * The type is whatever is matched to an X or X2 or B type. We must
+ * explicitly set the value in the driver to switch the behaviour on
+ */
+ public $blobAllowsDefaultValue;
- function GetCommentSQL($table,$col)
+ function getCommentSQL($table,$col)
{
return false;
}
- function SetCommentSQL($table,$col,$cmt)
+ function setCommentSQL($table,$col,$cmt)
{
return false;
}
- function MetaTables()
+ function metaTables()
{
- if (!$this->connection->IsConnected()) return array();
- return $this->connection->MetaTables();
+ if (!$this->connection->isConnected()) return array();
+ return $this->connection->metaTables();
}
- function MetaColumns($tab, $upper=true, $schema=false)
+ function metaColumns($tab, $upper=true, $schema=false)
{
- if (!$this->connection->IsConnected()) return array();
- return $this->connection->MetaColumns($this->TableName($tab), $upper, $schema);
+ if (!$this->connection->isConnected()) return array();
+ return $this->connection->metaColumns($this->tableName($tab), $upper, $schema);
}
- function MetaPrimaryKeys($tab,$owner=false,$intkey=false)
+ function metaPrimaryKeys($tab,$owner=false,$intkey=false)
{
- if (!$this->connection->IsConnected()) return array();
- return $this->connection->MetaPrimaryKeys($this->TableName($tab), $owner, $intkey);
+ if (!$this->connection->isConnected()) return array();
+ return $this->connection->metaPrimaryKeys($this->tableName($tab), $owner, $intkey);
}
- function MetaIndexes($table, $primary = false, $owner = false)
+ function metaIndexes($table, $primary = false, $owner = false)
{
- if (!$this->connection->IsConnected()) return array();
- return $this->connection->MetaIndexes($this->TableName($table), $primary, $owner);
+ if (!$this->connection->isConnected()) return array();
+ return $this->connection->metaIndexes($this->tableName($table), $primary, $owner);
}
- function MetaType($t,$len=-1,$fieldobj=false)
+ function metaType($t,$len=-1,$fieldobj=false)
{
static $typeMap = array(
'VARCHAR' => 'C',
@@ -323,15 +342,15 @@ function MetaType($t,$len=-1,$fieldobj=false)
"SQLBOOL" => 'L'
);
- if (!$this->connection->IsConnected()) {
+ if (!$this->connection->isConnected()) {
$t = strtoupper($t);
if (isset($typeMap[$t])) return $typeMap[$t];
- return 'N';
+ return ADODB_DEFAULT_METATYPE;
}
- return $this->connection->MetaType($t,$len,$fieldobj);
+ return $this->connection->metaType($t,$len,$fieldobj);
}
- function NameQuote($name = NULL,$allowBrackets=false)
+ function nameQuote($name = NULL,$allowBrackets=false)
{
if (!is_string($name)) {
return FALSE;
@@ -360,16 +379,16 @@ function NameQuote($name = NULL,$allowBrackets=false)
return $name;
}
- function TableName($name)
+ function tableName($name)
{
if ( $this->schema ) {
- return $this->NameQuote($this->schema) .'.'. $this->NameQuote($name);
+ return $this->nameQuote($this->schema) .'.'. $this->nameQuote($name);
}
- return $this->NameQuote($name);
+ return $this->nameQuote($name);
}
- // Executes the sql array returned by GetTableSQL and GetIndexSQL
- function ExecuteSQLArray($sql, $continueOnError = true)
+ // Executes the sql array returned by getTableSQL and getIndexSQL
+ function executeSQLArray($sql, $continueOnError = true)
{
$rez = 2;
$conn = $this->connection;
@@ -377,10 +396,10 @@ function ExecuteSQLArray($sql, $continueOnError = true)
foreach($sql as $line) {
if ($this->debug) $conn->debug = true;
- $ok = $conn->Execute($line);
+ $ok = $conn->execute($line);
$conn->debug = $saved;
if (!$ok) {
- if ($this->debug) ADOConnection::outp($conn->ErrorMsg());
+ if ($this->debug) ADOConnection::outp($conn->errorMsg());
if (!$continueOnError) return 0;
$rez = 1;
}
@@ -406,17 +425,17 @@ function ExecuteSQLArray($sql, $continueOnError = true)
N: Numeric or decimal number
*/
- function ActualType($meta)
+ function actualType($meta)
{
return $meta;
}
- function CreateDatabase($dbname,$options=false)
+ function createDatabase($dbname,$options=false)
{
- $options = $this->_Options($options);
+ $options = $this->_options($options);
$sql = array();
- $s = 'CREATE DATABASE ' . $this->NameQuote($dbname);
+ $s = 'CREATE DATABASE ' . $this->nameQuote($dbname);
if (isset($options[$this->upperName]))
$s .= ' '.$options[$this->upperName];
@@ -427,7 +446,7 @@ function CreateDatabase($dbname,$options=false)
/*
Generates the SQL to create index. Returns an array of sql strings.
*/
- function CreateIndexSQL($idxname, $tabname, $flds, $idxoptions = false)
+ function createIndexSQL($idxname, $tabname, $flds, $idxoptions = false)
{
if (!is_array($flds)) {
$flds = explode(',',$flds);
@@ -435,27 +454,27 @@ function CreateIndexSQL($idxname, $tabname, $flds, $idxoptions = false)
foreach($flds as $key => $fld) {
# some indexes can use partial fields, eg. index first 32 chars of "name" with NAME(32)
- $flds[$key] = $this->NameQuote($fld,$allowBrackets=true);
+ $flds[$key] = $this->nameQuote($fld,$allowBrackets=true);
}
- return $this->_IndexSQL($this->NameQuote($idxname), $this->TableName($tabname), $flds, $this->_Options($idxoptions));
+ return $this->_indexSQL($this->nameQuote($idxname), $this->tableName($tabname), $flds, $this->_options($idxoptions));
}
- function DropIndexSQL ($idxname, $tabname = NULL)
+ function dropIndexSQL ($idxname, $tabname = NULL)
{
- return array(sprintf($this->dropIndex, $this->NameQuote($idxname), $this->TableName($tabname)));
+ return array(sprintf($this->dropIndex, $this->nameQuote($idxname), $this->tableName($tabname)));
}
- function SetSchema($schema)
+ function setSchema($schema)
{
$this->schema = $schema;
}
- function AddColumnSQL($tabname, $flds)
+ function addColumnSQL($tabname, $flds)
{
- $tabname = $this->TableName ($tabname);
+ $tabname = $this->tableName($tabname);
$sql = array();
- list($lines,$pkey,$idxs) = $this->_GenFields($flds);
+ list($lines,$pkey,$idxs) = $this->_genFields($flds);
// genfields can return FALSE at times
if ($lines == null) $lines = array();
$alter = 'ALTER TABLE ' . $tabname . $this->addCol . ' ';
@@ -464,7 +483,7 @@ function AddColumnSQL($tabname, $flds)
}
if (is_array($idxs)) {
foreach($idxs as $idx => $idxdef) {
- $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
+ $sql_idxs = $this->createIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
$sql = array_merge($sql, $sql_idxs);
}
}
@@ -474,19 +493,19 @@ function AddColumnSQL($tabname, $flds)
/**
* Change the definition of one column
*
- * As some DBM's can't do that on there own, you need to supply the complete defintion of the new table,
- * to allow, recreating the table and copying the content over to the new table
+ * As some DBMs can't do that on their 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 defintion of the new table, eg. for postgres, default ''
- * @param array/string $tableoptions='' options for the new table see CreateTableSQL, default ''
+ * @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 ''
* @return array with SQL strings
*/
- function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
+ 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,$pkey,$idxs) = $this->_genFields($flds);
// genfields can return FALSE at times
if ($lines == null) $lines = array();
$alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' ';
@@ -495,7 +514,7 @@ function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
}
if (is_array($idxs)) {
foreach($idxs as $idx => $idxdef) {
- $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
+ $sql_idxs = $this->createIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
$sql = array_merge($sql, $sql_idxs);
}
@@ -506,71 +525,71 @@ function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
/**
* Rename one column
*
- * Some DBM's can only do this together with changeing the type of the column (even if that stays the same, eg. mysql)
+ * Some DBMs can only do this together with changeing the type of the column (even if that stays the same, eg. mysql)
* @param string $tabname table-name
* @param string $oldcolumn column-name to be renamed
* @param string $newcolumn new column-name
- * @param string $flds='' complete column-defintion-string like for AddColumnSQL, only used by mysql atm., default=''
+ * @param string $flds='' complete column-definition-string like for addColumnSQL, only used by mysql atm., default=''
* @return array with SQL strings
*/
- function RenameColumnSQL($tabname,$oldcolumn,$newcolumn,$flds='')
+ function renameColumnSQL($tabname,$oldcolumn,$newcolumn,$flds='')
{
- $tabname = $this->TableName ($tabname);
+ $tabname = $this->tableName($tabname);
if ($flds) {
- list($lines,$pkey,$idxs) = $this->_GenFields($flds);
+ list($lines,$pkey,$idxs) = $this->_genFields($flds);
// genfields can return FALSE at times
if ($lines == null) $lines = array();
$first = current($lines);
list(,$column_def) = preg_split("/[\t ]+/",$first,2);
}
- return array(sprintf($this->renameColumn,$tabname,$this->NameQuote($oldcolumn),$this->NameQuote($newcolumn),$column_def));
+ return array(sprintf($this->renameColumn,$tabname,$this->nameQuote($oldcolumn),$this->nameQuote($newcolumn),$column_def));
}
/**
* Drop one column
*
- * Some DBM's can't do that on there own, you need to supply the complete defintion of the new table,
+ * Some DBM's can't do that on their 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 defintion of the new table, eg. for postgres, default ''
- * @param array/string $tableoptions='' options for the new table see CreateTableSQL, default ''
+ * @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 ''
* @return array with SQL strings
*/
- function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
+ function dropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
{
- $tabname = $this->TableName ($tabname);
+ $tabname = $this->tableName($tabname);
if (!is_array($flds)) $flds = explode(',',$flds);
$sql = array();
$alter = 'ALTER TABLE ' . $tabname . $this->dropCol . ' ';
foreach($flds as $v) {
- $sql[] = $alter . $this->NameQuote($v);
+ $sql[] = $alter . $this->nameQuote($v);
}
return $sql;
}
- function DropTableSQL($tabname)
+ function dropTableSQL($tabname)
{
- return array (sprintf($this->dropTable, $this->TableName($tabname)));
+ return array (sprintf($this->dropTable, $this->tableName($tabname)));
}
- function RenameTableSQL($tabname,$newname)
+ function renameTableSQL($tabname,$newname)
{
- return array (sprintf($this->renameTable, $this->TableName($tabname),$this->TableName($newname)));
+ return array (sprintf($this->renameTable, $this->tableName($tabname),$this->tableName($newname)));
}
/**
Generate the SQL to create table. Returns an array of sql strings.
*/
- function CreateTableSQL($tabname, $flds, $tableoptions=array())
+ 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();
- $taboptions = $this->_Options($tableoptions);
- $tabname = $this->TableName ($tabname);
- $sql = $this->_TableSQL($tabname,$lines,$pkey,$taboptions);
+ $taboptions = $this->_options($tableoptions);
+ $tabname = $this->tableName($tabname);
+ $sql = $this->_tableSQL($tabname,$lines,$pkey,$taboptions);
// ggiunta - 2006/10/12 - KLUDGE:
// if we are on autoincrement, and table options includes REPLACE, the
@@ -579,12 +598,12 @@ function CreateTableSQL($tabname, $flds, $tableoptions=array())
// creating sql that double-drops the sequence
if ($this->autoIncrement && isset($taboptions['REPLACE']))
unset($taboptions['REPLACE']);
- $tsql = $this->_Triggers($tabname,$taboptions);
+ $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']);
+ $sql_idxs = $this->createIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
$sql = array_merge($sql, $sql_idxs);
}
}
@@ -594,13 +613,13 @@ function CreateTableSQL($tabname, $flds, $tableoptions=array())
- function _GenFields($flds,$widespacing=false)
+ function _genFields($flds,$widespacing=false)
{
if (is_string($flds)) {
$padding = ' ';
$txt = $flds.$padding;
$flds = array();
- $flds0 = Lens_ParseArgs($txt,',');
+ $flds0 = lens_ParseArgs($txt,',');
$hasparam = false;
foreach($flds0 as $f0) {
$f1 = array();
@@ -643,8 +662,8 @@ function _GenFields($flds,$widespacing=false)
$pkey = array();
$idxs = array();
foreach($flds as $fld) {
- $fld = _array_change_key_case($fld);
-
+ if (is_array($fld))
+ $fld = array_change_key_case($fld,CASE_UPPER);
$fname = false;
$fdefault = false;
$fautoinc = false;
@@ -660,18 +679,23 @@ function _GenFields($flds,$widespacing=false)
$funsigned = false;
$findex = '';
$funiqueindex = false;
+ $fOptions = array();
//-----------------
// Parse attributes
foreach($fld as $attr => $v) {
- if ($attr == 2 && is_numeric($v)) $attr = 'SIZE';
- else if (is_numeric($attr) && $attr > 1 && !is_numeric($v)) $attr = strtoupper($v);
+ if ($attr == 2 && is_numeric($v))
+ $attr = 'SIZE';
+ elseif ($attr == 2 && strtoupper($ftype) == 'ENUM')
+ $attr = 'ENUM';
+ else if (is_numeric($attr) && $attr > 1 && !is_numeric($v))
+ $attr = strtoupper($v);
switch($attr) {
case '0':
case 'NAME': $fname = $v; break;
case '1':
- case 'TYPE': $ty = $v; $ftype = $this->ActualType(strtoupper($v)); break;
+ case 'TYPE': $ty = $v; $ftype = $this->actualType(strtoupper($v)); break;
case 'SIZE':
$dotat = strpos($v,'.'); if ($dotat === false) $dotat = strpos($v,',');
@@ -697,6 +721,8 @@ function _GenFields($flds,$widespacing=false)
// let INDEX keyword create a 'very standard' index on column
case 'INDEX': $findex = $v; break;
case 'UNIQUE': $funiqueindex = true; break;
+ case 'ENUM':
+ $fOptions['ENUM'] = $v; break;
} //switch
} // foreach $fld
@@ -708,7 +734,7 @@ function _GenFields($flds,$widespacing=false)
}
$fid = strtoupper(preg_replace('/^`(.+)`$/', '$1', $fname));
- $fname = $this->NameQuote($fname);
+ $fname = $this->nameQuote($fname);
if (!strlen($ftype)) {
if ($this->debug) ADOConnection::outp("Undefined TYPE for field '$fname'");
@@ -717,14 +743,24 @@ function _GenFields($flds,$widespacing=false)
$ftype = strtoupper($ftype);
}
- $ftype = $this->_GetSize($ftype, $ty, $fsize, $fprec);
+ $ftype = $this->_getSize($ftype, $ty, $fsize, $fprec, $fOptions);
- if ($ty == 'X' || $ty == 'X2' || $ty == 'B') $fnotnull = false; // some blob types do not accept nulls
+ if (($ty == 'X' || $ty == 'X2' || $ty == 'XL' || $ty == 'B') && !$this->blobAllowsNotNull)
+ /*
+ * some blob types do not accept nulls, so we override the
+ * previously defined value
+ */
+ $fnotnull = false;
- if ($fprimary) $pkey[] = $fname;
+ if ($fprimary)
+ $pkey[] = $fname;
- // some databases do not allow blobs to have defaults
- if ($ty == 'X') $fdefault = false;
+ if (($ty == 'X' || $ty == 'X2' || $ty == 'XL' || $ty == 'B') && !$this->blobAllowsDefaultValue)
+ /*
+ * some databases do not allow blobs to have defaults, so we
+ * override the previously defined value
+ */
+ $fdefault = false;
// build list of indexes
if ($findex != '') {
@@ -769,11 +805,11 @@ function _GenFields($flds,$widespacing=false)
// convert default date into database-aware code
if ($ty == 'T')
{
- $fdefault = $this->connection->DBTimeStamp($fdefault);
+ $fdefault = $this->connection->dbTimeStamp($fdefault);
}
else
{
- $fdefault = $this->connection->DBDate($fdefault);
+ $fdefault = $this->connection->dbDate($fdefault);
}
}
else
@@ -783,7 +819,7 @@ function _GenFields($flds,$widespacing=false)
$fdefault = $this->connection->qstr($fdefault);
}
}
- $suffix = $this->_CreateSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned);
+ $suffix = $this->_createSuffix($fname,$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint,$funsigned);
// add index creation
if ($widespacing) $fname = str_pad($fname,24);
@@ -806,19 +842,38 @@ function _GenFields($flds,$widespacing=false)
$ftype is the actual type
$ty is the type defined originally in the DDL
*/
- function _GetSize($ftype, $ty, $fsize, $fprec)
+ function _getSize($ftype, $ty, $fsize, $fprec, $options=false)
{
if (strlen($fsize) && $ty != 'X' && $ty != 'B' && strpos($ftype,'(') === false) {
$ftype .= "(".$fsize;
if (strlen($fprec)) $ftype .= ",".$fprec;
$ftype .= ')';
}
+
+ /*
+ * Handle additional options
+ */
+ if (is_array($options))
+ {
+ foreach($options as $type=>$value)
+ {
+ switch ($type)
+ {
+ case 'ENUM':
+ $ftype .= '(' . $value . ')';
+ break;
+
+ default:
+ }
+ }
+ }
+
return $ftype;
}
// return string must begin with space
- 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";
@@ -827,7 +882,7 @@ function _CreateSuffix($fname,&$ftype,$fnotnull,$fdefault,$fautoinc,$fconstraint
return $suffix;
}
- function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
+ function _indexSQL($idxname, $tabname, $flds, $idxoptions)
{
$sql = array();
@@ -856,25 +911,26 @@ function _IndexSQL($idxname, $tabname, $flds, $idxoptions)
return $sql;
}
- function _DropAutoIncrement($tabname)
+ function _dropAutoIncrement($tabname)
{
return false;
}
- function _TableSQL($tabname,$lines,$pkey,$tableoptions)
+ function _tableSQL($tabname,$lines,$pkey,$tableoptions)
{
$sql = array();
if (isset($tableoptions['REPLACE']) || isset ($tableoptions['DROP'])) {
$sql[] = sprintf($this->dropTable,$tabname);
if ($this->autoIncrement) {
- $sInc = $this->_DropAutoIncrement($tabname);
+ $sInc = $this->_dropAutoIncrement($tabname);
if ($sInc) $sql[] = $sInc;
}
if ( isset ($tableoptions['DROP']) ) {
return $sql;
}
}
+
$s = "CREATE TABLE $tabname (\n";
$s .= implode(",\n", $lines);
if (sizeof($pkey)>0) {
@@ -898,7 +954,7 @@ function _TableSQL($tabname,$lines,$pkey,$tableoptions)
GENERATE TRIGGERS IF NEEDED
used when table has auto-incrementing field that is emulated using triggers
*/
- function _Triggers($tabname,$taboptions)
+ function _triggers($tabname,$taboptions)
{
return array();
}
@@ -906,7 +962,7 @@ function _Triggers($tabname,$taboptions)
/**
Sanitize options, so that array elements with no keys are promoted to keys
*/
- function _Options($opts)
+ function _options($opts)
{
if (!is_array($opts)) return array();
$newopts = array();
@@ -938,25 +994,25 @@ function _getSizePrec($size)
This function changes/adds new fields to your table. You don't
have to know if the col is new or not. It will check on its own.
*/
- function ChangeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=false)
+ function changeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=false)
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
- if ($this->connection->fetchMode !== false) $savem = $this->connection->SetFetchMode(false);
+ if ($this->connection->fetchMode !== false) $savem = $this->connection->setFetchMode(false);
// check table exists
$save_handler = $this->connection->raiseErrorFn;
$this->connection->raiseErrorFn = '';
- $cols = $this->MetaColumns($tablename);
+ $cols = $this->metaColumns($tablename);
$this->connection->raiseErrorFn = $save_handler;
- if (isset($savem)) $this->connection->SetFetchMode($savem);
+ if (isset($savem)) $this->connection->setFetchMode($savem);
$ADODB_FETCH_MODE = $save;
if ( empty($cols)) {
- return $this->CreateTableSQL($tablename, $flds, $tableoptions);
+ return $this->createTableSQL($tablename, $flds, $tableoptions);
}
if (is_array($flds)) {
@@ -976,7 +1032,7 @@ function ChangeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=f
$c = $cols[$k];
$ml = $c->max_length;
- $mt = $this->MetaType($c->type,$ml);
+ $mt = $this->metaType($c->type,$ml);
if (isset($c->scale)) $sc = $c->scale;
else $sc = 99; // always force change if scale not known.
@@ -998,16 +1054,16 @@ function ChangeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=f
// already exists, alter table instead
- list($lines,$pkey,$idxs) = $this->_GenFields($flds);
+ list($lines,$pkey,$idxs) = $this->_genFields($flds);
// genfields can return FALSE at times
if ($lines == null) $lines = array();
- $alter = 'ALTER TABLE ' . $this->TableName($tablename);
+ $alter = 'ALTER TABLE ' . $this->tableName($tablename);
$sql = array();
foreach ( $lines as $id => $v ) {
if ( isset($cols[$id]) && is_object($cols[$id]) ) {
- $flds = Lens_ParseArgs($v,',');
+ $flds = lens_ParseArgs($v,',');
// We are trying to change the size of the field, if not allowed, simply ignore the request.
// $flds[1] holds the type, $flds[2] holds the size -postnuke addition
diff --git a/adodb/adodb-error.inc.php b/adodb/adodb-error.inc.php
index 2e7707f..517cf9b 100644
--- a/adodb/adodb-error.inc.php
+++ b/adodb/adodb-error.inc.php
@@ -1,19 +1,27 @@
DB_ERROR_CANNOT_CREATE,
1007 => DB_ERROR_ALREADY_EXISTS,
1008 => DB_ERROR_CANNOT_DROP,
- 1045 => DB_ERROR_ACCESS_VIOLATION,
+ 1045 => DB_ERROR_ACCESS_VIOLATION,
1046 => DB_ERROR_NODBSELECTED,
- 1049 => DB_ERROR_NOSUCHDB,
+ 1049 => DB_ERROR_NOSUCHDB,
1050 => DB_ERROR_ALREADY_EXISTS,
1051 => DB_ERROR_NOSUCHTABLE,
1054 => DB_ERROR_NOSUCHFIELD,
@@ -257,8 +269,8 @@ function adodb_error_mysql()
1136 => DB_ERROR_VALUE_COUNT_ON_ROW,
1146 => DB_ERROR_NOSUCHTABLE,
1048 => DB_ERROR_CONSTRAINT,
- 2002 => DB_ERROR_CONNECT_FAILED,
- 2005 => DB_ERROR_CONNECT_FAILED
+ 2002 => DB_ERROR_CONNECT_FAILED,
+ 2005 => DB_ERROR_CONNECT_FAILED
);
return $MAP;
diff --git a/adodb/adodb-errorhandler.inc.php b/adodb/adodb-errorhandler.inc.php
index 5861557..0cd3f21 100644
--- a/adodb/adodb-errorhandler.inc.php
+++ b/adodb/adodb-errorhandler.inc.php
@@ -1,18 +1,23 @@
Execute("select * from adoxyz");
- foreach($rs as $k => $v) {
- echo $k; print_r($v); echo " ";
- }
-
-
- Iterator code based on http://cvs.php.net/cvs.php/php-src/ext/spl/examples/cachingiterator.inc?login=2
-
-
- Moved to adodb.inc.php to improve performance.
- */
diff --git a/adodb/adodb-lib.inc.php b/adodb/adodb-lib.inc.php
index f729269..ced5e12 100644
--- a/adodb/adodb-lib.inc.php
+++ b/adodb/adodb-lib.inc.php
@@ -1,25 +1,40 @@
array_pop($tmp)];
+ }
if ($arr)
if (strpos($arr[1], '(') !== false) {
$at = strpos($sql, $arr[1]);
@@ -39,6 +54,7 @@ function adodb_strip_order_by($sql)
} else {
$sql = str_replace($arr[1], '', $sql);
}
+
return $sql;
}
@@ -118,98 +134,79 @@ function adodb_transpose(&$arr, &$newarr, &$hdr, &$fobjs)
}
}
-// Force key to upper.
-// See also http://www.php.net/manual/en/function.array-change-key-case.php
-function _array_change_key_case($an_array)
-{
- if (is_array($an_array)) {
- $new_array = array();
- foreach($an_array as $key=>$value)
- $new_array[strtoupper($key)] = $value;
-
- return $new_array;
- }
-
- return $an_array;
-}
function _adodb_replace(&$zthis, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc)
{
- if (count($fieldArray) == 0) return 0;
- $first = true;
- $uSet = '';
+ // Add Quote around table name to support use of spaces / reserved keywords
+ $table=sprintf('%s%s%s', $zthis->nameQuote,$table,$zthis->nameQuote);
- if (!is_array($keyCol)) {
- $keyCol = array($keyCol);
- }
- foreach($fieldArray as $k => $v) {
- if ($v === null) {
- $v = 'NULL';
- $fieldArray[$k] = $v;
- } else if ($autoQuote && /*!is_numeric($v) /*and strncmp($v,"'",1) !== 0 -- sql injection risk*/ strcasecmp($v,$zthis->null2null)!=0) {
- $v = $zthis->qstr($v);
- $fieldArray[$k] = $v;
- }
- if (in_array($k,$keyCol)) continue; // skip UPDATE if is key
-
- if ($first) {
- $first = false;
- $uSet = "$k=$v";
- } else
- $uSet .= ",$k=$v";
- }
+ if (count($fieldArray) == 0) return 0;
- $where = false;
- foreach ($keyCol as $v) {
- if (isset($fieldArray[$v])) {
- if ($where) $where .= ' and '.$v.'='.$fieldArray[$v];
- else $where = $v.'='.$fieldArray[$v];
- }
+ if (!is_array($keyCol)) {
+ $keyCol = array($keyCol);
+ }
+ $uSet = '';
+ foreach($fieldArray as $k => $v) {
+ if ($v === null) {
+ $v = 'NULL';
+ $fieldArray[$k] = $v;
+ } else if ($autoQuote && /*!is_numeric($v) /*and strncmp($v,"'",1) !== 0 -- sql injection risk*/ strcasecmp($v,$zthis->null2null)!=0) {
+ $v = $zthis->qstr($v);
+ $fieldArray[$k] = $v;
}
+ if (in_array($k,$keyCol)) continue; // skip UPDATE if is key
- if ($uSet && $where) {
- $update = "UPDATE $table SET $uSet WHERE $where";
+ // Add Quote around column name to support use of spaces / reserved keywords
+ $uSet .= sprintf(',%s%s%s=%s',$zthis->nameQuote,$k,$zthis->nameQuote,$v);
+ }
+ $uSet = ltrim($uSet, ',');
- $rs = $zthis->Execute($update);
+ // Add Quote around column name in where clause
+ $where = '';
+ foreach ($keyCol as $v) {
+ if (isset($fieldArray[$v])) {
+ $where .= sprintf(' and %s%s%s=%s ', $zthis->nameQuote,$v,$zthis->nameQuote,$fieldArray[$v]);
+ }
+ }
+ if ($where) {
+ $where = substr($where, 5);
+ }
+ if ($uSet && $where) {
+ $update = "UPDATE $table SET $uSet WHERE $where";
+ $rs = $zthis->Execute($update);
- if ($rs) {
- if ($zthis->poorAffectedRows) {
- /*
- The Select count(*) wipes out any errors that the update would have returned.
- PHPLens Issue No: 5696
- */
- if ($zthis->ErrorNo()<>0) return 0;
+ if ($rs) {
+ if ($zthis->poorAffectedRows) {
+ // The Select count(*) wipes out any errors that the update would have returned.
+ // PHPLens Issue No: 5696
+ if ($zthis->ErrorNo()<>0) return 0;
- # affected_rows == 0 if update field values identical to old values
- # for mysql - which is silly.
+ // affected_rows == 0 if update field values identical to old values
+ // for mysql - which is silly.
+ $cnt = $zthis->GetOne("select count(*) from $table where $where");
+ if ($cnt > 0) return 1; // record already exists
+ } else {
+ if (($zthis->Affected_Rows()>0)) return 1;
+ }
+ } else
+ return 0;
+ }
- $cnt = $zthis->GetOne("select count(*) from $table where $where");
- if ($cnt > 0) return 1; // record already exists
- } else {
- if (($zthis->Affected_Rows()>0)) return 1;
- }
- } else
- return 0;
- }
+ $iCols = $iVals = '';
+ foreach($fieldArray as $k => $v) {
+ if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col
- // print "
Error=".$this->ErrorNo().'
';
- $first = true;
- foreach($fieldArray as $k => $v) {
- if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col
+ // Add Quote around Column Name
+ $iCols .= sprintf(',%s%s%s',$zthis->nameQuote,$k,$zthis->nameQuote);
+ $iVals .= ",$v";
+ }
+ $iCols = ltrim($iCols, ',');
+ $iVals = ltrim($iVals, ',');
- if ($first) {
- $first = false;
- $iCols = "$k";
- $iVals = "$v";
- } else {
- $iCols .= ",$k";
- $iVals .= ",$v";
- }
- }
- $insert = "INSERT INTO $table ($iCols) VALUES ($iVals)";
- $rs = $zthis->Execute($insert);
- return ($rs) ? 2 : 0;
+ $insert = "INSERT INTO $table ($iCols) VALUES ($iVals)";
+ $rs = $zthis->Execute($insert);
+ return ($rs) ? 2 : 0;
}
function _adodb_getmenu(&$zthis, $name,$defstr='',$blank1stItem=true,$multiple=false,
@@ -407,10 +404,23 @@ function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0)
{
$qryRecs = 0;
- if (!empty($zthis->_nestedSQL) || preg_match("/^\s*SELECT\s+DISTINCT/is", $sql) ||
- preg_match('/\s+GROUP\s+BY\s+/is',$sql) ||
- preg_match('/\s+UNION\s+/is',$sql)) {
+ /*
+ * These databases require a "SELECT * FROM (SELECT" type
+ * statement to have an alias for the result
+ */
+ $requiresAlias = '';
+ $requiresAliasArray = array('postgres9','postgres','mysql','mysqli','mssql','mssqlnative','sqlsrv');
+ if (in_array($zthis->databaseType,$requiresAliasArray)
+ || in_array($zthis->dsnType,$requiresAliasArray)
+ ) {
+ $requiresAlias = '_ADODB_ALIAS_';
+ }
+ if (!empty($zthis->_nestedSQL)
+ || preg_match("/^\s*SELECT\s+DISTINCT/is", $sql)
+ || preg_match('/\s+GROUP\s+BY\s+/is',$sql)
+ || preg_match('/\s+UNION\s+/is',$sql)
+ ) {
$rewritesql = adodb_strip_order_by($sql);
// ok, has SELECT DISTINCT or GROUP BY so see if we can use a table alias
@@ -421,24 +431,37 @@ function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0)
$rewritesql = "SELECT ".$hint[0]." COUNT(*) FROM (".$rewritesql.")";
} else
$rewritesql = "SELECT COUNT(*) FROM (".$rewritesql.")";
-
- } else if (strncmp($zthis->databaseType,'postgres',8) == 0
- || strncmp($zthis->databaseType,'mysql',5) == 0
- || strncmp($zthis->databaseType,'mssql',5) == 0
- || strncmp($zthis->dsnType,'sqlsrv',5) == 0
- || strncmp($zthis->dsnType,'mssql',5) == 0
- ){
- $rewritesql = "SELECT COUNT(*) FROM ($rewritesql) _ADODB_ALIAS_";
} else {
- $rewritesql = "SELECT COUNT(*) FROM ($rewritesql)";
+ $rewritesql = "SELECT COUNT(*) FROM ($rewritesql) $requiresAlias";
}
+
} else {
- // now replace SELECT ... FROM with SELECT COUNT(*) FROM
- if ( strpos($sql, '_ADODB_COUNT') !== FALSE ) {
- $rewritesql = preg_replace('/^\s*?SELECT\s+_ADODB_COUNT(.*)_ADODB_COUNT\s/is','SELECT COUNT(*) ',$sql);
- } else {
- $rewritesql = preg_replace('/^\s*SELECT\s.*\s+FROM\s/Uis','SELECT COUNT(*) FROM ',$sql);
+ // Replace 'SELECT ... FROM' with 'SELECT COUNT(*) FROM'
+ // Parse the query one char at a time starting after the SELECT
+ // to find the FROM clause's position, ignoring any sub-queries.
+ $start = stripos($sql, 'SELECT') + 7;
+ if ($start === false) {
+ // Not a SELECT statement - probably should trigger an exception here
+ return 0;
+ }
+ $len = strlen($sql);
+ $numParentheses = 0;
+ for ($pos = $start; $pos < $len; $pos++) {
+ switch ($sql[$pos]) {
+ case '(': $numParentheses++; continue 2;
+ case ')': $numParentheses--; continue 2;
+ }
+ // Ignore whatever is between parentheses (sub-queries)
+ if ($numParentheses > 0) {
+ continue;
+ }
+ // Exit loop if 'FROM' keyword was found
+ if (strtoupper(substr($sql, $pos, 4)) == 'FROM') {
+ break;
+ }
}
+ $rewritesql = 'SELECT COUNT(*) ' . substr($sql, $pos);
+
// fix by alexander zhukov, alex#unipack.ru, because count(*) and 'order by' fails
// with mssql, access and postgresql. Also a good speedup optimization - skips sorting!
// also see PHPLens Issue No: 12752
@@ -446,7 +469,9 @@ function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0)
}
if (isset($rewritesql) && $rewritesql != $sql) {
- if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) $rewritesql .= $limitarr[0];
+ if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) {
+ $rewritesql .= $limitarr[0];
+ }
if ($secs2cache) {
// we only use half the time of secs2cache because the count can quickly
@@ -455,18 +480,23 @@ function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0)
} else {
$qryRecs = $zthis->GetOne($rewritesql,$inputarr);
- }
+ }
if ($qryRecs !== false) return $qryRecs;
}
+
//--------------------------------------------
// query rewrite failed - so try slower way...
-
// strip off unneeded ORDER BY if no UNION
- if (preg_match('/\s*UNION\s*/is', $sql)) $rewritesql = $sql;
- else $rewritesql = $rewritesql = adodb_strip_order_by($sql);
+ if (preg_match('/\s*UNION\s*/is', $sql)) {
+ $rewritesql = $sql;
+ } else {
+ $rewritesql = $rewritesql = adodb_strip_order_by($sql);
+ }
- if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) $rewritesql .= $limitarr[0];
+ if (preg_match('/\sLIMIT\s+[0-9]+/i',$sql,$limitarr)) {
+ $rewritesql .= $limitarr[0];
+ }
if ($secs2cache) {
$rstest = $zthis->CacheExecute($secs2cache,$rewritesql,$inputarr);
@@ -476,18 +506,11 @@ function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0)
if (!$rstest) $rstest = $zthis->Execute($sql,$inputarr);
}
if ($rstest) {
- $qryRecs = $rstest->RecordCount();
+ $qryRecs = $rstest->RecordCount();
if ($qryRecs == -1) {
- global $ADODB_EXTENSION;
- // some databases will return -1 on MoveLast() - change to MoveNext()
- if ($ADODB_EXTENSION) {
- while(!$rstest->EOF) {
- adodb_movenext($rstest);
- }
- } else {
- while(!$rstest->EOF) {
- $rstest->MoveNext();
- }
+ // some databases will return -1 on MoveLast() - change to MoveNext()
+ while(!$rstest->EOF) {
+ $rstest->MoveNext();
}
$qryRecs = $rstest->_currentRow;
}
@@ -650,148 +673,193 @@ function _adodb_pageexecute_no_last_page(&$zthis, $sql, $nrows, $page, $inputarr
return $rsreturn;
}
-function _adodb_getupdatesql(&$zthis,&$rs, $arrFields,$forceUpdate=false,$magicq=false,$force=2)
+/**
+ * Performs case conversion and quoting of the given field name.
+ *
+ * See Global variable $ADODB_QUOTE_FIELDNAMES.
+ *
+ * @param ADOConnection $zthis
+ * @param string $fieldName
+ *
+ * @return string Quoted field name
+ */
+function _adodb_quote_fieldname($zthis, $fieldName)
{
global $ADODB_QUOTE_FIELDNAMES;
- if (!$rs) {
- printf(ADODB_BAD_RS,'GetUpdateSQL');
- return false;
- }
+ // Case conversion - defaults to UPPER
+ $case = is_bool($ADODB_QUOTE_FIELDNAMES) ? 'UPPER' : $ADODB_QUOTE_FIELDNAMES;
+ switch ($case) {
+ case 'LOWER':
+ $fieldName = strtolower($fieldName);
+ break;
+ case 'NATIVE':
+ // Do nothing
+ break;
+ case 'UPPER':
+ case 'BRACKETS':
+ default:
+ $fieldName = strtoupper($fieldName);
+ break;
+ }
- $fieldUpdatedCount = 0;
- $arrFields = _array_change_key_case($arrFields);
+ // Quote field if requested, or necessary (field contains space)
+ if ($ADODB_QUOTE_FIELDNAMES || strpos($fieldName, ' ') !== false ) {
+ if ($ADODB_QUOTE_FIELDNAMES === 'BRACKETS') {
+ return $zthis->leftBracket . $fieldName . $zthis->rightBracket;
+ } else {
+ return $zthis->nameQuote . $fieldName . $zthis->nameQuote;
+ }
+ } else {
+ return $fieldName;
+ }
+}
- $hasnumeric = isset($rs->fields[0]);
- $setFields = '';
+function _adodb_getupdatesql(&$zthis, &$rs, $arrFields, $forceUpdate=false, $force=2)
+{
+ if (!$rs) {
+ printf(ADODB_BAD_RS,'GetUpdateSQL');
+ return false;
+ }
- // Loop through all of the fields in the recordset
- for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) {
- // Get the field from the recordset
- $field = $rs->FetchField($i);
+ $fieldUpdatedCount = 0;
+ if (is_array($arrFields))
+ $arrFields = array_change_key_case($arrFields,CASE_UPPER);
- // If the recordset field is one
- // of the fields passed in then process.
- $upperfname = strtoupper($field->name);
- if (adodb_key_exists($upperfname,$arrFields,$force)) {
+ $hasnumeric = isset($rs->fields[0]);
+ $setFields = '';
- // If the existing field value in the recordset
- // is different from the value passed in then
- // go ahead and append the field name and new value to
- // the update query.
+ // Loop through all of the fields in the recordset
+ for ($i=0, $max=$rs->fieldCount(); $i < $max; $i++) {
+ // Get the field from the recordset
+ $field = $rs->fetchField($i);
- if ($hasnumeric) $val = $rs->fields[$i];
- else if (isset($rs->fields[$upperfname])) $val = $rs->fields[$upperfname];
- else if (isset($rs->fields[$field->name])) $val = $rs->fields[$field->name];
- else if (isset($rs->fields[strtolower($upperfname)])) $val = $rs->fields[strtolower($upperfname)];
- else $val = '';
+ // If the recordset field is one
+ // of the fields passed in then process.
+ $upperfname = strtoupper($field->name);
+ if (adodb_key_exists($upperfname, $arrFields, $force)) {
+ // If the existing field value in the recordset
+ // is different from the value passed in then
+ // go ahead and append the field name and new value to
+ // the update query.
- if ($forceUpdate || strcmp($val, $arrFields[$upperfname])) {
- // Set the counter for the number of fields that will be updated.
- $fieldUpdatedCount++;
+ if ($hasnumeric) $val = $rs->fields[$i];
+ else if (isset($rs->fields[$upperfname])) $val = $rs->fields[$upperfname];
+ else if (isset($rs->fields[$field->name])) $val = $rs->fields[$field->name];
+ else if (isset($rs->fields[strtolower($upperfname)])) $val = $rs->fields[strtolower($upperfname)];
+ else $val = '';
- // Based on the datatype of the field
- // Format the value properly for the database
- $type = $rs->MetaType($field->type);
+ if ($forceUpdate || strcmp($val, $arrFields[$upperfname])) {
+ // Set the counter for the number of fields that will be updated.
+ $fieldUpdatedCount++;
+ // Based on the datatype of the field
+ // Format the value properly for the database
+ $type = $rs->metaType($field->type);
- if ($type == 'null') {
- $type = 'C';
- }
+ if ($type == 'null') {
+ $type = 'C';
+ }
- if ((strpos($upperfname,' ') !== false) || ($ADODB_QUOTE_FIELDNAMES)) {
- switch ($ADODB_QUOTE_FIELDNAMES) {
- case 'LOWER':
- $fnameq = $zthis->nameQuote.strtolower($field->name).$zthis->nameQuote;break;
- case 'NATIVE':
- $fnameq = $zthis->nameQuote.$field->name.$zthis->nameQuote;break;
- case 'UPPER':
- default:
- $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;break;
- }
- } else
- $fnameq = $upperfname;
+ $fnameq = _adodb_quote_fieldname($zthis, $field->name);
- //********************************************************//
- if (is_null($arrFields[$upperfname])
+ //********************************************************//
+ if (is_null($arrFields[$upperfname])
|| (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
- || $arrFields[$upperfname] === $zthis->null2null
- )
- {
- switch ($force) {
+ || $arrFields[$upperfname] === $zthis->null2null
+ ) {
- //case 0:
- // //Ignore empty values. This is allready handled in "adodb_key_exists" function.
- //break;
+ switch ($force) {
- case 1:
- //Set null
- $setFields .= $field->name . " = null, ";
- break;
+ //case 0:
+ // // Ignore empty values. This is already handled in "adodb_key_exists" function.
+ // break;
+
+ case 1:
+ // set null
+ $setFields .= $fnameq . " = null, ";
+ break;
+
+ case 2:
+ // set empty
+ $arrFields[$upperfname] = "";
+ $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq, $arrFields);
+ break;
- case 2:
- //Set empty
- $arrFields[$upperfname] = "";
- $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
- break;
default:
- case 3:
- //Set the value that was given in array, so you can give both null and empty values
- if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === $zthis->null2null) {
- $setFields .= $field->name . " = null, ";
- } else {
- $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,$arrFields, $magicq);
- }
- break;
- }
- //********************************************************//
- } else {
- //we do this so each driver can customize the sql for
- //DB specific column types.
- //Oracle needs BLOB types to be handled with a returning clause
- //postgres has special needs as well
- $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq,
- $arrFields, $magicq);
+ case 3:
+ // set the value that was given in array, so you can give both null and empty values
+ if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === $zthis->null2null) {
+ $setFields .= $fnameq . " = null, ";
+ } else {
+ $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq, $arrFields);
+ }
+ break;
+
+ case ADODB_FORCE_NULL_AND_ZERO:
+
+ switch ($type) {
+ case 'N':
+ case 'I':
+ case 'L':
+ $setFields .= $fnameq . ' = 0, ';
+ break;
+ default:
+ $setFields .= $fnameq . ' = null, ';
+ break;
+ }
+ break;
+
}
+ //********************************************************//
+ } else {
+ // we do this so each driver can customize the sql for
+ // DB specific column types.
+ // Oracle needs BLOB types to be handled with a returning clause
+ // postgres has special needs as well
+ $setFields .= _adodb_column_sql($zthis, 'U', $type, $upperfname, $fnameq, $arrFields);
}
}
}
+ }
- // If there were any modified fields then build the rest of the update query.
- if ($fieldUpdatedCount > 0 || $forceUpdate) {
- // Get the table name from the existing query.
- if (!empty($rs->tableName)) $tableName = $rs->tableName;
- else {
- preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName);
- $tableName = $tableName[1];
- }
- // Get the full where clause excluding the word "WHERE" from
- // the existing query.
- preg_match('/\sWHERE\s(.*)/is', $rs->sql, $whereClause);
-
- $discard = false;
- // not a good hack, improvements?
- if ($whereClause) {
- #var_dump($whereClause);
- if (preg_match('/\s(ORDER\s.*)/is', $whereClause[1], $discard));
- else if (preg_match('/\s(LIMIT\s.*)/is', $whereClause[1], $discard));
- else if (preg_match('/\s(FOR UPDATE.*)/is', $whereClause[1], $discard));
- else preg_match('/\s.*(\) WHERE .*)/is', $whereClause[1], $discard); # see https://sourceforge.net/p/adodb/bugs/37/
- } else
- $whereClause = array(false,false);
+ // If there were any modified fields then build the rest of the update query.
+ if ($fieldUpdatedCount > 0 || $forceUpdate) {
+ // Get the table name from the existing query.
+ if (!empty($rs->tableName)) {
+ $tableName = $rs->tableName;
+ } else {
+ preg_match("/FROM\s+".ADODB_TABLE_REGEX."/is", $rs->sql, $tableName);
+ $tableName = $tableName[1];
+ }
- if ($discard)
- $whereClause[1] = substr($whereClause[1], 0, strlen($whereClause[1]) - strlen($discard[1]));
+ // Get the full where clause excluding the word "WHERE" from the existing query.
+ preg_match('/\sWHERE\s(.*)/is', $rs->sql, $whereClause);
- $sql = 'UPDATE '.$tableName.' SET '.substr($setFields, 0, -2);
- if (strlen($whereClause[1]) > 0)
- $sql .= ' WHERE '.$whereClause[1];
+ $discard = false;
+ // not a good hack, improvements?
+ if ($whereClause) {
+ #var_dump($whereClause);
+ if (preg_match('/\s(ORDER\s.*)/is', $whereClause[1], $discard));
+ else if (preg_match('/\s(LIMIT\s.*)/is', $whereClause[1], $discard));
+ else if (preg_match('/\s(FOR UPDATE.*)/is', $whereClause[1], $discard));
+ else preg_match('/\s.*(\) WHERE .*)/is', $whereClause[1], $discard); # see https://sourceforge.net/p/adodb/bugs/37/
+ } else {
+ $whereClause = array(false, false);
+ }
- return $sql;
+ if ($discard) {
+ $whereClause[1] = substr($whereClause[1], 0, strlen($whereClause[1]) - strlen($discard[1]));
+ }
- } else {
- return false;
+ $sql = 'UPDATE '.$tableName.' SET '.substr($setFields, 0, -2);
+ if (strlen($whereClause[1]) > 0) {
+ $sql .= ' WHERE '.$whereClause[1];
+ }
+ return $sql;
+ } else {
+ return false;
}
}
@@ -802,10 +870,10 @@ function adodb_key_exists($key, &$arr,$force=2)
return (!empty($arr[$key])) || (isset($arr[$key]) && strlen($arr[$key])>0);
}
- if (isset($arr[$key])) return true;
+ if (isset($arr[$key]))
+ return true;
## null check below
- if (ADODB_PHPVER >= 0x4010) return array_key_exists($key,$arr);
- return false;
+ return array_key_exists($key,$arr);
}
/**
@@ -815,18 +883,18 @@ function adodb_key_exists($key, &$arr,$force=2)
*
*
*/
-function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false,$force=2)
+function _adodb_getinsertsql(&$zthis, &$rs, $arrFields, $force=2)
{
static $cacheRS = false;
static $cacheSig = 0;
static $cacheCols;
- global $ADODB_QUOTE_FIELDNAMES;
$tableName = '';
$values = '';
$fields = '';
$recordSet = null;
- $arrFields = _array_change_key_case($arrFields);
+ if (is_array($arrFields))
+ $arrFields = array_change_key_case($arrFields,CASE_UPPER);
$fieldInsertedCount = 0;
if (is_string($rs)) {
@@ -870,19 +938,7 @@ function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false,$force=2)
$upperfname = strtoupper($field->name);
if (adodb_key_exists($upperfname,$arrFields,$force)) {
$bad = false;
- if ((strpos($upperfname,' ') !== false) || ($ADODB_QUOTE_FIELDNAMES)) {
- switch ($ADODB_QUOTE_FIELDNAMES) {
- case 'LOWER':
- $fnameq = $zthis->nameQuote.strtolower($field->name).$zthis->nameQuote;break;
- case 'NATIVE':
- $fnameq = $zthis->nameQuote.$field->name.$zthis->nameQuote;break;
- case 'UPPER':
- default:
- $fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;break;
- }
- } else
- $fnameq = $upperfname;
-
+ $fnameq = _adodb_quote_fieldname($zthis, $field->name);
$type = $recordSet->MetaType($field->type);
/********************************************************/
@@ -893,29 +949,44 @@ function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false,$force=2)
{
switch ($force) {
- case 0: // we must always set null if missing
+ case ADODB_FORCE_IGNORE: // we must always set null if missing
$bad = true;
break;
- case 1:
+ case ADODB_FORCE_NULL:
$values .= "null, ";
break;
- case 2:
+ case ADODB_FORCE_EMPTY:
//Set empty
$arrFields[$upperfname] = "";
- $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,$arrFields, $magicq);
+ $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields);
break;
default:
- case 3:
+ case ADODB_FORCE_VALUE:
//Set the value that was given in array, so you can give both null and empty values
if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === $zthis->null2null) {
$values .= "null, ";
} else {
- $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields, $magicq);
+ $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields);
}
break;
+
+ case ADODB_FORCE_NULL_AND_ZERO:
+ switch ($type)
+ {
+ case 'N':
+ case 'I':
+ case 'L':
+ $values .= '0, ';
+ break;
+ default:
+ $values .= "null, ";
+ break;
+ }
+ break;
+
} // switch
/*********************************************************/
@@ -924,8 +995,7 @@ function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false,$force=2)
//DB specific column types.
//Oracle needs BLOB types to be handled with a returning clause
//postgres has special needs as well
- $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq,
- $arrFields, $magicq);
+ $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields);
}
if ($bad) continue;
@@ -976,7 +1046,7 @@ function _adodb_getinsertsql(&$zthis,&$rs,$arrFields,$magicq=false,$force=2)
* @return string
*
*/
-function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFields, $magicq)
+function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFields)
{
$sql = '';
@@ -1008,7 +1078,7 @@ function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFie
} else {
//this is to maintain compatibility
//with older adodb versions.
- $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
+ $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, false);
}
break;
@@ -1031,19 +1101,19 @@ function _adodb_column_sql_oci8(&$zthis,$action, $type, $fname, $fnameq, $arrFie
} else {
//this is to maintain compatibility
//with older adodb versions.
- $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
+ $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, false);
}
break;
default:
- $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq,false);
+ $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, false);
break;
}
return $sql;
}
-function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, $recurse=true)
+function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $recurse=true)
{
if ($recurse) {
@@ -1052,7 +1122,7 @@ function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields,
if ($type == 'L') $type = 'C';
break;
case 'oci8':
- return _adodb_column_sql_oci8($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq);
+ return _adodb_column_sql_oci8($zthis, $action, $type, $fname, $fnameq, $arrFields);
}
}
@@ -1061,7 +1131,7 @@ function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields,
case "C":
case "X":
case 'B':
- $val = $zthis->qstr($arrFields[$fname],$magicq);
+ $val = $zthis->qstr($arrFields[$fname]);
break;
case "D":
@@ -1091,9 +1161,7 @@ function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields,
if ($action == 'I') return $val . ", ";
-
return $fnameq . "=" . $val . ", ";
-
}
@@ -1105,8 +1173,16 @@ function _adodb_debug_execute(&$zthis, $sql, $inputarr)
foreach($inputarr as $kk=>$vv) {
if (is_string($vv) && strlen($vv)>64) $vv = substr($vv,0,64).'...';
if (is_null($vv)) $ss .= "($kk=>null) ";
- else $ss .= "($kk=>'$vv') ";
+ else
+ {
+ if (is_array($vv))
+ {
+ $vv = sprintf("Array Of Values: [%s]", implode(',',$vv));
+ }
+ $ss .= "($kk=>'$vv') ";
+ }
}
+
$ss = "[ $ss ]";
}
$sqlTxt = is_array($sql) ? $sql[0] : $sql;
diff --git a/adodb/adodb-loadbalancer.inc.php b/adodb/adodb-loadbalancer.inc.php
new file mode 100644
index 0000000..2e4f392
--- /dev/null
+++ b/adodb/adodb-loadbalancer.inc.php
@@ -0,0 +1,773 @@
+ 0, 'write' => 0, 'readonly' => 0);
+
+ /**
+ * @var array Weights of all connections for each type.
+ */
+ protected $total_connection_weights = array('all' => 0, 'write' => 0, 'readonly' => 0);
+
+ /**
+ * @var bool When in transactions, always use this connection.
+ */
+ protected $pinned_connection_id = false;
+
+ /**
+ * @var array Last connection_id for each database type.
+ */
+ protected $last_connection_id = array('write' => false, 'readonly' => false, 'all' => false);
+
+ /**
+ * @var bool Session variables that must be maintained across all connections, ie: SET TIME ZONE.
+ */
+ protected $session_variables = false;
+
+ /**
+ * @var bool Called immediately after connecting to any DB.
+ */
+ protected $user_defined_session_init_sql = false;
+
+
+ /**
+ * Defines SQL queries that are executed each time a new database connection is established.
+ *
+ * @param $sql
+ * @return bool
+ */
+ public function setSessionInitSQL($sql)
+ {
+ $this->user_defined_session_init_sql[] = $sql;
+
+ return true;
+ }
+
+ /**
+ * Adds a new database connection to the pool, but no actual connection is made until its needed.
+ *
+ * @param $obj
+ * @return bool
+ * @throws Exception
+ */
+ public function addConnection($obj)
+ {
+ if ($obj instanceof ADOdbLoadBalancerConnection) {
+ $this->connections[] = $obj;
+ end($this->connections);
+ $i = key($this->connections);
+
+ $this->total_connections[$obj->type]++;
+ $this->total_connections['all']++;
+
+ $this->total_connection_weights[$obj->type] += abs($obj->weight);
+ $this->total_connection_weights['all'] += abs($obj->weight);
+
+ if ($obj->type == 'write') {
+ $this->connections_write[] = $i;
+ } else {
+ $this->connections_readonly[] = $i;
+ }
+
+ return true;
+ }
+
+ throw new Exception('Connection object is not an instance of ADOdbLoadBalancerConnection');
+ }
+
+ /**
+ * Removes a database connection from the pool.
+ *
+ * @param $i
+ * @return bool
+ */
+ public function removeConnection($i)
+ {
+ if (isset($this->connections[$i])) {
+ $obj = $this->connections[ $i ];
+
+ $this->total_connections[ $obj->type ]--;
+ $this->total_connections['all']--;
+
+ $this->total_connection_weights[ $obj->type ] -= abs($obj->weight);
+ $this->total_connection_weights['all'] -= abs($obj->weight);
+
+ if ($obj->type == 'write') {
+ unset($this->connections_write[array_search($i, $this->connections_write)]);
+ // Reindex array.
+ $this->connections_write = array_values($this->connections_write);
+ } else {
+ unset($this->connections_readonly[array_search($i, $this->connections_readonly)]);
+ // Reindex array.
+ $this->connections_readonly = array_values($this->connections_readonly);
+ }
+
+ // Remove any sticky connections as well.
+ if ($this->last_connection_id[$obj->type] == $i) {
+ $this->last_connection_id[$obj->type] = false;
+ }
+
+ unset($this->connections[$i]);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns a database connection of the specified type.
+ *
+ * Takes into account the connection weight for load balancing.
+ *
+ * @param string $type Type of database connection, either: 'write' capable or 'readonly'
+ * @return bool|int|string
+ */
+ private function getConnectionByWeight($type)
+ {
+ if ($type == 'readonly') {
+ $total_weight = $this->total_connection_weights['all'];
+ } else {
+ $total_weight = $this->total_connection_weights['write'];
+ }
+
+ $i = false;
+ if (is_array($this->connections)) {
+ $n = 0;
+ $num = mt_rand(0, $total_weight);
+ foreach ($this->connections as $i => $connection_obj) {
+ if ($connection_obj->weight > 0 && ($type == 'readonly' || $connection_obj->type == 'write')) {
+ $n += $connection_obj->weight;
+ if ($n >= $num) {
+ break;
+ }
+ }
+ }
+ }
+
+ return $i;
+ }
+
+ /**
+ * Returns the proper database connection when taking into account sticky sessions and load balancing.
+ *
+ * @param $type
+ * @return bool|int|mixed|string
+ */
+ public function getLoadBalancedConnection($type)
+ {
+ if ($this->total_connections == 0) {
+ $connection_id = 0;
+ } else {
+ if ($this->enable_sticky_sessions == true && $this->last_connection_id[$type] !== false) {
+ $connection_id = $this->last_connection_id[$type];
+ } else {
+ if ($type == 'write' && $this->total_connections['write'] == 1) {
+ $connection_id = $this->connections_write[0];
+ } else {
+ $connection_id = $this->getConnectionByWeight($type);
+ }
+ }
+ }
+
+ return $connection_id;
+ }
+
+ /**
+ * Returns the ADODB connection object by connection_id.
+ *
+ * Ensures that it's connected and the session variables are executed.
+ *
+ * @param $connection_id
+ * @return bool|ADOConnection
+ * @throws Exception
+ */
+ private function _getConnection($connection_id)
+ {
+ if (isset($this->connections[$connection_id])) {
+ $connection_obj = $this->connections[$connection_id];
+ /** @var ADOConnection $adodb_obj */
+ $adodb_obj = $connection_obj->getADOdbObject();
+ if (is_object($adodb_obj) && $adodb_obj->_connectionID == false) {
+ try {
+ if ($connection_obj->persistent_connection == true) {
+ $adodb_obj->Pconnect(
+ $connection_obj->host,
+ $connection_obj->user,
+ $connection_obj->password,
+ $connection_obj->database
+ );
+ } else {
+ $adodb_obj->Connect(
+ $connection_obj->host,
+ $connection_obj->user,
+ $connection_obj->password,
+ $connection_obj->database
+ );
+ }
+ } catch (Exception $e) {
+ // Connection error, see if there are other connections to try still.
+ throw $e; // No connections left, reThrow exception so application can catch it.
+ }
+
+ if (is_array($this->user_defined_session_init_sql)) {
+ foreach ($this->user_defined_session_init_sql as $session_init_sql) {
+ $adodb_obj->Execute($session_init_sql);
+ }
+ }
+ $this->executeSessionVariables($adodb_obj);
+ }
+
+ return $adodb_obj;
+ } else {
+ throw new Exception('Unable to return Connection object...');
+ }
+ }
+
+ /**
+ * Returns the ADODB connection object by database type.
+ *
+ * Ensures that it's connected and the session variables are executed.
+ *
+ * @param string $type
+ * @param null $pin_connection
+ * @return ADOConnection|bool
+ * @throws Exception
+ */
+ public function getConnection($type = 'write', $pin_connection = null)
+ {
+ while (($type == 'write' && $this->total_connections['write'] > 0)
+ || ($type == 'readonly' && $this->total_connections['all'] > 0)
+ ) {
+ if ($this->pinned_connection_id !== false) {
+ $connection_id = $this->pinned_connection_id;
+ } else {
+ $connection_id = $this->getLoadBalancedConnection($type);
+ }
+
+ if ($connection_id !== false) {
+ try {
+ $adodb_obj = $this->_getConnection($connection_id);
+ // $connection_obj = $this->connections[$connection_id];
+ break;
+ } catch (Exception $e) {
+ // Connection error, see if there are other connections to try still.
+ $this->removeConnection($connection_id);
+ if ( ($type == 'write' && $this->total_connections['write'] == 0)
+ || ($type == 'readonly' && $this->total_connections['all'] == 0)
+ ) {
+ throw $e;
+ }
+ }
+ } else {
+ throw new Exception('Connection ID is invalid!');
+ }
+ }
+
+ $this->last_connection_id[$type] = $connection_id;
+
+ if ($pin_connection === true) {
+ $this->pinned_connection_id = $connection_id;
+ } elseif ($pin_connection === false && $adodb_obj->transOff <= 1) {
+ // UnPin connection only if we are 1 level deep in a transaction.
+ $this->pinned_connection_id = false;
+
+ // When unpinning connection, reset last_connection_id so readonly
+ // queries don't get stuck on the write capable connection.
+ $this->last_connection_id['write'] = false;
+ $this->last_connection_id['readonly'] = false;
+ }
+
+ return $adodb_obj;
+ }
+
+ /**
+ * This is a hack to work around pass by reference error.
+ *
+ * Parameter 1 to ADOConnection::GetInsertSQL() expected to be a reference,
+ * value given in adodb-loadbalancer.inc.php on line 83
+ *
+ * @param $arr
+ * @return array
+ */
+ private function makeValuesReferenced($arr)
+ {
+ $refs = array();
+
+ foreach ($arr as $key => $value) {
+ $refs[$key] = &$arr[$key];
+ }
+
+ return $refs;
+ }
+
+ /**
+ * Allow setting session variables that are maintained across connections.
+ *
+ * Its important that these are set using name/value, so it can determine
+ * if the same variable is set multiple times causing bloat/clutter when
+ * new connections are established. For example if the time_zone is set to
+ * many different ones through the course of a single connection, a new
+ * connection should only set it to the most recent value.
+ *
+ * @param $name
+ * @param $value
+ * @param bool $execute_immediately
+ * @return array|bool|mixed
+ * @throws Exception
+ */
+ public function setSessionVariable($name, $value, $execute_immediately = true)
+ {
+ $this->session_variables[$name] = $value;
+
+ if ($execute_immediately == true) {
+ return $this->executeSessionVariables();
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Executes the session variables on a given ADODB object.
+ *
+ * @param ADOConnection|bool $adodb_obj
+ * @return array|bool|mixed
+ * @throws Exception
+ */
+ private function executeSessionVariables($adodb_obj = false)
+ {
+ if (is_array($this->session_variables)) {
+ $sql = '';
+ foreach ($this->session_variables as $name => $value) {
+ // $sql .= 'SET SESSION '. $name .' '. $value;
+ // MySQL uses: SET SESSION foo_bar='foo'
+ // PGSQL uses: SET SESSION foo_bar 'foo'
+ // So leave it up to the user to pass the proper value with '=' if needed.
+ // This may be a candidate to move into ADOdb proper.
+ $sql .= 'SET SESSION ' . $name . ' ' . $value;
+ }
+
+ if ($adodb_obj !== false) {
+ return $adodb_obj->Execute($sql);
+ } else {
+ return $this->ClusterExecute($sql);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Executes the same SQL QUERY on the entire cluster of connections.
+ * Would be used for things like SET SESSION TIME ZONE calls and such.
+ *
+ * @param $sql
+ * @param bool $inputarr
+ * @param bool $return_all_results
+ * @param bool $existing_connections_only
+ * @return array|bool|mixed
+ * @throws Exception
+ */
+ public function clusterExecute(
+ $sql,
+ $inputarr = false,
+ $return_all_results = false,
+ $existing_connections_only = true
+ ) {
+ if (is_array($this->connections) && count($this->connections) > 0) {
+ foreach ($this->connections as $key => $connection_obj) {
+ if ($existing_connections_only == false
+ || ($existing_connections_only == true
+ && $connection_obj->getADOdbObject()->_connectionID !== false
+ )
+ ) {
+ $adodb_obj = $this->_getConnection($key);
+ if (is_object($adodb_obj)) {
+ $result_arr[] = $adodb_obj->Execute($sql, $inputarr);
+ }
+ }
+ }
+
+ if (isset($result_arr) && $return_all_results == true) {
+ return $result_arr;
+ } else {
+ // Loop through all results checking to see if they match, if they do return the first one
+ // otherwise return an array of all results.
+ if (isset($result_arr)) {
+ foreach ($result_arr as $result) {
+ if ($result == false) {
+ return $result_arr;
+ }
+ }
+
+ return $result_arr[0];
+ } else {
+ // When using lazy connections, there are cases where
+ // setSessionVariable() is called early on, but there are
+ // no connections to execute the queries on yet.
+ // This captures that case and forces a RETURN TRUE to occur.
+ // As likely the queries will be executed as soon as a
+ // connection is established.
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Determines if a SQL query is read-only or not.
+ *
+ * @param string $sql SQL Query to test.
+ * @return bool
+ */
+ public function isReadOnlyQuery($sql)
+ {
+ if ( stripos($sql, 'SELECT') === 0
+ && stripos($sql, 'FOR UPDATE') === false
+ && stripos($sql, ' INTO ') === false
+ && stripos($sql, 'LOCK IN') === false
+ ) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Use this instead of __call() as it significantly reduces the overhead of call_user_func_array().
+ *
+ * @param $sql
+ * @param bool $inputarr
+ * @return array|bool|mixed
+ * @throws Exception
+ */
+ public function execute($sql, $inputarr = false)
+ {
+ $type = 'write';
+ $pin_connection = null;
+
+ // Prevent leading spaces from causing isReadOnlyQuery/stripos from failing.
+ $sql = trim($sql);
+
+ // SELECT queries that can write and therefore must be run on a write capable connection.
+ // SELECT ... FOR UPDATE;
+ // SELECT ... INTO ...
+ // SELECT .. LOCK IN ... (MYSQL)
+ if ($this->isReadOnlyQuery($sql) == true) {
+ $type = 'readonly';
+ } elseif (stripos($sql, 'SET') === 0) {
+ // SET SQL statements should likely use setSessionVariable() instead,
+ // so state is properly maintained across connections, especially when they are lazily created.
+ return $this->ClusterExecute($sql, $inputarr);
+ }
+
+ $adodb_obj = $this->getConnection($type, $pin_connection);
+ if ($adodb_obj !== false) {
+ return $adodb_obj->Execute($sql, $inputarr);
+ }
+
+ return false;
+ }
+
+ /**
+ * Magic method to intercept method and callback to the proper ADODB object for write/readonly connections.
+ *
+ * @param string $method ADODB method to call.
+ * @param array $args Arguments to the ADODB method.
+ * @return bool|mixed
+ * @throws Exception
+ */
+ public function __call($method, $args)
+ {
+ $type = 'write';
+ $pin_connection = null;
+
+ // Intercept specific methods to determine if they are read-only or not.
+ $method = strtolower($method);
+ switch ($method) {
+ // case 'execute': // This is the direct overloaded function above instead.
+ case 'getone':
+ case 'getrow':
+ case 'getall':
+ case 'getcol':
+ case 'getassoc':
+ case 'selectlimit':
+ if ($this->isReadOnlyQuery(trim($args[0])) == true) {
+ $type = 'readonly';
+ }
+ break;
+ case 'cachegetone':
+ case 'cachegetrow':
+ case 'cachegetall':
+ case 'cachegetcol':
+ case 'cachegetassoc':
+ case 'cacheexecute':
+ case 'cacheselect':
+ case 'pageexecute':
+ case 'cachepageexecute':
+ $type = 'readonly';
+ break;
+ // case 'ignoreerrors':
+ // // When ignoreerrors is called, PIN to the connection until its called again.
+ // if (!isset($args[0]) || (isset($args[0]) && $args[0] == FALSE)) {
+ // $pin_connection = TRUE;
+ // } else {
+ // $pin_connection = FALSE;
+ // }
+ // break;
+
+ // Manual transactions
+ case 'begintrans':
+ case 'settransactionmode':
+ $pin_connection = true;
+ break;
+ case 'rollbacktrans':
+ case 'committrans':
+ $pin_connection = false;
+ break;
+ // Smart transactions
+ case 'starttrans':
+ $pin_connection = true;
+ break;
+ case 'completetrans':
+ case 'failtrans':
+ // getConnection() will only unpin the transaction if we're exiting the last nested transaction
+ $pin_connection = false;
+ break;
+
+ // Functions that don't require any connection and therefore
+ // shouldn't force a connection be established before they run.
+ case 'qstr':
+ case 'escape':
+ case 'binddate':
+ case 'bindtimestamp':
+ case 'setfetchmode':
+ $type = false; // No connection necessary.
+ break;
+
+ // Default to assuming write connection is required to be on the safe side.
+ default:
+ break;
+ }
+
+ if ($type === false) {
+ if (is_array($this->connections) && count($this->connections) > 0) {
+ foreach ($this->connections as $key => $connection_obj) {
+ $adodb_obj = $connection_obj->getADOdbObject();
+ return call_user_func_array(array($adodb_obj, $method), $this->makeValuesReferenced($args)); // Just makes the function call on the first object.
+ }
+ }
+ } else {
+ $adodb_obj = $this->getConnection($type, $pin_connection);
+ if (is_object($adodb_obj)) {
+ $result = call_user_func_array(array($adodb_obj, $method), $this->makeValuesReferenced($args));
+
+ return $result;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Magic method to proxy property getter calls back to the proper ADODB object currently in use.
+ *
+ * @param $property
+ * @return mixed
+ * @throws Exception
+ */
+ public function __get($property)
+ {
+ if (is_array($this->connections) && count($this->connections) > 0) {
+ foreach ($this->connections as $key => $connection_obj) {
+ // Just returns the property from the first object.
+ return $connection_obj->getADOdbObject()->$property;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Magic method to proxy property setter calls back to the proper ADODB object currently in use.
+ *
+ * @param $property
+ * @param $value
+ * @return mixed
+ * @throws Exception
+ */
+ public function __set($property, $value)
+ {
+ // Special function to set object properties on all objects
+ // without initiating a connection to the database.
+ if (is_array($this->connections) && count($this->connections) > 0) {
+ foreach ($this->connections as $key => $connection_obj) {
+ $connection_obj->getADOdbObject()->$property = $value;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Override the __clone() magic method.
+ */
+ private function __clone()
+ {
+ }
+}
+
+/**
+ * Class ADOdbLoadBalancerConnection
+ */
+class ADOdbLoadBalancerConnection
+{
+ /**
+ * @var bool ADOdb drive name.
+ */
+ protected $driver = false;
+
+ /**
+ * @var bool ADODB object.
+ */
+ protected $adodb_obj = false;
+
+ /**
+ * @var string Type of connection, either 'write' capable or 'readonly'
+ */
+ public $type = 'write';
+
+ /**
+ * @var int Weight of connection, lower receives less queries, higher receives more queries.
+ */
+ public $weight = 1;
+
+ /**
+ * @var bool Determines if the connection persistent.
+ */
+ public $persistent_connection = false;
+
+ /**
+ * @var string Database connection host
+ */
+ public $host = '';
+
+ /**
+ * @var string Database connection user
+ */
+ public $user = '';
+
+ /**
+ * @var string Database connection password
+ */
+ public $password = '';
+
+ /**
+ * @var string Database connection database name
+ */
+ public $database = '';
+
+ /**
+ * ADOdbLoadBalancerConnection constructor to setup the ADODB object.
+ *
+ * @param $driver
+ * @param string $type
+ * @param int $weight
+ * @param bool $persistent_connection
+ * @param string $argHostname
+ * @param string $argUsername
+ * @param string $argPassword
+ * @param string $argDatabaseName
+ */
+ public function __construct(
+ $driver,
+ $type = 'write',
+ $weight = 1,
+ $persistent_connection = false,
+ $argHostname = '',
+ $argUsername = '',
+ $argPassword = '',
+ $argDatabaseName = ''
+ ) {
+ if ($type !== 'write' && $type !== 'readonly') {
+ return false;
+ }
+
+ $this->adodb_obj = ADONewConnection($driver);
+
+ $this->type = $type;
+ $this->weight = $weight;
+ $this->persistent_connection = $persistent_connection;
+
+ $this->host = $argHostname;
+ $this->user = $argUsername;
+ $this->password = $argPassword;
+ $this->database = $argDatabaseName;
+
+ return true;
+ }
+
+ /**
+ * Returns the ADODB object for this connection.
+ *
+ * @return bool
+ */
+ public function getADOdbObject()
+ {
+ return $this->adodb_obj;
+ }
+}
diff --git a/adodb/adodb-memcache.lib.inc.php b/adodb/adodb-memcache.lib.inc.php
index 15ecd60..7f110e7 100644
--- a/adodb/adodb-memcache.lib.inc.php
+++ b/adodb/adodb-memcache.lib.inc.php
@@ -1,4 +1,23 @@
memCache = true; /// should we use memCache instead of caching in files
-$db->memCacheHost = array($ip1, $ip2, $ip3);
-$db->memCachePort = 11211; /// this is default memCache port
-$db->memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib)
-
-$db->Connect(...);
-$db->CacheExecute($sql);
-
- Note the memcache class is shared by all connections, is created during the first call to Connect/PConnect.
-
- Class instance is stored in $ADODB_CACHE
-*/
-
class ADODB_Cache_MemCache {
var $createdir = false; // create caching directory structure?
+ // $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;
+
//-----------------------------
// memcache specific variables
@@ -60,18 +56,23 @@ function __construct(&$obj)
// implement as lazy connection. The connection only occurs on CacheExecute call
function connect(&$err)
{
- if (!function_exists('memcache_pconnect')) {
- $err = 'Memcache module PECL extension not found!';
+ // 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!';
return false;
}
- $memcache = new MemCache;
-
if (!is_array($this->hosts)) $this->hosts = array($this->hosts);
$failcnt = 0;
foreach($this->hosts as $host) {
- if (!@$memcache->addServer($host,$this->port,true)) {
+ if (!@$memcache->addServer($host,$this->port)) {
$failcnt += 1;
}
}
@@ -93,8 +94,25 @@ function writecache($filename, $contents, $debug, $secs2cache)
}
if (!$this->_memcache) return false;
- if (!$this->_memcache->set($filename, $contents, $this->compress ? MEMCACHE_COMPRESSED : 0, $secs2cache)) {
- if ($debug) ADOConnection::outp(" Failed to save data at the memcached server! \n");
+ $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;
+ default:
+ $failed=true;
+ break;
+ }
+
+ if($failed) {
+ if ($debug) ADOConnection::outp(" Failed to save data at the memcache server! \n");
return false;
}
@@ -110,7 +128,7 @@ function readcache($filename, &$err, $secs2cache, $rsClass)
$rs = $this->_memcache->get($filename);
if (!$rs) {
- $err = 'Item with such key doesn\'t exists on the memcached server.';
+ $err = 'Item with such key doesn\'t exist on the memcache server.';
return $false;
}
@@ -176,8 +194,8 @@ function flushcache($filename, $debug=false)
$del = $this->_memcache->delete($filename);
if ($debug)
- if (!$del) ADOConnection::outp("flushcache: $key entry doesn't exist on memcached server! \n");
- else ADOConnection::outp("flushcache: $key entry flushed from memcached server! \n");
+ if (!$del) ADOConnection::outp("flushcache: $key entry doesn't exist on memcache server! \n");
+ else ADOConnection::outp("flushcache: $key entry flushed from memcache server! \n");
return $del;
}
diff --git a/adodb/adodb-pager.inc.php b/adodb/adodb-pager.inc.php
index 2106f01..cfe981d 100644
--- a/adodb/adodb-pager.inc.php
+++ b/adodb/adodb-pager.inc.php
@@ -1,28 +1,24 @@
implemented Render_PageLinks().
-
- Please note, this class is entirely unsupported,
- and no free support requests except for bug reports
- will be entertained by the author.
-
-*/
class ADODB_Pager {
var $id; // unique id for pager (defaults to 'adodb')
var $db; // ADODB connection object
@@ -275,7 +271,7 @@ function Render($rows=10)
}
//------------------------------------------------------
- // override this to control overall layout and formating
+ // override this to control overall layout and formatting
function RenderLayout($header,$grid,$footer,$attributes='border=1 bgcolor=beige')
{
echo "
",
diff --git a/adodb/adodb-pear.inc.php b/adodb/adodb-pear.inc.php
index 60fb69f..c48ef13 100644
--- a/adodb/adodb-pear.inc.php
+++ b/adodb/adodb-pear.inc.php
@@ -1,18 +1,25 @@
+ * and Tomas V.V.Cox . Portions (c)1997-2002 The PHP Group.
*
- * PEAR DB Emulation Layer for ADODB.
+ * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
*
- * The following code is modelled on PEAR DB code by Stig Bakken |
- * and Tomas V.V.Cox . Portions (c)1997-2002 The PHP Group.
+ * @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
*/
/*
@@ -336,7 +343,7 @@ function parseDSN($dsn)
$parsed['hostspec'] = urldecode($str);
}
- // Get dabase if any
+ // Get database if any
// $dsn => database
if (!empty($dsn)) {
$parsed['database'] = $dsn;
diff --git a/adodb/adodb-perf.inc.php b/adodb/adodb-perf.inc.php
index 1c48e9e..d9d8a99 100644
--- a/adodb/adodb-perf.inc.php
+++ b/adodb/adodb-perf.inc.php
@@ -1,22 +1,23 @@
_queryID);
}
$ok = $conn->Execute($isql,$arr);
+ if($conn instanceof ADODB_mysqli && $conn->_queryID){
+ mysqli_free_result($conn->_queryID);
+ }
} else
$ok = true;
@@ -229,7 +233,7 @@ class adodb_perf {
var $cliFormat = "%32s => %s \r\n";
var $sql1 = 'sql1'; // used for casting sql1 to text for mssql
var $explain = true;
- var $helpurl = 'LogSQL help';
+ var $helpurl = 'LogSQL help';
var $createTableSQL = false;
var $maxLength = 2000;
@@ -263,12 +267,6 @@ function _CPULoad()
// Algorithm is taken from
// http://social.technet.microsoft.com/Forums/en-US/winservergen/thread/414b0e1b-499c-411e-8a02-6a12e339c0f1/
if (strncmp(PHP_OS,'WIN',3)==0) {
- if (PHP_VERSION == '5.0.0') return false;
- if (PHP_VERSION == '5.0.1') return false;
- if (PHP_VERSION == '5.0.2') return false;
- if (PHP_VERSION == '5.0.3') return false;
- if (PHP_VERSION == '4.3.10') return false; # see http://bugs.php.net/bug.php?id=31737
-
static $FAIL = false;
if ($FAIL) return false;
@@ -593,7 +591,7 @@ function DBParameter($param)
}
/*
- Raw function returning array of poll paramters
+ Raw function returning array of poll parameters
*/
function PollParameters()
{
@@ -694,16 +692,6 @@ function UI($pollsecs=5)
}
$this->conn->LogSQL($savelog);
- // magic quotes
- // PHP7.4 spits deprecated notice, PHP8 removed magic_* stuff
- if (isset($_GET['sql']) &&
- version_compare(PHP_VERSION, '7.4.0', '<')
- && function_exists('get_magic_quotes_gpc')
- && get_magic_quotes_gpc()
- ) {
- $_GET['sql'] = $_GET['sql'] = str_replace(array("\\'",'\"'),array("'",'"'),$_GET['sql']);
- }
-
if (!isset($_SESSION['ADODB_PERF_SQL'])) $nsql = $_SESSION['ADODB_PERF_SQL'] = 10;
else $nsql = $_SESSION['ADODB_PERF_SQL'];
@@ -728,7 +716,7 @@ function UI($pollsecs=5)
if (empty($_GET['hidem']))
echo "
Performance StatsView SQLView TablesPoll Stats",
$allowsql ? ' Run SQL' : '',
@@ -959,7 +947,7 @@ function DoSQLForm()
undomq(trim($sql));
+ $sql = trim($sql);
if (substr($sql,strlen($sql)-1) === ';') {
$print = true;
$sqla = $this->SplitSQL($sql);
@@ -1003,18 +991,6 @@ function SplitSQL($sql)
return $arr;
}
- function undomq($m)
- {
- if (get_magic_quotes_gpc()) {
- // undo the damage
- $m = str_replace('\\\\','\\',$m);
- $m = str_replace('\"','"',$m);
- $m = str_replace('\\\'','\'',$m);
- }
- return $m;
-}
-
-
/************************************************************************/
/**
diff --git a/adodb/adodb-php4.inc.php b/adodb/adodb-php4.inc.php
deleted file mode 100644
index 4557eed..0000000
--- a/adodb/adodb-php4.inc.php
+++ /dev/null
@@ -1,16 +0,0 @@
- 4 digit year conversion. The maximum is billions of years in the
-future, but this is a theoretical limit as the computation of that year
-would take too long with the current implementation of adodb_mktime().
-
-This library replaces native functions as follows:
-
-
- getdate() with adodb_getdate()
- date() with adodb_date()
- gmdate() with adodb_gmdate()
- mktime() with adodb_mktime()
- gmmktime() with adodb_gmmktime()
- strftime() with adodb_strftime()
- strftime() with adodb_gmstrftime()
-
-
-The parameters are identical, except that adodb_date() accepts a subset
-of date()'s field formats. Mktime() will convert from local time to GMT,
-and date() will convert from GMT to local time, but daylight savings is
-not handled currently.
-
-This library is independant of the rest of ADOdb, and can be used
-as standalone code.
-
-PERFORMANCE
-
-For high speed, this library uses the native date functions where
-possible, and only switches to PHP code when the dates fall outside
-the 32-bit signed integer range.
-
-GREGORIAN CORRECTION
-
-Pope Gregory shortened October of A.D. 1582 by ten days. Thursday,
-October 4, 1582 (Julian) was followed immediately by Friday, October 15,
-1582 (Gregorian).
-
-Since 0.06, we handle this correctly, so:
-
-adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582)
- == 24 * 3600 (1 day)
-
-=============================================================================
-
-COPYRIGHT
-
-(c) 2003-2014 John Lim and released under BSD-style license except for code by
-jackbbs, which includes adodb_mktime, adodb_get_gmt_diff, adodb_is_leap_year
-and originally found at http://www.php.net/manual/en/function.mktime.php
-
+/**
+ * ADOdb Date Library.
+ *
+ * PHP native date functions use integer timestamps for computations.
+ * Because of this, dates are restricted to the years 1901-2038 on Unix
+ * and 1970-2038 on Windows due to integer overflow for dates beyond
+ * those years. This library overcomes these limitations by replacing the
+ * native function's signed integers (normally 32-bits) with PHP floating
+ * point numbers (normally 64-bits).
+ *
+ * Dates from 100 A.D. to 3000 A.D. and later have been tested.
+ * The minimum is 100 A.D. as <100 will invoke the 2 => 4 digit year
+ * conversion. The maximum is billions of years in the future, but this
+ * is a theoretical limit as the computation of that year would take too
+ * long with the current implementation of adodb_mktime().
+ *
+ * Replaces native functions as follows:
+ * - getdate() with adodb_getdate()
+ * - date() with adodb_date()
+ * - gmdate() with adodb_gmdate()
+ * - mktime() with adodb_mktime()
+ * - gmmktime() with adodb_gmmktime()
+ * - strftime() with adodb_strftime()
+ * - strftime() with adodb_gmstrftime()
+ *
+ * The parameters are identical, except that adodb_date() accepts a subset
+ * of date()'s field formats. Mktime() will convert from local time to GMT,
+ * and date() will convert from GMT to local time, but daylight savings is
+ * not handled currently.
+ *
+ * To improve performance, the native date functions are used whenever
+ * possible, the library only switches to PHP code when the dates fall outside
+ * of the 32-bit signed integer range.
+ *
+ * This library is independent of the rest of ADOdb, and can be used
+ * as standalone code.
+ *
+ * GREGORIAN CORRECTION
+ *
+ * Pope Gregory shortened October of A.D. 1582 by ten days. Thursday,
+ * October 4, 1582 (Julian) was followed immediately by Friday, October 15,
+ * 1582 (Gregorian). We handle this correctly, so:
+ * adodb_mktime(0, 0, 0, 10, 15, 1582) - adodb_mktime(0, 0, 0, 10, 4, 1582)
+ * == 24 * 3600 (1 day)
+ *
+ * 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 2003-2013 John Lim
+ * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
+ */
+/*
=============================================================================
FUNCTION DESCRIPTIONS
@@ -261,7 +256,7 @@
* Now adodb_mktime(0,0,0,24,1,2037) works correctly.
- 15 July 2007 0.30
-Added PHP 5.2.0 compatability fixes.
+Added PHP 5.2.0 compatibility fixes.
* gmtime behaviour for 1970 has changed. We use the actual date if it is between 1970 to 2038 to get the
* timezone, otherwise we use the current year as the baseline to retrieve the timezone.
* Also the timezone's in php 5.2.* support historical data better, eg. if timezone today was +8, but
@@ -397,8 +392,6 @@ function adodb_daylight_sv(&$arr, $is_gmt)
*/
define('ADODB_DATE_VERSION',0.35);
-$ADODB_DATETIME_CLASS = (PHP_VERSION >= 5.2);
-
/*
This code was originally for windows. But apparently this problem happens
also with Linux, RH 7.3 and later!
@@ -525,8 +518,8 @@ function adodb_date_test()
if (adodb_year_digit_check(50) != 1950) print "Err 2-digit 1950 ";
if (adodb_year_digit_check(90) != 1990) print "Err 2-digit 1990 ";
- // Test string formating
- print "
Testing date formating
";
+ // Test string formatting
+ print "
Testing date formatting
";
$fmt = '\d\a\t\e T Y-m-d H:i:s a A d D F g G h H i j l L m M n O \R\F\C2822 r s t U w y Y z Z 2003';
$s1 = date($fmt,0);
@@ -730,13 +723,12 @@ function adodb_get_gmt_diff_ts($ts)
*/
function adodb_get_gmt_diff($y,$m,$d)
{
-static $TZ,$tzo;
-global $ADODB_DATETIME_CLASS;
+ static $TZ,$tzo;
if (!defined('ADODB_TEST_DATES')) $y = false;
else if ($y < 1970 || $y >= 2038) $y = false;
- if ($ADODB_DATETIME_CLASS && $y !== false) {
+ if ($y !== false) {
$dt = new DateTime();
$dt->setISODate($y,$m,$d);
if (empty($tzo)) {
@@ -1028,20 +1020,20 @@ function _adodb_getdate($origd=false,$fast=false,$is_gmt=false)
0 => $origd
);
}
-/*
- if ($isphp5)
- $dates .= sprintf('%s%04d',($gmt<=0)?'+':'-',abs($gmt)/36);
- else
- $dates .= sprintf('%s%04d',($gmt<0)?'+':'-',abs($gmt)/36);
- break;*/
-function adodb_tz_offset($gmt,$isphp5)
+
+/**
+ * Compute timezone offset.
+ *
+ * @param int $gmt Time offset from GMT, in seconds
+ * @param bool $ignored Param leftover from removed PHP4-compatibility code
+ * kept to avoid altering function signature.
+ * @return string
+ */
+function adodb_tz_offset($gmt, $ignored=true)
{
- $zhrs = abs($gmt)/3600;
+ $zhrs = abs($gmt) / 3600;
$hrs = floor($zhrs);
- if ($isphp5)
- return sprintf('%s%02d%02d',($gmt<=0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60);
- else
- return sprintf('%s%02d%02d',($gmt<0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60);
+ return sprintf('%s%02d%02d', ($gmt <= 0) ? '+' : '-', $hrs, ($zhrs - $hrs) * 60);
}
@@ -1074,10 +1066,8 @@ function adodb_date2($fmt, $d=false, $is_gmt=false)
*/
function adodb_date($fmt,$d=false,$is_gmt=false)
{
-static $daylight;
-global $ADODB_DATETIME_CLASS;
-static $jan1_1971;
-
+ static $daylight;
+ static $jan1_1971;
if (!isset($daylight)) {
$daylight = function_exists('adodb_daylight_sv');
@@ -1086,7 +1076,15 @@ function adodb_date($fmt,$d=false,$is_gmt=false)
if ($d === false) return ($is_gmt)? @gmdate($fmt): @date($fmt);
if (!defined('ADODB_TEST_DATES')) {
- if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
+
+ /*
+ * Format 'Q' is an ADOdb custom format, not supported in PHP
+ * so if there is a 'Q' in the format, we force it to use our
+ * function. There is a trivial overhead in this
+ */
+
+ if ((abs($d) <= 0x7FFFFFFF) && strpos($fmt,'Q') === false)
+ { // check if number in 32-bit signed range
if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= $jan1_1971) // if windows, must be +ve integer
return ($is_gmt)? @gmdate($fmt,$d): @date($fmt,$d);
@@ -1109,8 +1107,6 @@ function adodb_date($fmt,$d=false,$is_gmt=false)
$max = strlen($fmt);
$dates = '';
- $isphp5 = PHP_VERSION >= 5;
-
/*
at this point, we have the following integer vars to manipulate:
$year, $month, $day, $hour, $min, $secs
@@ -1121,12 +1117,9 @@ function adodb_date($fmt,$d=false,$is_gmt=false)
$dates .= date('e');
break;
case 'T':
- if ($ADODB_DATETIME_CLASS) {
- $dt = new DateTime();
- $dt->SetDate($year,$month,$day);
- $dates .= $dt->Format('T');
- } else
- $dates .= date('T');
+ $dt = new DateTime();
+ $dt->SetDate($year,$month,$day);
+ $dates .= $dt->Format('T');
break;
// YEAR
case 'L': $dates .= $arr['leap'] ? '1' : '0'; break;
@@ -1145,14 +1138,16 @@ function adodb_date($fmt,$d=false,$is_gmt=false)
$gmt = adodb_get_gmt_diff($year,$month,$day);
- $dates .= ' '.adodb_tz_offset($gmt,$isphp5);
+ $dates .= ' '.adodb_tz_offset($gmt);
break;
case 'Y': $dates .= $year; break;
case 'y': $dates .= substr($year,strlen($year)-2,2); break;
// MONTH
case 'm': if ($month<10) $dates .= '0'.$month; else $dates .= $month; break;
- case 'Q': $dates .= ($month+3)>>2; break;
+ case 'Q':
+ $dates .= ceil($month / 3);
+ break;
case 'n': $dates .= $month; break;
case 'M': $dates .= date('M',mktime(0,0,0,$month,2,1971)); break;
case 'F': $dates .= date('F',mktime(0,0,0,$month,2,1971)); break;
@@ -1160,6 +1155,9 @@ function adodb_date($fmt,$d=false,$is_gmt=false)
case 't': $dates .= $arr['ndays']; break;
case 'z': $dates .= $arr['yday']; break;
case 'w': $dates .= adodb_dow($year,$month,$day); break;
+ case 'W':
+ $dates .= sprintf('%02d',ceil( $arr['yday'] / 7) - 1);
+ break;
case 'l': $dates .= gmdate('l',$_day_power*(3+adodb_dow($year,$month,$day))); break;
case 'D': $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))); break;
case 'j': $dates .= $day; break;
@@ -1178,7 +1176,7 @@ function adodb_date($fmt,$d=false,$is_gmt=false)
case 'O':
$gmt = ($is_gmt) ? 0 : adodb_get_gmt_diff($year,$month,$day);
- $dates .= adodb_tz_offset($gmt,$isphp5);
+ $dates .= adodb_tz_offset($gmt);
break;
case 'H':
diff --git a/adodb/adodb-xmlschema.inc.php b/adodb/adodb-xmlschema.inc.php
index c3af7fa..58e3aff 100644
--- a/adodb/adodb-xmlschema.inc.php
+++ b/adodb/adodb-xmlschema.inc.php
@@ -1,21 +1,29 @@
mgq = version_compare(PHP_VERSION, '7.4.0', '<') && function_exists('get_magic_quotes_runtime') && get_magic_quotes_runtime();
- if ($this->mgq !== false) {
- ini_set('magic_quotes_runtime', 0);
- }
-
$this->db = $db;
$this->debug = $this->db->debug;
- $this->dict = NewDataDictionary( $this->db );
+ $this->dict = newDataDictionary( $this->db );
$this->sqlArray = array();
$this->schemaVersion = XMLS_SCHEMA_VERSION;
$this->executeInline( XMLS_EXECUTE_INLINE );
@@ -2196,11 +2191,7 @@ function getSQL( $format = NULL, $sqlArray = NULL ) {
* Call this method to clean up after an adoSchema object that is no longer in use.
* @deprecated adoSchema now cleans up automatically.
*/
- function Destroy() {
- if ($this->mgq !== false) {
- ini_set('magic_quotes_runtime', $this->mgq );
- }
- }
+ function Destroy() {}
}
/**
diff --git a/adodb/adodb-xmlschema03.inc.php b/adodb/adodb-xmlschema03.inc.php
index f675d99..de1ea26 100644
--- a/adodb/adodb-xmlschema03.inc.php
+++ b/adodb/adodb-xmlschema03.inc.php
@@ -1,21 +1,29 @@
currentElement = strtoupper( $tag );
switch( $this->currentElement ) {
@@ -345,8 +353,16 @@ function _tag_open( &$parser, $tag, $attributes ) {
*
* @access private
*/
- function _tag_cdata( &$parser, $cdata ) {
+ function _tag_cdata( $parser, $cdata ) {
switch( $this->currentElement ) {
+ // Table or field comment
+ case 'DESCR':
+ if( isset( $this->current_field ) ) {
+ $this->addFieldOpt( $this->current_field, $this->currentElement, $cdata );
+ } else {
+ $this->addTableComment( $cdata );
+ }
+ break;
// Table/field constraint
case 'CONSTRAINT':
if( isset( $this->current_field ) ) {
@@ -373,7 +389,7 @@ function _tag_cdata( &$parser, $cdata ) {
*
* @access private
*/
- function _tag_close( &$parser, $tag ) {
+ function _tag_close( $parser, $tag ) {
$this->currentElement = '';
switch( strtoupper( $tag ) ) {
@@ -449,7 +465,7 @@ function addData( $attributes ) {
* @return array Field specifier array
*/
function addField( $name, $type, $size = NULL, $opts = NULL ) {
- $field_id = $this->FieldID( $name );
+ $field_id = $this->fieldID( $name );
// Set the field index so we know where we are
$this->current_field = $field_id;
@@ -506,11 +522,15 @@ function addFieldOpt( $field, $opt, $value = NULL ) {
*/
function addTableOpt( $opt ) {
if(isset($this->currentPlatform)) {
- $this->opts[$this->parent->db->databaseType] = $opt;
+ $this->opts[$this->parent->db->dataProvider] = $opt;
}
return $this->opts;
}
+ function addTableComment( $opt ) {
+ $this->opts['comment'] = $opt;
+ return $this->opts;
+ }
/**
* Generates the SQL that will create the table in the database
@@ -522,9 +542,9 @@ function create( &$xmls ) {
$sql = array();
// drop any existing indexes
- if( is_array( $legacy_indexes = $xmls->dict->MetaIndexes( $this->name ) ) ) {
+ if( is_array( $legacy_indexes = $xmls->dict->metaIndexes( $this->name ) ) ) {
foreach( $legacy_indexes as $index => $index_details ) {
- $sql[] = $xmls->dict->DropIndexSQL( $index, $this->name );
+ $sql[] = $xmls->dict->dropIndexSQL( $index, $this->name );
}
}
@@ -534,10 +554,10 @@ function create( &$xmls ) {
}
// if table exists
- if( is_array( $legacy_fields = $xmls->dict->MetaColumns( $this->name ) ) ) {
+ if( is_array( $legacy_fields = $xmls->dict->metaColumns( $this->name ) ) ) {
// drop table
if( $this->drop_table ) {
- $sql[] = $xmls->dict->DropTableSQL( $this->name );
+ $sql[] = $xmls->dict->dropTableSQL( $this->name );
return $sql;
}
@@ -545,7 +565,7 @@ function create( &$xmls ) {
// drop any existing fields not in schema
foreach( $legacy_fields as $field_id => $field ) {
if( !isset( $this->fields[$field_id] ) ) {
- $sql[] = $xmls->dict->DropColumnSQL( $this->name, $field->name );
+ $sql[] = $xmls->dict->dropColumnSQL( $this->name, $field->name );
}
}
// if table doesn't exist
@@ -591,21 +611,21 @@ function create( &$xmls ) {
if( empty( $legacy_fields ) ) {
// Create the new table
- $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
- logMsg( end( $sql ), 'Generated CreateTableSQL' );
+ $sql[] = $xmls->dict->createTableSQL( $this->name, $fldarray, $this->opts );
+ logMsg( end( $sql ), 'Generated createTableSQL' );
} else {
// Upgrade an existing table
logMsg( "Upgrading {$this->name} using '{$xmls->upgrade}'" );
switch( $xmls->upgrade ) {
// Use ChangeTableSQL
case 'ALTER':
- logMsg( 'Generated ChangeTableSQL (ALTERing table)' );
- $sql[] = $xmls->dict->ChangeTableSQL( $this->name, $fldarray, $this->opts );
+ logMsg( 'Generated changeTableSQL (ALTERing table)' );
+ $sql[] = $xmls->dict->changeTableSQL( $this->name, $fldarray, $this->opts );
break;
case 'REPLACE':
logMsg( 'Doing upgrade REPLACE (testing)' );
- $sql[] = $xmls->dict->DropTableSQL( $this->name );
- $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
+ $sql[] = $xmls->dict->dropTableSQL( $this->name );
+ $sql[] = $xmls->dict->createTableSQL( $this->name, $fldarray, $this->opts );
break;
// ignore table
default:
@@ -698,7 +718,7 @@ function __construct( &$parent, $attributes = NULL ) {
*
* @access private
*/
- function _tag_open( &$parser, $tag, $attributes ) {
+ function _tag_open( $parser, $tag, $attributes ) {
$this->currentElement = strtoupper( $tag );
switch( $this->currentElement ) {
@@ -725,7 +745,7 @@ function _tag_open( &$parser, $tag, $attributes ) {
*
* @access private
*/
- function _tag_cdata( &$parser, $cdata ) {
+ function _tag_cdata( $parser, $cdata ) {
switch( $this->currentElement ) {
// Index field name
case 'COL':
@@ -741,7 +761,7 @@ function _tag_cdata( &$parser, $cdata ) {
*
* @access private
*/
- function _tag_close( &$parser, $tag ) {
+ function _tag_close( $parser, $tag ) {
$this->currentElement = '';
switch( strtoupper( $tag ) ) {
@@ -758,7 +778,7 @@ function _tag_close( &$parser, $tag ) {
* @return string Field list
*/
function addField( $name ) {
- $this->columns[$this->FieldID( $name )] = $name;
+ $this->columns[$this->fieldID( $name )] = $name;
// Return the field list
return $this->columns;
@@ -795,7 +815,7 @@ function create( &$xmls ) {
}
}
- return $xmls->dict->CreateIndexSQL( $this->name, $this->parent->name, $this->columns, $this->opts );
+ return $xmls->dict->createIndexSQL( $this->name, $this->parent->name, $this->columns, $this->opts );
}
/**
@@ -841,7 +861,7 @@ function __construct( &$parent, $attributes = NULL ) {
*
* @access private
*/
- function _tag_open( &$parser, $tag, $attributes ) {
+ function _tag_open( $parser, $tag, $attributes ) {
$this->currentElement = strtoupper( $tag );
switch( $this->currentElement ) {
@@ -863,7 +883,7 @@ function _tag_open( &$parser, $tag, $attributes ) {
*
* @access private
*/
- function _tag_cdata( &$parser, $cdata ) {
+ function _tag_cdata( $parser, $cdata ) {
switch( $this->currentElement ) {
// Index field name
case 'F':
@@ -879,7 +899,7 @@ function _tag_cdata( &$parser, $cdata ) {
*
* @access private
*/
- function _tag_close( &$parser, $tag ) {
+ function _tag_close( $parser, $tag ) {
$this->currentElement = '';
switch( strtoupper( $tag ) ) {
@@ -903,7 +923,7 @@ function addField( $attributes ) {
// Set the field index so we know where we are
if( isset( $attributes['NAME'] ) ) {
- $this->current_field = $this->FieldID( $attributes['NAME'] );
+ $this->current_field = $this->fieldID( $attributes['NAME'] );
} else {
$this->current_field = count( $this->data[$this->row] );
}
@@ -935,12 +955,12 @@ function addData( $cdata ) {
* @return array Array containing index creation SQL
*/
function create( &$xmls ) {
- $table = $xmls->dict->TableName($this->parent->name);
+ $table = $xmls->dict->tableName($this->parent->name);
$table_field_count = count($this->parent->fields);
- $tables = $xmls->db->MetaTables();
+ $tables = $xmls->db->metaTables();
$sql = array();
- $ukeys = $xmls->db->MetaPrimaryKeys( $table );
+ $ukeys = $xmls->db->metaPrimaryKeys( $table );
if( !empty( $this->parent->indexes ) and !empty( $ukeys ) ) {
foreach( $this->parent->indexes as $indexObj ) {
if( !in_array( $indexObj->name, $ukeys ) ) $ukeys[] = $indexObj->name;
@@ -1027,19 +1047,19 @@ function create( &$xmls ) {
$where .= $key . ' = ' . $xmls->db->qstr( $mfields[$key] );
}
}
- $records = $xmls->db->Execute( 'SELECT * FROM ' . $table . ' WHERE ' . $where );
- switch( $records->RecordCount() ) {
+ $records = $xmls->db->execute( 'SELECT * FROM ' . $table . ' WHERE ' . $where );
+ switch( $records->recordCount() ) {
case 0:
// No matching record, so safe to insert.
logMsg( "No matching records. Inserting new row with unique data" );
- $sql[] = $xmls->db->GetInsertSQL( $records, $mfields );
+ $sql[] = $xmls->db->getInsertSQL( $records, $mfields );
break;
case 1:
// Exactly one matching record, so we can update if the mode permits.
logMsg( "One matching record..." );
if( $mode == XMLS_MODE_UPDATE ) {
logMsg( "...Updating existing row from unique data" );
- $sql[] = $xmls->db->GetUpdateSQL( $records, $mfields );
+ $sql[] = $xmls->db->getUpdateSQL( $records, $mfields );
}
break;
default:
@@ -1115,7 +1135,7 @@ function __construct( &$parent, $attributes = NULL ) {
*
* @access private
*/
- function _tag_open( &$parser, $tag, $attributes ) {
+ function _tag_open( $parser, $tag, $attributes ) {
$this->currentElement = strtoupper( $tag );
switch( $this->currentElement ) {
@@ -1137,7 +1157,7 @@ function _tag_open( &$parser, $tag, $attributes ) {
/**
* XML Callback to process CDATA elements
*/
- function _tag_cdata( &$parser, $cdata ) {
+ function _tag_cdata( $parser, $cdata ) {
switch( $this->currentElement ) {
// Line of queryset SQL data
case 'QUERY':
@@ -1153,7 +1173,7 @@ function _tag_cdata( &$parser, $cdata ) {
*
* @access private
*/
- function _tag_close( &$parser, $tag ) {
+ function _tag_close( $parser, $tag ) {
$this->currentElement = '';
switch( strtoupper( $tag ) ) {
@@ -1353,13 +1373,6 @@ class adoSchema {
*/
var $objectPrefix = '';
- /**
- * @var long Original Magic Quotes Runtime value
- * @access private
- * @deprecated
- */
- var $mgq;
-
/**
* @var long System debug
* @access private
@@ -1408,15 +1421,9 @@ class adoSchema {
* @param object $db ADOdb database connection object.
*/
function __construct( $db ) {
- // PHP7.4 has deprecated notice, PHP8 removed magic_* stuff
- $this->mgq = version_compare(PHP_VERSION, '7.4.0', '<') && function_exists('get_magic_quotes_runtime') && get_magic_quotes_runtime();
- if ($this->mgq !== false) {
- ini_set('magic_quotes_runtime', 0 );
- }
-
$this->db = $db;
$this->debug = $this->db->debug;
- $this->dict = NewDataDictionary( $this->db );
+ $this->dict = newDataDictionary( $this->db );
$this->sqlArray = array();
$this->schemaVersion = XMLS_SCHEMA_VERSION;
$this->executeInline( XMLS_EXECUTE_INLINE );
@@ -1441,7 +1448,7 @@ function __construct( $db ) {
* @param string $method Upgrade method (ALTER|REPLACE|BEST|NONE)
* @returns string Upgrade method used
*/
- function SetUpgradeMethod( $method = '' ) {
+ function setUpgradeMethod( $method = '' ) {
if( !is_string( $method ) ) {
return FALSE;
}
@@ -1489,7 +1496,7 @@ function SetUpgradeMethod( $method = '' ) {
* @param int $mode XMLS_MODE_INSERT, XMLS_MODE_UPDATE, or XMLS_MODE_IGNORE
* @return int current mode
*/
- function ExistingData( $mode = NULL ) {
+ function existingData( $mode = NULL ) {
if( is_int( $mode ) ) {
switch( $mode ) {
case XMLS_MODE_UPDATE:
@@ -1524,7 +1531,7 @@ function ExistingData( $mode = NULL ) {
*
* @see ParseSchema(), ExecuteSchema()
*/
- function ExecuteInline( $mode = NULL ) {
+ function executeInline( $mode = NULL ) {
if( is_bool( $mode ) ) {
$this->executeInline = $mode;
}
@@ -1545,7 +1552,7 @@ function ExecuteInline( $mode = NULL ) {
*
* @see addSQL(), ExecuteSchema()
*/
- function ContinueOnError( $mode = NULL ) {
+ function continueOnError( $mode = NULL ) {
if( is_bool( $mode ) ) {
$this->continueOnError = $mode;
}
@@ -1566,8 +1573,8 @@ function ContinueOnError( $mode = NULL ) {
* @param bool $returnSchema Return schema rather than parsing.
* @return array Array of SQL queries, ready to execute
*/
- function ParseSchema( $filename, $returnSchema = FALSE ) {
- return $this->ParseSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
+ function parseSchema( $filename, $returnSchema = FALSE ) {
+ return $this->parseSchemaString( $this->convertSchemaFile( $filename ), $returnSchema );
}
/**
@@ -1576,22 +1583,22 @@ function ParseSchema( $filename, $returnSchema = FALSE ) {
* Call this method to load the specified schema directly from a file (see
* the DTD for the proper format) and generate the SQL necessary to create
* the database described by the schema. Use this method when you are dealing
- * with large schema files. Otherwise, ParseSchema() is faster.
+ * with large schema files. Otherwise, parseSchema() is faster.
* This method does not automatically convert the schema to the latest axmls
* schema version. You must convert the schema manually using either the
- * ConvertSchemaFile() or ConvertSchemaString() method.
- * @see ParseSchema()
- * @see ConvertSchemaFile()
- * @see ConvertSchemaString()
+ * convertSchemaFile() or convertSchemaString() method.
+ * @see parseSchema()
+ * @see convertSchemaFile()
+ * @see convertSchemaString()
*
* @param string $file Name of XML schema file.
* @param bool $returnSchema Return schema rather than parsing.
* @return array Array of SQL queries, ready to execute.
*
- * @deprecated Replaced by adoSchema::ParseSchema() and adoSchema::ParseSchemaString()
- * @see ParseSchema(), ParseSchemaString()
+ * @deprecated Replaced by adoSchema::parseSchema() and adoSchema::parseSchemaString()
+ * @see parseSchema(), parseSchemaString()
*/
- function ParseSchemaFile( $filename, $returnSchema = FALSE ) {
+ function parseSchemaFile( $filename, $returnSchema = FALSE ) {
// Open the file
if( !($fp = fopen( $filename, 'r' )) ) {
logMsg( 'Unable to open file' );
@@ -1599,7 +1606,7 @@ function ParseSchemaFile( $filename, $returnSchema = FALSE ) {
}
// do version detection here
- if( $this->SchemaFileVersion( $filename ) != $this->schemaVersion ) {
+ if( $this->schemaFileVersion( $filename ) != $this->schemaVersion ) {
logMsg( 'Invalid Schema Version' );
return FALSE;
}
@@ -1637,13 +1644,13 @@ function ParseSchemaFile( $filename, $returnSchema = FALSE ) {
*
* Call this method to parse a string containing an XML schema (see the DTD for the proper format)
* and generate the SQL necessary to create the database described by the schema.
- * @see ParseSchema()
+ * @see parseSchema()
*
* @param string $xmlstring XML schema string.
* @param bool $returnSchema Return schema rather than parsing.
* @return array Array of SQL queries, ready to execute.
*/
- function ParseSchemaString( $xmlstring, $returnSchema = FALSE ) {
+ function parseSchemaString( $xmlstring, $returnSchema = FALSE ) {
if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
logMsg( 'Empty or Invalid Schema' );
return FALSE;
@@ -1687,8 +1694,8 @@ function ParseSchemaString( $xmlstring, $returnSchema = FALSE ) {
* @param bool $returnSchema Return schema rather than parsing.
* @return array Array of SQL queries, ready to execute
*/
- function RemoveSchema( $filename, $returnSchema = FALSE ) {
- return $this->RemoveSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
+ function removeSchema( $filename, $returnSchema = FALSE ) {
+ return $this->removeSchemaString( $this->convertSchemaFile( $filename ), $returnSchema );
}
/**
@@ -1696,38 +1703,38 @@ function RemoveSchema( $filename, $returnSchema = FALSE ) {
*
* Call this method to parse a string containing an XML schema (see the DTD for the proper format)
* and generate the SQL necessary to uninstall the database described by the schema.
- * @see RemoveSchema()
+ * @see removeSchema()
*
* @param string $schema XML schema string.
* @param bool $returnSchema Return schema rather than parsing.
* @return array Array of SQL queries, ready to execute.
*/
- function RemoveSchemaString( $schema, $returnSchema = FALSE ) {
+ function removeSchemaString( $schema, $returnSchema = FALSE ) {
// grab current version
- if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
+ if( !( $version = $this->schemaStringVersion( $schema ) ) ) {
return FALSE;
}
- return $this->ParseSchemaString( $this->TransformSchema( $schema, 'remove-' . $version), $returnSchema );
+ return $this->parseSchemaString( $this->transformSchema( $schema, 'remove-' . $version), $returnSchema );
}
/**
* Applies the current XML schema to the database (post execution).
*
* Call this method to apply the current schema (generally created by calling
- * ParseSchema() or ParseSchemaString() ) to the database (creating the tables, indexes,
+ * parseSchema() or parseSchemaString() ) to the database (creating the tables, indexes,
* and executing other SQL specified in the schema) after parsing.
- * @see ParseSchema(), ParseSchemaString(), ExecuteInline()
+ * @see parseSchema(), parseSchemaString(), executeInline()
*
* @param array $sqlArray Array of SQL statements that will be applied rather than
* the current schema.
* @param boolean $continueOnErr Continue to apply the schema even if an error occurs.
* @returns integer 0 if failure, 1 if errors, 2 if successful.
*/
- function ExecuteSchema( $sqlArray = NULL, $continueOnErr = NULL ) {
+ function executeSchema( $sqlArray = NULL, $continueOnErr = NULL ) {
if( !is_bool( $continueOnErr ) ) {
- $continueOnErr = $this->ContinueOnError();
+ $continueOnErr = $this->continueOnError();
}
if( !isset( $sqlArray ) ) {
@@ -1737,7 +1744,7 @@ function ExecuteSchema( $sqlArray = NULL, $continueOnErr = NULL ) {
if( !is_array( $sqlArray ) ) {
$this->success = 0;
} else {
- $this->success = $this->dict->ExecuteSQLArray( $sqlArray, $continueOnErr );
+ $this->success = $this->dict->executeSQLArray( $sqlArray, $continueOnErr );
}
return $this->success;
@@ -1747,12 +1754,12 @@ function ExecuteSchema( $sqlArray = NULL, $continueOnErr = NULL ) {
* Returns the current SQL array.
*
* Call this method to fetch the array of SQL queries resulting from
- * ParseSchema() or ParseSchemaString().
+ * parseSchema() or parseSchemaString().
*
* @param string $format Format: HTML, TEXT, or NONE (PHP array)
* @return array Array of SQL statements or FALSE if an error occurs
*/
- function PrintSQL( $format = 'NONE' ) {
+ function printSQL( $format = 'NONE' ) {
$sqlArray = null;
return $this->getSQL( $format, $sqlArray );
}
@@ -1766,7 +1773,7 @@ function PrintSQL( $format = 'NONE' ) {
* @param string $filename Path and name where the file should be saved.
* @return boolean TRUE if save is successful, else FALSE.
*/
- function SaveSQL( $filename = './schema.sql' ) {
+ function saveSQL( $filename = './schema.sql' ) {
if( !isset( $sqlArray ) ) {
$sqlArray = $this->sqlArray;
@@ -1807,7 +1814,7 @@ function create_parser() {
*
* @access private
*/
- function _tag_open( &$parser, $tag, $attributes ) {
+ function _tag_open( $parser, $tag, $attributes ) {
switch( strtoupper( $tag ) ) {
case 'TABLE':
if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
@@ -1832,7 +1839,7 @@ function _tag_open( &$parser, $tag, $attributes ) {
*
* @access private
*/
- function _tag_cdata( &$parser, $cdata ) {
+ function _tag_cdata( $parser, $cdata ) {
}
/**
@@ -1841,7 +1848,7 @@ function _tag_cdata( &$parser, $cdata ) {
* @access private
* @internal
*/
- function _tag_close( &$parser, $tag ) {
+ function _tag_close( $parser, $tag ) {
}
@@ -1854,17 +1861,17 @@ function _tag_close( &$parser, $tag ) {
* parameter is specified, the schema will be converted to the current DTD version.
* If the newFile parameter is provided, the converted schema will be written to the specified
* file.
- * @see ConvertSchemaFile()
+ * @see convertSchemaFile()
*
* @param string $schema String containing XML schema that will be converted.
* @param string $newVersion DTD version to convert to.
* @param string $newFile File name of (converted) output file.
* @return string Converted XML schema or FALSE if an error occurs.
*/
- function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
+ function convertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
// grab current version
- if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
+ if( !( $version = $this->schemaStringVersion( $schema ) ) ) {
return FALSE;
}
@@ -1875,7 +1882,7 @@ function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
if( $version == $newVersion ) {
$result = $schema;
} else {
- $result = $this->TransformSchema( $schema, 'convert-' . $version . '-' . $newVersion);
+ $result = $this->transformSchema( $schema, 'convert-' . $version . '-' . $newVersion);
}
if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
@@ -1903,17 +1910,17 @@ function _file_get_contents($path)
* parameter is specified, the schema will be converted to the current DTD version.
* If the newFile parameter is provided, the converted schema will be written to the specified
* file.
- * @see ConvertSchemaString()
+ * @see convertSchemaString()
*
* @param string $filename Name of XML schema file that will be converted.
* @param string $newVersion DTD version to convert to.
* @param string $newFile File name of (converted) output file.
* @return string Converted XML schema or FALSE if an error occurs.
*/
- function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
+ function convertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
// grab current version
- if( !( $version = $this->SchemaFileVersion( $filename ) ) ) {
+ if( !( $version = $this->schemaFileVersion( $filename ) ) ) {
return FALSE;
}
@@ -1929,7 +1936,7 @@ function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
$result = substr( $result, 3 );
}
} else {
- $result = $this->TransformSchema( $filename, 'convert-' . $version . '-' . $newVersion, 'file' );
+ $result = $this->transformSchema( $filename, 'convert-' . $version . '-' . $newVersion, 'file' );
}
if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
@@ -1940,7 +1947,7 @@ function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
return $result;
}
- function TransformSchema( $schema, $xsl, $schematype='string' )
+ function transformSchema( $schema, $xsl, $schematype='string' )
{
// Fail if XSLT extension is not available
if( ! function_exists( 'xslt_create' ) ) {
@@ -2051,7 +2058,7 @@ function xslt_error_handler( $parser, $errno, $level, $fields ) {
* @param string $filename AXMLS schema file
* @return string Schema version number or FALSE on error
*/
- function SchemaFileVersion( $filename ) {
+ function schemaFileVersion( $filename ) {
// Open the file
if( !($fp = fopen( $filename, 'r' )) ) {
// die( 'Unable to open file' );
@@ -2077,7 +2084,7 @@ function SchemaFileVersion( $filename ) {
* @param string $xmlstring XML schema string
* @return string Schema version number or FALSE on error
*/
- function SchemaStringVersion( $xmlstring ) {
+ function schemaStringVersion( $xmlstring ) {
if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
return FALSE;
}
@@ -2094,20 +2101,20 @@ function SchemaStringVersion( $xmlstring ) {
*
* Call this method to create an XML schema string from an existing database.
* If the data parameter is set to TRUE, AXMLS will include the data from the database
- * in the schema.
+ * tables in the schema.
*
- * @param boolean $data Include data in schema dump
- * @indent string indentation to use
- * @prefix string extract only tables with given prefix
- * @stripprefix strip prefix string when storing in XML schema
+ * @param boolean $data include data in schema dump
+ * @param string $indent indentation to use
+ * @param string $prefix extract only tables with given prefix
+ * @param boolean $stripprefix strip prefix string when storing in XML schema
* @return string Generated XML schema
*/
- function ExtractSchema( $data = FALSE, $indent = ' ', $prefix = '' , $stripprefix=false) {
- $old_mode = $this->db->SetFetchMode( ADODB_FETCH_NUM );
+ function extractSchema( $data = FALSE, $indent = ' ', $prefix = '' , $stripprefix=false) {
+ $old_mode = $this->db->setFetchMode( ADODB_FETCH_NUM );
$schema = '' . "\n"
. '' . "\n";
- if( is_array( $tables = $this->db->MetaTables( 'TABLES' ,false ,($prefix) ? str_replace('_','\_',$prefix).'%' : '') ) ) {
+ if( is_array( $tables = $this->db->metaTables( 'TABLES' ,false ,($prefix) ? str_replace('_','\_',$prefix).'%' : '') ) ) {
foreach( $tables as $table ) {
$schema .= $indent
. '
' . "\n";
// grab details from database
- $rs = $this->db->Execute( 'SELECT * FROM ' . $table . ' WHERE -1' );
- $fields = $this->db->MetaColumns( $table );
- $indexes = $this->db->MetaIndexes( $table );
+ $rs = $this->db->execute('SELECT * FROM ' . $table . ' WHERE 0=1');
+ $fields = $this->db->metaColumns( $table );
+ $indexes = $this->db->metaIndexes( $table );
if( is_array( $fields ) ) {
foreach( $fields as $details ) {
@@ -2149,7 +2156,7 @@ function ExtractSchema( $data = FALSE, $indent = ' ', $prefix = '' , $strippref
// this stops the creation of 'R' columns,
// AUTOINCREMENT is used to create auto columns
$details->primary_key = 0;
- $type = $rs->MetaType( $details );
+ $type = $rs->metaType( $details );
$schema .= str_repeat( $indent, 2 ) . 'db->Execute( 'SELECT * FROM ' . $table );
+ $rs = $this->db->execute( 'SELECT * FROM ' . $table );
if( is_object( $rs ) && !$rs->EOF ) {
$schema .= str_repeat( $indent, 2 ) . "\n";
- while( $row = $rs->FetchRow() ) {
+ while( $row = $rs->fetchRow() ) {
foreach( $row as $key => $val ) {
if ( $val != htmlentities( $val ) ) {
$row[$key] = '';
@@ -2203,7 +2210,7 @@ function ExtractSchema( $data = FALSE, $indent = ' ', $prefix = '' , $strippref
}
}
- $this->db->SetFetchMode( $old_mode );
+ $this->db->setFetchMode( $old_mode );
$schema .= '';
return $schema;
@@ -2219,7 +2226,7 @@ function ExtractSchema( $data = FALSE, $indent = ' ', $prefix = '' , $strippref
* @param boolean $underscore If TRUE, automatically append an underscore character to the prefix.
* @return boolean TRUE if successful, else FALSE
*/
- function SetPrefix( $prefix = '', $underscore = TRUE ) {
+ function setPrefix( $prefix = '', $underscore = TRUE ) {
switch( TRUE ) {
// clear prefix
case empty( $prefix ):
@@ -2378,10 +2385,7 @@ function getSQL( $format = NULL, $sqlArray = NULL ) {
* Call this method to clean up after an adoSchema object that is no longer in use.
* @deprecated adoSchema now cleans up automatically.
*/
- function Destroy() {
- if ($this->mgq !== false) {
- ini_set('magic_quotes_runtime', $this->mgq );
- }
+ function destroy() {
}
}
diff --git a/adodb/adodb.inc.php b/adodb/adodb.inc.php
index c97e0bb..f15158f 100644
--- a/adodb/adodb.inc.php
+++ b/adodb/adodb.inc.php
@@ -1,34 +1,22 @@
fields is available on EOF
$ADODB_FETCH_MODE, // DEFAULT, NUM, ASSOC or BOTH. Default follows native driver default...
$ADODB_GETONE_EOF,
@@ -82,35 +69,52 @@ class library to hide the differences between the different database API's (enca
// GLOBAL SETUP
//==============================================================================================
- $ADODB_EXTENSION = defined('ADODB_EXTENSION');
-
- // ********************************************************
- // Controls $ADODB_FORCE_TYPE mode. Default is ADODB_FORCE_VALUE (3).
- // Used in GetUpdateSql and GetInsertSql functions. Thx to Niko, nuko#mbnet.fi
- //
- // 0 = ignore empty fields. All empty fields in array are ignored.
- // 1 = force null. All empty, php null and string 'null' fields are changed to sql NULL values.
- // 2 = force empty. All empty, php null and string 'null' fields are changed to sql empty '' or 0 values.
- // 3 = force value. Value is left as it is. Php null and string 'null' are set to sql NULL values and empty fields '' are set to empty '' sql values.
-
+ /*********************************************************
+ * Controls $ADODB_FORCE_TYPE mode. Default is ADODB_FORCE_VALUE (3).
+ * Used in GetUpdateSql and GetInsertSql functions. Thx to Niko, nuko#mbnet.fi
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:adodb_force_type
+ *
+ * 0 = ignore empty fields. All empty fields in array are ignored.
+ * 1 = force null. All empty, php null and string 'null' fields are
+ * changed to sql NULL values.
+ * 2 = force empty. All empty, php null and string 'null' fields are
+ * changed to sql empty '' or 0 values.
+ * 3 = force value. Value is left as it is. Php null and string 'null'
+ * are set to sql NULL values and empty fields '' are set to empty '' sql values.
+ * 4 = force value. Like 1 but numeric empty fields are set to zero.
+ */
define('ADODB_FORCE_IGNORE',0);
define('ADODB_FORCE_NULL',1);
define('ADODB_FORCE_EMPTY',2);
define('ADODB_FORCE_VALUE',3);
+ define('ADODB_FORCE_NULL_AND_ZERO',4);
// ********************************************************
- if (!$ADODB_EXTENSION || ADODB_EXTENSION < 4.0) {
+ /**
+ * Constants for returned values from the charMax and textMax methods.
+ * If not specifically defined in the driver, methods return the NOTSET value.
+ */
+ define ('ADODB_STRINGMAX_NOTSET', -1);
+ define ('ADODB_STRINGMAX_NOLIMIT',-2);
- define('ADODB_BAD_RS','
Bad $rs in %s. Connection or SQL invalid. Try using $connection->debug=true;
');
+ /*
+ * Defines the the default meta type returned
+ * when ADOdb encounters a type that it is not
+ * defined in the metaTypes.
+ */
+ if (!defined('ADODB_DEFAULT_METATYPE'))
+ define ('ADODB_DEFAULT_METATYPE','N');
+
+ define('ADODB_BAD_RS','
Bad $rs in %s. Connection or SQL invalid. Try using $connection->debug=true;
');
// allow [ ] @ ` " and . in table names
- define('ADODB_TABLE_REGEX','([]0-9a-z_\:\"\`\.\@\[-]*)');
+ define('ADODB_TABLE_REGEX','([]0-9a-z_\:\"\`\.\@\[-]*)');
// prefetching used by oracle
- if (!defined('ADODB_PREFETCH_ROWS')) {
- define('ADODB_PREFETCH_ROWS',10);
- }
+ if (!defined('ADODB_PREFETCH_ROWS')) {
+ define('ADODB_PREFETCH_ROWS',10);
+ }
/**
@@ -125,10 +129,10 @@ class library to hide the differences between the different database API's (enca
* - BOTH: array(0 => 456, 'id' => 456, 1 => 'john', 'name' => 'john')
* - DEFAULT: driver-dependent
*/
- define('ADODB_FETCH_DEFAULT', 0);
- define('ADODB_FETCH_NUM', 1);
- define('ADODB_FETCH_ASSOC', 2);
- define('ADODB_FETCH_BOTH', 3);
+ define('ADODB_FETCH_DEFAULT', 0);
+ define('ADODB_FETCH_NUM', 1);
+ define('ADODB_FETCH_ASSOC', 2);
+ define('ADODB_FETCH_BOTH', 3);
/**
* Associative array case constants
@@ -145,53 +149,23 @@ class library to hide the differences between the different database API's (enca
* NOTE: This functionality is not implemented everywhere, it currently
* works only with: mssql, odbc, oci8 and ibase derived drivers
*/
- define('ADODB_ASSOC_CASE_LOWER', 0);
- define('ADODB_ASSOC_CASE_UPPER', 1);
- define('ADODB_ASSOC_CASE_NATIVE', 2);
-
-
- if (!defined('TIMESTAMP_FIRST_YEAR')) {
- define('TIMESTAMP_FIRST_YEAR',100);
- }
-
- /**
- * AutoExecute constants
- * (moved from adodb-pear.inc.php since they are only used in here)
- */
- define('DB_AUTOQUERY_INSERT', 1);
- define('DB_AUTOQUERY_UPDATE', 2);
+ define('ADODB_ASSOC_CASE_LOWER', 0);
+ define('ADODB_ASSOC_CASE_UPPER', 1);
+ define('ADODB_ASSOC_CASE_NATIVE', 2);
- // PHP's version scheme makes converting to numbers difficult - workaround
- $_adodb_ver = (float) PHP_VERSION;
- if ($_adodb_ver >= 5.2) {
- define('ADODB_PHPVER',0x5200);
- } else if ($_adodb_ver >= 5.0) {
- define('ADODB_PHPVER',0x5000);
- } else {
- die("PHP5 or later required. You are running ".PHP_VERSION);
- }
- unset($_adodb_ver);
+ if (!defined('TIMESTAMP_FIRST_YEAR')) {
+ define('TIMESTAMP_FIRST_YEAR',100);
}
-
/**
- Accepts $src and $dest arrays, replacing string $data
- */
- function ADODB_str_replace($src, $dest, $data) {
- if (ADODB_PHPVER >= 0x4050) {
- return str_replace($src,$dest,$data);
- }
+ * AutoExecute constants
+ * (moved from adodb-pear.inc.php since they are only used in here)
+ */
+ define('DB_AUTOQUERY_INSERT', 1);
+ define('DB_AUTOQUERY_UPDATE', 2);
+
- $s = reset($src);
- $d = reset($dest);
- while ($s !== false) {
- $data = str_replace($s,$d,$data);
- $s = next($src);
- $d = next($dest);
- }
- return $data;
- }
function ADODB_Setup() {
GLOBAL
@@ -224,7 +198,7 @@ function ADODB_Setup() {
/**
* ADODB version as a string.
*/
- $ADODB_vers = 'v5.20.20 01-Feb-2021';
+ $ADODB_vers = 'v5.21.2 2021-08-22';
/**
* Determines whether recordset->RecordCount() is used.
@@ -439,6 +413,8 @@ abstract class ADOConnection {
var $false = '0'; /// string that represents FALSE for a database
var $replaceQuote = "\\'"; /// string to use to replace quotes
var $nameQuote = '"'; /// string to use to quote identifiers and names
+ var $leftBracket = '['; /// left square bracked for t-sql styled column names
+ var $rightBracket = ']'; /// right square bracked for t-sql styled column names
var $charSet=false; /// character set to use - only for interbase, postgres and oci8
var $metaDatabasesSQL = '';
var $metaTablesSQL = '';
@@ -458,10 +434,9 @@ abstract class ADOConnection {
//--
var $genID = 0; /// sequence id used by GenID();
- /**
- * @var string|false Error function to call
- */
+ /** @var bool|callable Error function to call */
var $raiseErrorFn = false;
+
var $isoDates = false; /// accepts dates in ISO format
var $cacheSecs = 3600; /// cache for 1 hour
@@ -469,7 +444,7 @@ abstract class ADOConnection {
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)
+ var $memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib, not supported w/memcached library)
var $sysDate = false; /// name of function that returns the current date
var $sysTimeStamp = false; /// name of function that returns the current timestamp
@@ -487,14 +462,10 @@ abstract class ADOConnection {
var $autoRollback = false; // autoRollback on PConnect().
var $poorAffectedRows = false; // affectedRows not working or unreliable
- /**
- * @var string|false Execute function to call
- */
+ /** @var bool|callable Execute function to call */
var $fnExecute = false;
- /**
- * @var string|false Cache execution function to call
- */
+ /** @var bool|callable Cache execution function to call */
var $fnCacheExecute = false;
var $blobEncodeType = false; // false=not required, 'I'=encode to integer, 'C'=encode to char
@@ -513,7 +484,8 @@ abstract class ADOConnection {
//
var $_oldRaiseFn = false;
var $_transOK = null;
- var $_connectionID = false; /// The returned link identifier whenever a successful database connection is made.
+ /** @var resource Identifier for the native database connection */
+ var $_connectionID = false;
var $_errorMsg = false; /// A variable which was used to keep the returned last error message. The value will
/// then returned by the errorMsg() function
var $_errorCode = false; /// Last error code, not guaranteed to be used - only by oci8
@@ -526,32 +498,60 @@ abstract class ADOConnection {
var $_logsql = false;
var $_transmode = ''; // transaction mode
- /*
- * Additional parameters that may be passed to drivers in the connect string
- * Driver must be coded to accept the parameters
+ /**
+ * Additional parameters that may be passed to drivers in the connect string.
+ *
+ * Data is stored as an array of arrays and not a simple associative array,
+ * because some drivers (e.g. mysql) allow multiple parameters with the same
+ * key to be set.
+ * @link https://github.com/ADOdb/ADOdb/issues/187
+ *
+ * @see setConnectionParameter()
+ *
+ * @var array $connectionParameters Set of ParameterName => Value pairs
*/
protected $connectionParameters = array();
/**
- * Adds a parameter to the connection string.
- *
- * These parameters are added to the connection string when connecting,
- * if the driver is coded to use it.
- *
- * @param string $parameter The name of the parameter to set
- * @param string $value The value of the parameter
- *
- * @return null
- *
- * @example, for mssqlnative driver ('CharacterSet','UTF-8')
- */
- final public function setConnectionParameter($parameter,$value)
+ * Default Constructor.
+ * We define it even though it does not actually do anything. This avoids
+ * getting a PHP Fatal error: Cannot call constructor if a subclass tries
+ * to call its parent constructor.
+ */
+ public function __construct()
{
+ }
- $this->connectionParameters[$parameter] = $value;
-
+ /**
+ * Adds a parameter to the connection string.
+ *
+ * Parameters must be added before the connection is established;
+ * they are then passed on to the connect statement, which will.
+ * process them if the driver supports this feature.
+ *
+ * Example usage:
+ * - mssqlnative: setConnectionParameter('CharacterSet','UTF-8');
+ * - mysqli: setConnectionParameter(MYSQLI_SET_CHARSET_NAME,'utf8mb4');
+ *
+ * If used in a portable environment, parameters set in this manner should
+ * be predicated on the database provider, as unexpected results may occur
+ * if applied to the wrong database.
+ *
+ * @param string $parameter The name of the parameter to set
+ * @param string $value The value of the parameter
+ *
+ * @return bool True if success, false otherwise (e.g. parameter is not valid)
+ */
+ public function setConnectionParameter($parameter, $value) {
+ $this->connectionParameters[] = array($parameter=>$value);
+ return true;
}
+ /**
+ * ADOdb version.
+ *
+ * @return string
+ */
static function Version() {
global $ADODB_vers;
@@ -573,15 +573,20 @@ static function Version() {
}
/**
- Get server version info...
-
- @returns An array with 2 elements: $arr['string'] is the description string,
- and $arr[version] is the version (also a string).
- */
+ * 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).
+ */
function ServerInfo() {
return array('description' => '', 'version' => '');
}
+ /**
+ * Return true if connected to the database.
+ *
+ * @return bool
+ */
function IsConnected() {
return !empty($this->_connectionID);
}
@@ -595,9 +600,13 @@ function _findvers($str) {
}
/**
- * All error messages go through this bottleneck function.
- * You can define your own handler by defining the function name in ADODB_OUTP.
- */
+ * All error messages go through this bottleneck function.
+ *
+ * You can define your own handler by defining the function name in ADODB_OUTP.
+ *
+ * @param string $msg Message to print
+ * @param bool $newline True to add a newline after printing $msg
+ */
static function outp($msg,$newline=true) {
global $ADODB_FLUSH,$ADODB_OUTP;
@@ -606,8 +615,7 @@ static function outp($msg,$newline=true) {
$fn($msg,$newline);
return;
} else if (isset($ADODB_OUTP)) {
- $fn = $ADODB_OUTP;
- $fn($msg,$newline);
+ call_user_func($ADODB_OUTP,$msg,$newline);
return;
}
@@ -628,6 +636,10 @@ static function outp($msg,$newline=true) {
}
+ /**
+ * Return the database server's current date and time.
+ * @return int|false
+ */
function Time() {
$rs = $this->_Execute("select $this->sysTimeStamp");
if ($rs && !$rs->EOF) {
@@ -658,15 +670,15 @@ protected function parseHostNameAndPort() {
}
/**
- * Connect to database
+ * Connect to database.
*
- * @param [argHostname] Host to connect to
- * @param [argUsername] Userid to login
- * @param [argPassword] Associated password
- * @param [argDatabaseName] database
- * @param [forceNew] force new connection
+ * @param string $argHostname Host to connect to
+ * @param string $argUsername Userid to login
+ * @param string $argPassword Associated password
+ * @param string $argDatabaseName Database name
+ * @param bool $forceNew Force new connection
*
- * @return true or false
+ * @return bool
*/
function Connect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "", $forceNew = false) {
if ($argHostname != "") {
@@ -721,30 +733,31 @@ function _nconnect($argHostname, $argUsername, $argPassword, $argDatabaseName) {
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabaseName);
}
-
/**
- * Always force a new connection to database - currently only works with oracle
+ * Always force a new connection to database.
+ *
+ * Currently this only works with Oracle.
*
- * @param [argHostname] Host to connect to
- * @param [argUsername] Userid to login
- * @param [argPassword] Associated password
- * @param [argDatabaseName] 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 true or false
+ * @return bool
*/
function NConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "") {
return $this->Connect($argHostname, $argUsername, $argPassword, $argDatabaseName, true);
}
/**
- * Establish persistent connect to database
+ * Establish persistent connection to database.
*
- * @param [argHostname] Host to connect to
- * @param [argUsername] Userid to login
- * @param [argPassword] Associated password
- * @param [argDatabaseName] 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 return true or false
+ * @return bool
*/
function PConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "") {
@@ -781,7 +794,7 @@ function PConnect($argHostname = "", $argUsername = "", $argPassword = "", $argD
$ret = false;
} else {
$err = "Missing extension for ".$this->dataProvider;
- $ret = 0;
+ $ret = false;
}
if ($fn = $this->raiseErrorFn) {
$fn($this->databaseType,'PCONNECT',$this->ErrorNo(),$err,$this->host,$this->database,$this);
@@ -802,7 +815,11 @@ function outp_throw($msg,$src='WARN',$sql='') {
ADOConnection::outp($msg);
}
- // create cache class. Code is backward compat with old memcache implementation
+ /**
+ * Create cache class.
+ *
+ * Code is backwards-compatible with old memcache implementation.
+ */
function _CreateCache() {
global $ADODB_CACHE, $ADODB_CACHE_CLASS;
@@ -818,8 +835,16 @@ function _CreateCache() {
}
}
- // Format date column in sql string given an input format that understands Y M D
- function SQLDate($fmt, $col=false) {
+ /**
+ * Format date column in sql string.
+ *
+ * See https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:sqldate
+ * for documentation on supported formats.
+ *
+ * @param string $fmt Format string
+ * @param string $col Date column; use system date if not specified.
+ */
+ function SQLDate($fmt, $col = '') {
if (!$col) {
$col = $this->sysDate;
}
@@ -827,7 +852,8 @@ function SQLDate($fmt, $col=false) {
}
/**
- * Should prepare the sql statement and return the stmt resource.
+ * Prepare an sql statement and return the statement resource.
+ *
* For databases that do not support this, we return the $sql. To ensure
* compatibility with databases that do not support prepare:
*
@@ -835,60 +861,47 @@ function SQLDate($fmt, $col=false) {
* $db->Execute($stmt,array(1,'Jill')) or die('insert failed');
* $db->Execute($stmt,array(2,'Joe')) or die('insert failed');
*
- * @param sql SQL to send to database
- *
- * @return return FALSE, or the prepared statement, or the original sql if
- * if the database does not support prepare.
+ * @param string $sql SQL to send to database
*
+ * @return mixed|false The prepared statement, or the original sql if the
+ * database does not support prepare.
*/
function Prepare($sql) {
return $sql;
}
/**
+ * Prepare a Stored Procedure and return the statement resource.
+ *
* Some databases, eg. mssql require a different function for preparing
* stored procedures. So we cannot use Prepare().
*
- * Should prepare the stored procedure and return the stmt resource.
- * For databases that do not support this, we return the $sql. To ensure
- * compatibility with databases that do not support prepare:
- *
- * @param sql SQL to send to database
+ * For databases that do not support this, we return the $sql.
*
- * @return return FALSE, or the prepared statement, or the original sql if
- * if the database does not support prepare.
+ * @param string $sql SQL to send to database
+ * @param bool $param
*
+ * @return mixed|false The prepared statement, or the original sql if the
+ * database does not support prepare.
*/
function PrepareSP($sql,$param=true) {
return $this->Prepare($sql,$param);
}
/**
- * PEAR DB Compat
- */
- function Quote($s) {
- return $this->qstr($s,false);
- }
-
- /**
- * Requested by "Karsten Dambekalns"
- * @deprecated 5.20.20
+ * PEAR DB Compat - alias for qStr.
+ * @param $s
+ * @return string
*/
- function QMagic($s) {
- // magic quotes
- // PHP7.4 spits deprecated notice, PHP8 removed magic_* stuff
- $magic_quotes = version_compare(PHP_VERSION, '7.4.0', '<')
- && function_exists('get_magic_quotes_gpc')
- && get_magic_quotes_gpc();
-
- return $this->qstr($s, $magic_quotes);
+ function Quote($s) {
+ return $this->qstr($s);
}
function q(&$s) {
//if (!empty($this->qNull && $s == 'null') {
// return $s;
//}
- $s = $this->qstr($s,false);
+ $s = $this->qstr($s);
}
/**
@@ -910,17 +923,26 @@ function nextId($seq_name) {
* Lock a row, will escalate and lock the table if row locking not supported
* will normally free the lock at the end of the transaction
*
- * @param $table name of table to lock
- * @param $where where clause to use, eg: "WHERE row=12". If left empty, will escalate to table lock
+ * @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
*/
function RowLock($table,$where,$col='1 as adodbignore') {
return false;
}
+ /**
+ * @param string $table
+ * @return true
+ */
function CommitLock($table) {
return $this->CommitTrans();
}
+ /**
+ * @param string $table
+ * @return true
+ */
function RollbackLock($table) {
return $this->RollbackTrans();
}
@@ -931,8 +953,9 @@ function RollbackLock($table) {
* The fetch modes for NUMERIC and ASSOC for PEAR DB and ADODB are identical
* for easy porting :-)
*
- * @param mode The fetchmode ADODB_FETCH_ASSOC or ADODB_FETCH_NUM
- * @returns The previous fetch mode
+ * @param int $mode The fetchmode ADODB_FETCH_ASSOC or ADODB_FETCH_NUM
+ *
+ * @return int Previous fetch mode
*/
function SetFetchMode($mode) {
$old = $this->fetchMode;
@@ -948,6 +971,11 @@ function SetFetchMode($mode) {
/**
* PEAR DB Compat - do not use internally.
+ *
+ * @param string $sql
+ * @param array|bool $inputarr
+ *
+ * @return ADORecordSet|bool
*/
function Query($sql, $inputarr=false) {
$rs = $this->Execute($sql, $inputarr);
@@ -959,8 +987,8 @@ function Query($sql, $inputarr=false) {
/**
- * PEAR DB Compat - do not use internally
- */
+ * PEAR DB Compat - do not use internally
+ */
function LimitQuery($sql, $offset, $count, $params=false) {
$rs = $this->SelectLimit($sql, $count, $offset, $params);
if (!$rs && defined('ADODB_PEAR')) {
@@ -971,22 +999,26 @@ function LimitQuery($sql, $offset, $count, $params=false) {
/**
- * PEAR DB Compat - do not use internally
- */
+ * PEAR DB Compat - do not use internally
+ */
function Disconnect() {
return $this->Close();
}
/**
- * Returns a placeholder for query parameters
+ * Returns a placeholder for query parameters.
+ *
* e.g. $DB->Param('a') will return
* - '?' for most databases
* - ':a' for Oracle
* - '$1', '$2', etc. for PostgreSQL
- * @param string $name parameter's name, false to force a reset of the
- * number to 1 (for databases that require positioned
- * params such as PostgreSQL; note that ADOdb will
- * automatically reset this when executing a query )
+ *
+ * @param mixed $name parameter's name.
+ * For databases that require positioned params (e.g. PostgreSQL),
+ * a "falsy" value can be used to force resetting the placeholder
+ * count; using boolean 'false' will reset it without actually
+ * returning a placeholder. ADOdb will also automatically reset
+ * the count when executing a query.
* @param string $type (unused)
* @return string query parameter placeholder
*/
@@ -1134,11 +1166,14 @@ function HasFailedTrans() {
/**
* Execute SQL
*
- * @param sql SQL statement to execute, or possibly an array holding prepared statement ($sql[0] will hold sql text)
- * @param [inputarr] holds the input data to bind to. Null elements will be set to null.
- * @return RecordSet or false
+ * @param string $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 ADORecordSet|bool
*/
- function Execute($sql,$inputarr=false) {
+ public function Execute($sql, $inputarr = false) {
if ($this->fnExecute) {
$fn = $this->fnExecute;
$ret = $fn($this,$sql,$inputarr);
@@ -1269,13 +1304,14 @@ function _Execute($sql,$inputarr=false) {
if( is_string($sql) ) {
// Strips keyword used to help generate SELECT COUNT(*) queries
// from SQL if it exists.
- $sql = ADODB_str_replace( '_ADODB_COUNT', '', $sql );
+ // TODO: obsoleted by #715 - kept for backwards-compatibility
+ $sql = str_replace( '_ADODB_COUNT', '', $sql );
}
if ($this->debug) {
global $ADODB_INCLUDED_LIB;
if (empty($ADODB_INCLUDED_LIB)) {
- include(ADODB_DIR.'/adodb-lib.inc.php');
+ include_once(ADODB_DIR.'/adodb-lib.inc.php');
}
$this->_queryID = _adodb_debug_execute($this, $sql,$inputarr);
} else {
@@ -1306,8 +1342,17 @@ function _Execute($sql,$inputarr=false) {
return $rs;
}
+ if ($this->dataProvider == 'pdo' && $this->databaseType != 'pdo') {
+ // PDO uses a slightly different naming convention for the
+ // recordset class if the database type is changed, so we must
+ // treat it specifically. The mysql driver leaves the
+ // databaseType as pdo
+ $rsclass = $this->rsPrefix . 'pdo_' . $this->databaseType;
+ } else {
+ $rsclass = $this->rsPrefix . $this->databaseType;
+ }
+
// return real recordset from select statement
- $rsclass = $this->rsPrefix.$this->databaseType;
$rs = new $rsclass($this->_queryID,$this->fetchMode);
$rs->connection = $this; // Pablo suggestion
$rs->Init();
@@ -1344,12 +1389,14 @@ function DropSequence($seqname='adodbseq') {
}
/**
- * Generates a sequence id and stores it in $this->genID;
+ * Generates a sequence id and stores it in $this->genID.
+ *
* GenID is only available if $this->hasGenID = true;
*
- * @param seqname name of sequence to use
- * @param startID if sequence does not exist, start at this ID
- * @return 0 if not supported, otherwise a sequence id
+ * @param string $seqname Name of sequence to use
+ * @param int $startID If sequence does not exist, start at this ID
+ *
+ * @return int Sequence id, 0 if not supported
*/
function GenID($seqname='adodbseq',$startID=1) {
if (!$this->hasGenID) {
@@ -1384,16 +1431,22 @@ function GenID($seqname='adodbseq',$startID=1) {
}
/**
- * @param $table string name of the table, not needed by all databases (eg. mysql), default ''
- * @param $column string name of the column, not needed by all databases (eg. mysql), default ''
- * @return the last inserted ID. Not all databases support this.
+ * Returns the last inserted ID.
+ *
+ * Not all databases support this feature. Some do not require to specify
+ * table or column name (e.g. MySQL).
+ *
+ * @param string $table Table name, default ''
+ * @param string $column Column name, default ''
+ *
+ * @return int The last inserted ID.
*/
function Insert_ID($table='',$column='') {
if ($this->_logsql && $this->lastInsID) {
return $this->lastInsID;
}
if ($this->hasInsertID) {
- return $this->_insertid($table,$column);
+ return $this->_insertID($table,$column);
}
if ($this->debug) {
ADOConnection::outp( '
");
+
+ $this->ServerVersion();
+
return true;
}
@@ -508,13 +541,10 @@ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
}
+
function Prepare($sql)
{
return $sql; // prepare does not work properly with bind parameters as bind parameters are managed by sqlsrv_prepare!
-
- $stmt = sqlsrv_prepare( $this->_connectionID, $sql);
- if (!$stmt) return $sql;
- return array($sql,$stmt);
}
// returns concatenated string
@@ -569,34 +599,67 @@ function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
return $this->Execute($sql) != false;
}
- // returns query ID if successful, otherwise false
- function _query($sql,$inputarr=false)
+ /**
+ * Execute a query.
+ *
+ * If executing an INSERT statement and $hasInsertId is true, will set
+ * $lastInsId.
+ *
+ * @param string $sql
+ * @param array $inputarr
+ * @return resource|false Query Id if successful, otherwise false
+ */
+ function _query($sql, $inputarr = false)
{
$this->_errorMsg = false;
- if (is_array($sql)) $sql = $sql[1];
+ if (is_array($sql)) {
+ $sql = $sql[1];
+ }
- $insert = false;
- // handle native driver flaw for retrieving the last insert ID
- if(preg_match('/^\W*insert[\s\w()[\]",.]+values\s*\((?:[^;\']|\'\'|(?:(?:\'\')*\'[^\']+\'(?:\'\')*))*;?$/i', $sql)) {
- $insert = true;
- $sql .= '; '.$this->identitySQL; // select scope_identity()
+ // Handle native driver flaw for retrieving the last insert ID
+ if ($this->hasInsertID) {
+ // Check if it's an INSERT statement
+ $retrieveLastInsertID = preg_match(
+ '/^\W*insert[\s\w()[\]",.]+values\s*\((?:[^;\']|\'\'|(?:(?:\'\')*\'[^\']+\'(?:\'\')*))*;?$/i',
+ $sql
+ );
+ if ($retrieveLastInsertID) {
+ // Append the identity SQL, so it is executed in the same
+ // scope as the insert query.
+ $sql .= '; ' . $this->identitySQL;
+ }
+ } else {
+ $retrieveLastInsertID = false;
}
- if($inputarr) {
+
+ if ($inputarr) {
+ // Ensure that the input array is indexed numerically, as required
+ // by sqlsrv_query(). If param() was used to create portable binds
+ // then the array might be associative.
+ $inputarr = array_values($inputarr);
$rez = sqlsrv_query($this->_connectionID, $sql, $inputarr);
} else {
- $rez = sqlsrv_query($this->_connectionID,$sql);
+ $rez = sqlsrv_query($this->_connectionID, $sql);
}
- if ($this->debug) ADOConnection::outp("running query: ".var_export($sql,true)."input array: ".var_export($inputarr,true)."result: ".var_export($rez,true));
+ if ($this->debug) {
+ ADOConnection::outp("running query: " . var_export($sql, true)
+ . "input array: " . var_export($inputarr, true)
+ . "result: " . var_export($rez, true)
+ );
+ }
- if(!$rez) {
+ $this->lastInsID = false;
+ if (!$rez) {
$rez = false;
- } else if ($insert) {
- // retrieve the last insert ID (where applicable)
- while ( sqlsrv_next_result($rez) ) {
+ } elseif ($retrieveLastInsertID) {
+ // Get the inserted id from the last result
+ // Note: loop is required as server may return more than one row,
+ // e.g. if triggers are involved (see #41)
+ while (sqlsrv_next_result($rez)) {
sqlsrv_fetch($rez);
- $this->lastInsertID = sqlsrv_get_field($rez, 0);
+ $this->lastInsID = sqlsrv_get_field($rez, 0, SQLSRV_PHPTYPE_INT);
}
}
return $rez;
@@ -605,22 +668,16 @@ function _query($sql,$inputarr=false)
// returns true or false
function _close()
{
- if ($this->transCnt) $this->RollbackTrans();
- $rez = @sqlsrv_close($this->_connectionID);
+ if ($this->transCnt) {
+ $this->RollbackTrans();
+ }
+ if($this->_connectionID) {
+ $rez = sqlsrv_close($this->_connectionID);
+ }
$this->_connectionID = false;
return $rez;
}
- // mssql uses a default date like Dec 30 2000 12:00AM
- static function UnixDate($v)
- {
- return ADORecordSet_array_mssqlnative::UnixDate($v);
- }
-
- static function UnixTimeStamp($v)
- {
- return ADORecordSet_array_mssqlnative::UnixTimeStamp($v);
- }
function MetaIndexes($table,$primary=false, $owner = false)
{
@@ -679,7 +736,7 @@ function MetaForeignKeys($table, $owner=false, $upper=false)
where upper(object_name(fkeyid)) = $table
order by constraint_name, referenced_table_name, keyno";
- $constraints =& $this->GetArray($sql);
+ $constraints = $this->GetArray($sql);
$ADODB_FETCH_MODE = $save;
@@ -695,7 +752,11 @@ function MetaForeignKeys($table, $owner=false, $upper=false)
foreach($arr as $k => $v) {
foreach($v as $a => $b) {
if ($upper) $a = strtoupper($a);
- $arr2[$a] = $b;
+ if (is_array($arr2[$a])) { // a previous foreign key was define for this reference table, we merge the new one
+ $arr2[$a] = array_merge($arr2[$a], $b);
+ } else {
+ $arr2[$a] = $b;
+ }
}
}
return $arr2;
@@ -705,7 +766,7 @@ function MetaForeignKeys($table, $owner=false, $upper=false)
function MetaDatabases()
{
$this->SelectDB("master");
- $rs =& $this->Execute($this->metaDatabasesSQL);
+ $rs = $this->Execute($this->metaDatabasesSQL);
$rows = $rs->GetRows();
$ret = array();
for($i=0;$icachedSchemaFlush)
$cached_columns = array();
@@ -769,10 +832,7 @@ function MetaColumns($table, $upper=true, $schema=false){
if (array_key_exists($table,$cached_columns)){
return $cached_columns[$table];
}
- # end adg
- if (!$this->mssql_version)
- $this->ServerVersion();
$this->_findschema($table,$schema);
if ($schema) {
@@ -806,7 +866,7 @@ function MetaColumns($table, $upper=true, $schema=false){
$fld->type = $rs->fields[1];
$fld->max_length = $rs->fields[2];
$fld->precision = $rs->fields[3];
- $fld->scale = $rs->fields[4];
+ $fld->scale = $rs->fields[4];
$fld->not_null =!$rs->fields[5];
$fld->has_default = $rs->fields[6];
$fld->xtype = $rs->fields[7];
@@ -817,7 +877,7 @@ function MetaColumns($table, $upper=true, $schema=false){
$fld->type = $rs->fields['type'];
$fld->max_length = $rs->fields['length'];
$fld->precision = $rs->fields['precision'];
- $fld->scale = $rs->fields['scale'];
+ $fld->scale = $rs->fields['scale'];
$fld->not_null =!$rs->fields['nullable'];
$fld->has_default = $rs->fields['default_value'];
$fld->xtype = $rs->fields['xtype'];
@@ -834,16 +894,125 @@ function MetaColumns($table, $upper=true, $schema=false){
}
$rs->Close();
- # start adg
$cached_columns[$table] = $retarr;
- # end adg
+
return $retarr;
}
+ /**
+ * Returns a substring of a varchar type field
+ *
+ * The SQL server version varies because the length is mandatory, so
+ * we append a reasonable string length
+ *
+ * @param string $fld The field to sub-string
+ * @param int $start The start point
+ * @param int $length An optional length
+ *
+ * @return The SQL text
+ */
+ function substr($fld,$start,$length=0)
+ {
+ if ($length == 0)
+ /*
+ * The length available to varchar is 2GB, but that makes no
+ * sense in a substring, so I'm going to arbitrarily limit
+ * the length to 1K, but you could change it if you want
+ */
+ $length = 1024;
+
+ $text = "SUBSTRING($fld,$start,$length)";
+ return $text;
+ }
+
+ /**
+ * Returns the maximum size of a MetaType C field. Because of the
+ * database design, SQL Server places no limits on the size of data inserted
+ * Although the actual limit is 2^31-1 bytes.
+ *
+ * @return int
+ */
+ function charMax()
+ {
+ return ADODB_STRINGMAX_NOLIMIT;
+ }
+
+ /**
+ * Returns the maximum size of a MetaType X field. Because of the
+ * database design, SQL Server places no limits on the size of data inserted
+ * Although the actual limit is 2^31-1 bytes.
+ *
+ * @return int
+ */
+ function textMax()
+ {
+ return ADODB_STRINGMAX_NOLIMIT;
+ }
+ /**
+ * Lists procedures, functions and methods in an array.
+ *
+ * @param string $procedureNamePattern (optional)
+ * @param string $catalog (optional)
+ * @param string $schemaPattern (optional)
+
+ * @return array of stored objects in current database.
+ *
+ */
+ public function metaProcedures($procedureNamePattern = null, $catalog = null, $schemaPattern = null)
+ {
+ $metaProcedures = array();
+ $procedureSQL = '';
+ $catalogSQL = '';
+ $schemaSQL = '';
+
+ if ($procedureNamePattern)
+ $procedureSQL = "AND ROUTINE_NAME LIKE " . strtoupper($this->qstr($procedureNamePattern));
+
+ if ($catalog)
+ $catalogSQL = "AND SPECIFIC_SCHEMA=" . strtoupper($this->qstr($catalog));
+
+ if ($schemaPattern)
+ $schemaSQL = "AND ROUTINE_SCHEMA LIKE {$this->qstr($schemaPattern)}";
+
+ $fields = " ROUTINE_NAME,ROUTINE_TYPE,ROUTINE_SCHEMA,ROUTINE_CATALOG";
+
+ $SQL = "SELECT $fields
+ FROM {$this->database}.information_schema.routines
+ WHERE 1=1
+ $procedureSQL
+ $catalogSQL
+ $schemaSQL
+ ORDER BY ROUTINE_NAME
+ ";
+
+ $result = $this->execute($SQL);
+
+ if (!$result)
+ return false;
+ while ($r = $result->fetchRow()){
+ if (!isset($r[0]))
+ /*
+ * Convert to numeric
+ */
+ $r = array_values($r);
+
+ $procedureName = $r[0];
+ $schemaName = $r[2];
+ $routineCatalog= $r[3];
+ $metaProcedures[$procedureName] = array('type'=> $r[1],
+ 'catalog' => $routineCatalog,
+ 'schema' => $schemaName,
+ 'remarks' => '',
+ );
+ }
+
+ return $metaProcedures;
+ }
+
}
/*--------------------------------------------------------------------------------------
- Class Name: Recordset
+ Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordset_mssqlnative extends ADORecordSet {
@@ -853,6 +1022,62 @@ class ADORecordset_mssqlnative extends ADORecordSet {
var $fieldOffset = 0;
// _mths works only in non-localised system
+ /**
+ * @var bool True if we have retrieved the fields metadata
+ */
+ private $fieldObjectsRetrieved = false;
+
+ /*
+ * Cross-reference the objects by name for easy access
+ */
+ private $fieldObjectsIndex = array();
+
+ /*
+ * Cross references the dateTime objects for faster decoding
+ */
+ private $dateTimeObjects = array();
+
+ /*
+ * flags that we have dateTimeObjects to handle
+ */
+ private $hasDateTimeObjects = false;
+
+ /*
+ * This is cross reference between how the types are stored
+ * in SQL Server and their english-language description
+ * -154 is a time field, see #432
+ */
+ private $_typeConversion = array(
+ -155 => 'datetimeoffset',
+ -154 => 'char',
+ -152 => 'xml',
+ -151 => 'udt',
+ -11 => 'uniqueidentifier',
+ -10 => 'ntext',
+ -9 => 'nvarchar',
+ -8 => 'nchar',
+ -7 => 'bit',
+ -6 => 'tinyint',
+ -5 => 'bigint',
+ -4 => 'image',
+ -3 => 'varbinary',
+ -2 => 'timestamp',
+ -1 => 'text',
+ 1 => 'char',
+ 2 => 'numeric',
+ 3 => 'decimal',
+ 4 => 'int',
+ 5 => 'smallint',
+ 6 => 'float',
+ 7 => 'real',
+ 12 => 'varchar',
+ 91 => 'date',
+ 93 => 'datetime'
+ );
+
+
+
+
function __construct($id,$mode=false)
{
if ($mode === false) {
@@ -861,29 +1086,15 @@ function __construct($id,$mode=false)
}
$this->fetchMode = $mode;
- return parent::__construct($id,$mode);
+ parent::__construct($id);
}
function _initrs()
{
- global $ADODB_COUNTRECS;
- # KMN # if ($this->connection->debug) ADOConnection::outp("(before) ADODB_COUNTRECS: {$ADODB_COUNTRECS} _numOfRows: {$this->_numOfRows} _numOfFields: {$this->_numOfFields}");
- /*$retRowsAff = sqlsrv_rows_affected($this->_queryID);//"If you need to determine the number of rows a query will return before retrieving the actual results, appending a SELECT COUNT ... query would let you get that information, and then a call to next_result would move you to the "real" results."
- ADOConnection::outp("rowsaff: ".serialize($retRowsAff));
- $this->_numOfRows = ($ADODB_COUNTRECS)? $retRowsAff:-1;*/
$this->_numOfRows = -1;//not supported
- $fieldmeta = sqlsrv_field_metadata($this->_queryID);
- $this->_numOfFields = ($fieldmeta)? count($fieldmeta):-1;
- # KMN # if ($this->connection->debug) ADOConnection::outp("(after) _numOfRows: {$this->_numOfRows} _numOfFields: {$this->_numOfFields}");
- /*
- * Copy the oracle method and cache the metadata at init time
- */
- if ($this->_numOfFields>0) {
- $this->_fieldobjs = array();
- $max = $this->_numOfFields;
- for ($i=0;$i<$max; $i++) $this->_fieldobjs[] = $this->_FetchField($i);
- }
+ // Cache the metadata right now
+ $this->_fetchField();
}
@@ -908,8 +1119,9 @@ function Fields($colname)
* Too early
*/
return;
- if ($this->fetchMode != ADODB_FETCH_NUM)
+ if ($this->fetchMode != ADODB_FETCH_NUM)
return $this->fields[$colname];
+
if (!$this->bind) {
$this->bind = array();
for ($i=0; $i < $this->_numOfFields; $i++) {
@@ -921,79 +1133,63 @@ function Fields($colname)
return $this->fields[$this->bind[strtoupper($colname)]];
}
- /* Returns: an object containing field information.
- Get column information in the Recordset object. fetchField() can be used in order to obtain information about
- fields in a certain query result. If the field offset isn't specified, the next field that wasn't yet retrieved by
- fetchField() is retrieved.
- Designed By jcortinap#jc.com.mx
+ /**
+ * 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
*/
- function _FetchField($fieldOffset = -1)
+ private function _fetchField($fieldOffset = -1)
{
- $_typeConversion = array(
- -155 => 'datetimeoffset',
- -154 => 'char',
- -152 => 'xml',
- -151 => 'udt',
- -11 => 'uniqueidentifier',
- -10 => 'ntext',
- -9 => 'nvarchar',
- -8 => 'nchar',
- -7 => 'bit',
- -6 => 'tinyint',
- -5 => 'bigint',
- -4 => 'image',
- -3 => 'varbinary',
- -2 => 'timestamp',
- -1 => 'text',
- 1 => 'char',
- 2 => 'numeric',
- 3 => 'decimal',
- 4 => 'int',
- 5 => 'smallint',
- 6 => 'float',
- 7 => 'real',
- 12 => 'varchar',
- 91 => 'date',
- 93 => 'datetime'
- );
+ if ($this->fieldObjectsRetrieved) {
+ if ($this->fieldObjectsCache) {
+ // Already got the information
+ if ($fieldOffset == -1) {
+ return $this->fieldObjectsCache;
+ } else {
+ return $this->fieldObjectsCache[$fieldOffset];
+ }
+ } else {
+ // No metadata available
+ return false;
+ }
+ }
- $fa = @sqlsrv_field_metadata($this->_queryID);
- if ($fieldOffset != -1) {
- $fa = $fa[$fieldOffset];
+ $this->fieldObjectsRetrieved = true;
+ /*
+ * Retrieve all metadata in one go. This is always returned as a
+ * numeric array.
+ */
+ $fieldMetaData = sqlsrv_field_metadata($this->_queryID);
+
+ if (!$fieldMetaData) {
+ // Not a statement that gives us metaData
+ return false;
}
- $false = false;
- if (empty($fa)) {
- $f = false;//PHP Notice: Only variable references should be returned by reference
+
+ $this->_numOfFields = count($fieldMetaData);
+ foreach ($fieldMetaData as $key=>$value) {
+ $fld = new ADOFieldObject;
+ // Caution - keys are case-sensitive, must respect casing of values
+ $fld->name = $value['Name'];
+ $fld->max_length = $value['Size'];
+ $fld->column_source = $value['Name'];
+ $fld->type = $this->_typeConversion[$value['Type']];
+
+ $this->fieldObjectsCache[$key] = $fld;
+ $this->fieldObjectsIndex[$fld->name] = $key;
}
- else
- {
- // Convert to an object
- $fa = array_change_key_case($fa, CASE_LOWER);
- $fb = array();
- if ($fieldOffset != -1)
- {
- $fb = array(
- 'name' => $fa['name'],
- 'max_length' => $fa['size'],
- 'column_source' => $fa['name'],
- 'type' => $_typeConversion[$fa['type']]
- );
- }
- else
- {
- foreach ($fa as $key => $value)
- {
- $fb[] = array(
- 'name' => $value['name'],
- 'max_length' => $value['size'],
- 'column_source' => $value['name'],
- 'type' => $_typeConversion[$value['type']]
- );
- }
- }
- $f = (object) $fb;
+ if ($fieldOffset == -1) {
+ return $this->fieldObjectsCache;
}
- return $f;
+
+ return $this->fieldObjectsCache[$fieldOffset];
}
/*
@@ -1001,12 +1197,16 @@ function _FetchField($fieldOffset = -1)
* into the _fieldobjs array once, to save multiple calls to the
* sqlsrv_field_metadata function
*
+ * @param int $fieldOffset (optional)
+ *
+ * @return adoFieldObject
+ *
* @author KM Newnham
* @date 02/20/2013
*/
- function FetchField($fieldOffset = -1)
+ function fetchField($fieldOffset = -1)
{
- return $this->_fieldobjs[$fieldOffset];
+ return $this->fieldObjectsCache[$fieldOffset];
}
function _seek($row)
@@ -1017,76 +1217,52 @@ function _seek($row)
// speedup
function MoveNext()
{
- //# KMN # if ($this->connection->debug) ADOConnection::outp("movenext()");
- //# KMN # if ($this->connection->debug) ADOConnection::outp("eof (beginning): ".$this->EOF);
- if ($this->EOF) return false;
+ if ($this->EOF)
+ return false;
$this->_currentRow++;
- // # KMN # if ($this->connection->debug) ADOConnection::outp("_currentRow: ".$this->_currentRow);
- if ($this->_fetch()) return true;
+ if ($this->_fetch())
+ return true;
$this->EOF = true;
- //# KMN # if ($this->connection->debug) ADOConnection::outp("eof (end): ".$this->EOF);
return false;
}
-
- // INSERT UPDATE DELETE returns false even if no error occurs in 4.0.4
- // also the date format has been changed from YYYY-mm-dd to dd MMM YYYY in 4.0.4. Idiot!
function _fetch($ignore_fields=false)
{
- # KMN # if ($this->connection->debug) ADOConnection::outp("_fetch()");
if ($this->fetchMode & ADODB_FETCH_ASSOC) {
- if ($this->fetchMode & ADODB_FETCH_NUM) {
- //# KMN # if ($this->connection->debug) ADOConnection::outp("fetch mode: both");
+ if ($this->fetchMode & ADODB_FETCH_NUM)
$this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_BOTH);
- } else {
- //# KMN # if ($this->connection->debug) ADOConnection::outp("fetch mode: assoc");
+ else
$this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_ASSOC);
- }
- if (is_array($this->fields)) {
- if (ADODB_ASSOC_CASE == 0) {
- foreach($this->fields as $k=>$v) {
- $this->fields[strtolower($k)] = $v;
- }
- } else if (ADODB_ASSOC_CASE == 1) {
- foreach($this->fields as $k=>$v) {
- $this->fields[strtoupper($k)] = $v;
- }
- }
- }
- } else {
- //# KMN # if ($this->connection->debug) ADOConnection::outp("fetch mode: num");
- $this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_NUMERIC);
- }
- if(is_array($this->fields) && array_key_exists(1,$this->fields) && !array_key_exists(0,$this->fields)) {//fix fetch numeric keys since they're not 0 based
- $arrFixed = array();
- foreach($this->fields as $key=>$value) {
- if(is_numeric($key)) {
- $arrFixed[$key-1] = $value;
- } else {
- $arrFixed[$key] = $value;
- }
- }
- //if($this->connection->debug) ADOConnection::outp("fixing non 0 based return array, old: ".print_r($this->fields,true)." new: ".print_r($arrFixed,true));
- $this->fields = $arrFixed;
- }
- if(is_array($this->fields)) {
- foreach($this->fields as $key=>$value) {
- if (is_object($value) && method_exists($value, 'format')) {//is DateTime object
- $this->fields[$key] = $value->format("Y-m-d\TH:i:s\Z");
- }
+ if (is_array($this->fields))
+ {
+
+ if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_LOWER)
+ $this->fields = array_change_key_case($this->fields,CASE_LOWER);
+ else if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_UPPER)
+ $this->fields = array_change_key_case($this->fields,CASE_UPPER);
+
}
}
- if($this->fields === null) $this->fields = false;
- # KMN # if ($this->connection->debug) ADOConnection::outp("after _fetch, fields:
".print_r($this->fields,true)." backtrace: ".adodb_backtrace(false));
+ else
+ $this->fields = @sqlsrv_fetch_array($this->_queryID,SQLSRV_FETCH_NUMERIC);
+
+ if (!$this->fields)
+ return false;
+
return $this->fields;
}
- /* close() only needs to be called if you are worried about using too much memory while your script
- is running. All associated result memory for the specified result identifier will automatically be freed. */
+ /**
+ * close() only needs to be called if you are worried about using too much
+ * memory while your script is running. All associated result memory for
+ * the specified result identifier will automatically be freed.
+ *
+ * @return bool tru if we succeeded in closing down
+ */
function _close()
{
/*
@@ -1100,101 +1276,14 @@ function _close()
$this->_queryID = false;
return $rez;
}
- return true;
- }
- // mssql uses a default date like Dec 30 2000 12:00AM
- static function UnixDate($v)
- {
- return ADORecordSet_array_mssqlnative::UnixDate($v);
+ return true;
}
- static function UnixTimeStamp($v)
- {
- return ADORecordSet_array_mssqlnative::UnixTimeStamp($v);
- }
}
-class ADORecordSet_array_mssqlnative extends ADORecordSet_array {
- function __construct($id=-1,$mode=false)
- {
- parent::__construct($id,$mode);
- }
-
- // mssql uses a default date like Dec 30 2000 12:00AM
- static function UnixDate($v)
- {
-
- if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixDate($v);
-
- global $ADODB_mssql_mths,$ADODB_mssql_date_order;
-
- //Dec 30 2000 12:00AM
- if ($ADODB_mssql_date_order == 'dmy') {
- if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
- return parent::UnixDate($v);
- }
- if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
-
- $theday = $rr[1];
- $themth = substr(strtoupper($rr[2]),0,3);
- } else {
- if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4})|" ,$v, $rr)) {
- return parent::UnixDate($v);
- }
- if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
-
- $theday = $rr[2];
- $themth = substr(strtoupper($rr[1]),0,3);
- }
- $themth = $ADODB_mssql_mths[$themth];
- if ($themth <= 0) return false;
- // h-m-s-MM-DD-YY
- return adodb_mktime(0,0,0,$themth,$theday,$rr[3]);
- }
-
- static function UnixTimeStamp($v)
- {
-
- if (is_numeric(substr($v,0,1)) && ADODB_PHPVER >= 0x4200) return parent::UnixTimeStamp($v);
-
- global $ADODB_mssql_mths,$ADODB_mssql_date_order;
-
- //Dec 30 2000 12:00AM
- if ($ADODB_mssql_date_order == 'dmy') {
- if (!preg_match( "|^([0-9]{1,2})[-/\. ]+([A-Za-z]{3})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|"
- ,$v, $rr)) return parent::UnixTimeStamp($v);
- if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
-
- $theday = $rr[1];
- $themth = substr(strtoupper($rr[2]),0,3);
- } else {
- if (!preg_match( "|^([A-Za-z]{3})[-/\. ]+([0-9]{1,2})[-/\. ]+([0-9]{4}) +([0-9]{1,2}):([0-9]{1,2}) *([apAP]{0,1})|"
- ,$v, $rr)) return parent::UnixTimeStamp($v);
- if ($rr[3] <= TIMESTAMP_FIRST_YEAR) return 0;
-
- $theday = $rr[2];
- $themth = substr(strtoupper($rr[1]),0,3);
- }
-
- $themth = $ADODB_mssql_mths[$themth];
- if ($themth <= 0) return false;
-
- switch (strtoupper($rr[6])) {
- case 'P':
- if ($rr[4]<12) $rr[4] += 12;
- break;
- case 'A':
- if ($rr[4]==12) $rr[4] = 0;
- break;
- default:
- break;
- }
- // h-m-s-MM-DD-YY
- return adodb_mktime($rr[4],$rr[5],0,$themth,$theday,$rr[3]);
- }
-}
+class ADORecordSet_array_mssqlnative extends ADORecordSet_array {}
/*
Code Example 1:
diff --git a/adodb/drivers/adodb-mssqlpo.inc.php b/adodb/drivers/adodb-mssqlpo.inc.php
index a62cc73..f2d2f6f 100644
--- a/adodb/drivers/adodb-mssqlpo.inc.php
+++ b/adodb/drivers/adodb-mssqlpo.inc.php
@@ -1,29 +1,27 @@
_has_mssql_init) {
- ADOConnection::outp( "PrepareSP: mssql_init only available since PHP 4.1.0");
- return $sql;
- }
if (is_string($sql)) $sql = str_replace('||','+',$sql);
$stmt = mssql_init($sql,$this->_connectionID);
if (!$stmt) return $sql;
@@ -51,8 +45,4 @@ function _query($sql,$inputarr=false)
class ADORecordset_mssqlpo extends ADORecordset_mssql {
var $databaseType = "mssqlpo";
- function __construct($id,$mode=false)
- {
- parent::__construct($id,$mode);
- }
}
diff --git a/adodb/drivers/adodb-mysql.inc.php b/adodb/drivers/adodb-mysql.inc.php
index a208330..f07c081 100644
--- a/adodb/drivers/adodb-mysql.inc.php
+++ b/adodb/drivers/adodb-mysql.inc.php
@@ -1,22 +1,30 @@
rsPrefix .= 'ext_';
+ /**
+ * ADODB_mysql constructor.
+ */
+ public function __construct() {
+ if(version_compare(PHP_VERSION, '7.0.0', '>=')) {
+ $this->outp_throw(
+ 'mysql extension is not supported since PHP 7.0.0, use mysqli instead',
+ __METHOD__
+ );
+ die(1); // Stop execution even if not using Exceptions
+ } elseif(version_compare(PHP_VERSION, '5.5.0', '>=')) {
+ // If mysql extension is available just print a warning,
+ // otherwise die with an error message
+ if(function_exists('mysql_connect')) {
+ $this->outp('mysql extension is deprecated since PHP 5.5.0, consider using mysqli');
+ } else {
+ $this->outp_throw(
+ 'mysql extension is not available, use mysqli instead',
+ __METHOD__
+ );
+ die(1); // Stop execution even if not using Exceptions
+ }
+ }
}
-
- // SetCharSet - switch the client encoding
- function SetCharSet($charset_name)
+ function setCharSet($charset)
{
if (!function_exists('mysql_set_charset')) {
return false;
}
- if ($this->charSet !== $charset_name) {
- $ok = @mysql_set_charset($charset_name,$this->_connectionID);
+ if ($this->charSet !== $charset) {
+ $ok = @mysql_set_charset($charset,$this->_connectionID);
if ($ok) {
- $this->charSet = $charset_name;
+ $this->charSet = $charset;
return true;
}
return false;
@@ -75,19 +101,19 @@ function SetCharSet($charset_name)
return true;
}
- function ServerInfo()
+ function serverInfo()
{
$arr['description'] = ADOConnection::GetOne("select version()");
$arr['version'] = ADOConnection::_findvers($arr['description']);
return $arr;
}
- function IfNull( $field, $ifNull )
+ function ifNull( $field, $ifNull )
{
return " IFNULL($field, $ifNull) "; // if MySQL
}
- function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null)
+ function metaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null)
{
// save old fetch mode
global $ADODB_FETCH_MODE;
@@ -153,7 +179,7 @@ function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern =
*
* @return array list of tables
*/
- function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ function metaTables($ttype=false,$showSchema=false,$mask=false)
{
$save = $this->metaTablesSQL;
if ($showSchema && is_string($showSchema)) {
@@ -173,7 +199,7 @@ function MetaTables($ttype=false,$showSchema=false,$mask=false)
}
- function MetaIndexes ($table, $primary = FALSE, $owner=false)
+ function metaIndexes ($table, $primary = FALSE, $owner=false)
{
// save old fetch mode
global $ADODB_FETCH_MODE;
@@ -226,34 +252,41 @@ function MetaIndexes ($table, $primary = FALSE, $owner=false)
}
- // if magic quotes disabled, use mysql_real_escape_string()
- function qstr($s,$magic_quotes=false)
+ /**
+ * Appropriately quotes strings with ' characters for insertion into the database.
+ *
+ * Relies on mysql_real_escape_string()
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:qstr
+ *
+ * @param string $s The string to quote
+ * @param bool $magic_quotes This param is not used since 5.21.0.
+ * It remains for backwards compatibility.
+ *
+ * @return string Quoted string
+ */
+ function qStr($s, $magic_quotes=false)
{
- if (is_null($s)) return 'NULL';
- if (!$magic_quotes) {
+ if (is_null($s)) {
+ return 'NULL';
+ }
- if (ADODB_PHPVER >= 0x4300) {
- if (is_resource($this->_connectionID))
- return "'".mysql_real_escape_string($s,$this->_connectionID)."'";
- }
- if ($this->replaceQuote[0] == '\\'){
- $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
- }
- return "'".str_replace("'",$this->replaceQuote,$s)."'";
+ if (is_resource($this->_connectionID)) {
+ return "'" . mysql_real_escape_string($s, $this->_connectionID) . "'";
}
- // undo magic quotes for "
- $s = str_replace('\\"','"',$s);
- return "'$s'";
+ if ($this->replaceQuote[0] == '\\') {
+ $s = str_replace(array('\\', "\0"), array('\\\\', "\\\0"), $s);
+ }
+ return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
}
- function _insertid()
+ protected function _insertID($table = '', $column = '')
{
return ADOConnection::GetOne('SELECT LAST_INSERT_ID()');
//return mysql_insert_id($this->_connectionID);
}
- function GetOne($sql,$inputarr=false)
+ function getOne($sql,$inputarr=false)
{
global $ADODB_GETONE_EOF;
if ($this->compat323 == false && strncasecmp($sql,'sele',4) == 0) {
@@ -269,7 +302,7 @@ function GetOne($sql,$inputarr=false)
return false;
}
- function BeginTrans()
+ function beginTrans()
{
if ($this->debug) ADOConnection::outp("Transactions not supported in 'mysql' driver. Use 'mysqlt' or 'mysqli' driver");
}
@@ -287,7 +320,7 @@ function _affectedrows()
var $_genSeq2SQL = "insert into %s values (%s)";
var $_dropSeqSQL = "drop table if exists %s";
- function CreateSequence($seqname='adodbseq',$startID=1)
+ function createSequence($seqname='adodbseq',$startID=1)
{
if (empty($this->_genSeqSQL)) return false;
$u = strtoupper($seqname);
@@ -298,7 +331,7 @@ function CreateSequence($seqname='adodbseq',$startID=1)
}
- function GenID($seqname='adodbseq',$startID=1)
+ function genID($seqname='adodbseq',$startID=1)
{
// post-nuke sets hasGenID to false
if (!$this->hasGenID) return false;
@@ -327,7 +360,7 @@ function GenID($seqname='adodbseq',$startID=1)
return $this->genID;
}
- function MetaDatabases()
+ function metaDatabases()
{
$qid = mysql_list_dbs($this->_connectionID);
$arr = array();
@@ -343,7 +376,7 @@ function MetaDatabases()
// Format date column in sql string given an input format that understands Y M D
- function SQLDate($fmt, $col=false)
+ function sqlDate($fmt, $col=false)
{
if (!$col) $col = $this->sysTimeStamp;
$s = 'DATE_FORMAT('.$col.",'";
@@ -431,7 +464,7 @@ function SQLDate($fmt, $col=false)
// returns concatenated string
// much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
- function Concat()
+ function concat()
{
$s = "";
$arr = func_get_args();
@@ -442,7 +475,7 @@ function Concat()
else return '';
}
- function OffsetDate($dayFraction,$date=false)
+ function offsetDate($dayFraction,$date=false)
{
if (!$date) $date = $this->sysDate;
@@ -455,19 +488,23 @@ function OffsetDate($dayFraction,$date=false)
// returns true or false
function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
- if (!empty($this->port)) $argHostname .= ":".$this->port;
+ if (!empty($this->port))
+ $argHostname .= ":".$this->port;
- if (ADODB_PHPVER >= 0x4300)
- $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword,
- $this->forceNewConnect,$this->clientFlags);
- else if (ADODB_PHPVER >= 0x4200)
- $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword,
- $this->forceNewConnect);
- else
- $this->_connectionID = mysql_connect($argHostname,$argUsername,$argPassword);
+ $this->_connectionID =
+ mysql_connect($argHostname,
+ $argUsername,
+ $argPassword,
+ $this->forceNewConnect,
+ $this->clientFlags
+ );
+
+
+ if ($this->_connectionID === false)
+ return false;
+ if ($argDatabasename)
+ return $this->SelectDB($argDatabasename);
- if ($this->_connectionID === false) return false;
- if ($argDatabasename) return $this->SelectDB($argDatabasename);
return true;
}
@@ -476,13 +513,18 @@ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (!empty($this->port)) $argHostname .= ":".$this->port;
- if (ADODB_PHPVER >= 0x4300)
- $this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword,$this->clientFlags);
- else
- $this->_connectionID = mysql_pconnect($argHostname,$argUsername,$argPassword);
- if ($this->_connectionID === false) return false;
- if ($this->autoRollback) $this->RollbackTrans();
- if ($argDatabasename) return $this->SelectDB($argDatabasename);
+ $this->_connectionID =
+ mysql_pconnect($argHostname,
+ $argUsername,
+ $argPassword,
+ $this->clientFlags);
+
+ if ($this->_connectionID === false)
+ return false;
+ if ($this->autoRollback)
+ $this->RollbackTrans();
+ if ($argDatabasename)
+ return $this->SelectDB($argDatabasename);
return true;
}
@@ -492,7 +534,7 @@ function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
}
- function MetaColumns($table, $normalize=true)
+ function metaColumns($table, $normalize=true)
{
$this->_findschema($table,$schema);
if ($schema) {
@@ -572,7 +614,7 @@ function MetaColumns($table, $normalize=true)
}
// returns true or false
- function SelectDB($dbName)
+ function selectDB($dbName)
{
$this->database = $dbName;
$this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
@@ -583,7 +625,7 @@ function SelectDB($dbName)
}
// parameters use PostgreSQL convention, not MySQL
- function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs=0)
+ function selectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false,$secs=0)
{
$nrows = (int) $nrows;
$offset = (int) $offset;
@@ -613,7 +655,7 @@ function _query($sql,$inputarr=false)
}
/* Returns: the last error message from previous database operation */
- function ErrorMsg()
+ function errorMsg()
{
if ($this->_logsql) return $this->_errorMsg;
@@ -623,7 +665,7 @@ function ErrorMsg()
}
/* Returns: the last error number from previous database operation */
- function ErrorNo()
+ function errorNo()
{
if ($this->_logsql) return $this->_errorCode;
if (empty($this->_connectionID)) return @mysql_errno();
@@ -643,7 +685,7 @@ function _close()
/*
* Maximum size of C field
*/
- function CharMax()
+ function charMax()
{
return 255;
}
@@ -651,13 +693,13 @@ function CharMax()
/*
* Maximum size of X field
*/
- function TextMax()
+ function textMax()
{
return 4294967295;
}
// "Innox - Juan Carlos Gonzalez"
- function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
+ function metaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
{
global $ADODB_FETCH_MODE;
if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true;
@@ -743,7 +785,7 @@ function _initrs()
$this->_numOfFields = @mysql_num_fields($this->_queryID);
}
- function FetchField($fieldOffset = -1)
+ function fetchField($fieldOffset = -1)
{
if ($fieldOffset != -1) {
$o = @mysql_fetch_field($this->_queryID, $fieldOffset);
@@ -761,7 +803,7 @@ function FetchField($fieldOffset = -1)
return $o;
}
- function GetRowAssoc($upper = ADODB_ASSOC_CASE)
+ function getRowAssoc($upper = ADODB_ASSOC_CASE)
{
if ($this->fetchMode == MYSQL_ASSOC && $upper == ADODB_ASSOC_CASE_LOWER) {
$row = $this->fields;
@@ -773,7 +815,7 @@ function GetRowAssoc($upper = ADODB_ASSOC_CASE)
}
/* Use associative array to get fields array */
- function Fields($colname)
+ function fields($colname)
{
// added @ by "Michael William Miller"
if ($this->fetchMode != MYSQL_NUM) return @$this->fields[$colname];
@@ -794,10 +836,8 @@ function _seek($row)
return @mysql_data_seek($this->_queryID,$row);
}
- function MoveNext()
+ function moveNext()
{
- //return adodb_movenext($this);
- //if (defined('ADODB_EXTENSION')) return adodb_movenext($this);
if (@$this->fields = mysql_fetch_array($this->_queryID,$this->fetchMode)) {
$this->_updatefields();
$this->_currentRow += 1;
@@ -822,7 +862,7 @@ function _close() {
$this->_queryID = false;
}
- function MetaType($t,$len=-1,$fieldobj=false)
+ function metaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
$fieldobj = $t;
@@ -872,19 +912,18 @@ function MetaType($t,$len=-1,$fieldobj=false)
if (!empty($fieldobj->primary_key)) return 'R';
else return 'I';
- default: return 'N';
+ default: return ADODB_DEFAULT_METATYPE;
}
}
}
+/**
+ * Class ADORecordSet_ext_mysql
+ */
class ADORecordSet_ext_mysql extends ADORecordSet_mysql {
- function __construct($queryID,$mode=false)
- {
- parent::__construct($queryID,$mode);
- }
- function MoveNext()
+ function moveNext()
{
return @adodb_movenext($this);
}
diff --git a/adodb/drivers/adodb-mysqli.inc.php b/adodb/drivers/adodb-mysqli.inc.php
index 682d274..352810c 100644
--- a/adodb/drivers/adodb-mysqli.inc.php
+++ b/adodb/drivers/adodb-mysqli.inc.php
@@ -1,37 +1,44 @@
_transmode = $transaction_mode;
if (empty($transaction_mode)) {
- $this->Execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ');
+ $this->execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ');
return;
}
if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
- $this->Execute("SET SESSION TRANSACTION ".$transaction_mode);
+ $this->execute("SET SESSION TRANSACTION ".$transaction_mode);
+ }
+
+ /**
+ * Adds a parameter to the connection string.
+ *
+ * Parameter must be one of the the constants listed in mysqli_options().
+ * @see https://www.php.net/manual/en/mysqli.options.php
+ *
+ * @param int $parameter The parameter to set
+ * @param string $value The value of the parameter
+ *
+ * @example, for mssqlnative driver ('CharacterSet','UTF-8')
+ * @return bool
+ */
+ public function setConnectionParameter($parameter, $value) {
+ if(!is_numeric($parameter)) {
+ $this->outp_throw("Invalid connection parameter '$parameter'", __METHOD__);
+ return false;
+ }
+ $this->connectionParameters[$parameter] = $value;
+ return true;
}
- // returns true or false
- // To add: parameter int $port,
- // parameter string $socket
- function _connect($argHostname = NULL,
- $argUsername = NULL,
- $argPassword = NULL,
- $argDatabasename = NULL, $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.
+ */
+ function _connect($argHostname = null,
+ $argUsername = null,
+ $argPassword = null,
+ $argDatabasename = null,
+ $persist = false)
{
if(!extension_loaded("mysqli")) {
return null;
@@ -96,7 +156,7 @@ function _connect($argHostname = NULL,
if (is_null($this->_connectionID)) {
// mysqli_init only fails if insufficient memory
if ($this->debug) {
- ADOConnection::outp("mysqli_init() failed : " . $this->ErrorMsg());
+ ADOConnection::outp("mysqli_init() failed : " . $this->errorMsg());
}
return false;
}
@@ -105,12 +165,31 @@ function _connect($argHostname = NULL,
read connection options from the standard mysql configuration file
/etc/my.cnf - "Bastien Duclaux"
*/
+ $this->optionFlags = array();
foreach($this->optionFlags as $arr) {
mysqli_options($this->_connectionID,$arr[0],$arr[1]);
}
- //http ://php.net/manual/en/mysqli.persistconns.php
- if ($persist && PHP_VERSION > 5.2 && strncmp($argHostname,'p:',2) != 0) $argHostname = 'p:'.$argHostname;
+ // Now merge in the standard connection parameters setting
+ foreach ($this->connectionParameters as $parameter => $value) {
+ // Make sure parameter is numeric before calling mysqli_options()
+ // that to avoid Warning (or TypeError exception on PHP 8).
+ if (!is_numeric($parameter)
+ || !mysqli_options($this->_connectionID, $parameter, $value)
+ ) {
+ $this->outp_throw("Invalid connection parameter '$parameter'", __METHOD__);
+ }
+ }
+
+ //https://php.net/manual/en/mysqli.persistconns.php
+ if ($persist && strncmp($argHostname,'p:',2) != 0) {
+ $argHostname = 'p:' . $argHostname;
+ }
+
+ // 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);
+ }
#if (!empty($this->port)) $argHostname .= ":".$this->port;
$ok = @mysqli_real_connect($this->_connectionID,
@@ -124,154 +203,255 @@ function _connect($argHostname = NULL,
$this->clientFlags);
if ($ok) {
- if ($argDatabasename) return $this->SelectDB($argDatabasename);
+ if ($argDatabasename) return $this->selectDB($argDatabasename);
return true;
} else {
if ($this->debug) {
- ADOConnection::outp("Could not connect : " . $this->ErrorMsg());
+ ADOConnection::outp("Could not connect : " . $this->errorMsg());
}
$this->_connectionID = null;
return false;
}
}
- // returns true or false
- // How to force a persistent connection
+ /**
+ * 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);
}
- // When is this used? Close old connection first?
- // In _connect(), check $this->forceNewConnect?
+ /**
+ * Connect to a database, whilst setting $this->forceNewConnect to true.
+ *
+ * When is this used? Close old connection first?
+ * In _connect(), check $this->forceNewConnect?
+ *
+ * @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 _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
$this->forceNewConnect = true;
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
}
- function IfNull( $field, $ifNull )
+ /**
+ * Replaces a null value with a specified replacement.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:ifnull
+ *
+ * @param mixed $field The field in the table to check.
+ * @param mixed $ifNull The value to replace the null value with if it is found.
+ *
+ * @return string
+ */
+ function IfNull($field, $ifNull)
{
- return " IFNULL($field, $ifNull) "; // if MySQL
+ return " IFNULL($field, $ifNull) ";
}
- // do not use $ADODB_COUNTRECS
- function GetOne($sql,$inputarr=false)
+ /**
+ * Retrieves the first column of the first matching row of an executed SQL statement.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:getone
+ *
+ * @param string $sql The SQL to execute.
+ * @param bool|array $inputarr (Optional) An array containing any required SQL parameters, or false if none needed.
+ *
+ * @return bool|array|null
+ */
+ function GetOne($sql, $inputarr = false)
{
global $ADODB_GETONE_EOF;
$ret = false;
- $rs = $this->Execute($sql,$inputarr);
+ $rs = $this->execute($sql,$inputarr);
if ($rs) {
if ($rs->EOF) $ret = $ADODB_GETONE_EOF;
else $ret = reset($rs->fields);
- $rs->Close();
+ $rs->close();
}
return $ret;
}
+ /**
+ * Get information about the current MySQL server.
+ *
+ * @return array
+ */
function ServerInfo()
{
- $arr['description'] = $this->GetOne("select version()");
+ $arr['description'] = $this->getOne("select version()");
$arr['version'] = ADOConnection::_findvers($arr['description']);
return $arr;
}
-
+ /**
+ * Begins a granular transaction.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:begintrans
+ *
+ * @return bool Always returns true.
+ */
function BeginTrans()
{
if ($this->transOff) return true;
$this->transCnt += 1;
- //$this->Execute('SET AUTOCOMMIT=0');
+ //$this->execute('SET AUTOCOMMIT=0');
mysqli_autocommit($this->_connectionID, false);
- $this->Execute('BEGIN');
+ $this->execute('BEGIN');
return true;
}
- function CommitTrans($ok=true)
+ /**
+ * Commits a granular transaction.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:committrans
+ *
+ * @param bool $ok (Optional) If false, will rollback the transaction instead.
+ *
+ * @return bool Always returns true.
+ */
+ function CommitTrans($ok = true)
{
if ($this->transOff) return true;
- if (!$ok) return $this->RollbackTrans();
+ if (!$ok) return $this->rollbackTrans();
if ($this->transCnt) $this->transCnt -= 1;
- $this->Execute('COMMIT');
+ $this->execute('COMMIT');
- //$this->Execute('SET AUTOCOMMIT=1');
+ //$this->execute('SET AUTOCOMMIT=1');
mysqli_autocommit($this->_connectionID, true);
return true;
}
+ /**
+ * Rollback a smart transaction.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:rollbacktrans
+ *
+ * @return bool Always returns true.
+ */
function RollbackTrans()
{
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
- $this->Execute('ROLLBACK');
- //$this->Execute('SET AUTOCOMMIT=1');
+ $this->execute('ROLLBACK');
+ //$this->execute('SET AUTOCOMMIT=1');
mysqli_autocommit($this->_connectionID, true);
return true;
}
- function RowLock($tables,$where='',$col='1 as adodbignore')
+ /**
+ * Lock a table row for a duration of a transaction.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:rowlock
+ *
+ * @param string $tables The table(s) to lock rows for.
+ * @param string $where (Optional) The WHERE clause to use to determine which rows to lock.
+ * @param string $col (Optional) The columns to select.
+ *
+ * @return bool True if the locking SQL statement executed successfully, otherwise false.
+ */
+ function RowLock($tables, $where = '', $col = '1 as adodbignore')
{
- if ($this->transCnt==0) $this->BeginTrans();
+ if ($this->transCnt==0) $this->beginTrans();
if ($where) $where = ' where '.$where;
- $rs = $this->Execute("select $col from $tables $where for update");
+ $rs = $this->execute("select $col from $tables $where for update");
return !empty($rs);
}
/**
- * Quotes a string to be sent to the database
- * When there is no active connection,
- * @param string $s The string to quote
- * @param boolean $magic_quotes If false, use mysqli_real_escape_string()
- * if you are quoting a string extracted from a POST/GET variable,
- * then pass get_magic_quotes_gpc() as the second parameter. This will
- * ensure that the variable is not quoted twice, once by qstr() and
- * once by the magic_quotes_gpc.
- * Eg. $s = $db->qstr(_GET['name'],get_magic_quotes_gpc());
+ * Appropriately quotes strings with ' characters for insertion into the database.
+ *
+ * Relies on mysqli_real_escape_string()
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:qstr
+ *
+ * @param string $s The string to quote
+ * @param bool $magic_quotes This param is not used since 5.21.0.
+ * It remains for backwards compatibility.
+ *
* @return string Quoted string
*/
- function qstr($s, $magic_quotes = false)
+ function qStr($s, $magic_quotes=false)
{
- if (is_null($s)) return 'NULL';
- if (!$magic_quotes) {
- // mysqli_real_escape_string() throws a warning when the given
- // connection is invalid
- if (PHP_VERSION >= 5 && $this->_connectionID) {
- return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'";
- }
+ if (is_null($s)) {
+ return 'NULL';
+ }
- if ($this->replaceQuote[0] == '\\') {
- $s = adodb_str_replace(array('\\',"\0"), array('\\\\',"\\\0") ,$s);
- }
- return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
+ // mysqli_real_escape_string() throws a warning when the given
+ // connection is invalid
+ if ($this->_connectionID) {
+ return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'";
}
- // undo magic quotes for "
- $s = str_replace('\\"','"',$s);
- return "'$s'";
+
+ if ($this->replaceQuote[0] == '\\') {
+ $s = str_replace(array('\\', "\0"), array('\\\\', "\\\0") ,$s);
+ }
+ return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
}
- function _insertid()
+ /**
+ * Return the AUTO_INCREMENT id of the last row that has been inserted or updated in a table.
+ *
+ * @inheritDoc
+ */
+ protected function _insertID($table = '', $column = '')
{
- $result = @mysqli_insert_id($this->_connectionID);
+ // mysqli_insert_id does not return the last_insert_id if called after
+ // execution of a stored procedure so we execute this instead.
+ if ($this->useLastInsertStatement)
+ $result = ADOConnection::getOne('SELECT LAST_INSERT_ID()');
+ else
+ $result = @mysqli_insert_id($this->_connectionID);
+
if ($result == -1) {
- if ($this->debug) ADOConnection::outp("mysqli_insert_id() failed : " . $this->ErrorMsg());
+ if ($this->debug)
+ ADOConnection::outp("mysqli_insert_id() failed : " . $this->errorMsg());
}
+ // reset prepared statement flags
+ $this->usePreparedStatement = false;
+ $this->useLastInsertStatement = false;
return $result;
}
- // Only works for INSERT, UPDATE and DELETE query's
+ /**
+ * Returns how many rows were effected by the most recently executed SQL statement.
+ * Only works for INSERT, UPDATE and DELETE queries.
+ *
+ * @return int The number of rows affected.
+ */
function _affectedrows()
{
+ if ($this->isSelectStatement) {
+ // Affected rows works fine against selects, returning
+ // the rowcount, but ADOdb does not do that.
+ return false;
+ }
+
$result = @mysqli_affected_rows($this->_connectionID);
if ($result == -1) {
- if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : " . $this->ErrorMsg());
+ if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : " . $this->errorMsg());
}
return $result;
}
- // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
// Reference on Last_Insert_ID on the recommended way to simulate sequences
var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
var $_genSeqSQL = "create table if not exists %s (id int not null)";
@@ -279,60 +459,96 @@ function _affectedrows()
var $_genSeq2SQL = "insert into %s values (%s)";
var $_dropSeqSQL = "drop table if exists %s";
- function CreateSequence($seqname='adodbseq',$startID=1)
+ /**
+ * 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.
+ */
+ function CreateSequence($seqname = 'adodbseq', $startID = 1)
{
if (empty($this->_genSeqSQL)) return false;
- $u = strtoupper($seqname);
- $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
+ $ok = $this->execute(sprintf($this->_genSeqSQL,$seqname));
if (!$ok) return false;
- return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
+ return $this->execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
}
- 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 bool|int|string
+ */
+ function GenID($seqname = 'adodbseq', $startID = 1)
{
// post-nuke sets hasGenID to false
if (!$this->hasGenID) return false;
$getnext = sprintf($this->_genIDSQL,$seqname);
$holdtransOK = $this->_transOK; // save the current status
- $rs = @$this->Execute($getnext);
+ $rs = @$this->execute($getnext);
if (!$rs) {
if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset
- $u = strtoupper($seqname);
- $this->Execute(sprintf($this->_genSeqSQL,$seqname));
- $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname));
- if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
- $rs = $this->Execute($getnext);
+ $this->execute(sprintf($this->_genSeqSQL,$seqname));
+ $cnt = $this->getOne(sprintf($this->_genSeqCountSQL,$seqname));
+ if (!$cnt) $this->execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
+ $rs = $this->execute($getnext);
}
if ($rs) {
$this->genID = mysqli_insert_id($this->_connectionID);
- $rs->Close();
+ if ($this->genID == 0) {
+ $getnext = "select LAST_INSERT_ID() from " . $seqname;
+ $rs = $this->execute($getnext);
+ $this->genID = (int)$rs->fields[0];
+ }
+ $rs->close();
} else
$this->genID = 0;
return $this->genID;
}
+ /**
+ * Return a list of all visible databases except the 'mysql' database.
+ *
+ * @return array|false An array of database names, or false if the query failed.
+ */
function MetaDatabases()
{
$query = "SHOW DATABASES";
- $ret = $this->Execute($query);
+ $ret = $this->execute($query);
if ($ret && is_object($ret)){
$arr = array();
while (!$ret->EOF){
- $db = $ret->Fields('Database');
+ $db = $ret->fields('Database');
if ($db != 'mysql') $arr[] = $db;
- $ret->MoveNext();
+ $ret->moveNext();
}
return $arr;
}
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.
+ */
+ function MetaIndexes($table, $primary = false, $owner = false)
{
// save old fetch mode
global $ADODB_FETCH_MODE;
@@ -341,15 +557,15 @@ function MetaIndexes ($table, $primary = FALSE, $owner = false)
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
- $savem = $this->SetFetchMode(FALSE);
+ $savem = $this->setFetchMode(FALSE);
}
// 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)) {
- $this->SetFetchMode($savem);
+ $this->setFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
@@ -360,7 +576,7 @@ function MetaIndexes ($table, $primary = FALSE, $owner = false)
$indexes = array ();
// parse index data into array
- while ($row = $rs->FetchRow()) {
+ while ($row = $rs->fetchRow()) {
if ($primary == FALSE AND $row[2] == 'PRIMARY') {
continue;
}
@@ -384,9 +600,17 @@ function MetaIndexes ($table, $primary = FALSE, $owner = false)
return $indexes;
}
-
- // Format date column in sql string given an input format that understands Y M D
- function SQLDate($fmt, $col=false)
+ /**
+ * Returns a portably-formatted date string from a timestamp database column.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:sqldate
+ *
+ * @param string $fmt The date format to use.
+ * @param string|bool $col (Optional) The table column to date format, or if false, use NOW().
+ *
+ * @return bool|string The SQL DATE_FORMAT() string, or false if the provided date format was empty.
+ */
+ function SQLDate($fmt, $col = false)
{
if (!$col) $col = $this->sysTimeStamp;
$s = 'DATE_FORMAT('.$col.",'";
@@ -463,11 +687,15 @@ function SQLDate($fmt, $col=false)
return $s;
}
- // returns concatenated string
- // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
+ /**
+ * Returns a database-specific concatenation of strings.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:concat
+ *
+ * @return string
+ */
function Concat()
{
- $s = "";
$arr = func_get_args();
// suggestion by andrew005@mnogo.ru
@@ -476,8 +704,17 @@ function Concat()
else return '';
}
- // dayFraction is a day in floating point
- function OffsetDate($dayFraction,$date=false)
+ /**
+ * 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
+ */
+ function OffsetDate($dayFraction, $date = false)
{
if (!$date) $date = $this->sysDate;
@@ -487,17 +724,25 @@ function OffsetDate($dayFraction,$date=false)
// return "from_unixtime(unix_timestamp($date)+$fraction)";
}
+ /**
+ * Returns information about stored procedures and stored functions.
+ *
+ * @param string|bool $NamePattern (Optional) Only look for procedures/functions with a name matching this pattern.
+ * @param null $catalog (Optional) Unused.
+ * @param null $schemaPattern (Optional) Unused.
+ *
+ * @return array
+ */
function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern = null)
{
// save old fetch mode
global $ADODB_FETCH_MODE;
- $false = false;
$save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) {
- $savem = $this->SetFetchMode(FALSE);
+ $savem = $this->setFetchMode(FALSE);
}
$procedures = array ();
@@ -508,11 +753,11 @@ function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern
if ($NamePattern) {
$likepattern = " LIKE '".$NamePattern."'";
}
- $rs = $this->Execute('SHOW PROCEDURE STATUS'.$likepattern);
+ $rs = $this->execute('SHOW PROCEDURE STATUS'.$likepattern);
if (is_object($rs)) {
// parse index data into array
- while ($row = $rs->FetchRow()) {
+ while ($row = $rs->fetchRow()) {
$procedures[$row[1]] = array(
'type' => 'PROCEDURE',
'catalog' => '',
@@ -522,10 +767,10 @@ function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern
}
}
- $rs = $this->Execute('SHOW FUNCTION STATUS'.$likepattern);
+ $rs = $this->execute('SHOW FUNCTION STATUS'.$likepattern);
if (is_object($rs)) {
// parse index data into array
- while ($row = $rs->FetchRow()) {
+ while ($row = $rs->fetchRow()) {
$procedures[$row[1]] = array(
'type' => 'FUNCTION',
'catalog' => '',
@@ -537,7 +782,7 @@ function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern
// restore fetchmode
if (isset($savem)) {
- $this->SetFetchMode($savem);
+ $this->setFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
@@ -547,13 +792,13 @@ function MetaProcedures($NamePattern = false, $catalog = null, $schemaPattern
/**
* Retrieves a list of tables based on given criteria
*
- * @param string $ttype Table type = 'TABLE', 'VIEW' or false=both (default)
- * @param string $showSchema schema name, false = current schema (default)
- * @param string $mask filters the table by name
+ * @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
*/
- function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ function MetaTables($ttype = false, $showSchema = false, $mask = false)
{
$save = $this->metaTablesSQL;
if ($showSchema && is_string($showSchema)) {
@@ -566,26 +811,43 @@ function MetaTables($ttype=false,$showSchema=false,$mask=false)
$mask = $this->qstr($mask);
$this->metaTablesSQL .= " AND table_name LIKE $mask";
}
- $ret = ADOConnection::MetaTables($ttype,$showSchema);
+ $ret = ADOConnection::metaTables($ttype,$showSchema);
$this->metaTablesSQL = $save;
return $ret;
}
- // "Innox - Juan Carlos Gonzalez"
- function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
+ /**
+ * Return information about a table's foreign keys.
+ *
+ * @param string $table The name of the table to get the foreign keys for.
+ * @param string|bool $owner (Optional) The database the table belongs to, or false to assume the current db.
+ * @param string|bool $upper (Optional) Force uppercase table name on returned array keys.
+ * @param bool $associative (Optional) Whether to return an associate or numeric array.
+ *
+ * @return array|bool An array of foreign keys, or false no foreign keys could be found.
+ */
+ function MetaForeignKeys($table, $owner = false, $upper = false, $associative = false)
{
- global $ADODB_FETCH_MODE;
- if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true;
+ global $ADODB_FETCH_MODE;
+
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC
+ || $this->fetchMode == ADODB_FETCH_ASSOC)
+ $associative = true;
+
+ $savem = $ADODB_FETCH_MODE;
+ $this->setFetchMode(ADODB_FETCH_ASSOC);
if ( !empty($owner) ) {
$table = "$owner.$table";
}
+
$a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
- if ($associative) {
- $create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"];
- } else $create_sql = $a_create_table[1];
+
+ $this->setFetchMode($savem);
+
+ $create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"];
$matches = array();
@@ -618,7 +880,15 @@ function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative =
return $foreign_keys;
}
- 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.
+ */
+ function MetaColumns($table, $normalize = true)
{
$false = false;
if (!$this->metaColumnsSQL)
@@ -631,17 +901,17 @@ function MetaColumns($table, $normalize=true)
$savem = $this->SetFetchMode(false);
/*
* Return assoc array where key is column name, value is column type
- * [1] => int unsigned
+ * [1] => int unsigned
*/
-
- $SQL = "SELECT column_name, column_type
- FROM information_schema.columns
- WHERE table_schema='{$this->databaseName}'
+
+ $SQL = "SELECT column_name, column_type
+ FROM information_schema.columns
+ WHERE table_schema='{$this->databaseName}'
AND table_name='$table'";
-
+
$schemaArray = $this->getAssoc($SQL);
$schemaArray = array_change_key_case($schemaArray,CASE_LOWER);
-
+
$rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
if (isset($savem)) $this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
@@ -653,7 +923,7 @@ function MetaColumns($table, $normalize=true)
$fld = new ADOFieldObject();
$fld->name = $rs->fields[0];
$type = $rs->fields[1];
-
+
/*
* Type from information_schema returns
* the same format in V8 mysql as V5
@@ -679,7 +949,7 @@ function MetaColumns($table, $normalize=true)
$fld->type = $type;
$fld->max_length = -1;
}
-
+
$fld->not_null = ($rs->fields[2] != 'YES');
$fld->primary_key = ($rs->fields[3] == 'PRI');
$fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
@@ -702,14 +972,22 @@ function MetaColumns($table, $normalize=true)
} else {
$retarr[strtoupper($fld->name)] = $fld;
}
- $rs->MoveNext();
+ $rs->moveNext();
}
- $rs->Close();
+ $rs->close();
return $retarr;
}
- // returns true or false
+ /**
+ * Select which database to connect to.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:selectdb
+ *
+ * @param string $dbName The name of the database to select.
+ *
+ * @return bool True if the database was selected successfully, otherwise false.
+ */
function SelectDB($dbName)
{
// $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);
@@ -719,19 +997,32 @@ function SelectDB($dbName)
if ($this->_connectionID) {
$result = @mysqli_select_db($this->_connectionID, $dbName);
if (!$result) {
- ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg());
+ ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->errorMsg());
}
return $result;
}
return false;
}
- // parameters use PostgreSQL convention, not MySQL
+ /**
+ * 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 $secs (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.
+ */
function SelectLimit($sql,
- $nrows = -1,
- $offset = -1,
- $inputarr = false,
- $secs = 0)
+ $nrows = -1,
+ $offset = -1,
+ $inputarr = false,
+ $secs = 0)
{
$nrows = (int) $nrows;
$offset = (int) $offset;
@@ -739,30 +1030,53 @@ function SelectLimit($sql,
if ($nrows < 0) $nrows = '18446744073709551615';
if ($secs)
- $rs = $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr );
+ $rs = $this->cacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr );
else
- $rs = $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr );
+ $rs = $this->execute($sql . " LIMIT $offsetStr$nrows" , $inputarr );
return $rs;
}
-
+ /**
+ * Prepares an SQL statement and returns a handle to use.
+ *
+ * @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 string The original SQL that was provided.
+ */
function Prepare($sql)
{
+ /*
+ * Flag the insert_id method to use the correct retrieval method
+ */
+ $this->usePreparedStatement = true;
+
+ /*
+ * Prepared statements are not yet handled correctly
+ */
return $sql;
$stmt = $this->_connectionID->prepare($sql);
if (!$stmt) {
- echo $this->ErrorMsg();
+ echo $this->errorMsg();
return $sql;
}
return array($sql,$stmt);
}
-
- // returns queryID or false
+ /**
+ * Return the query id.
+ *
+ * @param string|array $sql
+ * @param array $inputarr
+ *
+ * @return bool|mysqli_result
+ */
function _query($sql, $inputarr)
{
- global $ADODB_COUNTRECS;
+ global $ADODB_COUNTRECS;
// Move to the next recordset, or return false if there is none. In a stored proc
// call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
// returns false. I think this is because the last "recordset" is actually just the
@@ -783,21 +1097,36 @@ function _query($sql, $inputarr)
else $a .= 'd';
}
+ /*
+ * set prepared statement flags
+ */
+ if ($this->usePreparedStatement)
+ $this->useLastInsertStatement = true;
+
$fnarr = array_merge( array($stmt,$a) , $inputarr);
- $ret = call_user_func_array('mysqli_stmt_bind_param',$fnarr);
+ call_user_func_array('mysqli_stmt_bind_param',$fnarr);
$ret = mysqli_stmt_execute($stmt);
return $ret;
}
+ else
+ {
+ /*
+ * reset prepared statement flags, in case we set them
+ * previously and didn't use them
+ */
+ $this->usePreparedStatement = false;
+ $this->useLastInsertStatement = false;
+ }
/*
if (!$mysql_res = mysqli_query($this->_connectionID, $sql, ($ADODB_COUNTRECS) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT)) {
- if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
+ if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->errorMsg());
return false;
}
return $mysql_res;
*/
-
+
if ($this->multiQuery) {
$rs = mysqli_multi_query($this->_connectionID, $sql.';');
if ($rs) {
@@ -806,18 +1135,26 @@ function _query($sql, $inputarr)
}
} else {
$rs = mysqli_query($this->_connectionID, $sql, $ADODB_COUNTRECS ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT);
-
- if ($rs) return $rs;
+ if ($rs) {
+ $this->isSelectStatement = is_object($rs);
+ return $rs;
+ }
}
if($this->debug)
- ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
+ ADOConnection::outp("Query: " . $sql . " failed. " . $this->errorMsg());
return false;
}
- /* Returns: the last error message from previous database operation */
+ /**
+ * Returns a database specific error message.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:errormsg
+ *
+ * @return string The last error message.
+ */
function ErrorMsg()
{
if (empty($this->_connectionID))
@@ -827,7 +1164,11 @@ function ErrorMsg()
return $this->_errorMsg;
}
- /* Returns: the last error number from previous database operation */
+ /**
+ * Returns the last error number from previous database operation.
+ *
+ * @return int The last error number.
+ */
function ErrorNo()
{
if (empty($this->_connectionID))
@@ -836,72 +1177,73 @@ function ErrorNo()
return @mysqli_errno($this->_connectionID);
}
- // returns true or false
+ /**
+ * Close the database connection.
+ *
+ * @return void
+ */
function _close()
{
- @mysqli_close($this->_connectionID);
+ if($this->_connectionID) {
+ mysqli_close($this->_connectionID);
+ }
$this->_connectionID = false;
}
- /*
- * Maximum size of C field
- */
+ /**
+ * Returns the largest length of data that can be inserted into a character field.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:charmax
+ *
+ * @return int
+ */
function CharMax()
{
return 255;
}
- /*
- * Maximum size of X field
- */
+ /**
+ * Returns the largest length of data that can be inserted into a text field.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:textmax
+ *
+ * @return int
+ */
function TextMax()
{
return 4294967295;
}
-
- // this is a set of functions for managing client encoding - very important if the encodings
- // of your database and your output target (i.e. HTML) don't match
- // for instance, you may have UTF8 database and server it on-site as latin1 etc.
- // GetCharSet - get the name of the character set the client is using now
- // Under Windows, the functions should work with MySQL 4.1.11 and above, the set of charsets supported
- // depends on compile flags of mysql distribution
-
- function GetCharSet()
+ function getCharSet()
{
- //we will use ADO's builtin property charSet
- if (!method_exists($this->_connectionID,'character_set_name'))
+ if (!$this->_connectionID || !method_exists($this->_connectionID,'character_set_name')) {
return false;
-
- $this->charSet = @$this->_connectionID->character_set_name();
- if (!$this->charSet) {
- return false;
- } else {
- return $this->charSet;
}
+
+ $this->charSet = $this->_connectionID->character_set_name();
+ return $this->charSet ?: false;
}
- // SetCharSet - switch the client encoding
- function SetCharSet($charset_name)
+ function setCharSet($charset)
{
- if (!method_exists($this->_connectionID,'set_charset')) {
+ if (!$this->_connectionID || !method_exists($this->_connectionID,'set_charset')) {
return false;
}
- if ($this->charSet !== $charset_name) {
- $if = @$this->_connectionID->set_charset($charset_name);
- return ($if === true & $this->GetCharSet() == $charset_name);
- } else {
- return true;
+ if ($this->charSet !== $charset) {
+ if (!$this->_connectionID->set_charset($charset)) {
+ return false;
+ }
+ $this->getCharSet();
}
+ return true;
}
}
-/*--------------------------------------------------------------------------------------
- Class Name: Recordset
---------------------------------------------------------------------------------------*/
-
+/**
+ * Class ADORecordSet_mysqli
+ */
class ADORecordSet_mysqli extends ADORecordSet{
var $databaseType = "mysqli";
@@ -959,6 +1301,15 @@ function _initrs()
131072 = MYSQLI_BINCMP_FLAG
*/
+ /**
+ * Returns raw, database specific information about a field.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:recordset:fetchfield
+ *
+ * @param int $fieldOffset (Optional) The field number to get information for.
+ *
+ * @return ADOFieldObject|bool
+ */
function FetchField($fieldOffset = -1)
{
$fieldnr = $fieldOffset;
@@ -980,19 +1331,43 @@ function FetchField($fieldOffset = -1)
// $o->blob = $o->flags & MYSQLI_BLOB_FLAG; /* not returned by MetaColumns */
$o->unsigned = $o->flags & MYSQLI_UNSIGNED_FLAG;
- return $o;
+ /*
+ * Trivial method to cast class to ADOfieldObject
+ */
+ $a = new ADOFieldObject;
+ foreach (get_object_vars($o) as $key => $name)
+ $a->$key = $name;
+ return $a;
}
+ /**
+ * Reads a row in associative mode if the recordset fetch mode is numeric.
+ * Using this function when the fetch mode is set to ADODB_FETCH_ASSOC may produce unpredictable results.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:getrowassoc
+ *
+ * @param int $upper Indicates whether the keys of the recordset should be upper case or lower case.
+ *
+ * @return array|bool
+ */
function GetRowAssoc($upper = ADODB_ASSOC_CASE)
{
if ($this->fetchMode == MYSQLI_ASSOC && $upper == ADODB_ASSOC_CASE_LOWER) {
return $this->fields;
}
- $row = ADORecordSet::GetRowAssoc($upper);
+ $row = ADORecordSet::getRowAssoc($upper);
return $row;
}
- /* Use associative array to get fields array */
+ /**
+ * Returns a single field in a single row of the current recordset.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:recordset:fields
+ *
+ * @param string $colname The name of the field to retrieve.
+ *
+ * @return mixed
+ */
function Fields($colname)
{
if ($this->fetchMode != MYSQLI_NUM) {
@@ -1002,13 +1377,20 @@ function Fields($colname)
if (!$this->bind) {
$this->bind = array();
for ($i = 0; $i < $this->_numOfFields; $i++) {
- $o = $this->FetchField($i);
+ $o = $this->fetchField($i);
$this->bind[strtoupper($o->name)] = $i;
}
}
return $this->fields[$this->bind[strtoupper($colname)]];
}
+ /**
+ * 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)
{
if ($this->_numOfRows == 0 || $row < 0) {
@@ -1020,10 +1402,16 @@ function _seek($row)
return true;
}
-
+ /**
+ * In databases that allow accessing of recordsets, retrieves the next set.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:recordset:nextrecordset
+ *
+ * @return bool
+ */
function NextRecordSet()
{
- global $ADODB_COUNTRECS;
+ global $ADODB_COUNTRECS;
mysqli_free_result($this->_queryID);
$this->_queryID = -1;
@@ -1031,25 +1419,32 @@ function NextRecordSet()
// call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
// returns false. I think this is because the last "recordset" is actually just the
// return value of the stored proc (ie the number of rows affected).
- if(!mysqli_next_result($this->connection->_connectionID)) {
- return false;
+ if (!mysqli_next_result($this->connection->_connectionID)) {
+ return false;
}
+
// CD: There is no $this->_connectionID variable, at least in the ADO version I'm using
- $this->_queryID = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->connection->_connectionID )
- : @mysqli_use_result( $this->connection->_connectionID );
- if(!$this->_queryID) {
+ $this->_queryID = ($ADODB_COUNTRECS) ? @mysqli_store_result($this->connection->_connectionID)
+ : @mysqli_use_result($this->connection->_connectionID);
+
+ if (!$this->_queryID) {
return false;
}
- $this->_inited = false;
- $this->bind = false;
+
+ $this->_inited = false;
+ $this->bind = false;
$this->_currentRow = -1;
- $this->Init();
+ $this->init();
return true;
}
- // 10% speedup to move MoveNext to child class
- // This is the only implementation that works now (23-10-2003).
- // Other functions return no or the wrong results.
+ /**
+ * Moves the cursor to the next record of the recordset from the current position.
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:movenext
+ *
+ * @return bool False if there are no more records to move on to, otherwise true.
+ */
function MoveNext()
{
if ($this->EOF) return false;
@@ -1064,6 +1459,11 @@ function MoveNext()
return false;
}
+ /**
+ * Attempt to fetch a result row using the current fetch mode and return whether or not this was successful.
+ *
+ * @return bool True if row was fetched successfully, otherwise false.
+ */
function _fetch()
{
$this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode);
@@ -1071,18 +1471,23 @@ function _fetch()
return is_array($this->fields);
}
+ /**
+ * Frees the memory associated with a result.
+ *
+ * @return void
+ */
function _close()
{
- //if results are attached to this pointer from Stored Proceedure calls, the next standard query will die 2014
- //only a problem with persistant connections
+ //if results are attached to this pointer from Stored Procedure calls, the next standard query will die 2014
+ //only a problem with persistent connections
- if(isset($this->connection->_connectionID) && $this->connection->_connectionID) {
- while(mysqli_more_results($this->connection->_connectionID)){
+ if (isset($this->connection->_connectionID) && $this->connection->_connectionID) {
+ while (mysqli_more_results($this->connection->_connectionID)) {
mysqli_next_result($this->connection->_connectionID);
}
}
- if($this->_queryID instanceof mysqli_result) {
+ if ($this->_queryID instanceof mysqli_result) {
mysqli_free_result($this->_queryID);
}
$this->_queryID = false;
@@ -1117,6 +1522,15 @@ function _close()
255 = MYSQLI_TYPE_GEOMETRY
*/
+ /**
+ * Get the MetaType character for a given field type.
+ *
+ * @param string|object $t The type to get the MetaType character for.
+ * @param int $len (Optional) Redundant. Will always be set to -1.
+ * @param bool|object $fieldobj (Optional)
+ *
+ * @return string The MetaType
+ */
function MetaType($t, $len = -1, $fieldobj = false)
{
if (is_object($t)) {
@@ -1125,99 +1539,107 @@ function MetaType($t, $len = -1, $fieldobj = false)
$len = $fieldobj->max_length;
}
-
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
- case 'STRING':
- case 'CHAR':
- case 'VARCHAR':
- case 'TINYBLOB':
- case 'TINYTEXT':
- case 'ENUM':
- case 'SET':
-
- case MYSQLI_TYPE_TINY_BLOB :
- #case MYSQLI_TYPE_CHAR :
- case MYSQLI_TYPE_STRING :
- case MYSQLI_TYPE_ENUM :
- case MYSQLI_TYPE_SET :
- case 253 :
- if ($len <= $this->blobSize) return 'C';
-
- case 'TEXT':
- case 'LONGTEXT':
- case 'MEDIUMTEXT':
- return 'X';
-
- // php_mysql extension always returns 'blob' even if 'text'
- // so we have to check whether binary...
- case 'IMAGE':
- case 'LONGBLOB':
- case 'BLOB':
- case 'MEDIUMBLOB':
-
- case MYSQLI_TYPE_BLOB :
- case MYSQLI_TYPE_LONG_BLOB :
- case MYSQLI_TYPE_MEDIUM_BLOB :
- return !empty($fieldobj->binary) ? 'B' : 'X';
-
- case 'YEAR':
- case 'DATE':
- case MYSQLI_TYPE_DATE :
- case MYSQLI_TYPE_YEAR :
- return 'D';
-
- case 'TIME':
- case 'DATETIME':
- case 'TIMESTAMP':
-
- case MYSQLI_TYPE_DATETIME :
- case MYSQLI_TYPE_NEWDATE :
- case MYSQLI_TYPE_TIME :
- case MYSQLI_TYPE_TIMESTAMP :
- return 'T';
-
- case 'INT':
- case 'INTEGER':
- case 'BIGINT':
- case 'TINYINT':
- case 'MEDIUMINT':
- case 'SMALLINT':
-
- case MYSQLI_TYPE_INT24 :
- case MYSQLI_TYPE_LONG :
- case MYSQLI_TYPE_LONGLONG :
- case MYSQLI_TYPE_SHORT :
- case MYSQLI_TYPE_TINY :
- if (!empty($fieldobj->primary_key)) return 'R';
- return 'I';
-
- // Added floating-point types
- // Maybe not necessery.
- case 'FLOAT':
- case 'DOUBLE':
-// case 'DOUBLE PRECISION':
- case 'DECIMAL':
- case 'DEC':
- case 'FIXED':
- default:
- //if (!is_numeric($t)) echo "
--- Error in type matching $t -----
";
- return 'N';
+ case 'STRING':
+ case 'CHAR':
+ case 'VARCHAR':
+ case 'TINYBLOB':
+ case 'TINYTEXT':
+ case 'ENUM':
+ case 'SET':
+
+ case MYSQLI_TYPE_TINY_BLOB :
+// case MYSQLI_TYPE_CHAR :
+ case MYSQLI_TYPE_STRING :
+ case MYSQLI_TYPE_ENUM :
+ case MYSQLI_TYPE_SET :
+ case 253 :
+ if ($len <= $this->blobSize) {
+ return 'C';
+ }
+
+ case 'TEXT':
+ case 'LONGTEXT':
+ case 'MEDIUMTEXT':
+ return 'X';
+
+ // php_mysql extension always returns 'blob' even if 'text'
+ // so we have to check whether binary...
+ case 'IMAGE':
+ case 'LONGBLOB':
+ case 'BLOB':
+ case 'MEDIUMBLOB':
+
+ case MYSQLI_TYPE_BLOB :
+ case MYSQLI_TYPE_LONG_BLOB :
+ case MYSQLI_TYPE_MEDIUM_BLOB :
+ return !empty($fieldobj->binary) ? 'B' : 'X';
+
+ case 'YEAR':
+ case 'DATE':
+ case MYSQLI_TYPE_DATE :
+ case MYSQLI_TYPE_YEAR :
+ return 'D';
+
+ case 'TIME':
+ case 'DATETIME':
+ case 'TIMESTAMP':
+
+ case MYSQLI_TYPE_DATETIME :
+ case MYSQLI_TYPE_NEWDATE :
+ case MYSQLI_TYPE_TIME :
+ case MYSQLI_TYPE_TIMESTAMP :
+ return 'T';
+
+ case 'INT':
+ case 'INTEGER':
+ case 'BIGINT':
+ case 'TINYINT':
+ case 'MEDIUMINT':
+ case 'SMALLINT':
+
+ case MYSQLI_TYPE_INT24 :
+ case MYSQLI_TYPE_LONG :
+ case MYSQLI_TYPE_LONGLONG :
+ case MYSQLI_TYPE_SHORT :
+ case MYSQLI_TYPE_TINY :
+ if (!empty($fieldobj->primary_key)) {
+ return 'R';
+ }
+ return 'I';
+
+ // Added floating-point types
+ // Maybe not necessary.
+ case 'FLOAT':
+ case 'DOUBLE':
+// case 'DOUBLE PRECISION':
+ case 'DECIMAL':
+ case 'DEC':
+ case 'FIXED':
+ default:
+ //if (!is_numeric($t)) echo "
--- Error in type matching $t -----
";
+ return 'N';
}
- } // function
+ }
} // rs class
-}
-
-class ADORecordSet_array_mysqli extends ADORecordSet_array {
-
- function __construct($id=-1,$mode=false)
- {
- parent::__construct($id,$mode);
- }
-
+/**
+ * Class ADORecordSet_array_mysqli
+ */
+class ADORecordSet_array_mysqli extends ADORecordSet_array
+{
+ /**
+ * Get the MetaType character for a given field type.
+ *
+ * @param string|object $t The type to get the MetaType character for.
+ * @param int $len (Optional) Redundant. Will always be set to -1.
+ * @param bool|object $fieldobj (Optional)
+ *
+ * @return string The MetaType
+ */
function MetaType($t, $len = -1, $fieldobj = false)
{
if (is_object($t)) {
@@ -1226,90 +1648,89 @@ function MetaType($t, $len = -1, $fieldobj = false)
$len = $fieldobj->max_length;
}
-
$len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) {
- case 'STRING':
- case 'CHAR':
- case 'VARCHAR':
- case 'TINYBLOB':
- case 'TINYTEXT':
- case 'ENUM':
- case 'SET':
-
- case MYSQLI_TYPE_TINY_BLOB :
- #case MYSQLI_TYPE_CHAR :
- case MYSQLI_TYPE_STRING :
- case MYSQLI_TYPE_ENUM :
- case MYSQLI_TYPE_SET :
- case 253 :
- if ($len <= $this->blobSize) return 'C';
-
- case 'TEXT':
- case 'LONGTEXT':
- case 'MEDIUMTEXT':
- return 'X';
-
- // php_mysql extension always returns 'blob' even if 'text'
- // so we have to check whether binary...
- case 'IMAGE':
- case 'LONGBLOB':
- case 'BLOB':
- case 'MEDIUMBLOB':
-
- case MYSQLI_TYPE_BLOB :
- case MYSQLI_TYPE_LONG_BLOB :
- case MYSQLI_TYPE_MEDIUM_BLOB :
-
- return !empty($fieldobj->binary) ? 'B' : 'X';
- case 'YEAR':
- case 'DATE':
- case MYSQLI_TYPE_DATE :
- case MYSQLI_TYPE_YEAR :
-
- return 'D';
-
- case 'TIME':
- case 'DATETIME':
- case 'TIMESTAMP':
-
- case MYSQLI_TYPE_DATETIME :
- case MYSQLI_TYPE_NEWDATE :
- case MYSQLI_TYPE_TIME :
- case MYSQLI_TYPE_TIMESTAMP :
-
- return 'T';
-
- case 'INT':
- case 'INTEGER':
- case 'BIGINT':
- case 'TINYINT':
- case 'MEDIUMINT':
- case 'SMALLINT':
-
- case MYSQLI_TYPE_INT24 :
- case MYSQLI_TYPE_LONG :
- case MYSQLI_TYPE_LONGLONG :
- case MYSQLI_TYPE_SHORT :
- case MYSQLI_TYPE_TINY :
-
- if (!empty($fieldobj->primary_key)) return 'R';
-
- return 'I';
-
-
- // Added floating-point types
- // Maybe not necessery.
- case 'FLOAT':
- case 'DOUBLE':
-// case 'DOUBLE PRECISION':
- case 'DECIMAL':
- case 'DEC':
- case 'FIXED':
- default:
- //if (!is_numeric($t)) echo "
--- Error in type matching $t -----
";
- return 'N';
- }
- } // function
+ case 'STRING':
+ case 'CHAR':
+ case 'VARCHAR':
+ case 'TINYBLOB':
+ case 'TINYTEXT':
+ case 'ENUM':
+ case 'SET':
+
+ case MYSQLI_TYPE_TINY_BLOB :
+// case MYSQLI_TYPE_CHAR :
+ case MYSQLI_TYPE_STRING :
+ case MYSQLI_TYPE_ENUM :
+ case MYSQLI_TYPE_SET :
+ case 253 :
+ if ($len <= $this->blobSize) {
+ return 'C';
+ }
+ case 'TEXT':
+ case 'LONGTEXT':
+ case 'MEDIUMTEXT':
+ return 'X';
+
+ // php_mysql extension always returns 'blob' even if 'text'
+ // so we have to check whether binary...
+ case 'IMAGE':
+ case 'LONGBLOB':
+ case 'BLOB':
+ case 'MEDIUMBLOB':
+
+ case MYSQLI_TYPE_BLOB :
+ case MYSQLI_TYPE_LONG_BLOB :
+ case MYSQLI_TYPE_MEDIUM_BLOB :
+ return !empty($fieldobj->binary) ? 'B' : 'X';
+
+ case 'YEAR':
+ case 'DATE':
+ case MYSQLI_TYPE_DATE :
+ case MYSQLI_TYPE_YEAR :
+ return 'D';
+
+ case 'TIME':
+ case 'DATETIME':
+ case 'TIMESTAMP':
+
+ case MYSQLI_TYPE_DATETIME :
+ case MYSQLI_TYPE_NEWDATE :
+ case MYSQLI_TYPE_TIME :
+ case MYSQLI_TYPE_TIMESTAMP :
+ return 'T';
+
+ case 'INT':
+ case 'INTEGER':
+ case 'BIGINT':
+ case 'TINYINT':
+ case 'MEDIUMINT':
+ case 'SMALLINT':
+
+ case MYSQLI_TYPE_INT24 :
+ case MYSQLI_TYPE_LONG :
+ case MYSQLI_TYPE_LONGLONG :
+ case MYSQLI_TYPE_SHORT :
+ case MYSQLI_TYPE_TINY :
+ if (!empty($fieldobj->primary_key)) {
+ return 'R';
+ }
+ return 'I';
+
+ // Added floating-point types
+ // Maybe not necessary.
+ case 'FLOAT':
+ case 'DOUBLE':
+// case 'DOUBLE PRECISION':
+ case 'DECIMAL':
+ case 'DEC':
+ case 'FIXED':
+ default:
+ //if (!is_numeric($t)) echo "
--- Error in type matching $t -----
";
+ return 'N';
+ }
+ }
}
+
+} // if defined _ADODB_MYSQLI_LAYER
diff --git a/adodb/drivers/adodb-mysqlpo.inc.php b/adodb/drivers/adodb-mysqlpo.inc.php
index cb81d64..8aa7779 100644
--- a/adodb/drivers/adodb-mysqlpo.inc.php
+++ b/adodb/drivers/adodb-mysqlpo.inc.php
@@ -1,24 +1,30 @@
-
- This driver extends the deprecated mysql driver, and was originally designed to be a
- portable driver in the same manner as oci8po and mssqlpo. Its functionality
- is exactly duplicated in the mysqlt driver, which is itself deprecated.
- This driver will be removed in ADOdb version 6.0.0.
-
- Requires mysql client. Works on Windows and Unix.
-*/
+/**
+ * Portable MySQL driver
+ *
+ * @deprecated
+ *
+ * Extends the deprecated mysql driver, and was originally designed to be a
+ * portable driver in the same manner as oci8po and mssqlpo. Its functionality
+ * is exactly duplicated in the mysqlt driver, which is itself deprecated.
+ * This driver will be removed in ADOdb version 6.0.0.
+ *
+ * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
+ *
+ * @package ADOdb
+ * @link https://adodb.org Project's web site and documentation
+ * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
+ *
+ * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
+ * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
+ * any later version. This means you can use it in proprietary products.
+ * See the LICENSE.md file distributed with this source code for details.
+ * @license BSD-3-Clause
+ * @license LGPL-2.1-or-later
+ *
+ * @copyright 2000-2013 John Lim
+ * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
+ */
// security - hide paths
if (!defined('ADODB_DIR')) die();
@@ -32,11 +38,6 @@ class ADODB_mysqlt extends ADODB_mysql {
var $hasTransactions = true;
var $autoRollback = true; // apparently mysql does not autorollback properly
- function __construct()
- {
- global $ADODB_EXTENSION; if ($ADODB_EXTENSION) $this->rsPrefix .= 'ext_';
- }
-
function BeginTrans()
{
if ($this->transOff) return true;
@@ -116,11 +117,6 @@ function MoveNext()
class ADORecordSet_ext_mysqlt extends ADORecordSet_mysqlt {
- function __construct($queryID,$mode=false)
- {
- parent::__construct($queryID,$mode);
- }
-
function MoveNext()
{
return adodb_movenext($this);
diff --git a/adodb/drivers/adodb-mysqlt.inc.php b/adodb/drivers/adodb-mysqlt.inc.php
index 1be54ef..cccd93f 100644
--- a/adodb/drivers/adodb-mysqlt.inc.php
+++ b/adodb/drivers/adodb-mysqlt.inc.php
@@ -1,21 +1,30 @@
rsPrefix .= 'ext_';
- }
-
/* set transaction mode
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
diff --git a/adodb/drivers/adodb-netezza.inc.php b/adodb/drivers/adodb-netezza.inc.php
index 5bcfe32..dc7c58e 100644
--- a/adodb/drivers/adodb-netezza.inc.php
+++ b/adodb/drivers/adodb-netezza.inc.php
@@ -1,21 +1,35 @@
+ */
+
// security - hide paths
if (!defined('ADODB_DIR')) die();
@@ -50,11 +64,6 @@ class ADODB_netezza extends ADODB_postgres64 {
// http://bugs.php.net/bug.php?id=25404
- function __construct()
- {
-
- }
-
function MetaColumns($table,$upper=true)
{
@@ -141,11 +150,6 @@ class ADORecordSet_netezza extends ADORecordSet_postgres64
var $databaseType = "netezza";
var $canSeek = true;
- function __construct($queryID,$mode=false)
- {
- parent::__construct($queryID,$mode);
- }
-
// _initrs modified to disable blob handling
function _initrs()
{
diff --git a/adodb/drivers/adodb-oci8.inc.php b/adodb/drivers/adodb-oci8.inc.php
index 800c3a0..e541b6b 100644
--- a/adodb/drivers/adodb-oci8.inc.php
+++ b/adodb/drivers/adodb-oci8.inc.php
@@ -1,20 +1,25 @@
-
- 13 Nov 2000 jlim - removed all ora_* references.
-*/
+/**
+ * FileDescription
+ *
+ * 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
+ * @author John Lim
+ * @author George Fourlanos
+ */
// security - hide paths
if (!defined('ADODB_DIR')) die();
@@ -89,7 +94,6 @@ class ADODB_oci8 extends ADOConnection {
var $connectSID = false;
var $_bind = false;
var $_nestedSQL = true;
- var $_hasOciFetchStatement = false;
var $_getarray = false; // currently not working
var $leftOuter = ''; // oracle wierdness, $col = $value (+) for LEFT OUTER, $col (+)= $value for RIGHT OUTER
var $session_sharing_force_blob = false; // alter session on updateblob if set to true
@@ -103,13 +107,20 @@ class ADODB_oci8 extends ADOConnection {
// var $ansiOuter = true; // if oracle9
- function __construct()
- {
- $this->_hasOciFetchStatement = ADODB_PHPVER >= 0x4200;
- if (defined('ADODB_EXTENSION')) {
- $this->rsPrefix .= 'ext_';
- }
- }
+ /*
+ * Legacy compatibility for sequence names for emulated auto-increments
+ */
+ public $useCompactAutoIncrements = false;
+
+ /*
+ * Defines the schema name for emulated auto-increment columns
+ */
+ public $schema = false;
+
+ /*
+ * Defines the prefix for emulated auto-increment columns
+ */
+ public $seqPrefix = 'SEQ_';
/* function MetaColumns($table, $normalize=true) added by smondino@users.sourceforge.net*/
function MetaColumns($table, $normalize=true)
@@ -308,6 +319,42 @@ function IfNull( $field, $ifNull )
return " NVL($field, $ifNull) "; // if Oracle
}
+ protected function _insertID($table = '', $column = '')
+ {
+
+ if (!$this->seqField)
+ return false;
+
+ if ($this->schema)
+ {
+ $t = strpos($table,'.');
+ if ($t !== false)
+ $tab = substr($table,$t+1);
+ else
+ $tab = $table;
+
+ if ($this->useCompactAutoIncrements)
+ $tab = sprintf('%u',crc32(strtolower($tab)));
+
+ $seqname = $this->schema.'.'.$this->seqPrefix.$tab;
+ }
+ else
+ {
+ if ($this->useCompactAutoIncrements)
+ $table = sprintf('%u',crc32(strtolower($table)));
+
+ $seqname = $this->seqPrefix.$table;
+ }
+
+ if (strlen($seqname) > 30)
+ /*
+ * We cannot successfully identify the sequence
+ */
+ return false;
+
+ return $this->getOne("SELECT $seqname.currval FROM dual");
+ }
+
// format and return date string in database date format
function DBDate($d,$isfld=false)
{
@@ -1497,37 +1544,27 @@ function TextMax()
}
/**
- * Quotes a string.
- * An example is $db->qstr("Don't bother",magic_quotes_runtime());
+ * Correctly quotes a string so that all strings are escaped.
+ * We prefix and append to the string single-quotes.
+ * An example is $db->qstr("Don't bother");
+ *
+ * @param string $s The string to quote
+ * @param bool $magic_quotes This param is not used since 5.21.0.
+ * It remains for backwards compatibility.
*
- * @param string $s the string to quote
- * @param bool $magic_quotes if $s is GET/POST var, set to get_magic_quotes_gpc().
- * This undoes the stupidity of magic quotes for GPC.
+ * @return string Quoted string to be sent back to database
*
- * @return string quoted string to be sent back to database
+ * @noinspection PhpUnusedParameterInspection
*/
- function qstr($s,$magic_quotes=false)
+ function qStr($s, $magic_quotes=false)
{
- //$nofixquotes=false;
-
- if ($this->noNullStrings && strlen($s)==0) {
+ if ($this->noNullStrings && strlen($s) == 0) {
$s = ' ';
}
- if (!$magic_quotes) {
- if ($this->replaceQuote[0] == '\\'){
- $s = str_replace('\\','\\\\',$s);
- }
- return "'".str_replace("'",$this->replaceQuote,$s)."'";
- }
-
- // undo magic quotes for " unless sybase is on
- if (!ini_get('magic_quotes_sybase')) {
- $s = str_replace('\\"','"',$s);
- $s = str_replace('\\\\','\\',$s);
- return "'".str_replace("\\'",$this->replaceQuote,$s)."'";
- } else {
- return "'".$s."'";
+ if ($this->replaceQuote[0] == '\\'){
+ $s = str_replace('\\','\\\\',$s);
}
+ return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
}
}
@@ -1565,7 +1602,7 @@ function __construct($queryID,$mode=false)
$this->adodbFetchMode = $mode;
$this->_queryID = $queryID;
}
-
+
/**
* Overrides the core destructor method as that causes problems here
*
@@ -1751,7 +1788,8 @@ function _close()
oci_free_cursor($this->_refcursor);
$this->_refcursor = false;
}
- @oci_free_statement($this->_queryID);
+ if (is_resource($this->_queryID))
+ @oci_free_statement($this->_queryID);
$this->_queryID = false;
}
@@ -1808,16 +1846,12 @@ function MetaType($t, $len=-1, $fieldobj=false)
return 'I';
default:
- return 'N';
+ return ADODB_DEFAULT_METATYPE;
}
}
}
class ADORecordSet_ext_oci8 extends ADORecordSet_oci8 {
- function __construct($queryID,$mode=false)
- {
- parent::__construct($queryID, $mode);
- }
function MoveNext()
{
diff --git a/adodb/drivers/adodb-oci805.inc.php b/adodb/drivers/adodb-oci805.inc.php
index 40f5152..0195828 100644
--- a/adodb/drivers/adodb-oci805.inc.php
+++ b/adodb/drivers/adodb-oci805.inc.php
@@ -1,18 +1,27 @@
-
- Should some emulation of RecordCount() be implemented?
-
-*/
+/**
+ * Portable version of Oracle oci8 driver
+ *
+ * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
+ *
+ * Portable version of oci8 driver, to make it more similar to other database
+ * drivers. The main differences are
+ * 1. that the OCI_ASSOC names are in lowercase instead of uppercase.
+ * 2. bind variables are mapped using ? instead of :
+ *
+ * @package ADOdb
+ * @link https://adodb.org Project's web site and documentation
+ * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
+ *
+ * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
+ * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
+ * any later version. This means you can use it in proprietary products.
+ * See the LICENSE.md file distributed with this source code for details.
+ * @license BSD-3-Clause
+ * @license LGPL-2.1-or-later
+ *
+ * @copyright 2000-2013 John Lim
+ * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
+ */
// security - hide paths
if (!defined('ADODB_DIR')) die();
@@ -30,12 +35,6 @@ class ADODB_oci8po extends ADODB_oci8 {
var $metaColumnsSQL = "select lower(cname),coltype,width, SCALE, PRECISION, NULLS, DEFAULTVAL from col where tname='%s' order by colno"; //changed by smondino@users.sourceforge. net
var $metaTablesSQL = "select lower(table_name),table_type from cat where table_type in ('TABLE','VIEW')";
- function __construct()
- {
- $this->_hasOCIFetchStatement = ADODB_PHPVER >= 0x4200;
- # oci8po does not support adodb extension: adodb_movenext()
- }
-
function Param($name,$type='C')
{
return '?';
@@ -86,6 +85,7 @@ function _query($sql,$inputarr=false)
}
return ADODB_oci8::_query($sql,$inputarr);
}
+
/**
* Replaces compatibility bind markers with oracle ones and returns a
* valid sql statement
@@ -94,13 +94,13 @@ function _query($sql,$inputarr=false)
* to numerous tweaks, as more extreme test cases have appeared. This
* is now done this like this to help maintainability and avoid the
* need to rely on regexp experienced maintainers
- *
+ *
* @param string $sql The sql statement
* @param string[] $inputarr The bind array
*
* @return string The modified statement
*/
- final private function extractBinds($sql,$inputarr)
+ private function extractBinds($sql,$inputarr)
{
$inString = false;
$escaped = 0;
@@ -120,7 +120,7 @@ final private function extractBinds($sql,$inputarr)
/*
* find the next character of the string
*/
- $c = $sql{$i};
+ $c = $sql[$i];
if ($c == "'" && !$inString && $escaped==0)
/*
@@ -173,11 +173,6 @@ class ADORecordset_oci8po extends ADORecordset_oci8 {
var $databaseType = 'oci8po';
- function __construct($queryID,$mode=false)
- {
- parent::__construct($queryID,$mode);
- }
-
function Fields($colname)
{
if ($this->fetchMode & OCI_ASSOC) return $this->fields[$colname];
diff --git a/adodb/drivers/adodb-oci8quercus.inc.php b/adodb/drivers/adodb-oci8quercus.inc.php
index 07b3362..f9312c9 100644
--- a/adodb/drivers/adodb-oci8quercus.inc.php
+++ b/adodb/drivers/adodb-oci8quercus.inc.php
@@ -1,23 +1,23 @@
-
- Should some emulation of RecordCount() be implemented?
-
-*/
+/**
+ * Oracle "quercus" driver.
+ *
+ * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
+ *
+ * @package ADOdb
+ * @link https://adodb.org Project's web site and documentation
+ * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
+ *
+ * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
+ * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
+ * any later version. This means you can use it in proprietary products.
+ * See the LICENSE.md file distributed with this source code for details.
+ * @license BSD-3-Clause
+ * @license LGPL-2.1-or-later
+ *
+ * @copyright 2000-2013 John Lim
+ * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
+ */
// security - hide paths
if (!defined('ADODB_DIR')) die();
@@ -28,10 +28,6 @@ class ADODB_oci8quercus extends ADODB_oci8 {
var $databaseType = 'oci8quercus';
var $dataProvider = 'oci8';
- function __construct()
- {
- }
-
}
/*--------------------------------------------------------------------------------------
@@ -42,11 +38,6 @@ class ADORecordset_oci8quercus extends ADORecordset_oci8 {
var $databaseType = 'oci8quercus';
- function __construct($queryID,$mode=false)
- {
- parent::__construct($queryID,$mode);
- }
-
function _FetchField($fieldOffset = -1)
{
global $QUERCUS;
diff --git a/adodb/drivers/adodb-odbc.inc.php b/adodb/drivers/adodb-odbc.inc.php
index 78e1a76..a9705e2 100644
--- a/adodb/drivers/adodb-odbc.inc.php
+++ b/adodb/drivers/adodb-odbc.inc.php
@@ -1,22 +1,41 @@
_haserrorfunctions = ADODB_PHPVER >= 0x4050;
- $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
- }
+ function __construct() {}
// returns true or false
function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
@@ -93,7 +111,7 @@ function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
function ServerInfo()
{
- if (!empty($this->host) && ADODB_PHPVER >= 0x4300) {
+ if (!empty($this->host)) {
$dsn = strtoupper($this->host);
$first = true;
$found = false;
@@ -180,30 +198,25 @@ function GenID($seq='adodbseq',$start=1)
function ErrorMsg()
{
- if ($this->_haserrorfunctions) {
- if ($this->_errorMsg !== false) return $this->_errorMsg;
- if (empty($this->_connectionID)) return @odbc_errormsg();
- return @odbc_errormsg($this->_connectionID);
- } else return ADOConnection::ErrorMsg();
+ if ($this->_errorMsg !== false) return $this->_errorMsg;
+ if (empty($this->_connectionID)) return @odbc_errormsg();
+ return @odbc_errormsg($this->_connectionID);
}
function ErrorNo()
{
+ if ($this->_errorCode !== false) {
+ // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
+ return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode;
+ }
- if ($this->_haserrorfunctions) {
- if ($this->_errorCode !== false) {
- // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
- return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode;
- }
-
- if (empty($this->_connectionID)) $e = @odbc_error();
- else $e = @odbc_error($this->_connectionID);
+ if (empty($this->_connectionID)) $e = @odbc_error();
+ else $e = @odbc_error($this->_connectionID);
- // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
- // so we check and patch
- if (strlen($e)<=2) return 0;
- return $e;
- } else return ADOConnection::ErrorNo();
+ // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
+ // so we check and patch
+ if (strlen($e)<=2) return 0;
+ return $e;
}
@@ -258,7 +271,6 @@ function MetaPrimaryKeys($table,$owner=false)
$ADODB_FETCH_MODE = $savem;
if (!$rs) return false;
- $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
$arr = $rs->GetArray();
$rs->Close();
@@ -287,7 +299,6 @@ function MetaTables($ttype=false,$showSchema=false,$mask=false)
$false = false;
return $false;
}
- $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
$arr = $rs->GetArray();
//print_r($arr);
@@ -390,12 +401,11 @@ function MetaColumns($table, $normalize=true)
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
- /*if (false) { // after testing, confirmed that the following does not work becoz of a bug
+ /*if (false) { // after testing, confirmed that the following does not work because of a bug
$qid2 = odbc_tables($this->_connectionID);
$rs = new ADORecordSet_odbc($qid2);
$ADODB_FETCH_MODE = $savem;
if (!$rs) return false;
- $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
$rs->_fetch();
while (!$rs->EOF) {
@@ -434,7 +444,6 @@ function MetaColumns($table, $normalize=true)
$ADODB_FETCH_MODE = $savem;
if (!$rs) return $false;
- $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
$rs->_fetch();
$retarr = array();
@@ -459,7 +468,16 @@ function MetaColumns($table, $normalize=true)
if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
$fld = new ADOFieldObject();
$fld->name = $rs->fields[3];
- $fld->type = $this->ODBCTypes($rs->fields[4]);
+ if ($this->metaColumnsReturnType == METACOLUMNS_RETURNS_META)
+ /*
+ * This is the broken, original value
+ */
+ $fld->type = $this->ODBCTypes($rs->fields[4]);
+ else
+ /*
+ * This is the correct new value
+ */
+ $fld->type = $rs->fields[4];
// ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp
// access uses precision to store length for char/varchar
@@ -516,10 +534,8 @@ function _query($sql,$inputarr=false)
if (! odbc_execute($stmtid,$inputarr)) {
//@odbc_free_result($stmtid);
- if ($this->_haserrorfunctions) {
- $this->_errorMsg = odbc_errormsg();
- $this->_errorCode = odbc_error();
- }
+ $this->_errorMsg = odbc_errormsg();
+ $this->_errorCode = odbc_error();
return false;
}
@@ -527,10 +543,8 @@ function _query($sql,$inputarr=false)
$stmtid = $sql[1];
if (!odbc_execute($stmtid)) {
//@odbc_free_result($stmtid);
- if ($this->_haserrorfunctions) {
- $this->_errorMsg = odbc_errormsg();
- $this->_errorCode = odbc_error();
- }
+ $this->_errorMsg = odbc_errormsg();
+ $this->_errorCode = odbc_error();
return false;
}
} else
@@ -547,19 +561,11 @@ function _query($sql,$inputarr=false)
odbc_longreadlen($stmtid,$this->maxblobsize);
}
- if ($this->_haserrorfunctions) {
- $this->_errorMsg = '';
- $this->_errorCode = 0;
- } else {
- $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
- }
+ $this->_errorMsg = '';
+ $this->_errorCode = 0;
} else {
- if ($this->_haserrorfunctions) {
- $this->_errorMsg = odbc_errormsg();
- $this->_errorCode = odbc_error();
- } else {
- $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
- }
+ $this->_errorMsg = odbc_errormsg();
+ $this->_errorCode = odbc_error();
}
return $stmtid;
}
@@ -603,7 +609,6 @@ class ADORecordSet_odbc extends ADORecordSet {
var $databaseType = "odbc";
var $dataProvider = "odbc";
var $useFetchArray;
- var $_has_stupid_odbc_fetch_api_change;
function __construct($id,$mode=false)
{
@@ -661,7 +666,6 @@ function _initrs()
// some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0
if ($this->_numOfRows == 0) $this->_numOfRows = -1;
//$this->useFetchArray = $this->connection->useFetchArray;
- $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
}
function _seek($row)
@@ -712,12 +716,7 @@ function MoveNext()
function _fetch()
{
$this->fields = false;
- if ($this->_has_stupid_odbc_fetch_api_change)
- $rez = @odbc_fetch_into($this->_queryID,$this->fields);
- else {
- $row = 0;
- $rez = @odbc_fetch_into($this->_queryID,$row,$this->fields);
- }
+ $rez = @odbc_fetch_into($this->_queryID,$this->fields);
if ($rez) {
if ($this->fetchMode & ADODB_FETCH_ASSOC) {
$this->fields = $this->GetRowAssoc();
diff --git a/adodb/drivers/adodb-odbc_db2.inc.php b/adodb/drivers/adodb-odbc_db2.inc.php
index 7f6da60..8f0e60c 100644
--- a/adodb/drivers/adodb-odbc_db2.inc.php
+++ b/adodb/drivers/adodb-odbc_db2.inc.php
@@ -1,98 +1,29 @@
curMode = SQL_CUR_USE_ODBC;
-$db->Connect($dsn, $userid, $pwd);
-
-
-
-USING CLI INTERFACE
-===================
-
-I have had reports that the $host and $database params have to be reversed in
-Connect() when using the CLI interface. From Halmai Csongor csongor.halmai#nexum.hu:
-
-> The symptom is that if I change the database engine from postgres or any other to DB2 then the following
-> connection command becomes wrong despite being described this version to be correct in the docs.
->
-> $connection_object->Connect( $DATABASE_HOST, $DATABASE_AUTH_USER_NAME, $DATABASE_AUTH_PASSWORD, $DATABASE_NAME )
->
-> In case of DB2 I had to swap the first and last arguments in order to connect properly.
-
-
-System Error 5
-==============
-IF you get a System Error 5 when trying to Connect/Load, it could be a permission problem. Give the user connecting
-to DB2 full rights to the DB2 SQLLIB directory, and place the user in the DBUSERS group.
-*/
+/**
+ * DB2 driver via ODBC
+ *
+ * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
+ *
+ * @package ADOdb
+ * @link https://adodb.org Project's web site and documentation
+ * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
+ *
+ * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
+ * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
+ * any later version. This means you can use it in proprietary products.
+ * See the LICENSE.md file distributed with this source code for details.
+ * @license BSD-3-Clause
+ * @license LGPL-2.1-or-later
+ *
+ * @copyright 2000-2013 John Lim
+ * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
+ */
// security - hide paths
if (!defined('ADODB_DIR')) die();
if (!defined('_ADODB_ODBC_LAYER')) {
- include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
+ include_once(ADODB_DIR."/drivers/adodb-odbc.inc.php");
}
if (!defined('ADODB_ODBC_DB2')){
define('ADODB_ODBC_DB2',1);
@@ -131,7 +62,7 @@ function ServerInfo()
return array('description'=>'DB2 ODBC driver', 'version'=>$vers);
}
- function _insertid()
+ protected function _insertID($table = '', $column = '')
{
return $this->GetOne($this->identitySQL);
}
@@ -157,7 +88,6 @@ function MetaTables($ttype=false,$showSchema=false, $qtable="%", $qschema="%")
$false = false;
return $false;
}
- $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
$arr = $rs->GetArray();
//print_r($arr);
@@ -306,11 +236,6 @@ class ADORecordSet_odbc_db2 extends ADORecordSet_odbc {
var $databaseType = "db2";
- function __construct($id,$mode=false)
- {
- parent::__construct($id,$mode);
- }
-
function MetaType($t,$len=-1,$fieldobj=false)
{
if (is_object($t)) {
@@ -361,7 +286,7 @@ function MetaType($t,$len=-1,$fieldobj=false)
case 'I':
return 'I';
- default: return 'N';
+ default: return ADODB_DEFAULT_METATYPE;
}
}
}
diff --git a/adodb/drivers/adodb-odbc_mssql.inc.php b/adodb/drivers/adodb-odbc_mssql.inc.php
index a8a6bb1..37185aa 100644
--- a/adodb/drivers/adodb-odbc_mssql.inc.php
+++ b/adodb/drivers/adodb-odbc_mssql.inc.php
@@ -1,24 +1,29 @@
curmode = SQL_CUR_USE_ODBC;
- }
-
// crashes php...
function ServerInfo()
{
@@ -72,7 +71,7 @@ function IfNull( $field, $ifNull )
return " ISNULL($field, $ifNull) "; // if MS SQL Server
}
- function _insertid()
+ protected function _insertID($table = '', $column = '')
{
// SCOPE_IDENTITY()
// Returns the last IDENTITY value inserted into an IDENTITY column in
@@ -352,14 +351,89 @@ function SQLDate($fmt, $col=false)
return $s;
}
+ /**
+ * Returns a substring of a varchar type field
+ *
+ * The SQL server version varies because the length is mandatory, so
+ * we append a reasonable string length
+ *
+ * @param string $fld The field to sub-string
+ * @param int $start The start point
+ * @param int $length An optional length
+ *
+ * @return The SQL text
+ */
+ function substr($fld,$start,$length=0)
+ {
+ if ($length == 0)
+ /*
+ * The length available to varchar is 2GB, but that makes no
+ * sense in a substring, so I'm going to arbitrarily limit
+ * the length to 1K, but you could change it if you want
+ */
+ $length = 1024;
+
+ $text = "SUBSTRING($fld,$start,$length)";
+ return $text;
+ }
+
+ /**
+ * Returns the maximum size of a MetaType C field. Because of the
+ * database design, SQL Server places no limits on the size of data inserted
+ * Although the actual limit is 2^31-1 bytes.
+ *
+ * @return int
+ */
+ function charMax()
+ {
+ return ADODB_STRINGMAX_NOLIMIT;
+ }
+
+ /**
+ * Returns the maximum size of a MetaType X field. Because of the
+ * database design, SQL Server places no limits on the size of data inserted
+ * Although the actual limit is 2^31-1 bytes.
+ *
+ * @return int
+ */
+ function textMax()
+ {
+ return ADODB_STRINGMAX_NOLIMIT;
+ }
+
+ // returns concatenated string
+ // MSSQL requires integers to be cast as strings
+ // automatically cast every datatype to VARCHAR(255)
+ // @author David Rogers (introspectshun)
+ function Concat()
+ {
+ $s = "";
+ $arr = func_get_args();
+
+ // Split single record on commas, if possible
+ if (sizeof($arr) == 1) {
+ foreach ($arr as $arg) {
+ $args = explode(',', $arg);
+ }
+ $arr = $args;
+ }
+
+ array_walk(
+ $arr,
+ function(&$value, $key) {
+ $value = "CAST(" . $value . " AS VARCHAR(255))";
+ }
+ );
+ $s = implode('+',$arr);
+ if (sizeof($arr) > 0) return "$s";
+
+ return '';
+ }
+
}
class ADORecordSet_odbc_mssql extends ADORecordSet_odbc {
var $databaseType = 'odbc_mssql';
- function __construct($id,$mode=false)
- {
- return parent::__construct($id,$mode);
- }
}
diff --git a/adodb/drivers/adodb-odbc_mssql2012.inc.php b/adodb/drivers/adodb-odbc_mssql2012.inc.php
new file mode 100644
index 0000000..79fa325
--- /dev/null
+++ b/adodb/drivers/adodb-odbc_mssql2012.inc.php
@@ -0,0 +1,37 @@
+
+/**
+ * ODBTP driver
+ *
+ * @deprecated will be removed in ADOdb version 6
+ *
+ * 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
+ * @author stefan bogdan
+ */
// security - hide paths
if (!defined('ADODB_DIR')) die();
@@ -35,10 +46,6 @@ class ADODB_odbtp extends ADOConnection{
var $_canPrepareSP = false;
var $_dontPoolDBC = true;
- function __construct()
- {
- }
-
function ServerInfo()
{
return array('description' => @odbtp_get_attr( ODB_ATTR_DBMSNAME, $this->_connectionID),
@@ -80,7 +87,7 @@ function DBTimeStamp($d,$isfld=false)
}
*/
- function _insertid()
+ protected function _insertID($table = '', $column = '')
{
// SCOPE_IDENTITY()
// Returns the last IDENTITY value inserted into an IDENTITY column in
@@ -792,48 +799,28 @@ class ADORecordSet_odbtp_mssql extends ADORecordSet_odbtp {
var $databaseType = 'odbtp_mssql';
- function __construct($id,$mode=false)
- {
- return parent::__construct($id,$mode);
- }
}
class ADORecordSet_odbtp_access extends ADORecordSet_odbtp {
var $databaseType = 'odbtp_access';
- function __construct($id,$mode=false)
- {
- return parent::__construct($id,$mode);
- }
}
class ADORecordSet_odbtp_vfp extends ADORecordSet_odbtp {
var $databaseType = 'odbtp_vfp';
- function __construct($id,$mode=false)
- {
- return parent::__construct($id,$mode);
- }
}
class ADORecordSet_odbtp_oci8 extends ADORecordSet_odbtp {
var $databaseType = 'odbtp_oci8';
- function __construct($id,$mode=false)
- {
- return parent::__construct($id,$mode);
- }
}
class ADORecordSet_odbtp_sybase extends ADORecordSet_odbtp {
var $databaseType = 'odbtp_sybase';
- function __construct($id,$mode=false)
- {
- return parent::__construct($id,$mode);
- }
}
diff --git a/adodb/drivers/adodb-odbtp_unicode.inc.php b/adodb/drivers/adodb-odbtp_unicode.inc.php
index ce7d3a7..190c3ab 100644
--- a/adodb/drivers/adodb-odbtp_unicode.inc.php
+++ b/adodb/drivers/adodb-odbtp_unicode.inc.php
@@ -1,32 +1,38 @@
+/**
+ * ODBTP Unicode driver.
+ *
+ * @deprecated will be removed in ADOdb version 6
+ *
+ * Because the ODBTP server sends and reads UNICODE text data using UTF-8
+ * encoding, the following HTML meta tag must be included within the HTML
+ * head section of every HTML form and script page:
+ *
+ * Also, all SQL query strings must be submitted as UTF-8 encoded text.
+ *
+ * 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
+ * @author Robert Twitty
+ */
// security - hide paths
if (!defined('ADODB_DIR')) die();
-/*
- Because the ODBTP server sends and reads UNICODE text data using UTF-8
- encoding, the following HTML meta tag must be included within the HTML
- head section of every HTML form and script page:
-
-
-
- Also, all SQL query strings must be submitted as UTF-8 encoded text.
-*/
-
if (!defined('_ADODB_ODBTP_LAYER')) {
- include(ADODB_DIR."/drivers/adodb-odbtp.inc.php");
+ include_once(ADODB_DIR."/drivers/adodb-odbtp.inc.php");
}
class ADODB_odbtp_unicode extends ADODB_odbtp {
diff --git a/adodb/drivers/adodb-oracle.inc.php b/adodb/drivers/adodb-oracle.inc.php
index 776b740..1a2735b 100644
--- a/adodb/drivers/adodb-oracle.inc.php
+++ b/adodb/drivers/adodb-oracle.inc.php
@@ -1,18 +1,25 @@
pdoOptions = [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION];
*/
public $pdoParameters = array();
-
- function __construct()
- {
- }
function _UpdatePDO()
{
@@ -109,6 +104,7 @@ function _UpdatePDO()
$this->random = $d->random;
$this->concat_operator = $d->concat_operator;
$this->nameQuote = $d->nameQuote;
+ $this->arrayClass = $d->arrayClass;
$this->hasGenID = $d->hasGenID;
$this->_genIDSQL = $d->_genIDSQL;
@@ -151,6 +147,7 @@ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persis
case 'oci':
case 'pgsql':
case 'sqlite':
+ case 'firebird':
default:
$argDSN .= ';dbname='.$argDatabasename;
}
@@ -162,9 +159,10 @@ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persis
*/
if ($persist) {
$this->pdoParameters[\PDO::ATTR_PERSISTENT] = true;
- }
+ }
+
try {
- $this->_connectionID = new \PDO($argDSN, $argUsername, $argPassword,$this->pdoParameters);
+ $this->_connectionID = new \PDO($argDSN, $argUsername, $argPassword, $this->pdoParameters);
} catch (Exception $e) {
$this->_connectionID = false;
$this->_errorno = -1;
@@ -190,6 +188,16 @@ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persis
//$this->_connectionID->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_SILENT );
$this->_connectionID->setAttribute(PDO::ATTR_CASE,$m);
+ // Now merge in any provided attributes for PDO
+ foreach ($this->connectionParameters as $options) {
+ foreach($options as $k=>$v) {
+ if ($this->debug) {
+ ADOconnection::outp('Setting attribute: ' . $k . ' to ' . $v);
+ }
+ $this->_connectionID->setAttribute($k,$v);
+ }
+ }
+
$class = 'ADODB_pdo_'.$this->dsnType;
//$this->_connectionID->setAttribute(PDO::ATTR_AUTOCOMMIT,true);
switch($this->dsnType) {
@@ -199,6 +207,8 @@ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persis
case 'pgsql':
case 'sqlite':
case 'sqlsrv':
+ case 'firebird':
+ case 'dblib':
include_once(ADODB_DIR.'/drivers/adodb-pdo_'.$this->dsnType.'.inc.php');
break;
}
@@ -225,10 +235,7 @@ function Concat()
return call_user_func_array(array($this->_driver, 'Concat'), $args);
}
- if (PHP_VERSION >= 5.3) {
- return call_user_func_array('parent::Concat', $args);
- }
- return call_user_func_array(array($this,'parent::Concat'), $args);
+ return call_user_func_array('parent::Concat', $args);
}
// returns true or false
@@ -266,6 +273,64 @@ function MetaColumns($table,$normalize=true)
return $this->_driver->MetaColumns($table,$normalize);
}
+ public function metaIndexes($table,$normalize=true)
+ {
+ if (method_exists($this->_driver,'metaIndexes'))
+ return $this->_driver->metaIndexes($table,$normalize);
+ }
+
+ /**
+ * Return a list of Primary Keys for a specified table.
+ *
+ * @param string $table
+ * @param bool $owner (optional) not used in this driver
+ *
+ * @return string[] Array of indexes
+ */
+ public function metaPrimaryKeys($table,$owner=false)
+ {
+ if (method_exists($this->_driver,'metaPrimaryKeys'))
+ return $this->_driver->metaPrimaryKeys($table,$owner);
+ }
+
+ /**
+ * Returns a list of Foreign Keys for a specified table.
+ *
+ * @param string $table
+ * @param bool $owner (optional) not used in this driver
+ * @param bool $upper
+ * @param bool $associative
+ *
+ * @return string[] where keys are tables, and values are foreign keys
+ */
+ public function metaForeignKeys($table, $owner=false, $upper=false,$associative=false) {
+ if (method_exists($this->_driver,'metaForeignKeys'))
+ return $this->_driver->metaForeignKeys($table,$owner,$upper,$associative);
+ }
+
+ /**
+ * List procedures or functions in an array.
+ *
+ * @param $procedureNamePattern A procedure name pattern; must match the procedure name as it is stored in the database.
+ * @param $catalog A catalog name; must match the catalog name as it is stored in the database.
+ * @param $schemaPattern A schema name pattern.
+ *
+ * @return false|array false if not supported, or array of procedures on current database with structure below
+ * Array(
+ * [name_of_procedure] => Array(
+ * [type] => PROCEDURE or FUNCTION
+ * [catalog] => Catalog_name
+ * [schema] => Schema_name
+ * [remarks] => explanatory comment on the procedure
+ * )
+ * )
+ */
+ public function metaProcedures($procedureNamePattern = null, $catalog = null, $schemaPattern = null) {
+ if (method_exists($this->_driver,'metaProcedures'))
+ return $this->_driver->metaProcedures($procedureNamePattern,$catalog,$schemaPattern);
+ return false;
+ }
+
function InParameter(&$stmt,&$var,$name,$maxLen=4000,$type=false)
{
$obj = $stmt[1];
@@ -350,16 +415,16 @@ function ErrorNo()
return $err;
}
- /**
- * @param bool $auto_commit
- * @return void
- */
+ /**
+ * @param bool $auto_commit
+ * @return void
+ */
function SetAutoCommit($auto_commit)
- {
- if(method_exists($this->_driver, 'SetAutoCommit')) {
- $this->_driver->SetAutoCommit($auto_commit);
- }
- }
+ {
+ if(method_exists($this->_driver, 'SetAutoCommit')) {
+ $this->_driver->SetAutoCommit($auto_commit);
+ }
+ }
function SetTransactionMode($transaction_mode)
{
@@ -370,10 +435,10 @@ function SetTransactionMode($transaction_mode)
return parent::SetTransactionMode($transaction_mode);
}
- function BeginTrans()
+ function beginTrans()
{
- if(method_exists($this->_driver, 'BeginTrans')) {
- return $this->_driver->BeginTrans();
+ if(method_exists($this->_driver, 'beginTrans')) {
+ return $this->_driver->beginTrans();
}
if (!$this->hasTransactions) {
@@ -389,10 +454,11 @@ function BeginTrans()
return $this->_connectionID->beginTransaction();
}
- function CommitTrans($ok=true)
+ function commitTrans($ok=true)
{
- if(method_exists($this->_driver, 'CommitTrans')) {
- return $this->_driver->CommitTrans($ok);
+
+ if(method_exists($this->_driver, 'commitTrans')) {
+ return $this->_driver->commitTrans($ok);
}
if (!$this->hasTransactions) {
@@ -402,7 +468,7 @@ function CommitTrans($ok=true)
return true;
}
if (!$ok) {
- return $this->RollbackTrans();
+ return $this->rollbackTrans();
}
if ($this->transCnt) {
$this->transCnt -= 1;
@@ -456,10 +522,10 @@ function PrepareStmt($sql)
return $obj;
}
- function CreateSequence($seqname='adodbseq',$startID=1)
+ public function createSequence($seqname='adodbseq',$startID=1)
{
- if(method_exists($this->_driver, 'CreateSequence')) {
- return $this->_driver->CreateSequence($seqname, $startID);
+ if(method_exists($this->_driver, 'createSequence')) {
+ return $this->_driver->createSequence($seqname, $startID);
}
return parent::CreateSequence($seqname, $startID);
@@ -493,13 +559,16 @@ function _query($sql,$inputarr=false)
} else {
$stmt = $this->_connectionID->prepare($sql);
}
- #adodb_backtrace();
- #var_dump($this->_bindInputArray);
+
if ($stmt) {
if ($this->_driver instanceof ADODB_pdo) {
$this->_driver->debug = $this->debug;
}
if ($inputarr) {
+ /*
+ * inputarr must be numeric
+ */
+ $inputarr = array_values($inputarr);
$ok = $stmt->execute($inputarr);
}
else {
@@ -543,32 +612,30 @@ function _affectedrows()
return ($this->_stmt) ? $this->_stmt->rowCount() : 0;
}
- function _insertid()
+ protected function _insertID($table = '', $column = '')
{
return ($this->_connectionID) ? $this->_connectionID->lastInsertId() : 0;
}
/**
* Quotes a string to be sent to the database.
+ *
* If we have an active connection, delegates quoting to the underlying
- * PDO object. Otherwise, replace "'" by the value of $replaceQuote (same
- * behavior as mysqli driver)
- * @param string $s The string to quote
- * @param boolean $magic_quotes If false, use PDO::quote().
+ * PDO object PDO::quote(). Otherwise, replace "'" by the value of
+ * $replaceQuote (same behavior as mysqli driver).
+ *
+ * @param string $s The string to quote
+ * @param bool $magic_quotes This param is not used since 5.21.0.
+ * It remains for backwards compatibility.
+ *
* @return string Quoted string
*/
- function qstr($s, $magic_quotes = false)
+ function qStr($s, $magic_quotes = false)
{
- if (!$magic_quotes) {
- if ($this->_connectionID) {
- return $this->_connectionID->quote($s);
- }
- return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
+ if ($this->_connectionID) {
+ return $this->_connectionID->quote($s);
}
-
- // undo magic quotes for "
- $s = str_replace('\\"', '"', $s);
- return "'$s'";
+ return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
}
}
@@ -763,22 +830,22 @@ function FetchField($fieldOffset = -1)
}
//adodb_pr($arr);
$o->name = $arr['name'];
- if (isset($arr['sqlsrv:decl_type']) && $arr['sqlsrv:decl_type'] <> "null")
+ if (isset($arr['sqlsrv:decl_type']) && $arr['sqlsrv:decl_type'] <> "null")
{
/*
* If the database is SQL server, use the native built-ins
*/
$o->type = $arr['sqlsrv:decl_type'];
}
- elseif (isset($arr['native_type']) && $arr['native_type'] <> "null")
+ elseif (isset($arr['native_type']) && $arr['native_type'] <> "null")
{
$o->type = $arr['native_type'];
}
- else
+ else
{
$o->type = adodb_pdo_type($arr['pdo_type']);
}
-
+
$o->max_length = $arr['len'];
$o->precision = $arr['precision'];
@@ -830,3 +897,5 @@ function Fields($colname)
}
}
+
+class ADORecordSet_array_pdo extends ADORecordSet_array {}
diff --git a/adodb/drivers/adodb-pdo_dblib.inc.php b/adodb/drivers/adodb-pdo_dblib.inc.php
new file mode 100644
index 0000000..aae561b
--- /dev/null
+++ b/adodb/drivers/adodb-pdo_dblib.inc.php
@@ -0,0 +1,190 @@
+ 'master'";
+ var $metaTablesSQL="select name,case when type='U' then 'T' else 'V' end from sysobjects where (type='U' or type='V') and (name not in ('sysallocations','syscolumns','syscomments','sysdepends','sysfilegroups','sysfiles','sysfiles1','sysforeignkeys','sysfulltextcatalogs','sysindexes','sysindexkeys','sysmembers','sysobjects','syspermissions','sysprotects','sysreferences','systypes','sysusers','sysalternates','sysconstraints','syssegments','REFERENTIAL_CONSTRAINTS','CHECK_CONSTRAINTS','CONSTRAINT_TABLE_USAGE','CONSTRAINT_COLUMN_USAGE','VIEWS','VIEW_TABLE_USAGE','VIEW_COLUMN_USAGE','SCHEMATA','TABLES','TABLE_CONSTRAINTS','TABLE_PRIVILEGES','COLUMNS','COLUMN_DOMAIN_USAGE','COLUMN_PRIVILEGES','DOMAINS','DOMAIN_CONSTRAINTS','KEY_COLUMN_USAGE','dtproperties'))";
+
+ var $metaColumnsSQL = "SELECT c.NAME, OBJECT_NAME(c.id) as tbl_name, c.length, c.isnullable, c.status, ( CASE WHEN c.xusertype=61 THEN 0 ELSE c.xprec END), ( CASE WHEN c.xusertype=61 THEN 0 ELSE c.xscale END), ISNULL(i.is_primary_key, 0) as primary_key FROM syscolumns c INNER JOIN systypes t ON t.xusertype=c.xusertype INNER JOIN sysobjects o ON o.id=c.id LEFT JOIN sys.index_columns ic ON ic.object_id = c.id AND c.colid = ic.column_id LEFT JOIN sys.indexes i ON i.object_id = ic.object_id AND i.index_id = ic.index_id WHERE c.id = OBJECT_ID('%s') ORDER by c.colid";
+
+ function _init(ADODB_pdo $parentDriver)
+ {
+ $parentDriver->hasTransactions = true;
+ $parentDriver->_bindInputArray = true;
+ $parentDriver->hasInsertID = true;
+ $parentDriver->fmtTimeStamp = "'Y-m-d H:i:s'";
+ $parentDriver->fmtDate = "'Y-m-d'";
+ }
+
+ function BeginTrans()
+ {
+ $returnval = parent::BeginTrans();
+ return $returnval;
+ }
+
+ function MetaColumns($table, $normalize=true)
+ {
+ $this->_findschema($table,$schema);
+ if ($schema) {
+ $dbName = $this->database;
+ $this->SelectDB($schema);
+ }
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ if ($this->fetchMode !== false) $savem = $this->SetFetchMode(false);
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
+
+ if ($schema) {
+ $this->SelectDB($dbName);
+ }
+
+ if (isset($savem)) $this->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+ if (!is_object($rs)) {
+ $false = false;
+ return $false;
+ }
+
+ $retarr = array();
+ while (!$rs->EOF) {
+ $fld = new ADOFieldObject();
+ $fld->name = $rs->fields[0];
+ $fld->type = $rs->fields[1];
+ $fld->primary_key = $rs->fields[7];
+
+ $fld->not_null = (!$rs->fields[3]);
+ $fld->auto_increment = ($rs->fields[4] == 128); // sys.syscolumns status field. 0x80 = 128 ref: http://msdn.microsoft.com/en-us/library/ms186816.aspx
+
+ if (isset($rs->fields[5]) && $rs->fields[5]) {
+ if ($rs->fields[5]>0) $fld->max_length = $rs->fields[5];
+ $fld->scale = $rs->fields[6];
+ if ($fld->scale>0) $fld->max_length += 1;
+ } else
+ $fld->max_length = $rs->fields[2];
+
+ if ($save == ADODB_FETCH_NUM) {
+ $retarr[] = $fld;
+ } else {
+ $retarr[strtoupper($fld->name)] = $fld;
+ }
+ $rs->MoveNext();
+ }
+
+ $rs->Close();
+ return $retarr;
+ }
+
+ function MetaTables($ttype=false,$showSchema=false,$mask=false)
+ {
+ if ($mask) {
+ $save = $this->metaTablesSQL;
+ $mask = $this->qstr(($mask));
+ $this->metaTablesSQL .= " AND name like $mask";
+ }
+ $ret = ADOConnection::MetaTables($ttype,$showSchema);
+
+ if ($mask) {
+ $this->metaTablesSQL = $save;
+ }
+ return $ret;
+ }
+
+ function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0)
+ {
+ if ($nrows > 0 && $offset <= 0) {
+ $sql = preg_replace(
+ '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop." $nrows ",$sql);
+
+ if ($secs2cache)
+ $rs = $this->CacheExecute($secs2cache, $sql, $inputarr);
+ else
+ $rs = $this->Execute($sql,$inputarr);
+ } else
+ $rs = ADOConnection::SelectLimit($sql,$nrows,$offset,$inputarr,$secs2cache);
+
+ return $rs;
+ }
+
+ function _query($sql,$inputarr=false)
+ {
+ $this->_connectionID->setAttribute(\PDO::ATTR_EMULATE_PREPARES , true);
+ if (is_array($sql)) {
+ $stmt = $sql[1];
+ } else {
+ $stmt = $this->_connectionID->prepare($sql);
+ }
+
+ if ($stmt) {
+ $this->_driver->debug = $this->debug;
+ if ($inputarr) {
+ foreach ($inputarr as $key => $value) {
+ if(gettype($key) == 'integer') {
+ $key += 1;
+ }
+ $stmt->bindValue($key, $value, $this->GetPDODataType($value));
+ }
+ }
+ }
+
+ $ok = $stmt->execute();
+
+ $this->_errormsg = false;
+ $this->_errorno = false;
+
+ if ($ok) {
+ $this->_stmt = $stmt;
+ return $stmt;
+ }
+
+ if ($stmt) {
+
+ $arr = $stmt->errorinfo();
+ if ((integer)$arr[1]) {
+ $this->_errormsg = $arr[2];
+ $this->_errorno = $arr[1];
+ }
+
+ } else {
+ $this->_errormsg = false;
+ $this->_errorno = false;
+ }
+ return false;
+ }
+
+ private function GetPDODataType($var)
+ {
+ if(gettype($var) == 'integer') {
+ return PDO::PARAM_INT ;
+ }
+ return PDO::PARAM_STR;
+ }
+
+ function ServerInfo()
+ {
+ return ADOConnection::ServerInfo();
+ }
+}
diff --git a/adodb/drivers/adodb-pdo_firebird.inc.php b/adodb/drivers/adodb-pdo_firebird.inc.php
new file mode 100644
index 0000000..0ee5e02
--- /dev/null
+++ b/adodb/drivers/adodb-pdo_firebird.inc.php
@@ -0,0 +1,452 @@
+pdoDriver = $parentDriver;
+ //$parentDriver->_bindInputArray = true;
+ //$parentDriver->hasTransactions = false; // // should be set to false because of PDO SQLite driver not supporting changing autocommit mode
+ //$parentDriver->hasInsertID = true;
+ }
+
+ /**
+ * Gets the version iformation from the server
+ *
+ * @return string[]
+ */
+ 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;
+ }
+ $arr['version'] = ADOConnection::_findvers($s);
+ $arr['description'] = $s;
+ return $arr;
+ }
+
+ /**
+ * Returns the tables in the database.
+ *
+ * @param mixed $ttype
+ * @param bool $showSchema
+ * @param mixed $mask
+ *
+ * @return string[]
+ */
+ public function metaTables($ttype = false, $showSchema = false, $mask = false)
+ {
+ $ret = ADOConnection::MetaTables($ttype, $showSchema);
+
+ return $ret;
+ }
+
+ public function metaColumns($table, $normalize = true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ $rs = $this->Execute(sprintf($this->metaColumnsSQL, strtoupper($table)));
+
+ $ADODB_FETCH_MODE = $save;
+
+ if ($rs === false) {
+ return false;
+ }
+
+ $retarr = array();
+ $dialect3 = $this->dialect == 3;
+ while (!$rs->EOF) { //print_r($rs->fields);
+ $fld = new ADOFieldObject();
+ $fld->name = trim($rs->fields[0]);
+ $this->_ConvertFieldType($fld, $rs->fields[7], $rs->fields[3], $rs->fields[4], $rs->fields[5],
+ $rs->fields[6], $dialect3);
+ if (isset($rs->fields[1]) && $rs->fields[1]) {
+ $fld->not_null = true;
+ }
+ if (isset($rs->fields[2])) {
+
+ $fld->has_default = true;
+ $d = substr($rs->fields[2], strlen('default '));
+ switch ($fld->type) {
+ case 'smallint':
+ case 'integer':
+ $fld->default_value = (int)$d;
+ break;
+ case 'char':
+ case 'blob':
+ case 'text':
+ case 'varchar':
+ $fld->default_value = (string)substr($d, 1, strlen($d) - 2);
+ break;
+ case 'double':
+ case 'float':
+ $fld->default_value = (float)$d;
+ break;
+ default:
+ $fld->default_value = $d;
+ break;
+ }
+ }
+ if ((isset($rs->fields[5])) && ($fld->type == 'blob')) {
+ $fld->sub_type = $rs->fields[5];
+ } else {
+ $fld->sub_type = null;
+ }
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) {
+ $retarr[] = $fld;
+ } else {
+ $retarr[strtoupper($fld->name)] = $fld;
+ }
+
+ $rs->MoveNext();
+ }
+ $rs->Close();
+ if (empty($retarr)) {
+ return false;
+ } else {
+ return $retarr;
+ }
+ }
+
+ public function metaIndexes($table, $primary = false, $owner = false)
+ {
+ // save old fetch mode
+ global $ADODB_FETCH_MODE;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== false) {
+ $savem = $this->SetFetchMode(false);
+ }
+ $table = strtoupper($table);
+ $sql = "SELECT * FROM RDB\$INDICES WHERE RDB\$RELATION_NAME = '" . $table . "'";
+ if (!$primary) {
+ $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$%'";
+ } else {
+ $sql .= " AND RDB\$INDEX_NAME NOT LIKE 'RDB\$FOREIGN%'";
+ }
+
+ // get index details
+ $rs = $this->Execute($sql);
+ if (!is_object($rs)) {
+ // restore fetchmode
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+ return false;
+ }
+
+ $indexes = array();
+ while ($row = $rs->FetchRow()) {
+ $index = $row[0];
+ if (!isset($indexes[$index])) {
+ if (is_null($row[3])) {
+ $row[3] = 0;
+ }
+ $indexes[$index] = array(
+ 'unique' => ($row[3] == 1),
+ 'columns' => array()
+ );
+ }
+ $sql = "SELECT * FROM RDB\$INDEX_SEGMENTS WHERE RDB\$INDEX_NAME = '" . $index . "' ORDER BY RDB\$FIELD_POSITION ASC";
+ $rs1 = $this->Execute($sql);
+ while ($row1 = $rs1->FetchRow()) {
+ $indexes[$index]['columns'][$row1[2]] = $row1[1];
+ }
+ }
+ // restore fetchmode
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ return $indexes;
+ }
+
+ public function metaPrimaryKeys($table, $owner_notused = false, $internalKey = false)
+ {
+ if ($internalKey) {
+ return array('RDB$DB_KEY');
+ }
+
+ $table = strtoupper($table);
+
+ $sql = 'SELECT S.RDB$FIELD_NAME AFIELDNAME
+ FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON I.RDB$INDEX_NAME=S.RDB$INDEX_NAME
+ WHERE I.RDB$RELATION_NAME=\'' . $table . '\' and I.RDB$INDEX_NAME like \'RDB$PRIMARY%\'
+ ORDER BY I.RDB$INDEX_NAME,S.RDB$FIELD_POSITION';
+
+ $a = $this->GetCol($sql, false, true);
+ if ($a && sizeof($a) > 0) {
+ return $a;
+ }
+ return false;
+ }
+
+ public function createSequence($seqname = 'adodbseq', $startID = 1)
+ {
+ $ok = $this->execute("CREATE SEQUENCE $seqname");
+ if (!$ok) {
+ return false;
+ }
+
+ return $this->execute("ALTER SEQUENCE $seqname RESTART WITH " . ($startID - 1));
+ }
+
+ public function dropSequence($seqname = 'adodbseq')
+ {
+ $seqname = strtoupper($seqname);
+ return $this->Execute("DROP SEQUENCE $seqname");
+ }
+
+
+ public function _affectedrows()
+ {
+ return fbird_affected_rows($this->_transactionID ? $this->_transactionID : $this->_connectionID);
+ }
+
+ 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 SEQUENCE $seqname"));
+ $this->execute("ALTER SEQUENCE $seqname RESTART WITH " . ($startID - 1) . ';');
+ $rs = $this->execute($getnext);
+ }
+ if ($rs && !$rs->EOF) {
+ $this->genID = (integer)reset($rs->fields);
+ } else {
+ $this->genID = 0; // false
+ }
+
+ if ($rs) {
+ $rs->Close();
+ }
+
+ return $this->genID;
+ }
+
+ public function selectLimit($sql, $nrows = -1, $offset = -1, $inputarr = false, $secs = 0)
+ {
+ $nrows = (integer)$nrows;
+ $offset = (integer)$offset;
+ $str = 'SELECT ';
+ if ($nrows >= 0) {
+ $str .= "FIRST $nrows ";
+ }
+ $str .= ($offset >= 0) ? "SKIP $offset " : '';
+
+ $sql = preg_replace('/^[ \t]*select/i', $str, $sql);
+ if ($secs) {
+ $rs = $this->cacheExecute($secs, $sql, $inputarr);
+ } else {
+ $rs = $this->execute($sql, $inputarr);
+ }
+
+ return $rs;
+ }
+
+ /**
+ * Sets the appropriate type into the $fld variable
+ *
+ * @param ADOFieldObject $fld By reference
+ * @param int $ftype
+ * @param int $flen
+ * @param int $fscale
+ * @param int $fsubtype
+ * @param int $fprecision
+ * @param bool $dialect3
+ */
+ private function _convertFieldType(&$fld, $ftype, $flen, $fscale, $fsubtype, $fprecision, $dialect3)
+ {
+ $fscale = abs($fscale);
+ $fld->max_length = $flen;
+ $fld->scale = null;
+ switch ($ftype) {
+ case 7:
+ case 8:
+ if ($dialect3) {
+ switch ($fsubtype) {
+ case 0:
+ $fld->type = ($ftype == 7 ? 'smallint' : 'integer');
+ break;
+ case 1:
+ $fld->type = 'numeric';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ case 2:
+ $fld->type = 'decimal';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ } // switch
+ } else {
+ if ($fscale != 0) {
+ $fld->type = 'decimal';
+ $fld->scale = $fscale;
+ $fld->max_length = ($ftype == 7 ? 4 : 9);
+ } else {
+ $fld->type = ($ftype == 7 ? 'smallint' : 'integer');
+ }
+ }
+ break;
+ case 16:
+ if ($dialect3) {
+ switch ($fsubtype) {
+ case 0:
+ $fld->type = 'decimal';
+ $fld->max_length = 18;
+ $fld->scale = 0;
+ break;
+ case 1:
+ $fld->type = 'numeric';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ case 2:
+ $fld->type = 'decimal';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ } // switch
+ }
+ break;
+ case 10:
+ $fld->type = 'float';
+ break;
+ case 14:
+ $fld->type = 'char';
+ break;
+ case 27:
+ if ($fscale != 0) {
+ $fld->type = 'decimal';
+ $fld->max_length = 15;
+ $fld->scale = 5;
+ } else {
+ $fld->type = 'double';
+ }
+ break;
+ case 35:
+ if ($dialect3) {
+ $fld->type = 'timestamp';
+ } else {
+ $fld->type = 'date';
+ }
+ break;
+ case 12:
+ $fld->type = 'date';
+ break;
+ case 13:
+ $fld->type = 'time';
+ break;
+ case 37:
+ $fld->type = 'varchar';
+ break;
+ case 40:
+ $fld->type = 'cstring';
+ break;
+ case 261:
+ $fld->type = 'blob';
+ $fld->max_length = -1;
+ break;
+ } // switch
+ }
+}
+
+/**
+ * Class ADORecordSet_pdo_firebird
+ */
+class ADORecordSet_pdo_firebird extends ADORecordSet_pdo
+{
+
+ public $databaseType = "pdo_firebird";
+
+ /**
+ * returns the field object
+ *
+ * @param int $fieldOffset Optional field offset
+ *
+ * @return object The ADOFieldObject describing the field
+ */
+ public function fetchField($fieldOffset = 0)
+ {
+ }
+}
+
+/**
+ * Class ADORecordSet_array_pdo_firebird
+ */
+class ADORecordSet_array_pdo_firebird extends ADORecordSet_array_pdo
+{
+ public $databaseType = "pdo_firebird";
+ public $canSeek = true;
+
+ /**
+ * returns the field object
+ *
+ * @param int $fieldOffset Optional field offset
+ *
+ * @return object The ADOFieldObject describing the field
+ */
+ public function fetchField($fieldOffset = 0)
+ {
+
+ $fld = new ADOFieldObject;
+ $fld->name = $fieldOffset;
+ $fld->type = 'C';
+ $fld->max_length = 0;
+
+ // This needs to be populated from the metadata
+ $fld->not_null = false;
+ $fld->has_default = false;
+ $fld->default_value = 'null';
+
+ return $fld;
+ }
+}
diff --git a/adodb/drivers/adodb-pdo_mssql.inc.php b/adodb/drivers/adodb-pdo_mssql.inc.php
index 1ce6985..ef63b65 100644
--- a/adodb/drivers/adodb-pdo_mssql.inc.php
+++ b/adodb/drivers/adodb-pdo_mssql.inc.php
@@ -1,16 +1,23 @@
fetchMode !== FALSE) {
+ $savem = $this->setFetchMode(FALSE);
+ }
+
+ // get index details
+ $rs = $this->execute(sprintf('SHOW INDEXES FROM %s',$table));
+
+ // restore fetchmode
+ if (isset($savem)) {
+ $this->setFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
+
+ if (!is_object($rs)) {
+ return $false;
+ }
+
+ $indexes = array ();
+
+ // parse index data into array
+ while ($row = $rs->fetchRow()) {
+ if ($primary == FALSE AND $row[2] == 'PRIMARY') {
+ continue;
+ }
+
+ if (!isset($indexes[$row[2]])) {
+ $indexes[$row[2]] = array(
+ 'unique' => ($row[1] == 0),
+ 'columns' => array()
+ );
+ }
+
+ $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
+ }
+
+ // sort columns by order in the index
+ foreach ( array_keys ($indexes) as $index )
+ {
+ ksort ($indexes[$index]['columns']);
+ }
+
+ return $indexes;
+ }
function Concat()
{
@@ -310,4 +383,41 @@ function SQLDate($fmt, $col=false)
}
return $s;
}
+
+ function GenID($seqname='adodbseq',$startID=1)
+ {
+ $getnext = sprintf($this->_genIDSQL,$seqname);
+ $holdtransOK = $this->_transOK; // save the current status
+ $rs = @$this->Execute($getnext);
+ if (!$rs) {
+ if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset
+ $this->Execute(sprintf($this->_genSeqSQL,$seqname));
+ $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname));
+ if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
+ $rs = $this->Execute($getnext);
+ }
+
+ if ($rs) {
+ $this->genID = $this->_connectionID->lastInsertId($seqname);
+ $rs->Close();
+ } else {
+ $this->genID = 0;
+ }
+
+ return $this->genID;
+ }
+
+
+ function createSequence($seqname='adodbseq',$startID=1)
+ {
+ if (empty($this->_genSeqSQL)) {
+ return false;
+ }
+ $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname,$startID));
+ if (!$ok) {
+ return false;
+ }
+
+ return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
+ }
}
diff --git a/adodb/drivers/adodb-pdo_oci.inc.php b/adodb/drivers/adodb-pdo_oci.inc.php
index 22c2141..9a05ee6 100644
--- a/adodb/drivers/adodb-pdo_oci.inc.php
+++ b/adodb/drivers/adodb-pdo_oci.inc.php
@@ -1,16 +1,23 @@
hasTransactions) {
+ return false;
+ }
+ if ($this->transOff) {
+ return true;
+ }
+ $this->transCnt += 1;
+
+ return $this->_connectionID->beginTransaction();
+ }
+
+ function CommitTrans($ok = true)
+ {
+ if (!$this->hasTransactions) {
+ return false;
+ }
+ if ($this->transOff) {
+ return true;
+ }
+ if (!$ok) {
+ return $this->RollbackTrans();
+ }
+ if ($this->transCnt) {
+ $this->transCnt -= 1;
+ }
+ $this->_autocommit = true;
+
+ $ret = $this->_connectionID->commit();
+ return $ret;
+ }
+
+ function RollbackTrans()
+ {
+ if (!$this->hasTransactions) {
+ return false;
+ }
+ if ($this->transOff) {
+ return true;
+ }
+ if ($this->transCnt) {
+ $this->transCnt -= 1;
+ }
+ $this->_autocommit = true;
+
+ $ret = $this->_connectionID->rollback();
+ return $ret;
+ }
+
+ function SetTransactionMode( $transaction_mode )
+ {
+ $this->_transmode = $transaction_mode;
+ if (empty($transaction_mode)) {
+ $this->_connectionID->query('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
+ return;
+ }
+ if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
+ $this->_connectionID->query("SET TRANSACTION ".$transaction_mode);
+ }
}
diff --git a/adodb/drivers/adodb-pdo_sqlite.inc.php b/adodb/drivers/adodb-pdo_sqlite.inc.php
index d60dbad..b62ca35 100644
--- a/adodb/drivers/adodb-pdo_sqlite.inc.php
+++ b/adodb/drivers/adodb-pdo_sqlite.inc.php
@@ -1,19 +1,25 @@
+ * @author Sid Dunayer
+ */
class ADODB_pdo_sqlite extends ADODB_pdo {
var $metaTablesSQL = "SELECT name FROM sqlite_master WHERE type='table'";
diff --git a/adodb/drivers/adodb-pdo_sqlsrv.inc.php b/adodb/drivers/adodb-pdo_sqlsrv.inc.php
index 869e8e1..ed73f3a 100644
--- a/adodb/drivers/adodb-pdo_sqlsrv.inc.php
+++ b/adodb/drivers/adodb-pdo_sqlsrv.inc.php
@@ -1,14 +1,31 @@
_queryID->getColumnMeta($fieldOffset);
+
+ if (!$arr) {
+ $o->name = 'bad getColumnMeta()';
+ $o->max_length = -1;
+ $o->type = 'VARCHAR';
+ $o->precision = 0;
+ return $o;
+ }
+ $o->name = $arr['name'];
+ if (isset($arr['sqlsrv:decl_type']) && $arr['sqlsrv:decl_type'] <> "null") {
+ // Use the SQL Server driver specific value
+ $o->type = $arr['sqlsrv:decl_type'];
+ } else {
+ $o->type = adodb_pdo_type($arr['pdo_type']);
+ }
+ $o->max_length = $arr['len'];
+ $o->precision = $arr['precision'];
+
+ switch (ADODB_ASSOC_CASE) {
+ case ADODB_ASSOC_CASE_LOWER:
+ $o->name = strtolower($o->name);
+ break;
+ case ADODB_ASSOC_CASE_UPPER:
+ $o->name = strtoupper($o->name);
+ break;
+ }
+
+ return $o;
+ }
+}
+
+class ADORecordSet_array_pdo_sqlsrv extends ADORecordSet_array_pdo
+{
+
+ /**
+ * returns the field object
+ *
+ * Note that this is a direct copy of the ADORecordSet_pdo_sqlsrv method
+ *
+ * @param int $fieldOffset Optional field offset
+ *
+ * @return object The ADOfieldobject describing the field
+ */
+ public function fetchField($fieldOffset = 0)
+ {
+ // Default behavior allows passing in of -1 offset, which crashes the method
+ if ($fieldOffset == -1) {
+ $fieldOffset++;
+ }
+ $o = new ADOFieldObject();
+ $arr = @$this->_queryID->getColumnMeta($fieldOffset);
+
+ if (!$arr) {
+ $o->name = 'bad getColumnMeta()';
+ $o->max_length = -1;
+ $o->type = 'VARCHAR';
+ $o->precision = 0;
+ return $o;
+ }
+ $o->name = $arr['name'];
+ if (isset($arr['sqlsrv:decl_type']) && $arr['sqlsrv:decl_type'] <> "null") {
+ // Use the SQL Server driver specific value
+ $o->type = $arr['sqlsrv:decl_type'];
+ } else {
+ $o->type = adodb_pdo_type($arr['pdo_type']);
+ }
+ $o->max_length = $arr['len'];
+ $o->precision = $arr['precision'];
+
+ switch (ADODB_ASSOC_CASE) {
+ case ADODB_ASSOC_CASE_LOWER:
+ $o->name = strtolower($o->name);
+ break;
+ case ADODB_ASSOC_CASE_UPPER:
+ $o->name = strtoupper($o->name);
+ break;
+ }
+
+ return $o;
+ }
+
+ function SetTransactionMode( $transaction_mode )
+ {
+ $this->_transmode = $transaction_mode;
+ if (empty($transaction_mode)) {
+ $this->_connectionID->query('SET TRANSACTION ISOLATION LEVEL READ COMMITTED');
+ return;
+ }
+ if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
+ $this->_connectionID->query("SET TRANSACTION ".$transaction_mode);
+ }
}
diff --git a/adodb/drivers/adodb-postgres.inc.php b/adodb/drivers/adodb-postgres.inc.php
index 3e325b0..070ac1c 100644
--- a/adodb/drivers/adodb-postgres.inc.php
+++ b/adodb/drivers/adodb-postgres.inc.php
@@ -1,14 +1,25 @@
- jlim - changed concat operator to || and data types to MetaType to match documented pgsql types
- see http://www.postgresql.org/devel-corner/docs/postgres/datatype.htm
- 22 Nov 2000 jlim - added changes to FetchField() and MetaTables() contributed by "raser"
- 27 Nov 2000 jlim - added changes to _connect/_pconnect from ideas by "Lennie"
- 15 Dec 2000 jlim - added changes suggested by Additional code changes by "Eric G. Werk" egw@netguide.dk.
- 31 Jan 2002 jlim - finally installed postgresql. testing
- 01 Mar 2001 jlim - Freek Dijkstra changes, also support for text type
-
- See http://www.varlena.com/varlena/GeneralBits/47.php
-
- -- What indexes are on my table?
- select * from pg_indexes where tablename = 'tablename';
-
- -- What triggers are on my table?
- select c.relname as "Table", t.tgname as "Trigger Name",
- t.tgconstrname as "Constraint Name", t.tgenabled as "Enabled",
- t.tgisconstraint as "Is Constraint", cc.relname as "Referenced Table",
- p.proname as "Function Name"
- from pg_trigger t, pg_class c, pg_class cc, pg_proc p
- where t.tgfoid = p.oid and t.tgrelid = c.oid
- and t.tgconstrrelid = cc.oid
- and c.relname = 'tablename';
-
- -- What constraints are on my table?
- select r.relname as "Table", c.conname as "Constraint Name",
- contype as "Constraint Type", conkey as "Key Columns",
- confkey as "Foreign Columns", consrc as "Source"
- from pg_class r, pg_constraint c
- where r.oid = c.conrelid
- and relname = 'tablename';
-
-*/
+/**
+ * ADOdb PostgreSQL 6.4 driver
+ *
+ * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
+ *
+ * @package ADOdb
+ * @link https://adodb.org Project's web site and documentation
+ * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
+ *
+ * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
+ * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
+ * any later version. This means you can use it in proprietary products.
+ * See the LICENSE.md file distributed with this source code for details.
+ * @license BSD-3-Clause
+ * @license LGPL-2.1-or-later
+ *
+ * @copyright 2000-2013 John Lim
+ * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
+ */
// security - hide paths
if (!defined('ADODB_DIR')) die();
@@ -114,6 +89,7 @@ class ADODB_postgres64 extends ADOConnection{
var $_bindInputArray = false; // requires postgresql 7.3+ and ability to modify database
var $disableBlobs = false; // set to true to disable blob checking, resulting in 2-5% improvement in performance.
+ /** @var int $_pnum Number of the last assigned query parameter {@see param()} */
var $_pnum = 0;
// The last (fmtTimeStamp is not entirely correct:
@@ -124,19 +100,40 @@ class ADODB_postgres64 extends ADOConnection{
// to know what the concequences are. The other values are correct (wheren't in 0.94)
// -- Freek Dijkstra
- function __construct()
+ /**
+ * Retrieve Server information.
+ * In addition to server version and description, the function also returns
+ * the client version.
+ * @param bool $detailed If true, retrieve detailed version string (executes
+ * a SQL query) in addition to the version number
+ * @return array|bool Server info or false if version could not be retrieved
+ * e.g. if there is no active connection
+ */
+ function ServerInfo($detailed = true)
{
- // changes the metaColumnsSQL, adds columns: attnum[6]
- }
+ if (empty($this->version['version'])) {
+ // We don't have a connection, so we can't retrieve server info
+ if (!$this->_connectionID) {
+ return false;
+ }
- function ServerInfo()
- {
- if (isset($this->version)) return $this->version;
+ $version = pg_version($this->_connectionID);
+ $this->version = array(
+ // If PHP has been compiled with PostgreSQL 7.3 or lower, then
+ // server version is not set so we use pg_parameter_status()
+ // which includes logic to obtain values server_version
+ 'version' => isset($version['server'])
+ ? $version['server']
+ : pg_parameter_status($this->_connectionID, 'server_version'),
+ 'client' => $version['client'],
+ 'description' => null,
+ );
+ }
+ if ($detailed && $this->version['description'] === null) {
+ $this->version['description'] = $this->GetOne('select version()');
+ }
- $arr['description'] = $this->GetOne("select version()");
- $arr['version'] = ADOConnection::_findvers($arr['description']);
- $this->version = $arr;
- return $arr;
+ return $this->version;
}
function IfNull( $field, $ifNull )
@@ -161,8 +158,10 @@ function pg_insert_id($tablename,$fieldname)
* Using a OID as a unique identifier is not generally wise.
* Unless you are very careful, you might end up with a tuple having
* a different OID if a database must be reloaded.
+ *
+ * @inheritDoc
*/
- function _insertid($table,$column)
+ protected function _insertID($table = '', $column = '')
{
if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;
$oid = pg_last_oid($this->_resultid);
@@ -243,31 +242,32 @@ function MetaTables($ttype=false,$showSchema=false,$mask=false)
}
- // if magic quotes disabled, use pg_escape_string()
- function qstr($s,$magic_quotes=false)
+ /**
+ * Quotes a string to be sent to the database.
+ *
+ * Relies on pg_escape_string()
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:qstr
+ *
+ * @param string $s The string to quote
+ * @param bool $magic_quotes This param is not used since 5.21.0.
+ * It remains for backwards compatibility.
+ *
+ * @return string Quoted string
+ */
+ function qStr($s, $magic_quotes=false)
{
- if (is_bool($s)) return $s ? 'true' : 'false';
-
- if (!$magic_quotes) {
- if (ADODB_PHPVER >= 0x5200 && $this->_connectionID) {
- return "'".pg_escape_string($this->_connectionID,$s)."'";
- }
- if (ADODB_PHPVER >= 0x4200) {
- return "'".pg_escape_string($s)."'";
- }
- if ($this->replaceQuote[0] == '\\'){
- $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\\000"),$s);
- }
- return "'".str_replace("'",$this->replaceQuote,$s)."'";
+ if (is_bool($s)) {
+ return $s ? 'true' : 'false';
}
- // undo magic quotes for "
- $s = str_replace('\\"','"',$s);
- return "'$s'";
+ if ($this->_connectionID) {
+ return "'" . pg_escape_string($this->_connectionID, $s) . "'";
+ } else {
+ return "'" . pg_escape_string($s) . "'";
+ }
}
-
// Format date column in sql string given an input format that understands Y M D
function SQLDate($fmt, $col=false)
{
@@ -393,7 +393,7 @@ function BlobDelete( $blob )
}
/*
- Hueristic - not guaranteed to work.
+ Heuristic - not guaranteed to work.
*/
function GuessOID($oid)
{
@@ -430,24 +430,20 @@ function BlobDecode($blob,$maxsize=false,$hastrans=true)
return $realblob;
}
- /*
- See http://www.postgresql.org/idocs/index.php?datatype-binary.html
-
- NOTE: SQL string literals (input strings) must be preceded with two backslashes
- due to the fact that they must pass through two parsers in the PostgreSQL
- backend.
- */
+ /**
+ * Encode binary value prior to DB storage.
+ *
+ * See https://www.postgresql.org/docs/current/static/datatype-binary.html
+ *
+ * NOTE: SQL string literals (input strings) must be preceded with two
+ * backslashes due to the fact that they must pass through two parsers in
+ * the PostgreSQL backend.
+ *
+ * @param string $blob
+ */
function BlobEncode($blob)
{
- if (ADODB_PHPVER >= 0x5200) return pg_escape_bytea($this->_connectionID, $blob);
- if (ADODB_PHPVER >= 0x4200) return pg_escape_bytea($blob);
-
- /*92=backslash, 0=null, 39=single-quote*/
- $badch = array(chr(92),chr(0),chr(39)); # \ null '
- $fixch = array('\\\\134','\\\\000','\\\\047');
- return adodb_str_replace($badch,$fixch,$blob);
-
- // note that there is a pg_escape_bytea function only for php 4.2.0 or later
+ return pg_escape_bytea($this->_connectionID, $blob);
}
// assumes bytea for blob, and varchar for clob
@@ -606,15 +602,18 @@ function MetaColumns($table,$normalize=true)
}
- function Param($name,$type='C')
+ function param($name, $type='C')
{
- if ($name) {
- $this->_pnum += 1;
- } else {
- // Reset param num if $name is false
- $this->_pnum = 1;
+ if (!$name) {
+ // Reset parameter number if $name is falsy
+ $this->_pnum = 0;
+ if ($name === false) {
+ // and don't return placeholder if false (see #380)
+ return '';
+ }
}
- return '$'.$this->_pnum;
+
+ return '$' . ++$this->_pnum;
}
function MetaIndexes ($table, $primary = FALSE, $owner = false)
@@ -729,9 +728,9 @@ function _connect($str,$user='',$pwd='',$db='',$ctype=0)
if ($this->_connectionID === false) return false;
$this->Execute("set datestyle='ISO'");
- $info = $this->ServerInfo();
- $this->pgVersion = (float) substr($info['version'],0,3);
- if ($this->pgVersion >= 7.1) { // good till version 999
+ $info = $this->ServerInfo(false);
+
+ if (version_compare($info['version'], '7.1', '>=')) {
$this->_nestedSQL = true;
}
@@ -739,7 +738,10 @@ function _connect($str,$user='',$pwd='',$db='',$ctype=0)
# PHP does not handle 'hex' properly ('x74657374' is returned as 't657374')
# https://bugs.php.net/bug.php?id=59831 states this is in fact not a bug,
# so we manually set bytea_output
- if ( !empty($this->connection->noBlobs) && version_compare($info['version'], '9.0', '>=')) {
+ if (!empty($this->connection->noBlobs)
+ && version_compare($info['version'], '9.0', '>=')
+ && version_compare($info['client'], '9.2', '<')
+ ) {
$this->Execute('set bytea_output=escape');
}
@@ -848,20 +850,23 @@ function _errconnect()
/* Returns: the last error message from previous database operation */
function ErrorMsg()
{
- if ($this->_errorMsg !== false) return $this->_errorMsg;
- if (ADODB_PHPVER >= 0x4300) {
- if (!empty($this->_resultid)) {
- $this->_errorMsg = @pg_result_error($this->_resultid);
- if ($this->_errorMsg) return $this->_errorMsg;
+ if ($this->_errorMsg !== false) {
+ return $this->_errorMsg;
+ }
+
+ if (!empty($this->_resultid)) {
+ $this->_errorMsg = @pg_result_error($this->_resultid);
+ if ($this->_errorMsg) {
+ return $this->_errorMsg;
}
+ }
- if (!empty($this->_connectionID)) {
- $this->_errorMsg = @pg_last_error($this->_connectionID);
- } else $this->_errorMsg = $this->_errconnect();
+ if (!empty($this->_connectionID)) {
+ $this->_errorMsg = @pg_last_error($this->_connectionID);
} else {
- if (empty($this->_connectionID)) $this->_errconnect();
- else $this->_errorMsg = @pg_last_error($this->_connectionID);
+ $this->_errorMsg = $this->_errconnect();
}
+
return $this->_errorMsg;
}
@@ -946,10 +951,9 @@ function GetRowAssoc($upper = ADODB_ASSOC_CASE)
return $row;
}
-
- function _initrs()
+ function _initRS()
{
- global $ADODB_COUNTRECS;
+ global $ADODB_COUNTRECS;
$qid = $this->_queryID;
$this->_numOfRows = ($ADODB_COUNTRECS)? @pg_num_rows($qid):-1;
$this->_numOfFields = @pg_num_fields($qid);
@@ -964,10 +968,11 @@ function _initrs()
}
}
- /* Use associative array to get fields array */
- function Fields($colname)
+ function fields($colname)
{
- if ($this->fetchMode != PGSQL_NUM) return @$this->fields[$colname];
+ if ($this->fetchMode != PGSQL_NUM) {
+ return @$this->fields[$colname];
+ }
if (!$this->bind) {
$this->bind = array();
@@ -979,14 +984,14 @@ function Fields($colname)
return $this->fields[$this->bind[strtoupper($colname)]];
}
- function FetchField($off = 0)
+ function fetchField($fieldOffset = 0)
{
// offsets begin at 0
- $o= new ADOFieldObject();
- $o->name = @pg_field_name($this->_queryID,$off);
- $o->type = @pg_field_type($this->_queryID,$off);
- $o->max_length = @pg_field_size($this->_queryID,$off);
+ $o = new ADOFieldObject();
+ $o->name = @pg_field_name($this->_queryID, $fieldOffset);
+ $o->type = @pg_field_type($this->_queryID, $fieldOffset);
+ $o->max_length = @pg_field_size($this->_queryID, $fieldOffset);
return $o;
}
@@ -998,7 +1003,7 @@ function _seek($row)
function _decode($blob)
{
if ($blob === NULL) return NULL;
-// eval('$realblob="'.adodb_str_replace(array('"','$'),array('\"','\$'),$blob).'";');
+// eval('$realblob="'.str_replace(array('"','$'),array('\"','\$'),$blob).'";');
return pg_unescape_bytea($blob);
}
@@ -1073,6 +1078,7 @@ function MetaType($t,$len=-1,$fieldobj=false)
case 'NAME':
case 'BPCHAR':
case '_VARCHAR':
+ case 'CIDR':
case 'INET':
case 'MACADDR':
if ($len <= $this->blobSize) return 'C';
@@ -1116,7 +1122,7 @@ function MetaType($t,$len=-1,$fieldobj=false)
return 'R';
default:
- return 'N';
+ return ADODB_DEFAULT_METATYPE;
}
}
diff --git a/adodb/drivers/adodb-postgres7.inc.php b/adodb/drivers/adodb-postgres7.inc.php
index 1804924..59174f6 100644
--- a/adodb/drivers/adodb-postgres7.inc.php
+++ b/adodb/drivers/adodb-postgres7.inc.php
@@ -1,17 +1,23 @@
rsPrefix .= 'assoc_';
}
- $this->_bindInputArray = PHP_VERSION >= 5.1;
+ $this->_bindInputArray = true;
}
@@ -269,34 +275,47 @@ function _query($sql,$inputarr=false)
return $rez;
}
- // this is a set of functions for managing client encoding - very important if the encodings
- // of your database and your output target (i.e. HTML) don't match
- //for instance, you may have UNICODE database and server it on-site as WIN1251 etc.
- // GetCharSet - get the name of the character set the client is using now
- // the functions should work with Postgres 7.0 and above, the set of charsets supported
- // depends on compile flags of postgres distribution - if no charsets were compiled into the server
- // it will return 'SQL_ANSI' always
- function GetCharSet()
+ /**
+ * Retrieve the client connection's current character set.
+
+ * If no charsets were compiled into the server, the function will always
+ * return 'SQL_ASCII'.
+ * @see https://www.php.net/manual/en/function.pg-client-encoding.php
+ *
+ * @return string|false The character set, or false if it can't be determined.
+ */
+ function getCharSet()
{
- //we will use ADO's builtin property charSet
- $this->charSet = @pg_client_encoding($this->_connectionID);
- if (!$this->charSet) {
+ if (!$this->_connectionID) {
return false;
- } else {
- return $this->charSet;
}
+ $this->charSet = pg_client_encoding($this->_connectionID);
+ return $this->charSet ?: false;
}
- // SetCharSet - switch the client encoding
- function SetCharSet($charset_name)
+ /**
+ * Sets the client-side character set (encoding).
+ *
+ * Allows managing client encoding - very important if the database and
+ * the output target (i.e. HTML) don't match; for instance, you may have a
+ * UNICODE database and server your pages as WIN1251, etc.
+ *
+ * Supported on PostgreSQL 7.0 and above. Available charsets depend on
+ * PostgreSQL version and the distribution's compile flags.
+ *
+ * @param string $charset The character set to switch to.
+ *
+ * @return bool True if the character set was changed successfully, false otherwise.
+ */
+ function setCharSet($charset)
{
- $this->GetCharSet();
- if ($this->charSet !== $charset_name) {
- $if = pg_set_client_encoding($this->_connectionID, $charset_name);
- if ($if == "0" & $this->GetCharSet() == $charset_name) {
- return true;
- } else return false;
- } else return true;
+ if ($this->charSet !== $charset) {
+ if (!$this->_connectionID || pg_set_client_encoding($this->_connectionID, $charset) != 0) {
+ return false;
+ }
+ $this->getCharSet();
+ }
+ return true;
}
}
@@ -309,12 +328,6 @@ class ADORecordSet_postgres7 extends ADORecordSet_postgres64{
var $databaseType = "postgres7";
-
- function __construct($queryID, $mode=false)
- {
- parent::__construct($queryID, $mode);
- }
-
// 10% speedup to move MoveNext to child class
function MoveNext()
{
@@ -341,11 +354,6 @@ class ADORecordSet_assoc_postgres7 extends ADORecordSet_postgres64{
var $databaseType = "postgres7";
- function __construct($queryID, $mode=false)
- {
- parent::__construct($queryID, $mode);
- }
-
function _fetch()
{
if ($this->_currentRow >= $this->_numOfRows && $this->_numOfRows >= 0) {
diff --git a/adodb/drivers/adodb-postgres8.inc.php b/adodb/drivers/adodb-postgres8.inc.php
index bd595b7..37c2aae 100644
--- a/adodb/drivers/adodb-postgres8.inc.php
+++ b/adodb/drivers/adodb-postgres8.inc.php
@@ -1,15 +1,23 @@
GetOne("SELECT lastval()")
diff --git a/adodb/drivers/adodb-postgres9.inc.php b/adodb/drivers/adodb-postgres9.inc.php
index 90d6781..fb9c678 100644
--- a/adodb/drivers/adodb-postgres9.inc.php
+++ b/adodb/drivers/adodb-postgres9.inc.php
@@ -1,15 +1,23 @@
curmode = SQL_CUR_USE_ODBC;
- parent::__construct();
- }
-
function ServerInfo()
{
$info = ADODB_odbc::ServerInfo();
@@ -55,7 +54,7 @@ function MetaPrimaryKeys($table, $owner = false)
return $this->GetCol("SELECT columnname FROM COLUMNS WHERE tablename=$table AND mode='KEY' ORDER BY pos");
}
- function MetaIndexes ($table, $primary = FALSE, $owner = false)
+ function MetaIndexes ($table, $primary = FALSE, $owner = false)
{
$table = $this->Quote(strtoupper($table));
@@ -65,43 +64,43 @@ function MetaIndexes ($table, $primary = FALSE, $owner = false)
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
- $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
- if ($this->fetchMode !== FALSE) {
- $savem = $this->SetFetchMode(FALSE);
- }
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
- $rs = $this->Execute($sql);
- if (isset($savem)) {
- $this->SetFetchMode($savem);
- }
- $ADODB_FETCH_MODE = $save;
+ $rs = $this->Execute($sql);
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
- if (!is_object($rs)) {
- return FALSE;
- }
+ if (!is_object($rs)) {
+ return FALSE;
+ }
$indexes = array();
while ($row = $rs->FetchRow()) {
- $indexes[$row[0]]['unique'] = $row[1] == 'UNIQUE';
- $indexes[$row[0]]['columns'][] = $row[2];
- }
+ $indexes[$row[0]]['unique'] = $row[1] == 'UNIQUE';
+ $indexes[$row[0]]['columns'][] = $row[2];
+ }
if ($primary) {
$indexes['SYSPRIMARYKEYINDEX'] = array(
'unique' => True, // by definition
'columns' => $this->GetCol("SELECT columnname FROM COLUMNS WHERE tablename=$table AND mode='KEY' ORDER BY pos"),
);
}
- return $indexes;
+ return $indexes;
}
function MetaColumns ($table, $normalize = true)
{
global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE;
- $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
- if ($this->fetchMode !== FALSE) {
- $savem = $this->SetFetchMode(FALSE);
- }
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
$table = $this->Quote(strtoupper($table));
$retarr = array();
@@ -134,10 +133,10 @@ function MetaColumns ($table, $normalize = true)
}
$retarr[$fld->name] = $fld;
}
- if (isset($savem)) {
- $this->SetFetchMode($savem);
- }
- $ADODB_FETCH_MODE = $save;
+ if (isset($savem)) {
+ $this->SetFetchMode($savem);
+ }
+ $ADODB_FETCH_MODE = $save;
return $retarr;
}
@@ -150,7 +149,7 @@ function MetaColumnNames($table, $numIndexes = false, $useattnum = false)
}
// unlike it seems, this depends on the db-session and works in a multiuser environment
- function _insertid($table,$column)
+ protected function _insertID($table = '', $column = '')
{
return empty($table) ? False : $this->GetOne("SELECT $table.CURRVAL FROM DUAL");
}
@@ -158,13 +157,13 @@ function _insertid($table,$column)
/*
SelectLimit implementation problems:
- The following will return random 10 rows as order by performed after "WHERE rowno<10"
- which is not ideal...
+ The following will return random 10 rows as order by performed after "WHERE rowno<10"
+ which is not ideal...
- select * from table where rowno < 10 order by 1
+ select * from table where rowno < 10 order by 1
- This means that we have to use the adoconnection base class SelectLimit when
- there is an "order by".
+ This means that we have to use the adoconnection base class SelectLimit when
+ there is an "order by".
See http://listserv.sap.com/pipermail/sapdb.general/2002-January/010405.html
*/
@@ -172,14 +171,10 @@ function _insertid($table,$column)
};
-class ADORecordSet_sapdb extends ADORecordSet_odbc {
+class ADORecordSet_sapdb extends ADORecordSet_odbc {
var $databaseType = "sapdb";
- function __construct($id,$mode=false)
- {
- parent::__construct($id,$mode);
- }
}
} //define
diff --git a/adodb/drivers/adodb-sqlanywhere.inc.php b/adodb/drivers/adodb-sqlanywhere.inc.php
index 8029b48..88897af 100644
--- a/adodb/drivers/adodb-sqlanywhere.inc.php
+++ b/adodb/drivers/adodb-sqlanywhere.inc.php
@@ -1,66 +1,44 @@
create_blobvar($blobVarName);
-
- b) load blob var from file. $filename must be complete path
-
- $dbcon->load_blobvar_from_file($blobVarName, $filename);
-
- c) Use the $blobVarName in SQL insert or update statement in the values
- clause:
-
- $recordSet = $dbconn->Execute('INSERT INTO tabname (idcol, blobcol) '
- .
- 'VALUES (\'test\', ' . $blobVarName . ')');
-
- instead of loading blob from a file, you can also load from
- an unformatted (raw) blob variable:
- $dbcon->load_blobvar_from_var($blobVarName, $varName);
-
- d) drop blob variable on db server to free up resources:
- $dbconn->drop_blobvar($blobVarName);
-
- Sybase_SQLAnywhere data driver. Requires ODBC.
-
-*/
+/**
+ * SAP SQL Anywhere driver (previously Sybase SQL Anywhere)
+ *
+ * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
+ *
+ * @package ADOdb
+ * @link https://adodb.org Project's web site and documentation
+ * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
+ *
+ * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
+ * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
+ * any later version. This means you can use it in proprietary products.
+ * See the LICENSE.md file distributed with this source code for details.
+ * @license BSD-3-Clause
+ * @license LGPL-2.1-or-later
+ *
+ * @copyright 2000-2013 John Lim
+ * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
+ */
// security - hide paths
if (!defined('ADODB_DIR')) die();
if (!defined('_ADODB_ODBC_LAYER')) {
- include(ADODB_DIR."/drivers/adodb-odbc.inc.php");
+ include_once(ADODB_DIR."/drivers/adodb-odbc.inc.php");
}
if (!defined('ADODB_SYBASE_SQLANYWHERE')){
define('ADODB_SYBASE_SQLANYWHERE',1);
- class ADODB_sqlanywhere extends ADODB_odbc {
- var $databaseType = "sqlanywhere";
- var $hasInsertID = true;
+ class ADODB_sqlanywhere extends ADODB_odbc
+ {
+ var $databaseType = "sqlanywhere";
+ var $hasInsertID = true;
- function _insertid() {
- return $this->GetOne('select @@identity');
- }
+ protected function _insertID($table = '', $column = '')
+ {
+ return $this->GetOne('select @@identity');
+ }
function create_blobvar($blobVarName) {
$this->Execute("create variable $blobVarName long binary");
@@ -153,11 +131,6 @@ class ADORecordSet_sqlanywhere extends ADORecordSet_odbc {
var $databaseType = "sqlanywhere";
- function __construct($id,$mode=false)
- {
- parent::__construct($id,$mode);
- }
-
}; //class
diff --git a/adodb/drivers/adodb-sqlite.inc.php b/adodb/drivers/adodb-sqlite.inc.php
index 424c295..0711f1d 100644
--- a/adodb/drivers/adodb-sqlite.inc.php
+++ b/adodb/drivers/adodb-sqlite.inc.php
@@ -1,27 +1,34 @@
hasInsertID = true;
}
- function _insertid()
+ protected function _insertID($table = '', $column = '')
{
return sqlite_last_insert_rowid($this->_connectionID);
}
@@ -355,6 +358,63 @@ function MetaIndexes($table, $primary = FALSE, $owner = false)
return $indexes;
}
+ /**
+ * Returns the maximum size of a MetaType C field. Because of the
+ * database design, sqlite places no limits on the size of data inserted
+ *
+ * @return int
+ */
+ function charMax()
+ {
+ return ADODB_STRINGMAX_NOLIMIT;
+ }
+
+ /**
+ * Returns the maximum size of a MetaType X field. Because of the
+ * database design, sqlite places no limits on the size of data inserted
+ *
+ * @return int
+ */
+ function textMax()
+ {
+ return ADODB_STRINGMAX_NOLIMIT;
+ }
+
+ /*
+ * Converts a date to a month only field and pads it to 2 characters
+ *
+ * @param str $fld The name of the field to process
+ * @return str The SQL Statement
+ */
+ function month($fld)
+ {
+ $x = "strftime('%m',$fld)";
+
+ return $x;
+ }
+
+ /*
+ * Converts a date to a day only field and pads it to 2 characters
+ *
+ * @param str $fld The name of the field to process
+ * @return str The SQL Statement
+ */
+ function day($fld) {
+ $x = "strftime('%d',$fld)";
+ return $x;
+ }
+
+ /*
+ * Converts a date to a year only field
+ *
+ * @param str $fld The name of the field to process
+ * @return str The SQL Statement
+ */
+ function year($fld) {
+ $x = "strftime('%Y',$fld)";
+
+ return $x;
+ }
}
/*--------------------------------------------------------------------------------------
diff --git a/adodb/drivers/adodb-sqlite3.inc.php b/adodb/drivers/adodb-sqlite3.inc.php
index 3633db1..548727d 100644
--- a/adodb/drivers/adodb-sqlite3.inc.php
+++ b/adodb/drivers/adodb-sqlite3.inc.php
@@ -1,27 +1,32 @@
type;
+ $len = $fieldobj->max_length;
+ }
+
+ $t = strtoupper($t);
+
+ /*
+ * We are using the Sqlite affinity method here
+ * @link https://www.sqlite.org/datatype3.html
+ */
+ $affinity = array(
+ 'INT'=>'INTEGER',
+ 'INTEGER'=>'INTEGER',
+ 'TINYINT'=>'INTEGER',
+ 'SMALLINT'=>'INTEGER',
+ 'MEDIUMINT'=>'INTEGER',
+ 'BIGINT'=>'INTEGER',
+ 'UNSIGNED BIG INT'=>'INTEGER',
+ 'INT2'=>'INTEGER',
+ 'INT8'=>'INTEGER',
+
+ 'CHARACTER'=>'TEXT',
+ 'VARCHAR'=>'TEXT',
+ 'VARYING CHARACTER'=>'TEXT',
+ 'NCHAR'=>'TEXT',
+ 'NATIVE CHARACTER'=>'TEXT',
+ 'NVARCHAR'=>'TEXT',
+ 'TEXT'=>'TEXT',
+ 'CLOB'=>'TEXT',
+
+ 'BLOB'=>'BLOB',
+
+ 'REAL'=>'REAL',
+ 'DOUBLE'=>'REAL',
+ 'DOUBLE PRECISION'=>'REAL',
+ 'FLOAT'=>'REAL',
+
+ 'NUMERIC'=>'NUMERIC',
+ 'DECIMAL'=>'NUMERIC',
+ 'BOOLEAN'=>'NUMERIC',
+ 'DATE'=>'NUMERIC',
+ 'DATETIME'=>'NUMERIC'
+ );
+
+ if (!isset($affinity[$t]))
+ return ADODB_DEFAULT_METATYPE;
+
+ $subt = $affinity[$t];
+ /*
+ * Now that we have subclassed the provided data down
+ * the sqlite 'affinity', we convert to ADOdb metatype
+ */
+
+ $subclass = array('INTEGER'=>'I',
+ 'TEXT'=>'X',
+ 'BLOB'=>'B',
+ 'REAL'=>'N',
+ 'NUMERIC'=>'N');
+
+ return $subclass[$subt];
+ }
// mark newnham
function MetaColumns($table, $normalize=true)
{
@@ -129,13 +197,67 @@ function MetaColumns($table, $normalize=true)
return $arr;
}
+ function metaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
+ {
+ global $ADODB_FETCH_MODE;
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC
+ || $this->fetchMode == ADODB_FETCH_ASSOC)
+ $associative = true;
+
+ /*
+ * Read sqlite master to find foreign keys
+ */
+ $sql = "SELECT sql
+ FROM (
+ SELECT sql sql, type type, tbl_name tbl_name, name name
+ FROM sqlite_master
+ )
+ WHERE type != 'meta'
+ AND sql NOTNULL
+ AND LOWER(name) ='" . strtolower($table) . "'";
+
+ $tableSql = $this->getOne($sql);
+
+ $fkeyList = array();
+ $ylist = preg_split("/,+/",$tableSql);
+ foreach ($ylist as $y)
+ {
+ if (!preg_match('/FOREIGN/',$y))
+ continue;
+
+ $matches = false;
+ preg_match_all('/\((.+?)\)/i',$y,$matches);
+ $tmatches = false;
+ preg_match_all('/REFERENCES (.+?)\(/i',$y,$tmatches);
+
+ if ($associative)
+ {
+ if (!isset($fkeyList[$tmatches[1][0]]))
+ $fkeyList[$tmatches[1][0]] = array();
+ $fkeyList[$tmatches[1][0]][$matches[1][0]] = $matches[1][1];
+ }
+ else
+ $fkeyList[$tmatches[1][0]][] = $matches[1][0] . '=' . $matches[1][1];
+ }
+
+ if ($associative)
+ {
+ if ($upper)
+ $fkeyList = array_change_key_case($fkeyList,CASE_UPPER);
+ else
+ $fkeyList = array_change_key_case($fkeyList,CASE_LOWER);
+ }
+ return $fkeyList;
+ }
+
+
function _init($parentDriver)
{
$parentDriver->hasTransactions = false;
$parentDriver->hasInsertID = true;
}
- function _insertid()
+ protected function _insertID($table = '', $column = '')
{
return $this->_connectionID->lastInsertRowID();
}
@@ -160,11 +282,22 @@ function ErrorNo()
function SQLDate($fmt, $col=false)
{
+ /*
+ * In order to map the values correctly, we must ensure the proper
+ * casing for certain fields
+ * Y must be UC, because y is a 2 digit year
+ * d must be LC, because D is 3 char day
+ * A must be UC because a is non-portable am
+ * Q must be UC because q means nothing
+ */
+ $fromChars = array('y','D','a','q');
+ $toChars = array('Y','d','A','Q');
+ $fmt = str_replace($fromChars,$toChars,$fmt);
+
$fmt = $this->qstr($fmt);
return ($col) ? "adodb_date2($fmt,$col)" : "adodb_date($fmt)";
}
-
function _createFunctions()
{
$this->_connectionID->createFunction('adodb_date', 'adodb_date', 1);
@@ -289,7 +422,7 @@ function _close()
return $this->_connectionID->close();
}
- function MetaIndexes($table, $primary = FALSE, $owner = false)
+ function metaIndexes($table, $primary = FALSE, $owner = false)
{
$false = false;
// save old fetch mode
@@ -299,8 +432,36 @@ function MetaIndexes($table, $primary = FALSE, $owner = false)
if ($this->fetchMode !== FALSE) {
$savem = $this->SetFetchMode(FALSE);
}
- $SQL=sprintf("SELECT name,sql FROM sqlite_master WHERE type='index' AND tbl_name='%s'", strtolower($table));
- $rs = $this->Execute($SQL);
+
+ $pragmaData = array();
+
+ /*
+ * If we want the primary key, we must extract
+ * it from the table statement, and the pragma
+ */
+ if ($primary)
+ {
+ $sql = sprintf('PRAGMA table_info([%s]);',
+ strtolower($table)
+ );
+ $pragmaData = $this->getAll($sql);
+ }
+
+ /*
+ * Exclude the empty entry for the primary index
+ */
+ $sqlite = "SELECT name,sql
+ FROM sqlite_master
+ WHERE type='index'
+ AND sql IS NOT NULL
+ AND LOWER(tbl_name)='%s'";
+
+ $SQL = sprintf($sqlite,
+ strtolower($table)
+ );
+
+ $rs = $this->execute($SQL);
+
if (!is_object($rs)) {
if (isset($savem)) {
$this->SetFetchMode($savem);
@@ -310,10 +471,10 @@ function MetaIndexes($table, $primary = FALSE, $owner = false)
}
$indexes = array ();
- while ($row = $rs->FetchRow()) {
- if ($primary && preg_match("/primary/i",$row[1]) == 0) {
- continue;
- }
+
+ while ($row = $rs->FetchRow())
+ {
+
if (!isset($indexes[$row[0]])) {
$indexes[$row[0]] = array(
'unique' => preg_match("/unique/i",$row[1]),
@@ -321,23 +482,122 @@ function MetaIndexes($table, $primary = FALSE, $owner = false)
);
}
/**
- * There must be a more elegant way of doing this,
- * the index elements appear in the SQL statement
+ * The index elements appear in the SQL statement
* in cols[1] between parentheses
* e.g CREATE UNIQUE INDEX ware_0 ON warehouse (org,warehouse)
*/
- $cols = explode("(",$row[1]);
- $cols = explode(")",$cols[1]);
- array_pop($cols);
- $indexes[$row[0]]['columns'] = $cols;
+ preg_match_all('/\((.*)\)/',$row[1],$indexExpression);
+ $indexes[$row[0]]['columns'] = array_map('trim',explode(',',$indexExpression[1][0]));
}
+
if (isset($savem)) {
$this->SetFetchMode($savem);
$ADODB_FETCH_MODE = $save;
}
+
+ /*
+ * If we want primary, add it here
+ */
+ if ($primary){
+
+ /*
+ * Check the previously retrieved pragma to search
+ * with a closure
+ */
+
+ $pkIndexData = array('unique'=>1,'columns'=>array());
+
+ $pkCallBack = function ($value, $key) use (&$pkIndexData) {
+
+ /*
+ * As we iterate the elements check for pk index and sort
+ */
+ if ($value[5] > 0)
+ {
+ $pkIndexData['columns'][$value[5]] = strtolower($value[1]);
+ ksort($pkIndexData['columns']);
+ }
+ };
+
+ array_walk($pragmaData,$pkCallBack);
+
+ /*
+ * If we found no columns, there is no
+ * primary index
+ */
+ if (count($pkIndexData['columns']) > 0)
+ $indexes['PRIMARY'] = $pkIndexData;
+ }
+
return $indexes;
}
+ /**
+ * Returns the maximum size of a MetaType C field. Because of the
+ * database design, sqlite places no limits on the size of data inserted
+ *
+ * @return int
+ */
+ function charMax()
+ {
+ return ADODB_STRINGMAX_NOLIMIT;
+ }
+
+ /**
+ * Returns the maximum size of a MetaType X field. Because of the
+ * database design, sqlite places no limits on the size of data inserted
+ *
+ * @return int
+ */
+ function textMax()
+ {
+ return ADODB_STRINGMAX_NOLIMIT;
+ }
+
+ /**
+ * Converts a date to a month only field and pads it to 2 characters
+ *
+ * This uses the more efficient strftime native function to process
+ *
+ * @param str $fld The name of the field to process
+ *
+ * @return str The SQL Statement
+ */
+ function month($fld)
+ {
+ $x = "strftime('%m',$fld)";
+ return $x;
+ }
+
+ /**
+ * Converts a date to a day only field and pads it to 2 characters
+ *
+ * This uses the more efficient strftime native function to process
+ *
+ * @param str $fld The name of the field to process
+ *
+ * @return str The SQL Statement
+ */
+ function day($fld) {
+ $x = "strftime('%d',$fld)";
+ return $x;
+ }
+
+ /**
+ * Converts a date to a year only field
+ *
+ * This uses the more efficient strftime native function to process
+ *
+ * @param str $fld The name of the field to process
+ *
+ * @return str The SQL Statement
+ */
+ function year($fld)
+ {
+ $x = "strftime('%Y',$fld)";
+ return $x;
+ }
+
}
/*--------------------------------------------------------------------------------------
diff --git a/adodb/drivers/adodb-sqlitepo.inc.php b/adodb/drivers/adodb-sqlitepo.inc.php
index 1646807..cb69ff9 100644
--- a/adodb/drivers/adodb-sqlitepo.inc.php
+++ b/adodb/drivers/adodb-sqlitepo.inc.php
@@ -1,23 +1,31 @@
+ */
if (!defined('ADODB_DIR')) die();
@@ -35,11 +43,6 @@ class ADORecordset_sqlitepo extends ADORecordset_sqlite {
var $databaseType = 'sqlitepo';
- function __construct($queryID,$mode=false)
- {
- parent::__construct($queryID,$mode);
- }
-
// Modified to strip table names from returned fields
function _fetch($ignore_fields=false)
{
diff --git a/adodb/drivers/adodb-sybase.inc.php b/adodb/drivers/adodb-sybase.inc.php
index 91a717b..b8db074 100644
--- a/adodb/drivers/adodb-sybase.inc.php
+++ b/adodb/drivers/adodb-sybase.inc.php
@@ -1,21 +1,24 @@
+ */
// security - hide paths
if (!defined('ADODB_DIR')) die();
@@ -44,15 +47,15 @@ class ADODB_sybase extends ADOConnection {
var $port;
- function __construct()
- {
- }
-
- // might require begintrans -- committrans
- function _insertid()
+ /**
+ * might require begintrans -- committrans
+ * @inheritDoc
+ */
+ protected function _insertID($table = '', $column = '')
{
return $this->GetOne('select @@identity');
}
+
// might require begintrans -- committrans
function _affectedrows()
{
@@ -171,7 +174,7 @@ function _query($sql,$inputarr=false)
{
global $ADODB_COUNTRECS;
- if ($ADODB_COUNTRECS == false && ADODB_PHPVER >= 0x4300)
+ if ($ADODB_COUNTRECS == false)
return sybase_unbuffered_query($sql,$this->_connectionID);
else
return sybase_query($sql,$this->_connectionID);
@@ -320,7 +323,7 @@ function __construct($id,$mode=false)
}
if (!$mode) $this->fetchMode = ADODB_FETCH_ASSOC;
else $this->fetchMode = $mode;
- parent::__construct($id,$mode);
+ parent::__construct($id);
}
/* Returns: an object containing field information.
@@ -393,12 +396,8 @@ static function UnixTimeStamp($v)
}
class ADORecordSet_array_sybase extends ADORecordSet_array {
- function __construct($id=-1)
- {
- parent::__construct($id);
- }
- // sybase/mssql uses a default date like Dec 30 2000 12:00AM
+ // sybase/mssql uses a default date like Dec 30 2000 12:00AM
static function UnixDate($v)
{
global $ADODB_sybase_mths;
diff --git a/adodb/drivers/adodb-sybase_ase.inc.php b/adodb/drivers/adodb-sybase_ase.inc.php
index fc8c968..d301ba9 100644
--- a/adodb/drivers/adodb-sybase_ase.inc.php
+++ b/adodb/drivers/adodb-sybase_ase.inc.php
@@ -1,17 +1,24 @@
+ */
require_once ADODB_DIR."/drivers/adodb-sybase.inc.php";
@@ -22,10 +29,6 @@ class ADODB_sybase_ase extends ADODB_sybase {
var $metaColumnsSQL = "SELECT syscolumns.name AS field_name, systypes.name AS type, systypes.length AS width FROM sysobjects, syscolumns, systypes WHERE sysobjects.name='%s' AND syscolumns.id = sysobjects.id AND systypes.type=syscolumns.type";
var $metaDatabasesSQL ="SELECT a.name FROM master.dbo.sysdatabases a, master.dbo.syslogins b WHERE a.suid = b.suid and a.name like '%' and a.name != 'tempdb' and a.status3 != 256 order by 1";
- function __construct()
- {
- }
-
// split the Views, Tables and procedures.
function MetaTables($ttype=false,$showSchema=false,$mask=false)
{
@@ -111,10 +114,5 @@ function ErrorMsg()
}
class adorecordset_sybase_ase extends ADORecordset_sybase {
-var $databaseType = "sybase_ase";
-function __construct($id,$mode=false)
- {
- parent::__construct($id,$mode);
- }
-
+ var $databaseType = "sybase_ase";
}
diff --git a/adodb/drivers/adodb-text.inc.php b/adodb/drivers/adodb-text.inc.php
index f88665e..77ad06a 100644
--- a/adodb/drivers/adodb-text.inc.php
+++ b/adodb/drivers/adodb-text.inc.php
@@ -1,63 +1,25 @@
Connect($array,[$types],[$colnames]);
-
- Parameter $array is the 2 dimensional array of data. The first row can contain the
- column names. If column names is not defined in first row, you MUST define $colnames,
- the 3rd parameter.
-
- Parameter $types is optional. If defined, it should contain an array matching
- the number of columns in $array, with each element matching the correct type defined
- by MetaType: (B,C,I,L,N). If undefined, we will probe for $this->_proberows rows
- to guess the type. Only C,I and N are recognised.
-
- Parameter $colnames is optional. If defined, it is an array that contains the
- column names of $array. If undefined, we assume the first row of $array holds the
- column names.
-
- The Execute() function will return a recordset. The recordset works like a normal recordset.
- We have partial support for SQL parsing. We process the SQL using the following rules:
-
- 1. SQL order by's always work for the first column ordered. Subsequent cols are ignored
-
- 2. All operations take place on the same table. No joins possible. In fact the FROM clause
- is ignored! You can use any name for the table.
-
- 3. To simplify code, all columns are returned, except when selecting 1 column
-
- $rs = $db->Execute('select col1,col2 from table'); // sql ignored, will generate all cols
-
- We special case handling of 1 column because it is used in filter popups
-
- $rs = $db->Execute('select col1 from table');
- // sql accepted and processed -- any table name is accepted
-
- $rs = $db->Execute('select distinct col1 from table');
- // sql accepted and processed
-
-4. Where clauses are ignored, but searching with the 3rd parameter of Execute is permitted.
- This has to use PHP syntax and we will eval() it. You can even use PHP functions.
-
- $rs = $db->Execute('select * from table',false,"\$COL1='abc' and $\COL2=3")
- // the 3rd param is searched -- make sure that $COL1 is a legal column name
- // and all column names must be in upper case.
-
-4. Group by, having, other clauses are ignored
-
-5. Expression columns, min(), max() are ignored
-
-6. All data is readonly. Only SELECTs permitted.
-*/
+/**
+ * ADOdb Plain Text driver
+ *
+ * @deprecated
+ *
+ * This file is part of ADOdb, a Database Abstraction Layer library for PHP.
+ *
+ * @package ADOdb
+ * @link https://adodb.org Project's web site and documentation
+ * @link https://github.com/ADOdb/ADOdb Source code and issue tracker
+ *
+ * The ADOdb Library is dual-licensed, released under both the BSD 3-Clause
+ * and the GNU Lesser General Public Licence (LGPL) v2.1 or, at your option,
+ * any later version. This means you can use it in proprietary products.
+ * See the LICENSE.md file distributed with this source code for details.
+ * @license BSD-3-Clause
+ * @license LGPL-2.1-or-later
+ *
+ * @copyright 2000-2013 John Lim
+ * @copyright 2014 Damien Regad, Mark Newnham and the ADOdb community
+ */
// security - hide paths
if (!defined('ADODB_DIR')) die();
@@ -90,10 +52,6 @@ class ADODB_text extends ADOConnection {
var $_reznames;
var $_reztypes;
- function __construct()
- {
- }
-
function RSRecordCount()
{
if (!empty($this->_rezarray)) return sizeof($this->_rezarray);
@@ -101,11 +59,6 @@ function RSRecordCount()
return sizeof($this->_origarray);
}
- function _insertid()
- {
- return false;
- }
-
function _affectedrows()
{
return false;
@@ -325,7 +278,7 @@ function _query($sql,$input_arr,$eval=false)
// check for desc sort
$orderby = substr($orderby,strlen($col)+1);
- $arr == array();
+ $arr = array();
preg_match('/([A-Z_0-9]*)/i',$orderby,$arr);
if (trim($arr[1]) == 'DESC') $sortf = 'adodb_cmpr';
diff --git a/adodb/drivers/adodb-vfp.inc.php b/adodb/drivers/adodb-vfp.inc.php
index 1442545..bb43516 100644
--- a/adodb/drivers/adodb-vfp.inc.php
+++ b/adodb/drivers/adodb-vfp.inc.php
@@ -1,23 +1,31 @@
+/**
+ * Arabic language strings.
+ *
+ * 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
+ * @author El-Shamaa, Khaled
+ */
+
$ADODB_LANG_ARRAY = array (
'LANG' => 'ar',
DB_ERROR => 'خطأ غير Ů…ŘŘŻŘŻ',
diff --git a/adodb/lang/adodb-bg.inc.php b/adodb/lang/adodb-bg.inc.php
index 07069b4..bbfd92f 100644
--- a/adodb/lang/adodb-bg.inc.php
+++ b/adodb/lang/adodb-bg.inc.php
@@ -1,8 +1,24 @@
-*/
+/**
+ * Bulgarian language strings.
+ *
+ * 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
+ * @author Valentin Sheiretsky
+ */
$ADODB_LANG_ARRAY = array (
'LANG' => 'bg',
diff --git a/adodb/lang/adodb-ca.inc.php b/adodb/lang/adodb-ca.inc.php
index adbafac..4b04688 100644
--- a/adodb/lang/adodb-ca.inc.php
+++ b/adodb/lang/adodb-ca.inc.php
@@ -1,6 +1,25 @@
+ */
+
$ADODB_LANG_ARRAY = array (
'LANG' => 'ca',
DB_ERROR => 'error desconegut',
diff --git a/adodb/lang/adodb-cn.inc.php b/adodb/lang/adodb-cn.inc.php
index 9c97341..512ffb8 100644
--- a/adodb/lang/adodb-cn.inc.php
+++ b/adodb/lang/adodb-cn.inc.php
@@ -1,6 +1,25 @@
+ */
+
$ADODB_LANG_ARRAY = array (
'LANG' => 'cn',
DB_ERROR => '未知错误',
diff --git a/adodb/lang/adodb-cz.inc.php b/adodb/lang/adodb-cz.inc.php
index d79d714..eb2fb2e 100644
--- a/adodb/lang/adodb-cz.inc.php
+++ b/adodb/lang/adodb-cz.inc.php
@@ -1,7 +1,24 @@
+/**
+ * Czech language strings.
+ *
+ * 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
+ * @author Kamil Jakubovic
+ */
$ADODB_LANG_ARRAY = array (
'LANG' => 'cz',
diff --git a/adodb/lang/adodb-da.inc.php b/adodb/lang/adodb-da.inc.php
index 14e720b..e4c655b 100644
--- a/adodb/lang/adodb-da.inc.php
+++ b/adodb/lang/adodb-da.inc.php
@@ -1,5 +1,25 @@
+ */
+
$ADODB_LANG_ARRAY = array (
'LANG' => 'da',
DB_ERROR => 'ukendt fejl',
diff --git a/adodb/lang/adodb-de.inc.php b/adodb/lang/adodb-de.inc.php
index dca4ffe..a02dd72 100644
--- a/adodb/lang/adodb-de.inc.php
+++ b/adodb/lang/adodb-de.inc.php
@@ -1,32 +1,52 @@
+/**
+ * German language strings.
+ *
+ * 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
+ * @author Heinz Hombergs
+ */
+
$ADODB_LANG_ARRAY = array (
- 'LANG' => 'de',
- DB_ERROR => 'Unbekannter Fehler',
- DB_ERROR_ALREADY_EXISTS => 'existiert bereits',
- DB_ERROR_CANNOT_CREATE => 'kann nicht erstellen',
- DB_ERROR_CANNOT_DELETE => 'kann nicht löschen',
- DB_ERROR_CANNOT_DROP => 'Tabelle oder Index konnte nicht gelöscht werden',
- DB_ERROR_CONSTRAINT => 'Constraint Verletzung',
- DB_ERROR_DIVZERO => 'Division durch Null',
- DB_ERROR_INVALID => 'ungĂĽltig',
- DB_ERROR_INVALID_DATE => 'ungĂĽltiges Datum oder Zeit',
- DB_ERROR_INVALID_NUMBER => 'ungĂĽltige Zahl',
- DB_ERROR_MISMATCH => 'Unverträglichkeit',
- DB_ERROR_NODBSELECTED => 'keine Dantebank ausgewählt',
- DB_ERROR_NOSUCHFIELD => 'Feld nicht vorhanden',
- DB_ERROR_NOSUCHTABLE => 'Tabelle nicht vorhanden',
- DB_ERROR_NOT_CAPABLE => 'Funktion nicht installiert',
- DB_ERROR_NOT_FOUND => 'nicht gefunden',
- DB_ERROR_NOT_LOCKED => 'nicht gesperrt',
- DB_ERROR_SYNTAX => 'Syntaxfehler',
- DB_ERROR_UNSUPPORTED => 'nicht UnterstĂĽtzt',
- DB_ERROR_VALUE_COUNT_ON_ROW => 'Anzahl der zurĂĽckgelieferten Felder entspricht nicht der Anzahl der Felder in der Abfrage',
- DB_ERROR_INVALID_DSN => 'ungĂĽltiger DSN',
- DB_ERROR_CONNECT_FAILED => 'Verbindung konnte nicht hergestellt werden',
- 0 => 'kein Fehler', // DB_OK
- DB_ERROR_NEED_MORE_DATA => 'Nicht genĂĽgend Daten geliefert',
- DB_ERROR_EXTENSION_NOT_FOUND=> 'erweiterung nicht gefunden',
- DB_ERROR_NOSUCHDB => 'keine Datenbank',
- DB_ERROR_ACCESS_VIOLATION => 'ungenĂĽgende Rechte'
+ 'LANG' => 'de',
+ DB_ERROR => 'unbekannter Fehler',
+ DB_ERROR_ALREADY_EXISTS => 'existiert bereits',
+ DB_ERROR_CANNOT_CREATE => 'kann nicht erstellen',
+ DB_ERROR_CANNOT_DELETE => 'kann nicht löschen',
+ DB_ERROR_CANNOT_DROP => 'Tabelle oder Index konnte nicht gelöscht werden',
+ DB_ERROR_CONSTRAINT => 'Randbedingung verletzt',
+ DB_ERROR_DIVZERO => 'Division durch Null',
+ DB_ERROR_INVALID => 'ungĂĽltig',
+ DB_ERROR_INVALID_DATE => 'ungĂĽltiges Datum oder Zeit',
+ DB_ERROR_INVALID_NUMBER => 'ungĂĽltige Zahl',
+ DB_ERROR_MISMATCH => 'Unverträglichkeit',
+ DB_ERROR_NODBSELECTED => 'Keine Datenbank ausgewählt',
+ DB_ERROR_NOSUCHFIELD => 'Feld nicht vorhanden',
+ DB_ERROR_NOSUCHTABLE => 'Tabelle nicht vorhanden',
+ DB_ERROR_NOT_CAPABLE => 'Funktion nicht installiert',
+ DB_ERROR_NOT_FOUND => 'nicht gefunden',
+ DB_ERROR_NOT_LOCKED => 'nicht gesperrt',
+ DB_ERROR_SYNTAX => 'Syntaxfehler',
+ DB_ERROR_UNSUPPORTED => 'nicht unterstĂĽtzt',
+ DB_ERROR_VALUE_COUNT_ON_ROW => 'Anzahl der zurĂĽckgelieferten Felder entspricht nicht der Anzahl der Felder in der Abfrage',
+ DB_ERROR_INVALID_DSN => 'ungĂĽltiger DSN',
+ DB_ERROR_CONNECT_FAILED => 'Verbindung konnte nicht hergestellt werden',
+ 0 => 'kein Fehler', // DB_OK
+ DB_ERROR_NEED_MORE_DATA => 'Nicht genĂĽgend Daten geliefert',
+ DB_ERROR_EXTENSION_NOT_FOUND=> 'Erweiterung nicht gefunden',
+ DB_ERROR_NOSUCHDB => 'keine Datenbank',
+ DB_ERROR_ACCESS_VIOLATION => 'ungenĂĽgende Rechte'
);
diff --git a/adodb/lang/adodb-en.inc.php b/adodb/lang/adodb-en.inc.php
index 0582855..74c4ea0 100644
--- a/adodb/lang/adodb-en.inc.php
+++ b/adodb/lang/adodb-en.inc.php
@@ -1,4 +1,23 @@
'en',
diff --git a/adodb/lang/adodb-eo.inc.php b/adodb/lang/adodb-eo.inc.php
index baa589c..107a3b3 100644
--- a/adodb/lang/adodb-eo.inc.php
+++ b/adodb/lang/adodb-eo.inc.php
@@ -1,6 +1,24 @@
+ */
$ADODB_LANG_ARRAY = array (
'LANG' => 'eo',
diff --git a/adodb/lang/adodb-es.inc.php b/adodb/lang/adodb-es.inc.php
index a80a644..bcb0cce 100644
--- a/adodb/lang/adodb-es.inc.php
+++ b/adodb/lang/adodb-es.inc.php
@@ -1,5 +1,25 @@
+/**
+ * Spanish language strings.
+ *
+ * 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
+ * @author Horacio Degiorgi
+ */
+
$ADODB_LANG_ARRAY = array (
'LANG' => 'es',
DB_ERROR => 'error desconocido',
diff --git a/adodb/lang/adodb-fa.inc.php b/adodb/lang/adodb-fa.inc.php
index 7fa4618..84f17bd 100644
--- a/adodb/lang/adodb-fa.inc.php
+++ b/adodb/lang/adodb-fa.inc.php
@@ -1,6 +1,24 @@
*/
+/**
+ * Farsi language strings.
+ *
+ * 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
+ * @author Peyman Hooshmandi Raad"
+ */
$ADODB_LANG_ARRAY = array (
'LANG' => 'fa',
diff --git a/adodb/lang/adodb-fr.inc.php b/adodb/lang/adodb-fr.inc.php
index 620196b..b010d1e 100644
--- a/adodb/lang/adodb-fr.inc.php
+++ b/adodb/lang/adodb-fr.inc.php
@@ -1,4 +1,23 @@
'fr',
diff --git a/adodb/lang/adodb-hu.inc.php b/adodb/lang/adodb-hu.inc.php
index 49357ce..5a73827 100644
--- a/adodb/lang/adodb-hu.inc.php
+++ b/adodb/lang/adodb-hu.inc.php
@@ -1,6 +1,25 @@
+/**
+ * Hungarian language strings.
+ *
+ * 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
+ * @author Halászvári Gábor
+ */
+
$ADODB_LANG_ARRAY = array (
'LANG' => 'hu',
DB_ERROR => 'ismeretlen hiba',
diff --git a/adodb/lang/adodb-id.inc.php b/adodb/lang/adodb-id.inc.php
new file mode 100644
index 0000000..abd38ee
--- /dev/null
+++ b/adodb/lang/adodb-id.inc.php
@@ -0,0 +1,55 @@
+
+ */
+
+$ADODB_LANG_ARRAY = array (
+ 'LANG' => 'id',
+ DB_ERROR => 'kesalahan tidak diketahui',
+ DB_ERROR_ALREADY_EXISTS => 'sudah ada',
+ DB_ERROR_CANNOT_CREATE => 'tak dapat membuat',
+ DB_ERROR_CANNOT_DELETE => 'tak dapat menghapus',
+ DB_ERROR_CANNOT_DROP => 'tak dapat menghapus',
+ DB_ERROR_CONSTRAINT => 'pelanggaran kendala',
+ DB_ERROR_DIVZERO => 'pembagian dengan 0',
+ DB_ERROR_INVALID => 'tidak sah',
+ DB_ERROR_INVALID_DATE => 'tanggal atau waktu tidak valid',
+ DB_ERROR_INVALID_NUMBER => 'nomor tidak sah',
+ DB_ERROR_MISMATCH => 'tak cocok',
+ DB_ERROR_NODBSELECTED => 'tak ada database dipilih',
+ DB_ERROR_NOSUCHFIELD => 'kolom tak ditemukan',
+ DB_ERROR_NOSUCHTABLE => 'tabel tak ditemukan',
+ DB_ERROR_NOT_CAPABLE => 'kemampuan DB tak memadai',
+ DB_ERROR_NOT_FOUND => 'tidak ditemukan',
+ DB_ERROR_NOT_LOCKED => 'tidak terkunci',
+ DB_ERROR_SYNTAX => 'kesalahan sintak',
+ DB_ERROR_UNSUPPORTED => 'tak didukung',
+ DB_ERROR_VALUE_COUNT_ON_ROW => 'menghitung isi pada baris',
+ DB_ERROR_INVALID_DSN => 'DSN tidak sah',
+ DB_ERROR_CONNECT_FAILED => 'koneksi gagal',
+ 0 => 'tak ada kesalahan', // DB_OK
+ DB_ERROR_NEED_MORE_DATA => 'data yang dimasukan tidak memadai',
+ DB_ERROR_EXTENSION_NOT_FOUND=> 'ekstensi tak ditemukan',
+ DB_ERROR_NOSUCHDB => 'database tak ditemukan',
+ DB_ERROR_ACCESS_VIOLATION => 'izin tidak memadai',
+ DB_ERROR_DEADLOCK => 'kebuntuan terdeteksi',
+ DB_ERROR_STATEMENT_TIMEOUT => 'perintah kehabisan waktu',
+ DB_ERROR_SERIALIZATION_FAILURE => 'tak dapat melanjutkan akses'
+);
diff --git a/adodb/lang/adodb-it.inc.php b/adodb/lang/adodb-it.inc.php
index 80524e1..a651630 100644
--- a/adodb/lang/adodb-it.inc.php
+++ b/adodb/lang/adodb-it.inc.php
@@ -1,6 +1,25 @@
+ */
+
$ADODB_LANG_ARRAY = array (
'LANG' => 'it',
DB_ERROR => 'errore sconosciuto',
diff --git a/adodb/lang/adodb-nl.inc.php b/adodb/lang/adodb-nl.inc.php
index 43e3ee6..8a89819 100644
--- a/adodb/lang/adodb-nl.inc.php
+++ b/adodb/lang/adodb-nl.inc.php
@@ -1,5 +1,25 @@
+ */
+
$ADODB_LANG_ARRAY = array (
'LANG' => 'nl',
DB_ERROR => 'onbekende fout',
diff --git a/adodb/lang/adodb-oc.inc.php b/adodb/lang/adodb-oc.inc.php
new file mode 100644
index 0000000..3481e79
--- /dev/null
+++ b/adodb/lang/adodb-oc.inc.php
@@ -0,0 +1,51 @@
+ 'oc',
+ DB_ERROR => 'error desconeguda',
+ DB_ERROR_ALREADY_EXISTS => 'existĂs ja',
+ DB_ERROR_CANNOT_CREATE => 'creacion impossibla',
+ DB_ERROR_CANNOT_DELETE => 'escafament impossible',
+ DB_ERROR_CANNOT_DROP => 'supression impossibla',
+ DB_ERROR_CONSTRAINT => 'violacion de constrenta',
+ DB_ERROR_DIVZERO => 'division per zèro',
+ DB_ERROR_INVALID => 'invalid',
+ DB_ERROR_INVALID_DATE => 'data o ora invalida',
+ DB_ERROR_INVALID_NUMBER => 'nombre invalid',
+ DB_ERROR_MISMATCH => 'error de concordĂ ncia',
+ DB_ERROR_NODBSELECTED => 'pas de basa de donadas de seleccionada',
+ DB_ERROR_NOSUCHFIELD => 'nom de colomna invalid',
+ DB_ERROR_NOSUCHTABLE => 'taula o vista inexistenta',
+ DB_ERROR_NOT_CAPABLE => 'foncion opcionala pas installada',
+ DB_ERROR_NOT_FOUND => 'pas trobat',
+ DB_ERROR_NOT_LOCKED => 'pas verrolhat',
+ DB_ERROR_SYNTAX => 'error de sintaxi',
+ DB_ERROR_UNSUPPORTED => 'pas suportat',
+ DB_ERROR_VALUE_COUNT_ON_ROW => 'valor inserida tròp granda per colomna',
+ DB_ERROR_INVALID_DSN => 'DSN invalid',
+ DB_ERROR_CONNECT_FAILED => 'fracĂ s a la connexion',
+ 0 => "pas d'error", // DB_OK
+ DB_ERROR_NEED_MORE_DATA => 'donadas provesidas insufisentas',
+ DB_ERROR_EXTENSION_NOT_FOUND=> 'extension pas trobada',
+ DB_ERROR_NOSUCHDB => 'basa de donadas desconeguda',
+ DB_ERROR_ACCESS_VIOLATION => 'dreits insufisents'
+);
diff --git a/adodb/lang/adodb-pl.inc.php b/adodb/lang/adodb-pl.inc.php
index ffa10e3..f855153 100644
--- a/adodb/lang/adodb-pl.inc.php
+++ b/adodb/lang/adodb-pl.inc.php
@@ -1,6 +1,24 @@
+/**
+ * Polish language strings.
+ *
+ * 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
+ * @author Grzegorz Pacan
+ */
$ADODB_LANG_ARRAY = array (
'LANG' => 'pl',
diff --git a/adodb/lang/adodb-pt-br.inc.php b/adodb/lang/adodb-pt-br.inc.php
index 9c687b0..b6c0d1c 100644
--- a/adodb/lang/adodb-pt-br.inc.php
+++ b/adodb/lang/adodb-pt-br.inc.php
@@ -1,6 +1,25 @@
+ */
+
$ADODB_LANG_ARRAY = array (
'LANG' => 'pt-br',
DB_ERROR => 'erro desconhecido',
diff --git a/adodb/lang/adodb-ro.inc.php b/adodb/lang/adodb-ro.inc.php
index b6ddd31..011c016 100644
--- a/adodb/lang/adodb-ro.inc.php
+++ b/adodb/lang/adodb-ro.inc.php
@@ -1,6 +1,24 @@
*/
+/**
+ * Romanian language strings.
+ *
+ * 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
+ * @author Bogdan Stefan
+ */
$ADODB_LANG_ARRAY = array (
'LANG' => 'ro',
diff --git a/adodb/lang/adodb-ru.inc.php b/adodb/lang/adodb-ru.inc.php
index 67d80f2..a311784 100644
--- a/adodb/lang/adodb-ru.inc.php
+++ b/adodb/lang/adodb-ru.inc.php
@@ -1,6 +1,24 @@
+ */
$ADODB_LANG_ARRAY = array (
'LANG' => 'ru',
diff --git a/adodb/lang/adodb-sv.inc.php b/adodb/lang/adodb-sv.inc.php
index d3be6b0..72e2430 100644
--- a/adodb/lang/adodb-sv.inc.php
+++ b/adodb/lang/adodb-sv.inc.php
@@ -1,5 +1,25 @@
+ */
+
$ADODB_LANG_ARRAY = array (
'LANG' => 'en',
DB_ERROR => 'Okänt fel',
diff --git a/adodb/lang/adodb-th.inc.php b/adodb/lang/adodb-th.inc.php
index a068564..354acca 100644
--- a/adodb/lang/adodb-th.inc.php
+++ b/adodb/lang/adodb-th.inc.php
@@ -1,5 +1,25 @@
+/**
+ * Thai language strings.
+ *
+ * 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
+ * @author Trirat Petchsingh
+ */
+
$ADODB_LANG_ARRAY = array (
'LANG' => 'th',
DB_ERROR => 'error ไมŕąŕ¸Łŕ¸ąŕą‰ŕ¸Şŕ¸˛ŕą€ŕ¸«ŕ¸•ุ',
diff --git a/adodb/lang/adodb-uk.inc.php b/adodb/lang/adodb-uk.inc.php
index 2ace5bc..e54a967 100644
--- a/adodb/lang/adodb-uk.inc.php
+++ b/adodb/lang/adodb-uk.inc.php
@@ -1,6 +1,24 @@
+ */
$ADODB_LANG_ARRAY = array (
'LANG' => 'uk',
diff --git a/adodb/pear/Auth/Container/ADOdb.php b/adodb/pear/Auth/Container/ADOdb.php
index 2ece8c9..807da9d 100644
--- a/adodb/pear/Auth/Container/ADOdb.php
+++ b/adodb/pear/Auth/Container/ADOdb.php
@@ -1,36 +1,36 @@
- Richard Tango-Lowy
-*/
-
-require_once 'Auth/Container.php';
-require_once 'adodb.inc.php';
-require_once 'adodb-pear.inc.php';
-require_once 'adodb-errorpear.inc.php';
-
/**
* Storage driver for fetching login data from a database using ADOdb-PHP.
*
- * This storage driver can use all databases which are supported
- * by the ADBdb DB abstraction layer to fetch login data.
- * See http://adodb.org/ for information on ADOdb.
+ * This storage driver can use all databases which are supported by the ADBdb
+ * abstraction layer to fetch login data.
* NOTE: The ADOdb directory MUST be in your PHP include_path!
*
- * @author Richard Tango-Lowy
- * @package Auth
- * @version $Revision: 1.3 $
+ * 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
+ * @author Martin Jansen
+ * @author Richard Tango-Lowy
*/
+
+require_once 'Auth/Container.php';
+require_once 'adodb.inc.php';
+require_once 'adodb-pear.inc.php';
+require_once 'adodb-errorpear.inc.php';
+
+
class Auth_Container_ADOdb extends Auth_Container
{
@@ -58,7 +58,7 @@ class Auth_Container_ADOdb extends Auth_Container
/**
* Constructor of the container class
*
- * Initate connection to the database via PEAR::ADOdb
+ * Initiate connection to the database via PEAR::ADOdb
*
* @param string Connection data or DB object
* @return object Returns an error object if something went wrong
@@ -262,7 +262,7 @@ function fetchData($username, $password)
continue;
}
// Use reference to the auth object if exists
- // This is because the auth session variable can change so a static call to setAuthData does not make sence
+ // This is because the auth session variable can change so a static call to setAuthData does not make sense
if(is_object($this->_auth_obj)){
$this->_auth_obj->setAuthData($key, $value);
} else {
diff --git a/adodb/pear/auth_adodb_example.php b/adodb/pear/auth_adodb_example.php
index 3b7cf5e..77af939 100644
--- a/adodb/pear/auth_adodb_example.php
+++ b/adodb/pear/auth_adodb_example.php
@@ -1,5 +1,26 @@
tablesSQL) return false;
@@ -302,11 +313,9 @@ function optimizeTable( $table, $mode = ADODB_OPT_LOW)
case ADODB_OPT_LOW : $sql = $this->optimizeTableLow; break;
case ADODB_OPT_HIGH : $sql = $this->optimizeTableHigh; break;
default :
- {
- // May dont use __FUNCTION__ constant for BC (__FUNCTION__ Added in PHP 4.3.0)
+ // May don't use __FUNCTION__ constant for BC (__FUNCTION__ Added in PHP 4.3.0)
ADOConnection::outp( sprintf( "
", __CLASS__, 'optimizeTable', $mode));
return false;
- }
}
$sql = sprintf($sql, $table);
diff --git a/adodb/phpdoc b/adodb/phpdoc
new file mode 100644
index 0000000..d4cb73a
--- /dev/null
+++ b/adodb/phpdoc
@@ -0,0 +1,20 @@
+execute = false)
+ * - do not delete records in dest table first ($rep->deleteFirst = false).
+ * if $rep->deleteFirst is true and primary keys are defined,
+ * then no deletion will occur unless *INSERTONLY* is defined in pkey array
+ * - only commit once at the end of every ReplicateData ($rep->commitReplicate = true)
+ * - do not autocommit every x records processed ($rep->commitRecs = -1)
+ * - even if error occurs on one record, continue copying remaining records ($rep->neverAbort = true)
+ * - debugging turned off ($rep->debug = false)
+ *
+ * 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
+ */
define('ADODB_REPLICATE',1.2);
include_once(ADODB_DIR.'/adodb-datadict.inc.php');
-/*
-1.2 9 June 2009
-Minor patches
-
-1.1 8 June 2009
-Added $lastUpdateFld to replicatedata
-Added $rep->compat. If compat set to 1.0, then $lastUpdateFld not used during MergeData.
-
-1.0 Apr 2009
-Added support for MFFA
-
-0.9 ? 2008
-First release
-
-
- Note: this code assumes that comments such as / * * / ar`e allowed which works with:
- Note: this code assumes that comments such as / * * / are allowed which works with:
- mssql, postgresql, oracle, mssql
-
- Replication engine to
- - copy table structures and data from different databases (e.g. mysql to oracle)
- for replication purposes
- - generate CREATE TABLE, CREATE INDEX, INSERT ... for installation scripts
-
- Table Structure copying includes
- - fields and limited subset of types
- - optional default values
- - indexes
- - but not constraints
-
-
- Two modes of data copy:
-
- ReplicateData
- - Copy from src to dest, with update of status of copy back to src,
- with configurable src SELECT where clause
-
- MergeData
- - Copy from src to dest based on last mod date field and/or copied flag field
-
- Default settings are
- - do not execute, generate sql ($rep->execute = false)
- - do not delete records in dest table first ($rep->deleteFirst = false).
- if $rep->deleteFirst is true and primary keys are defined,
- then no deletion will occur unless *INSERTONLY* is defined in pkey array
- - only commit once at the end of every ReplicateData ($rep->commitReplicate = true)
- - do not autocommit every x records processed ($rep->commitRecs = -1)
- - even if error occurs on one record, continue copying remaining records ($rep->neverAbort = true)
- - debugging turned off ($rep->debug = false)
-*/
-
class ADODB_Replicate {
var $connSrc;
var $connDest;
@@ -114,8 +111,8 @@ function __construct($connSrc, $connDest, $connSrc2=false, $connDest2=false)
$this->connSrc2 = ($connSrc2) ? $connSrc2 : $connSrc;
$this->connDest2 = ($connDest2) ? $connDest2 : $connDest;
- $this->ddSrc = NewDataDictionary($connSrc);
- $this->ddDest = NewDataDictionary($connDest);
+ $this->ddSrc = newDataDictionary($connSrc);
+ $this->ddDest = newDataDictionary($connDest);
$this->htmlSpecialChars = isset($_SERVER['HTTP_HOST']);
}
diff --git a/adodb/replicate/replicate-steps.php b/adodb/replicate/replicate-steps.php
index 5b69656..fca719d 100644
--- a/adodb/replicate/replicate-steps.php
+++ b/adodb/replicate/replicate-steps.php
@@ -1,4 +1,23 @@
Use specified branch (defaults to '%s' for '.0'
+ -b | --branch Use specified branch (defaults to '{}' for '.0'
releases, or 'hotfix/' for patches)
-d | --debug Debug mode (ignores upstream: no fetch, allows
build even if local branch is not in sync)
-f | --fresh Create a fresh clone of the repository
-k | --keep Keep build directories after completion
(useful for debugging)
-''' % (
+'''.format(
path.basename(__file__),
release_branch
- )
-#end usage()
+ ))
+# end usage()
def set_version_and_tag(version):
- '''
- '''
global release_branch, debug_mode, fresh_clone, cleanup
# Delete existing tag to force creation in debug mode
if debug_mode:
try:
updateversion.tag_delete(version)
- except:
+ except subprocess.CalledProcessError:
pass
# Checkout release branch
- subprocess.call("git checkout %s" % release_branch, shell=True)
+ subprocess.call("git checkout {}".format(release_branch), shell=True)
if not debug_mode:
# Make sure we're up-to-date, ignore untracked files
ret = subprocess.check_output(
"git status --branch --porcelain --untracked-files=no",
+ text=True,
shell=True
)
if not re.search(release_branch + "$", ret):
- print "\nERROR: branch must be aligned with upstream"
+ print("\nERROR: branch must be aligned with upstream")
sys.exit(4)
# Update the code, create commit and tag
@@ -109,17 +124,17 @@ def set_version_and_tag(version):
def main():
global release_branch, debug_mode, fresh_clone, cleanup
- # Get command-line options
+ # Get command-line options
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], options, long_options)
- except getopt.GetoptError, err:
- print str(err)
+ except getopt.GetoptError as err:
+ print(str(err))
usage()
sys.exit(2)
if len(args) < 2:
usage()
- print "ERROR: please specify the version and release_path"
+ print("ERROR: please specify the version and release_path")
sys.exit(1)
for opt, val in opts:
@@ -145,33 +160,34 @@ def main():
# Default release branch
if updateversion.version_is_patch(version):
- release_branch = 'hotfix/' + version
+ release_branch = 'hotfix/' + version.rsplit('.', 1)[0]
# -------------------------------------------------------------------------
# Start the build
#
global release_prefix
- print "Building ADOdb release %s into '%s'\n" % (
+ print("Building ADOdb release {} into '{}'\n".format(
version,
release_path
- )
+ ))
if debug_mode:
- print "DEBUG MODE: ignoring upstream repository status"
+ print("DEBUG MODE: ignoring upstream repository status")
if fresh_clone:
# Create a new repo clone
- print "Cloning a new repository"
+ print("Cloning a new repository")
repo_path = tempfile.mkdtemp(prefix=release_prefix + "-",
suffix=".git")
subprocess.call(
- "git clone %s %s" % (origin_repo, repo_path),
+ "git clone {} {}".format(origin_repo, repo_path),
shell=True
)
os.chdir(repo_path)
else:
- repo_path = subprocess.check_output('git root', shell=True).rstrip()
+ # Git repo's root directory
+ repo_path = updateversion.git_root()
os.chdir(repo_path)
# Check for any uncommitted changes
@@ -181,17 +197,17 @@ def main():
"git diff --cached --exit-code",
shell=True
)
- except:
- print "ERROR: there are uncommitted changes in the repository"
+ except subprocess.CalledProcessError:
+ print("ERROR: there are uncommitted changes in the repository")
sys.exit(3)
# Update the repository
if not debug_mode:
- print "Updating repository in '%s'" % os.getcwd()
+ print("Updating repository in '{}'".format(os.getcwd()))
try:
subprocess.check_output("git fetch", shell=True)
- except:
- print "ERROR: unable to fetch\n"
+ except subprocess.CalledProcessError:
+ print("ERROR: unable to fetch\n")
sys.exit(3)
# Check existence of Tag for version in repo, create if not found
@@ -199,13 +215,13 @@ def main():
updateversion.tag_check(version)
if debug_mode:
set_version_and_tag(version)
- except:
+ except subprocess.CalledProcessError:
set_version_and_tag(version)
# Copy files to release dir
release_files = release_prefix + version.split(".")[0]
release_tmp_dir = path.join(release_path, release_files)
- print "Copying release files to '%s'" % release_tmp_dir
+ print("Copying release files to '{}'".format(release_tmp_dir))
retry = True
while True:
try:
@@ -215,56 +231,55 @@ def main():
ignore=shutil.ignore_patterns(*exclude_list)
)
break
- except OSError, err:
+ except OSError as err:
# First try and file exists, try to delete dir
if retry and err.errno == errno.EEXIST:
- print "WARNING: Directory '%s' exists, delete it and retry" % (
- release_tmp_dir
- )
+ print("WARNING: Directory '{}' exists, delete it and retry"
+ .format(release_tmp_dir))
shutil.rmtree(release_tmp_dir)
retry = False
continue
else:
- # We already tried to delete or some other error occured
+ # We already tried to delete or some other error occurred
raise
# Create tarballs
- print "Creating release tarballs..."
+ print("Creating release tarballs...")
release_name = release_prefix + '-' + version
- print release_prefix, version, release_name
os.chdir(release_path)
- print "- tar"
+ print("- tar")
subprocess.call(
- "tar -czf %s.tar.gz %s" % (release_name, release_files),
+ "tar -czf {}.tar.gz {}".format(release_name, release_files),
shell=True
)
- print "- zip"
+ print("- zip")
subprocess.call(
- "zip -rq %s.zip %s" % (release_name, release_files),
+ "zip -rq {}.zip {}".format(release_name, release_files),
shell=True
)
if cleanup:
- print "Deleting working directories"
+ print("Deleting working directories")
shutil.rmtree(release_tmp_dir)
if fresh_clone:
shutil.rmtree(repo_path)
else:
- print "\nThe following working directories were kept:"
+ print("\nThe following working directories were kept:")
if fresh_clone:
- print "- '%s' (repo clone)" % repo_path
- print "- '%s' (release temp dir)" % release_tmp_dir
- print "Delete them manually when they are no longer needed."
+ print("- '{}' (repo clone)".format(repo_path))
+ print("- '{}' (release temp dir)".format(release_tmp_dir))
+ print("Delete them manually when they are no longer needed.")
# Done
- print "\nADOdb release %s build complete, files saved in '%s'." % (
+ print("\nADOdb release {} build complete, files saved in '{}'.".format(
version,
release_path
- )
- print "Don't forget to generate a README file with the changelog"
+ ))
+ print("Don't forget to generate a README file with the changelog")
+
+# end main()
-#end main()
if __name__ == "__main__":
main()
diff --git a/adodb/scripts/env.yml.sample b/adodb/scripts/env.yml.sample
new file mode 100644
index 0000000..fce3840
--- /dev/null
+++ b/adodb/scripts/env.yml.sample
@@ -0,0 +1,7 @@
+# ADOdb maintenance scripts configuration file
+# Rename this file to 'env.yml' and update variables below as appropriate.
+
+# SourceForge API key
+# Get it from https://sourceforge.net/auth/preferences/
+# under "Releases API Key"
+api_key:
diff --git a/adodb/scripts/fix-static-docs.php b/adodb/scripts/fix-static-docs.php
new file mode 100644
index 0000000..c4159dd
--- /dev/null
+++ b/adodb/scripts/fix-static-docs.php
@@ -0,0 +1,232 @@
+ 1)
+ {
+ $dSlash .= array_shift($dList) . '/';
+ if (!is_dir($dSlash))
+ mkdir($dSlash);
+ }
+ if (!is_file($f))
+ continue;
+ if (substr($f,-4) <> 'html')
+ {
+ /*
+ * An image or something else, copy unmodified
+ */
+ copy ($f,$r);
+ continue;
+ }
+
+ $prepend = str_repeat('../',$depth);
+
+ $doc = new DOMDocument();
+ @$doc->loadHTMLFile($f);
+
+ /*
+ * Remove Page Tools Group
+ */
+ $xpath = new DOMXPath($doc);
+
+ /*
+ * Remove Top Menu Tools Group, and add a link to the ADOdb site
+ */
+ $nodes = $xpath->query("//div[@class='tools group']");
+ foreach($nodes as $node) {
+ $pn = $node->parentNode;
+ $pn->removeChild($node);
+ $newChild = $doc->createElement('div','');
+ $newDiv = $pn->appendChild($newChild);
+ $newDiv->setAttribute('style','text-align:right');
+ $newChild = $doc->createElement('a','ADOdb Web Site');
+ $newA = $newDiv->appendChild($newChild);
+ $newA->setAttribute('href','https://adodb.org');
+ }
+
+ /*
+ * Remove Trace
+ */
+ $nodes = $xpath->query("//div[@class='breadcrumbs']");
+ foreach($nodes as $node) {
+ $node->parentNode->removeChild($node);
+ }
+
+ /*
+ * Remove Side Menu Tools Group
+ */
+ $nodes = $xpath->query("//div[@id='dokuwiki__pagetools']");
+ foreach($nodes as $node) {
+ $node->parentNode->removeChild($node);
+ }
+
+ /*
+ * Fix main links
+ */
+ $nodes = $xpath->query("//a[@class='wikilink1']");
+ foreach($nodes as $node) {
+ $n = $node->getAttribute('title');
+ $p = $prepend . str_replace(':','/',$n) . '.html';
+ $node->setAttribute('href', $p);
+ }
+
+ /*
+ * Fix In Page links
+ */
+ $nodes = $xpath->query("//a[@class='wikilink2']");
+ foreach($nodes as $node) {
+ $n = $node->getAttribute('title');
+ $p = $prepend . str_replace(':','/',$n) . '.html';
+ $node->setAttribute('href', $p);
+ }
+
+ /*
+ * Make Graphic point to first page. This will break if the image size
+ * ever changes.
+ */
+ $corePage = $prepend . '/index.html';
+ $nodes = $xpath->query("//img[@width='176']");
+ foreach($nodes as $node) {
+ $node->parentNode->setAttribute('href', $corePage);
+ }
+
+ /*
+ * Change title of page
+ */
+ $nodes = $xpath->query("//title");
+ foreach($nodes as $node) {
+
+
+ $docTitle = implode(':',$titleList);
+ $docTitle = str_replace('.html','',$docTitle);
+ $pn = $node->parentNode;
+ $pn->removeChild($node);
+ $newChild = $doc->createElement('title',$docTitle);
+ $pn->appendChild($newChild);
+
+ }
+
+ $doc->saveHTMLFile($r);
+
+ echo $r, "\n";
+}
+/*
+* Now remove the original index and replace it with the hardcopy documentation one
+*/
+unlink ('documentation/index.html');
+rename('documentation/adodb_index.html','documentation/index.html');
+
+/*
+* We could add in an auto zip and upload here, but this is a good place to
+* stop and check the output
+*/
diff --git a/adodb/scripts/updateversion.py b/adodb/scripts/updateversion.py
index 429c542..5590f37 100644
--- a/adodb/scripts/updateversion.py
+++ b/adodb/scripts/updateversion.py
@@ -1,9 +1,25 @@
-#!/usr/bin/python -u
-'''
- ADOdb version update script
+#!/usr/bin/env -S python3 -u
+"""
+ADOdb version update script.
- Updates the version number, and release date in all php and html files
-'''
+Updates the version number, and release date in all php and html files
+
+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 2014 Damien Regad, Mark Newnham and the ADOdb community
+@author Damien Regad
+"""
from datetime import date
import getopt
@@ -13,24 +29,28 @@
import subprocess
import sys
-
# ADOdb version validation regex
# These are used by sed - they are not PCRE !
_version_dev = "dev"
-_version_regex = "[Vv]?([0-9]\.[0-9]+)(\.([0-9]+))?(-?%s)?" % _version_dev
-_release_date_regex = "[0-9?]+-.*-[0-9]+"
+_version_abrc = r"(alpha|beta|rc)(\.([0-9]+))?"
+_version_prerelease = r"(-?({0}|{1}))?".format(_version_dev, _version_abrc)
+_version_base = r"[Vv]?([0-9]\.[0-9]+)(\.([0-9]+))?"
+_version_regex = _version_base + _version_prerelease
+_release_date_regex = r"(Unreleased|[0-9?]+-.*-[0-9]+)"
_changelog_file = "docs/changelog.md"
_tag_prefix = "v"
-
# Command-line options
options = "hct"
long_options = ["help", "commit", "tag"]
def usage():
- print '''Usage: %s version
+ """
+ Print script's command-line arguments help.
+ """
+ print('''Usage: {0} version
Parameters:
version ADOdb version, format: [v]X.YY[a-z|dev]
@@ -39,41 +59,60 @@ def usage():
-c | --commit Automatically commit the changes
-t | --tag Create a tag for the new release
-h | --help Show this usage message
-''' % (
+'''.format(
path.basename(__file__)
- )
-#end usage()
+ ))
+# end usage()
def version_is_dev(version):
- ''' Returns true if version is a development release
- '''
+ """
+ Return true if version is a development release.
+ """
return version.endswith(_version_dev)
+def version_is_prerelease(version):
+ """
+ Return true if version is alpha, beta or release-candidate.
+ """
+ return re.search(_version_abrc, version) is not None
+
+
def version_is_patch(version):
- ''' Returns true if version is a patch release (i.e. X.Y.Z with Z > 0)
- '''
- return not version.endswith('.0')
+ """
+ Return true if version is a patch release (i.e. X.Y.Z with Z > 0).
+ """
+ return (re.search('^' + _version_base + '$', version) is not None
+ and not version.endswith('.0'))
def version_parse(version):
- ''' Breakdown the version into groups (Z and -dev are optional)
- 1:(X.Y), 2:(.Z), 3:(Z), 4:(-dev)
- '''
- return re.match(r'^%s$' % _version_regex, version)
+ """
+ Breakdown the version into groups (Z and -dev are optional).
+
+ Groups:
+ - 1:(X.Y)
+ - 2:(.Z)
+ - 3:(Z)
+ - 4:(-dev or -alpha/beta/rc.N)
+ - 8: N
+ """
+ return re.match(r'^{0}$'.format(_version_regex), version)
def version_check(version):
- ''' Checks that the given version is valid, exits with error if not.
- Returns the SemVer-normalized version without the "v" prefix
- - add '.0' if missing patch bit
- - add '-' before dev release suffix if needed
- '''
+ """
+ Check that the given version is valid, exit with error if not.
+
+ Returns the SemVer-normalized version without the "v" prefix
+ - add '.0' if missing patch bit
+ - add '-' before dev release suffix if needed
+ """
vparse = version_parse(version)
if not vparse:
usage()
- print "ERROR: invalid version ! \n"
+ print("ERROR: invalid version ! \n")
sys.exit(1)
vnorm = vparse.group(1)
@@ -88,48 +127,62 @@ def version_check(version):
# Normalize version number
if version_is_dev(version):
vnorm += '-' + _version_dev
+ elif version_is_prerelease(version):
+ vnorm += '-' + vparse.group(5)
+ # If no alpha/beta/rc version number specified, assume 1
+ if not vparse.group(8):
+ vnorm += ".1"
return vnorm
def get_release_date(version):
- ''' Returns the release date in DD-MMM-YYYY format
- For development releases, DD-MMM will be ??-???
- '''
+ """
+ Return the release date in YYYY-MM-DD format, or 'Unreleased' for
+ development releases.
+ """
# Development release
if version_is_dev(version):
- date_format = "??-???-%Y"
+ return "Unreleased"
else:
- date_format = "%d-%b-%Y"
+ return date.today().strftime("%Y-%m-%d")
- # Define release date
- return date.today().strftime(date_format)
+def git_root():
+ """
+ Return the git repository's root (top-level) directory.
+ """
+ return subprocess.check_output(
+ 'git rev-parse --show-toplevel',
+ text=True,
+ shell=True
+ ).rstrip()
-def sed_script(version):
- ''' Builds sed script to update version information in source files
- '''
+def sed_script(version):
+ """
+ Build sed script to update version information in source files.
+ """
# Version number and release date
- script = r"s/{}\s+(-?)\s+{}/v{} \5 {}/".format(
+ script = r"s/{0}\s+{1}/v{2} {3}/".format(
_version_regex,
_release_date_regex,
version,
get_release_date(version)
)
-
return script
def sed_filelist():
- ''' Build list of files to update
- '''
+ """
+ Build list of files to update.
+ """
dirlist = []
for root, dirs, files in os.walk(".", topdown=True):
# Filter files by extensions
files = [
f for f in files
- if re.search(r'\.(php|html?)$', f, re.IGNORECASE)
+ if re.search(r'\.php$', f, re.IGNORECASE)
]
for fname in files:
dirlist.append(path.join(root, fname))
@@ -137,25 +190,39 @@ def sed_filelist():
return dirlist
+def sed_run(script, files):
+ """
+ Run sed.
+ """
+ subprocess.call(
+ "sed -r -i '{0}' {1} ".format(script, files),
+ shell=True
+ )
+
+
def tag_name(version):
+ """
+ Return tag name (vX.Y.Z)
+ """
return _tag_prefix + version
def tag_check(version):
- ''' Checks if the tag for the specified version exists in the repository
- by attempting to check it out
- Throws exception if not
- '''
+ """
+ Checks if the tag for the specified version exists in the repository
+ by attempting to check it out, throws exception if not.
+ """
subprocess.check_call(
"git checkout --quiet " + tag_name(version),
stderr=subprocess.PIPE,
shell=True)
- print "Tag '%s' already exists" % tag_name(version)
+ print("Tag '{0}' already exists".format(tag_name(version)))
def tag_delete(version):
- ''' Deletes the specified tag
- '''
+ """
+ Deletes the specified tag
+ """
subprocess.check_call(
"git tag --delete " + tag_name(version),
stderr=subprocess.PIPE,
@@ -163,13 +230,15 @@ def tag_delete(version):
def tag_create(version):
- ''' Creates the tag for the specified version
- Returns True if tag created
- '''
- print "Creating release tag '%s'" % tag_name(version)
+ """
+ Create the tag for the specified version.
+
+ Returns True if tag created.
+ """
+ print("Creating release tag '{0}'".format(tag_name(version)))
result = subprocess.call(
- "git tag --sign --message '%s' %s" % (
- "ADOdb version %s released %s" % (
+ "git tag --sign --message '{0}' {1}".format(
+ "ADOdb version {0} released {1}".format(
version,
get_release_date(version)
),
@@ -181,161 +250,169 @@ def tag_create(version):
def section_exists(filename, version, print_message=True):
- ''' Checks given file for existing section with specified version
- '''
- script = True
+ """
+ Check given file for existing section with specified version.
+ """
for i, line in enumerate(open(filename)):
- if re.search(r'^## \[?' + version + r'\]', line):
+ if re.search(r'^## \[?' + version + r']', line):
if print_message:
- print " Existing section for v%s found," % version,
+ print(" Existing section for v{0} found,"
+ .format(version), end=" ")
return True
return False
+class UnsupportedPreviousVersion(Exception):
+ pass
+
+
+class NoPreviousVersion(Exception):
+ pass
+
+
def version_get_previous(version):
- ''' Returns the previous version number
- Don't decrease major versions (raises exception)
- '''
+ """
+ Returns the previous version number.
+
+ In pre-release scenarios, it would be complex to figure out what the
+ previous version is, so it is not worth the effort to implement as
+ this is a rare usage scenario; we just raise an exception in this case.
+ - 'UnsupportedPreviousVersion' when attempting facing pre-release
+ scenarios (rc -> beta -> alpha)
+ - 'NoPreviousVersion' when processing major version or .1 pre-releases
+ (can't handle e.g. alpha.0)
+ """
vprev = version.split('.')
item = len(vprev) - 1
while item > 0:
- val = int(vprev[item])
+ try:
+ val = int(vprev[item])
+ except ValueError:
+ raise UnsupportedPreviousVersion(
+ "Retrieving pre-release's previous version is not supported")
if val > 0:
vprev[item] = str(val - 1)
break
- else:
- item -= 1
+ item -= 1
- if item == 0:
- raise ValueError('Refusing to decrease major version number')
+ # Unhandled scenarios:
+ # - major version number (item == 0)
+ # - .0 pre-release
+ if (item == 0
+ or version_is_prerelease(version) and vprev[item] == '0'):
+ raise NoPreviousVersion
return '.'.join(vprev)
def update_changelog(version):
- ''' Updates the release date in the Change Log
- '''
- print "Updating Changelog"
-
- vparse = version_parse(version)
+ """
+ Update the release date in the Change Log.
+ """
+ print("Updating Changelog")
# Version number without '-dev' suffix
+ vparse = version_parse(version)
version_release = vparse.group(1) + vparse.group(2)
- version_previous = version_get_previous(version_release)
-
- if not section_exists(_changelog_file, version_previous, False):
- raise ValueError(
- "ERROR: previous version %s does not exist in changelog" %
- version_previous
- )
-
- # Check if version already exists in changelog
- version_exists = section_exists(_changelog_file, version_release)
- if (not version_exists
- and not version_is_patch(version)
- and not version_is_dev(version)):
- version += '-' + _version_dev
-
- release_date = get_release_date(version)
-
- # Development release
- # Insert a new section for next release before the most recent one
- if version_is_dev(version):
- # Check changelog file for existing section
- if version_exists:
- print "nothing to do"
- return
- # No existing section found, insert new one
- if version_is_patch(version_release):
- print " Inserting new section for hotfix release v%s" % version
+ # Make sure previous version exists in changelog, ignore .0 pre-releases
+ try:
+ if version_is_dev(version):
+ version_previous = version_get_previous(version_release)
else:
- print " Inserting new section for v%s" % version_release
- # Adjust previous version number (remove patch component)
- version_previous = version_parse(version_previous).group(1)
- script = "1,/^## \[{0}\]/s/^## \[{0}\].*$/## [{1}] - {2}\\n\\n\\0/".format(
- version_previous,
- version_release,
- release_date
- )
+ version_previous = version_get_previous(version)
+ if not section_exists(_changelog_file, version_previous, False):
+ raise ValueError(
+ "ERROR: previous version {0} does not exist in changelog"
+ .format(version_previous)
+ )
+ except NoPreviousVersion:
+ if version_is_prerelease(version):
+ version_previous = version_release
+ else:
+ version_previous = False
- # Stable release (X.Y.0)
- # Replace the 1st occurence of markdown level 2 header matching version
- # and release date patterns
- elif not version_is_patch(version):
- print " Updating release date for v%s" % version
- script = r"s/^(## )\[{0}\](\.0)? - {1}.*$/\1[{2}] - {3}/".format(
- vparse.group(1),
- _release_date_regex,
+ # If version exists, update the release date
+ if section_exists(_changelog_file, version):
+ print('updating release date')
+ script = r"s/^## \[{0}] .*$/## [{1}] - {2}/".format(
+ version.replace('.', r'\.'),
version,
- release_date
+ get_release_date(version)
)
-
- # Hotfix release (X.Y.[0-9])
- # Insert a new section for the hotfix release before the most recent
- # section for version X.Y and display a warning message
else:
- if version_exists:
- print 'updating release date'
- script = "s/^## \[{0}\].*$/## [{1}] - {2}/".format(
- version.replace('.', '\.'),
+ # If it's a .0 release, treat it as dev
+ if (not version_is_patch(version)
+ and not version_is_prerelease(version)
+ and not version_is_dev(version)):
+ version += '-' + _version_dev
+
+ # If development release already exists, nothing to do
+ if (version_is_dev(version)
+ and section_exists(_changelog_file, version_release)):
+ print("nothing to do")
+ return
+
+ print(" Inserting new section for v{0}".format(version))
+
+ # Prerelease section is inserted after the main version's,
+ # otherwise we insert the new section before it.
+ section_template = r"## \[{0}] - {1}"
+ if version_is_prerelease(version):
+ version_section = section_template.format(
version,
- release_date
+ get_release_date(version)
)
+ version_section = "\\0\\n\\n" + version_section
else:
- print " Inserting new section for hotfix release v%s" % version
- script = "1,/^## \[{0}\]/s/^## \[{0}\].*$/## [{1}] - {2}\\n\\n\\0/".format(
+ version_section = section_template.format(
+ version_release,
+ get_release_date(version)
+ )
+ version_section += "\\n\\n\\0"
+
+ if version_previous:
+ # Adjust previous version number (remove patch component)
+ version_previous = version_parse(version_previous).group(1)
+ script = r"1,/^## \[({0}|{2})/s/^## \[({0}|{2}).*$/{1}/".format(
version_previous,
- version,
- release_date
+ version_section,
+ version_release
)
- print " WARNING: review '%s' to ensure added section is correct" % (
- _changelog_file
- )
+ # We don't have a previous version, insert before the first section
+ else:
+ print("No previous version")
+ script = "1,/^## /s/^## .*$/{0}/".format(version_section)
- if not version_exists:
- # Adding the link to the release's commits list at the bottom
- # @TODO does not handle the "Unreleased" version case
- script += ";\n/^\[{0}\]/i[{1}]: https://github.com/adodb/adodb/compare/v{0}...v{1}".format(
- version_previous,
- version
- )
+ sed_run(script, _changelog_file)
- subprocess.call(
- "sed -r -i '%s' %s " % (
- script,
- _changelog_file
- ),
- shell=True
- )
-#end update_changelog
+ print(" WARNING: review '{0}' to ensure added section is correct".format(
+ _changelog_file
+ ))
+
+# end update_changelog
def version_set(version, do_commit=True, do_tag=True):
- ''' Bump version number and set release date in source files
- '''
- print "Preparing version bump commit"
+ """
+ Bump version number and set release date in source files.
+ """
+ print("Preparing version bump commit")
update_changelog(version)
- print "Updating version and date in source files"
- subprocess.call(
- "sed -r -i '%s' %s " % (
- sed_script(version),
- " ".join(sed_filelist())
- ),
- shell=True
- )
- print "Version set to %s" % version
+ print("Updating version and date in source files")
+ sed_run(sed_script(version), " ".join(sed_filelist()))
+ print("Version set to {0}".format(version))
if do_commit:
# Commit changes
- print "Committing"
+ print("Committing")
commit_ok = subprocess.call(
- "git commit --all --message '%s'" % (
- "Bump version to %s" % version
+ "git commit --all --message '{0}'".format(
+ "Bump version to {0}".format(version)
),
shell=True
)
@@ -346,38 +423,36 @@ def version_set(version, do_commit=True, do_tag=True):
tag_ok = False
if commit_ok == 0:
- print '''
+ print('''
NOTE: you should carefully review the new commit, making sure updates
to the files are correct and no additional changes are required.
If everything is fine, then the commit can be pushed upstream;
otherwise:
- Make the required corrections
- - Amend the commit ('git commit --all --amend' ) or create a new one'''
+ - Amend the commit ('git commit --all --amend' ) or create a new one''')
if tag_ok:
- print ''' - Drop the tag ('git tag --delete %s')
+ print(''' - Drop the tag ('git tag --delete {0}')
- run this script again
-''' % (
- tag_name(version)
- )
+'''.format(tag_name(version)))
else:
- print "Note: changes have been staged but not committed."
-#end version_set()
+ print("Note: changes have been staged but not committed.")
+# end version_set()
def main():
# Get command-line options
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], options, long_options)
- except getopt.GetoptError, err:
- print str(err)
+ except getopt.GetoptError as err:
+ print(str(err))
usage()
sys.exit(2)
if len(args) < 1:
usage()
- print "ERROR: please specify the version"
+ print("ERROR: please specify the version")
sys.exit(1)
do_commit = False
@@ -397,11 +472,16 @@ def main():
# Mandatory parameters
version = version_check(args[0])
+ # Change to Git repo's root directory
+ os.chdir(git_root())
+
# Let's do it
- os.chdir(subprocess.check_output('git root', shell=True).rstrip())
version_set(version, do_commit, do_tag)
-#end main()
+# end main()
+if sys.version_info < (3, 7):
+ print("ERROR: Python 3.7 or later is required")
+ sys.exit(1)
if __name__ == "__main__":
main()
diff --git a/adodb/scripts/uploadrelease.py b/adodb/scripts/uploadrelease.py
index 5b295cb..7d801ee 100644
--- a/adodb/scripts/uploadrelease.py
+++ b/adodb/scripts/uploadrelease.py
@@ -1,96 +1,170 @@
-#!/usr/bin/python -u
-'''
- ADOdb release upload script
-'''
+#!/usr/bin/env -S python3 -u
+"""
+ADOdb release upload script.
+
+Uploads release zip/tarball files generated by buildrelease.py to SourceForge.
+
+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 2014 Damien Regad, Mark Newnham and the ADOdb community
+@author Damien Regad
+"""
from distutils.version import LooseVersion
import getopt
+import getpass
import glob
+import json
import os
from os import path
import re
+import requests
import subprocess
import sys
+import yaml
# Directories and files to exclude from release tarballs
+# for debugging, set to a local dir e.g. "localhost:/tmp/sf-adodb/"
+
sf_files = "frs.sourceforge.net:/home/frs/project/adodb/"
+
+# SourceForge Release API base URL
+# https://sourceforge.net/p/forge/documentation/Using%20the%20Release%20API/
+sf_api_url = 'https://sourceforge.net/projects/adodb/files/{}/'
+
+# rsync command template
rsync_cmd = "rsync -vP --rsh ssh {opt} {src} {usr}@{dst}"
# Command-line options
-options = "hn"
-long_options = ["help", "dry-run"]
+options = "hu:ns"
+long_options = ["help", "user=", "dry-run", "skip-upload"]
+
+# Global flags
+dry_run = False
+api_key = ''
+username = getpass.getuser()
+release_path = ''
+skip_upload = False
def usage():
- print '''Usage: %s [options] username [release_path]
+ """
+ Print script's command-line arguments help.
+ """
+ print('''Usage: {} [options] username [release_path]
This script will upload the files in the given directory (or the
- current one if unspecified) to Sourceforge.
+ current one if unspecified) to SourceForge.
Parameters:
- username Sourceforge user account
- release_path Location of the release files to upload
- (see buildrelease.py)
+ release_path Location of the release files to upload,
+ see buildrelease.py to generate them.
+ Defaults to current directory.
Options:
-h | --help Show this usage message
- -n | --dry-run Do not upload the files
-''' % (
+ -u | --user SourceForge account (defaults to current user)
+ -s | --skip-upload Do not upload the release files (allows only
+ updating previously uploaded files information)
+ -n | --dry-run Do not upload or update sourceforge
+'''.format(
path.basename(__file__)
- )
-#end usage()
+ ))
+# end usage()
def call_rsync(usr, opt, src, dst):
- ''' Calls rsync to upload files with given parameters
- usr = ssh username
- opt = options
- src = source directory
- dst = target directory
- '''
+ """
+ Call rsync to upload files with given parameters.
+
+ :param usr: ssh username
+ :param opt: options
+ :param src: source directory
+ :param dst: target directory
+ """
global dry_run
command = rsync_cmd.format(usr=usr, opt=opt, src=src, dst=dst)
+ # Create directory if it does not exist
+ dst_split = dst.rsplit(':')
+ host = dst_split[0]
+ dst = dst_split[1]
+ mkdir = 'ssh {usr}@{host} mkdir -p {dst}'.format(
+ usr=usr,
+ host=host,
+ dst=dst
+ )
+
if dry_run:
- print command
+ print(mkdir)
+ print(command)
else:
+ subprocess.call(mkdir, shell=True)
subprocess.call(command, shell=True)
def get_release_version():
- ''' Get the version number from the zip file to upload
- '''
+ """
+ Return the version number (X.Y.Z) from the zip file to upload,
+ excluding the SemVer suffix.
+ """
try:
zipfile = glob.glob('adodb-*.zip')[0]
except IndexError:
- print "ERROR: release zip file not found in '%s'" % release_path
+ print("ERROR: release zip file not found in '{}'".format(release_path))
sys.exit(1)
try:
version = re.search(
- "^adodb-([\d]+\.[\d]+\.[\d]+)\.zip$",
+ r"^adodb-([\d]+\.[\d]+\.[\d]+)(-(alpha|beta|rc)\.[\d]+)?\.zip$",
zipfile
).group(1)
except AttributeError:
- print "ERROR: unable to extract version number from '%s'" % zipfile
- print " Only 3 groups of digits separated by periods are allowed"
+ print('''ERROR: unable to extract version number from '{}'
+ Only 3 groups of digits separated by periods are allowed'''
+ .format(zipfile))
sys.exit(1)
return version
def sourceforge_target_dir(version):
- ''' Returns the sourceforge target directory
- Base directory as defined in sf_files global variable, plus
- - if version >= 5.21: adodb-X.Y
- - for older versions: adodb-XYZ-for-php5
- '''
- # Keep only X.Y (discard patch number)
- short_version = version.rsplit('.', 1)[0]
-
- directory = 'adodb-php5-only/'
+ """
+ Return the SourceForge target directory.
+
+ This is relative to the root defined in sf_files global variable:
+ basedir/subdir, with
+ - basedir:
+ - for ADOdb version 5: adodb-php5-only
+ - for newer versions: adodbX (where X is the major version number)
+ - subdir:
+ - if version >= 5.21: adodb-X.Y
+ - for older versions: adodb-XYZ-for-php5
+ """
+ major_version = int(version.rsplit('.')[0])
+
+ # Base directory
+ if major_version == 5:
+ directory = 'adodb-php5-only/'
+ else:
+ directory = 'adodb{}/'.format(major_version)
+
+ # Keep only X.Y (discard patch number and pre-release suffix)
+ short_version = version.split('-')[0].rsplit('.', 1)[0]
+
if LooseVersion(version) >= LooseVersion('5.21'):
directory += "adodb-" + short_version
else:
@@ -99,74 +173,160 @@ def sourceforge_target_dir(version):
return directory
+def load_env():
+ """
+ Load environment from env.yml config file.
+ """
+ global api_key
+
+ # Load the config file
+ env_file = path.join(path.dirname(path.abspath(__file__)), 'env.yml')
+ try:
+ stream = open(env_file, 'r')
+ y = yaml.safe_load(stream)
+ except IOError:
+ print("ERROR: Environment file {} not found".format(env_file))
+ sys.exit(3)
+ except yaml.parser.ParserError as e:
+ print("ERROR: Invalid Environment file")
+ print(e)
+ sys.exit(3)
+
+ api_key = y['api_key']
+
+
def process_command_line():
- ''' Retrieve command-line options and set global variables accordingly
- '''
- global upload_files, upload_doc, dry_run, username, release_path
+ """
+ Retrieve command-line options and set global variables accordingly.
+ """
+ global dry_run, username, release_path, skip_upload
# Get command-line options
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], options, long_options)
- except getopt.GetoptError, err:
- print str(err)
+ except getopt.GetoptError as err:
+ print(str(err))
usage()
sys.exit(2)
- if len(args) < 1:
- usage()
- print "ERROR: please specify the Sourceforge user and release_path"
- sys.exit(1)
-
# Default values for flags
- dry_run = False
+ username = getpass.getuser()
for opt, val in opts:
if opt in ("-h", "--help"):
usage()
sys.exit(0)
+ elif opt in ("-u", "--user"):
+ username = val
+
+ elif opt in ("-s", "--skip-upload"):
+ skip_upload = True
+
elif opt in ("-n", "--dry-run"):
+ print("Dry-run mode - files will not be uploaded or modified")
dry_run = True
# Mandatory parameters
- username = args[0]
+ # (none)
# Change to release directory, current if not specified
try:
- release_path = args[1]
+ release_path = args[0]
os.chdir(release_path)
except IndexError:
release_path = os.getcwd()
def upload_release_files():
- ''' Upload release files from source directory to SourceForge
- '''
+ """
+ Upload release files from source directory to SourceForge.
+ """
version = get_release_version()
target = sf_files + sourceforge_target_dir(version)
- print
- print "Uploading release files..."
- print " Source:", release_path
- print " Target: " + target
- print
+ print()
+ print("Uploading release files...")
+ print(" Source:", release_path)
+ print(" Target: " + target)
+ print(" Files: " + ', '.join(glob.glob('*')))
+ print()
call_rsync(
username,
"",
path.join(release_path, "*"),
target
)
+ print()
+
+
+def set_sourceforge_file_info():
+ global api_key, dry_run
+
+ print("Updating uploaded files information")
+
+ base_url = sf_api_url.format(
+ sourceforge_target_dir(get_release_version())
+ )
+ headers = {'Accept': 'application/json"'}
+
+ # Loop through uploaded files
+ for file in glob.glob('adodb-*'):
+ print(" " + file)
+
+ # Determine defaults based on file extension
+ ext = path.splitext(file)[1]
+ if ext == '.zip':
+ defaults = ['windows']
+ elif ext == '.gz':
+ defaults = ['linux', 'mac', 'bsd', 'solaris', 'others']
+ else:
+ print("WARNING: Unknown extension for file", file)
+ continue
+
+ # SourceForge API request
+ url = path.join(base_url, file)
+ payload = {
+ 'default': defaults,
+ 'api_key': api_key
+ }
+ if dry_run:
+ req = requests.Request('PUT', url, headers=headers, params=payload)
+ r = req.prepare()
+ print(" Calling SourceForge Release API:", r.url)
+ else:
+ req = requests.put(url, headers=headers, params=payload)
+
+ # Print results
+ if req.status_code == requests.codes.ok:
+ result = json.loads(req.text)['result']
+ print(" Download default for:", result['x_sf']['default'])
+ else:
+ if req.status_code == requests.codes.unauthorized:
+ err = "access denied"
+ else:
+ err = "SourceForge API call failed"
+ print("ERROR: {} - check API key".format(err))
+ break
def main():
+ # Start upload process
+ print("ADOdb release upload script")
+
+ load_env()
process_command_line()
- # Start upload process
- print "ADOdb release upload script"
+ global skip_upload
+ if skip_upload:
+ print("Skipping upload of release files")
+ else:
+ upload_release_files()
+
+ set_sourceforge_file_info()
- upload_release_files()
+# end main()
-#end main()
if __name__ == "__main__":
main()
diff --git a/adodb/server.php b/adodb/server.php
index 396295b..76e757f 100644
--- a/adodb/server.php
+++ b/adodb/server.php
@@ -1,15 +1,31 @@
Connect($host,$uid,$pwd,$database)) err($conn->ErrorNo(). $sep . $conn->ErrorMsg());
-$sql = undomq($_REQUEST['sql']);
+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'];
@@ -93,12 +92,12 @@ function undomq(&$m)
if (isset($_REQUEST['nrows'])) {
$nrows = $_REQUEST['nrows'];
$offset = isset($_REQUEST['offset']) ? $_REQUEST['offset'] : -1;
- $rs = $conn->SelectLimit($sql,$nrows,$offset);
+ $rs = $conn->selectLimit($sql,$nrows,$offset);
} else
- $rs = $conn->Execute($sql);
+ $rs = $conn->execute($sql);
if ($rs){
//$rs->timeToLive = 1;
echo _rs2serialize($rs,$conn,$sql);
- $rs->Close();
+ $rs->close();
} else
- err($conn->ErrorNo(). $sep .$conn->ErrorMsg());
+ err($conn->errorNo(). $sep .$conn->errorMsg());
diff --git a/adodb/session/adodb-compress-bzip2.php b/adodb/session/adodb-compress-bzip2.php
index a2fa19b..17ad99f 100644
--- a/adodb/session/adodb-compress-bzip2.php
+++ b/adodb/session/adodb-compress-bzip2.php
@@ -1,24 +1,32 @@
+ */
if (!function_exists('bzcompress')) {
trigger_error('bzip2 functions are not available', E_USER_ERROR);
return 0;
}
-/*
-*/
+/**
+ */
class ADODB_Compress_Bzip2 {
/**
*/
@@ -41,8 +49,8 @@ function getBlockSize() {
/**
*/
function setBlockSize($block_size) {
- assert('$block_size >= 1');
- assert('$block_size <= 9');
+ assert($block_size >= 1);
+ assert($block_size <= 9);
$this->_block_size = (int) $block_size;
}
@@ -55,8 +63,8 @@ function getWorkLevel() {
/**
*/
function setWorkLevel($work_level) {
- assert('$work_level >= 0');
- assert('$work_level <= 250');
+ assert($work_level >= 0);
+ assert($work_level <= 250);
$this->_work_level = (int) $work_level;
}
@@ -69,7 +77,7 @@ function getMinLength() {
/**
*/
function setMinLength($min_length) {
- assert('$min_length >= 0');
+ assert($min_length >= 0);
$this->_min_length = (int) $min_length;
}
diff --git a/adodb/session/adodb-compress-gzip.php b/adodb/session/adodb-compress-gzip.php
index 604d12a..bbaf6c6 100644
--- a/adodb/session/adodb-compress-gzip.php
+++ b/adodb/session/adodb-compress-gzip.php
@@ -1,17 +1,23 @@
= 0');
- assert('$level <= 9');
+ assert($level >= 0);
+ assert($level <= 9);
$this->_level = (int) $level;
}
@@ -52,7 +58,7 @@ function getMinLength() {
/**
*/
function setMinLength($min_length) {
- assert('$min_length >= 0');
+ assert($min_length >= 0);
$this->_min_length = (int) $min_length;
}
diff --git a/adodb/session/adodb-cryptsession.php b/adodb/session/adodb-cryptsession.php
index 6add3c4..0880532 100644
--- a/adodb/session/adodb-cryptsession.php
+++ b/adodb/session/adodb-cryptsession.php
@@ -1,22 +1,25 @@
+ */
if (!defined('ADODB_SESSION')) {
require_once dirname(__FILE__) . '/adodb-session2.php';
diff --git a/adodb/session/adodb-session.php b/adodb/session/adodb-session.php
index 9ccc295..9e71623 100644
--- a/adodb/session/adodb-session.php
+++ b/adodb/session/adodb-session.php
@@ -1,16 +1,24 @@
+ */
/*
You may want to rename the 'data' field to 'session_data' as
@@ -70,7 +78,7 @@ function adodb_session_regenerate_id()
} else {
session_id(md5(uniqid(rand(), true)));
$ck = session_get_cookie_params();
- setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']);
+ setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure'], $ck['httponly']);
//@session_start();
}
$new_id = session_id();
@@ -80,7 +88,7 @@ function adodb_session_regenerate_id()
if (!$ok) {
session_id($old_id);
if (empty($ck)) $ck = session_get_cookie_params();
- setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure']);
+ setcookie(session_name(), session_id(), false, $ck['path'], $ck['domain'], $ck['secure'], $ck['httponly']);
return false;
}
@@ -599,7 +607,7 @@ function read($key)
$sql = "SELECT $data FROM $table WHERE sesskey = $binary $qkey AND expiry >= " . time();
/* Lock code does not work as it needs to hold transaction within whole page, and we don't know if
- developer has commited elsewhere... :(
+ developer has committed elsewhere... :(
*/
#if (ADODB_Session::Lock())
# $rs = $conn->RowLock($table, "$binary sesskey = $qkey AND expiry >= " . time(), $data);
@@ -921,12 +929,12 @@ function gc($maxlifetime)
if (empty($ADODB_SESSION_READONLY))
register_shutdown_function('session_write_close');
-// for backwards compatability only
+// for backwards compatibility only
function adodb_sess_open($save_path, $session_name, $persist = true) {
return ADODB_Session::open($save_path, $session_name, $persist);
}
-// for backwards compatability only
+// for backwards compatibility only
function adodb_sess_gc($t)
{
return ADODB_Session::gc($t);
diff --git a/adodb/session/adodb-session2.php b/adodb/session/adodb-session2.php
index e346849..bf64b41 100644
--- a/adodb/session/adodb-session2.php
+++ b/adodb/session/adodb-session2.php
@@ -1,61 +1,23 @@
debug = true;
- ADOConnection::outp( " driver=$driver user=$user db=$database ");
- }
-
- if (empty($conn->_connectionID)) { // not dsn
+ if (strpos($driver, 'pdo_') === 0){
+ $conn = ADONewConnection('pdo');
+ $driver = str_replace('pdo_', '', $driver);
+ $dsn = $driver.':'.'hostname='.$host.';dbname='.$database.';';
if ($persist) {
switch($persist) {
default:
- case 'P': $ok = $conn->PConnect($host, $user, $password, $database); break;
- case 'C': $ok = $conn->Connect($host, $user, $password, $database); break;
- case 'N': $ok = $conn->NConnect($host, $user, $password, $database); break;
+ case 'P': $ok = $conn->PConnect($dsn,$user,$password); break;
+ case 'C': $ok = $conn->Connect($dsn,$user,$password); break;
+ case 'N': $ok = $conn->NConnect($dsn,$user,$password); break;
}
} else {
- $ok = $conn->Connect($host, $user, $password, $database);
+ $ok = $conn->Connect($dsn,$user,$password);
+ }
+ }else{
+ $conn = ADONewConnection($driver);
+ if ($debug) {
+ $conn->debug = true;
+ ADOConnection::outp( " driver=$driver user=$user db=$database ");
+ }
+
+ if (empty($conn->_connectionID)) { // not dsn
+ if ($persist) {
+ switch($persist) {
+ default:
+ case 'P': $ok = $conn->PConnect($host, $user, $password, $database); break;
+ case 'C': $ok = $conn->Connect($host, $user, $password, $database); break;
+ case 'N': $ok = $conn->NConnect($host, $user, $password, $database); break;
+ }
+ } else {
+ $ok = $conn->Connect($host, $user, $password, $database);
+ }
+ } else {
+ $ok = true; // $conn->_connectionID is set after call to ADONewConnection
}
- } else {
- $ok = true; // $conn->_connectionID is set after call to ADONewConnection
}
+
if ($ok) $GLOBALS['ADODB_SESS_CONN'] = $conn;
else
ADOConnection::outp('
Session: connection failed
', false);
@@ -628,7 +605,7 @@ static function read($key)
$sql = "SELECT $ADODB_SESSION_SELECT_FIELDS FROM $table WHERE sesskey = $binary ".$conn->Param(0)." AND expiry >= " . $conn->sysTimeStamp;
/* Lock code does not work as it needs to hold transaction within whole page, and we don't know if
- developer has commited elsewhere... :(
+ developer has committed elsewhere... :(
*/
#if (ADODB_Session::Lock())
# $rs = $conn->RowLock($table, "$binary sesskey = $qkey AND expiry >= " . time(), sessdata);
@@ -806,7 +783,7 @@ static function destroy($key) {
//assert('$table');
$qkey = $conn->quote($key);
- $binary = $conn->dataProvider === 'mysql' ? '/*! BINARY */' : '';
+ $binary = $conn->dataProvider === 'mysql' || $conn->dataProvider === 'pdo' ? '/*! BINARY */' : '';
if ($expire_notify) {
reset($expire_notify);
@@ -926,12 +903,12 @@ static function gc($maxlifetime)
if (empty($ADODB_SESSION_READONLY))
register_shutdown_function('session_write_close');
-// for backwards compatability only
+// for backwards compatibility only
function adodb_sess_open($save_path, $session_name, $persist = true) {
return ADODB_Session::open($save_path, $session_name, $persist);
}
-// for backwards compatability only
+// for backwards compatibility only
function adodb_sess_gc($t)
{
return ADODB_Session::gc($t);
diff --git a/adodb/session/crypt.inc.php b/adodb/session/crypt.inc.php
index 94aa283..82121e3 100644
--- a/adodb/session/crypt.inc.php
+++ b/adodb/session/crypt.inc.php
@@ -1,5 +1,25 @@
+/**
+ * ADOdb Session Management
+ *
+ * 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
+ * @author Ari Kuorikoski
+ */
+
class MD5Crypt{
function keyED($txt,$encrypt_key)
{
diff --git a/adodb/session/old/adodb-cryptsession.php b/adodb/session/old/adodb-cryptsession.php
index 4dad676..6616de3 100644
--- a/adodb/session/old/adodb-cryptsession.php
+++ b/adodb/session/old/adodb-cryptsession.php
@@ -1,22 +1,29 @@
-
- Set tabs to 4 for best viewing.
-
- Latest version is available at http://adodb.org/
- ======================================================================
-
- This file provides PHP4 session management using the ADODB database
-wrapper library.
-
Example
=======
@@ -197,7 +204,7 @@ function adodb_sess_write($key, $val)
ADOConnection::outp( '
-- Session Replace: '.$ADODB_SESS_CONN->ErrorMsg().'',false);
} else {
- // bug in access driver (could be odbc?) means that info is not commited
+ // bug in access driver (could be odbc?) means that info is not committed
// properly unless select statement executed in Win2000
if ($ADODB_SESS_CONN->databaseType == 'access') $rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'");
diff --git a/adodb/session/old/adodb-session-clob.php b/adodb/session/old/adodb-session-clob.php
index f1cfce5..864fdfd 100644
--- a/adodb/session/old/adodb-session-clob.php
+++ b/adodb/session/old/adodb-session-clob.php
@@ -1,19 +1,29 @@
',false);
} else {
- // bug in access driver (could be odbc?) means that info is not commited
+ // bug in access driver (could be odbc?) means that info is not committed
// properly unless select statement executed in Win2000
if ($ADODB_SESS_CONN->databaseType == 'access')
$rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'");
diff --git a/adodb/session/old/adodb-session.php b/adodb/session/old/adodb-session.php
index 0a3f575..5fd43ab 100644
--- a/adodb/session/old/adodb-session.php
+++ b/adodb/session/old/adodb-session.php
@@ -1,19 +1,30 @@
ErrorMsg().'',false);
} else {
- // bug in access driver (could be odbc?) means that info is not commited
+ // bug in access driver (could be odbc?) means that info is not committed
// properly unless select statement executed in Win2000
if ($ADODB_SESS_CONN->databaseType == 'access')
$rs = $ADODB_SESS_CONN->Execute("select sesskey from $ADODB_SESSION_TBL WHERE sesskey='$key'");
diff --git a/adodb/session/old/crypt.inc.php b/adodb/session/old/crypt.inc.php
index 1ce75fe..089e24a 100644
--- a/adodb/session/old/crypt.inc.php
+++ b/adodb/session/old/crypt.inc.php
@@ -1,5 +1,27 @@
+/**
+ * ADOdb Session Management
+ *
+ * @deprecated
+ *
+ * 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
+ * @author Ari Kuorikoski
+ */
+
class MD5Crypt{
function keyED($txt,$encrypt_key)
{
diff --git a/adodb/session/session_schema.xml b/adodb/session/session_schema.xml
index 27e47bf..c1f7531 100644
--- a/adodb/session/session_schema.xml
+++ b/adodb/session/session_schema.xml
@@ -1,7 +1,7 @@
- table for ADOdb session-management
+ table for ADOdb session-managementsession key
diff --git a/adodb/session/session_schema2.xml b/adodb/session/session_schema2.xml
index f0d3ec9..89cb4f2 100644
--- a/adodb/session/session_schema2.xml
+++ b/adodb/session/session_schema2.xml
@@ -1,7 +1,7 @@
- table for ADOdb session-management
+ table for ADOdb session-managementsession key
diff --git a/adodb/tests/LibTest.php b/adodb/tests/LibTest.php
new file mode 100644
index 0000000..2f02e00
--- /dev/null
+++ b/adodb/tests/LibTest.php
@@ -0,0 +1,72 @@
+db = ADONewConnection('mysqli');
+ }
+
+ /**
+ * Test for {@see _adodb_quote_fieldname()}
+ *
+ * @dataProvider quoteProvider
+ */
+ public function testQuoteFieldNames($method, $field, $expected)
+ {
+ global $ADODB_QUOTE_FIELDNAMES;
+ $ADODB_QUOTE_FIELDNAMES = $method;
+ $this->assertSame($expected, _adodb_quote_fieldname($this->db, $field));
+ }
+
+ /**
+ * Data provider for {@see testQuoteFieldNames()}
+ * @return array
+ */
+ public function quoteProvider()
+ {
+ return [
+ 'No quoting, single-word field name' => [false, 'Field', 'FIELD'],
+ 'No quoting, field name with space' => [false, 'Field Name', '`FIELD NAME`'],
+ 'Quoting `true`' => [true, 'Field', '`FIELD`'],
+ 'Quoting `UPPER`' => ['UPPER', 'Field', '`FIELD`'],
+ 'Quoting `LOWER`' => ['LOWER', 'Field', '`field`'],
+ 'Quoting `NATIVE`' => ['NATIVE', 'Field', '`Field`'],
+ 'Quoting `BRACKETS`' => ['BRACKETS', 'Field', '[FIELD]'],
+ 'Unknown value defaults to UPPER' => ['XXX', 'Field', '`FIELD`'],
+ ];
+ }
+
+}
diff --git a/adodb/tests/benchmark.php b/adodb/tests/benchmark.php
new file mode 100644
index 0000000..5799031
--- /dev/null
+++ b/adodb/tests/benchmark.php
@@ -0,0 +1,95 @@
+
+
+ ADODB Benchmarks
+
+
+
+ADODB Version: $ADODB_version Host: $db->host Database: $db->database";
+
+ // perform query once to cache results so we are only testing throughput
+ $rs = $db->Execute($sql);
+ if (!$rs){
+ print "Error in recordset
Date m/d/Y =",$db->UserDate($rs->fields[4],'m/d/Y');
+ }
diff --git a/adodb/tests/test3.php b/adodb/tests/test3.php
new file mode 100644
index 0000000..38c5285
--- /dev/null
+++ b/adodb/tests/test3.php
@@ -0,0 +1,53 @@
+Connect('','scott','natsoft');
+$db->debug=1;
+
+$cnt = $db->GetOne("select count(*) from adoxyz");
+$rs = $db->Execute("select * from adoxyz order by id");
+
+$i = 0;
+foreach($rs as $k => $v) {
+ $i += 1;
+ echo $k; adodb_pr($v);
+ flush();
+}
+
+if ($i != $cnt) die("actual cnt is $i, cnt should be $cnt\n");
+
+
+
+$rs = $db->Execute("select bad from badder");
+
+} catch (exception $e) {
+ adodb_pr($e);
+ $e = adodb_backtrace($e->trace);
+}
diff --git a/adodb/tests/test4.php b/adodb/tests/test4.php
new file mode 100644
index 0000000..cdaf527
--- /dev/null
+++ b/adodb/tests/test4.php
@@ -0,0 +1,147 @@
+PConnect("", "sa", "natsoft", "northwind"); // connect to MySQL, testdb
+
+$conn = ADONewConnection("mysql"); // create a connection
+$conn->PConnect("localhost", "root", "", "test"); // connect to MySQL, testdb
+
+
+#$conn = ADONewConnection('oci8po');
+#$conn->Connect('','scott','natsoft');
+
+$connstr = "mysql:dbname=northwind";
+$u = 'root';$p='';
+$conn = ADONewConnection('pdo');
+$conn->Connect($connstr, $u, $p);
+
+//$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+
+
+$conn->debug=1;
+$conn->Execute("delete from adoxyz where lastname like 'Smi%'");
+
+$rs = $conn->Execute($sql); // Execute the query and get the empty recordset
+$record = array(); // Initialize an array to hold the record data to insert
+
+if (strpos($conn->databaseType,'mysql')===false) $record['id'] = 751;
+$record["firstname"] = 'Jann';
+$record["lastname"] = "Smitts";
+$record["created"] = time();
+
+$insertSQL = $conn->GetInsertSQL($rs, $record);
+$conn->Execute($insertSQL); // Insert the record into the database
+
+if (strpos($conn->databaseType,'mysql')===false) $record['id'] = 752;
+// Set the values for the fields in the record
+$record["firstname"] = 'anull';
+$record["lastname"] = "Smith\$@//";
+$record["created"] = time();
+
+if (isset($_GET['f'])) $ADODB_FORCE_TYPE = $_GET['f'];
+
+//$record["id"] = -1;
+
+// Pass the empty recordset and the array containing the data to insert
+// into the GetInsertSQL function. The function will process the data and return
+// a fully formatted insert sql statement.
+$insertSQL = $conn->GetInsertSQL($rs, $record);
+$conn->Execute($insertSQL); // Insert the record into the database
+
+
+
+$insertSQL2 = $conn->GetInsertSQL($table='ADOXYZ', $record);
+if ($insertSQL != $insertSQL2) echo "
Walt's new stuff failed: $insertSQL2
";
+//==========================
+// This code tests an update
+
+$sql = "
+SELECT *
+FROM ADOXYZ WHERE lastname=".$conn->Param('var'). " ORDER BY 1";
+// Select a record to update
+
+$varr = array('var'=>$record['lastname'].'');
+$rs = $conn->Execute($sql,$varr); // Execute the query and get the existing record to update
+if (!$rs || $rs->EOF) print "
No record found!
";
+
+$record = array(); // Initialize an array to hold the record data to update
+
+
+// Set the values for the fields in the record
+$record["firstName"] = "Caroline".rand();
+//$record["lasTname"] = ""; // Update Caroline's lastname from Miranda to Smith
+$record["creAted"] = '2002-12-'.(rand()%30+1);
+$record['num'] = '';
+// Pass the single record recordset and the array containing the data to update
+// into the GetUpdateSQL function. The function will process the data and return
+// a fully formatted update sql statement.
+// If the data has not changed, no recordset is returned
+
+$updateSQL = $conn->GetUpdateSQL($rs, $record);
+$conn->Execute($updateSQL,$varr); // Update the record in the database
+if ($conn->Affected_Rows() != 1)print "
Error1 : Rows Affected=".$conn->Affected_Rows().", should be 1
";
+
+$record["firstName"] = "Caroline".rand();
+$record["lasTname"] = "Smithy Jones"; // Update Caroline's lastname from Miranda to Smith
+$record["creAted"] = '2002-12-'.(rand()%30+1);
+$record['num'] = 331;
+$updateSQL = $conn->GetUpdateSQL($rs, $record);
+$conn->Execute($updateSQL,$varr); // Update the record in the database
+if ($conn->Affected_Rows() != 1)print "
Error 2: Rows Affected=".$conn->Affected_Rows().", should be 1
";
+
+$rs = $conn->Execute("select * from ADOXYZ where lastname like 'Sm%'");
+//adodb_pr($rs);
+rs2html($rs);
+
+$record["firstName"] = "Carol-new-".rand();
+$record["lasTname"] = "Smithy"; // Update Caroline's lastname from Miranda to Smith
+$record["creAted"] = '2002-12-'.(rand()%30+1);
+$record['num'] = 331;
+
+$conn->AutoExecute('ADOXYZ',$record,'UPDATE', "lastname like 'Sm%'");
+$rs = $conn->Execute("select * from ADOXYZ where lastname like 'Sm%'");
+//adodb_pr($rs);
+rs2html($rs);
+}
+
+
+testsql();
diff --git a/adodb/tests/test5.php b/adodb/tests/test5.php
new file mode 100644
index 0000000..15327d1
--- /dev/null
+++ b/adodb/tests/test5.php
@@ -0,0 +1,53 @@
+debug=1;
+ $conn->PConnect("localhost","root","","xphplens");
+ print $conn->databaseType.':'.$conn->GenID().' ';
+}
+
+if (0) {
+ $conn = ADONewConnection("oci8"); // create a connection
+ $conn->debug=1;
+ $conn->PConnect("falcon", "scott", "tiger", "juris8.ecosystem.natsoft.com.my"); // connect to MySQL, testdb
+ print $conn->databaseType.':'.$conn->GenID();
+}
+
+if (0) {
+ $conn = ADONewConnection("ibase"); // create a connection
+ $conn->debug=1;
+ $conn->Connect("localhost:c:\\Interbase\\Examples\\Database\\employee.gdb", "sysdba", "masterkey", ""); // connect to MySQL, testdb
+ print $conn->databaseType.':'.$conn->GenID().' ';
+}
+
+if (0) {
+ $conn = ADONewConnection('postgres');
+ $conn->debug=1;
+ @$conn->PConnect("susetikus","tester","test","test");
+ print $conn->databaseType.':'.$conn->GenID().' ';
+}
diff --git a/adodb/tests/test_mssqlnative.php b/adodb/tests/test_mssqlnative.php
new file mode 100644
index 0000000..9a4221f
--- /dev/null
+++ b/adodb/tests/test_mssqlnative.php
@@ -0,0 +1,150 @@
+\n".$Msg;
+}
+function DieTrace($Msg){
+ die(" \n".$Msg);
+}
+
+
+define('ADODB_ASSOC_CASE',0);
+$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+$db = ADONewConnection("mssqlnative"); // create a connection
+$db->Connect('127.0.0.1','adodb','natsoft','northwind') or die('Fail');
+
+//==========================
+// This code tests GenId
+//==========================
+function TestGenID() {
+ global $db;
+ $PrevDebug=$db->debug; $db->debug=false; // Hide debug if present as Drop can cause errors
+ $db->Execute("drop sequence MySequence1;
+drop sequence MySequence2;
+drop sequence MySequence3;
+drop table MySequence1Emul;
+drop table MySequence2Emul;
+drop table MySequence3Emul;
+");
+ $db->debug=$PrevDebug; // Restore debug Initial State
+
+ $ID1a=$db->GenID("MySequence1");
+ $ID2a=$db->GenID("MySequence2");
+ $ID1b=$db->GenID("MySequence1");
+ $ID2b=$db->GenID("MySequence2");
+ Trace("ID1a=$ID1a,ID1b=$ID1b, ID2a=$ID2a,ID2b=$ID2b");
+ if(intval($ID1a)+1!==intval($ID1b)) DieTrace(sprintf("ERROR : Second value obtains by MySequence1 should be %d but is %d",$ID1a+1,$ID1b));
+
+ $db->CreateSequence("MySequence3",100);
+ $ID2b=$db->GenID("MySequence3");
+ if(intval($ID2b)!==100) DieTrace(sprintf("ERROR : Value from MySequence3 should be 100 but is %d",$ID2b));
+
+ $db->mssql_version=10; // Force to simulate Pre 2012 (without sequence) behavior
+ $ID1a=$db->GenID("MySequence1Emul");
+ $ID2a=$db->GenID("MySequence2Emul");
+ $ID1b=$db->GenID("MySequence1Emul");
+ $ID2b=$db->GenID("MySequence2Emul");
+ echo "ID1a=$ID1a,ID1b=$ID1b, ID2a=$ID2a,ID2b=$ID2b \n";
+ if(intval($ID1a+1)!==intval($ID1b)) DieTrace(sprintf("ERROR : Second value obtains by MySequence1Emul should be %d but is %d",$ID1a+1,$ID1b));
+
+ $db->CreateSequence("MySequence3Emul",100);
+ $ID2b=$db->GenID("MySequence3Emul");
+ if(intval($ID2b)!==100) DieTrace(sprintf("ERROR : Value from MySequence3Emul should be 100 but is %d",$ID2b));
+ } //TestGenID()
+
+//==========================
+// This code tests SQLDate
+//==========================
+function TestSQLDate()
+{
+ global $db;
+ $res = $db->GetRow("select testdate,"
+ . $db->SQLDate("d/m/Y", "testdate") . " FR4,"
+ . $db->SQLDate("d/m/y", "testdate") . " FR4b,"
+ . $db->SQLDate("d/m/Y", "NULL") . " nullFR4,"
+ . $db->SQLDate("m/d/Y", "testdate") . " US4,"
+ . $db->SQLDate("m/d/y", "testdate") . " US4b,"
+ . $db->SQLDate("m-d-Y", "testdate") . " USD4,"
+ . $db->SQLDate("m-d-y", "testdate") . " USD4b,"
+ . $db->SQLDate("Y.m.d", "testdate") . " ANSI4,"
+ . $db->SQLDate("d.m.Y", "testdate") . " GE4,"
+ . $db->SQLDate("d.m.y", "testdate") . " GE4b,"
+ . $db->SQLDate("d-m-Y", "testdate") . " IT4,"
+ . $db->SQLDate("d-m-y", "testdate") . " IT4b,"
+ . $db->SQLDate("Y/m/d", "testdate") . " Japan4,"
+ . $db->SQLDate("y/m/d", "testdate") . " Japan4b,"
+ . $db->SQLDate("H:i:s", "testdate") . " timeonly,"
+ . $db->SQLDate("d m Y", "testdate") . " Space4," // Is done by former method
+ . $db->SQLDate("d m Y", "NULL") . " nullSpace4,"
+ . $db->SQLDate("m-d-Y", "testdatesmall") . " nowUSdash4,"
+ . "null from (select convert(datetime,'2016-12-17 18:55:30.590' ,121) testdate,
+ convert(datetime,'2016-01-01 18:55:30.590' ,121) testdatesmall,null nulldate) q "
+ );
+ $TestRes=array(
+ "fr4"=>"17/12/2016",
+ "fr4b"=>"17/12/2016",
+ "nullfr4"=>null,
+ "us4"=>"12/17/2016",
+ "us4b"=>"12/17/2016",
+ "ansi4"=>"2016.12.17",
+ "ge4"=>"17.12.2016",
+ "ge4b"=>"17.12.2016",
+ "it4"=>"17-12-2016",
+ "it4b"=>"17-12-2016",
+ "japan4"=>"2016/12/17",
+ "japan4b"=>"2016/12/17",
+ "space4"=>"17 12 2016",
+ "nullspace4"=>null,
+ "timeonly"=>"18:55:30",
+ );
+ var_dump($res);
+ foreach($TestRes as $k=>$v)
+ if($v!==$res[$k])
+ DieTrace(sprintf("ERROR : Expected for '%s' is '%s', but got '%s'",$k,$v,$res[$k]));
+} //TestSQLDate()
+
+//==========================
+// This code is the tests RUNNER
+//==========================
+$db->debug=true;
+// $ToTest Contains * or the name of the test function to RUN
+$ToTest="*";
+//$ToTest="TestSQLDate";
+
+// Here the generic test runner, will launch all functions of the current file beginning by "test", should not be changed use $ToTest
+$functions = get_defined_functions();
+$functions = $functions['user'];
+foreach( $functions as $f) {
+ $refFunc = new ReflectionFunction($f);
+ if(($refFunc->getFileName()==__FILE__)&&(substr($f,0,4)=='test'))
+ if(($ToTest=='*')||(strtolower($ToTest)==$f))
+ {
+ Trace("-------- Launch Test : $f ------------------");
+ $f();
+ }
+}
+
+Trace("=========== End of tests Without Error. ===================");
\ No newline at end of file
diff --git a/adodb/tests/test_rs_array.php b/adodb/tests/test_rs_array.php
new file mode 100644
index 0000000..75848c0
--- /dev/null
+++ b/adodb/tests/test_rs_array.php
@@ -0,0 +1,65 @@
+InitArray($array,$typearr);
+
+while (!$rs->EOF) {
+ print_r($rs->fields);echo " ";
+ $rs->MoveNext();
+}
+
+echo " 1 Seek ";
+$rs->Move(1);
+while (!$rs->EOF) {
+ print_r($rs->fields);echo " ";
+ $rs->MoveNext();
+}
+
+echo " 2 Seek ";
+$rs->Move(2);
+while (!$rs->EOF) {
+ print_r($rs->fields);echo " ";
+ $rs->MoveNext();
+}
+
+echo " 3 Seek ";
+$rs->Move(3);
+while (!$rs->EOF) {
+ print_r($rs->fields);echo " ";
+ $rs->MoveNext();
+}
+
+
+
+die();
diff --git a/adodb/tests/testcache.php b/adodb/tests/testcache.php
new file mode 100644
index 0000000..bf8676b
--- /dev/null
+++ b/adodb/tests/testcache.php
@@ -0,0 +1,38 @@
+
+
+PConnect('nwind');
+} else {
+ $db = ADONewConnection('mysql');
+ $db->PConnect('mangrove','root','','xphplens');
+}
+if (isset($cache)) $rs = $db->CacheExecute(120,'select * from products');
+else $rs = $db->Execute('select * from products');
+
+$arr = $rs->GetArray();
+print sizeof($arr);
diff --git a/adodb/tests/testdatabases.inc.php b/adodb/tests/testdatabases.inc.php
new file mode 100644
index 0000000..8c6358a
--- /dev/null
+++ b/adodb/tests/testdatabases.inc.php
@@ -0,0 +1,475 @@
+
+
+
+
+> Access
+> Interbase
+> MSSQL
+> MySQL
+> MySQL ODBC
+> MySQLi
+
+
+
+ SQL to be executed only on specific platforms
+
+ insert into mytable ( row1, row2 ) values ( 12, 'postgres stuff' )
+
+
+ insert into mytable ( row1, row2 ) values ( 12, 'mysql stuff' )
+
+
+ INSERT into simple_table ( name, description ) values ( '12', 'Microsoft stuff' )
+
+
+
\ No newline at end of file
diff --git a/adodb/tests/xmlschema.xml b/adodb/tests/xmlschema.xml
new file mode 100644
index 0000000..ea48ae2
--- /dev/null
+++ b/adodb/tests/xmlschema.xml
@@ -0,0 +1,33 @@
+
+
+
+
+ An integer row that's a primary key and autoincrements
+
+
+
+
+ A 16 character varchar row that can't be null
+
+
+
+
row1
+
row2
+
+
+
+ SQL to be executed only on specific platforms
+
+ insert into mytable ( row1, row2 ) values ( 12, 'postgres stuff' )
+
+
+ insert into mytable ( row1, row2 ) values ( 12, 'mysql stuff' )
+
+
+ insert into mytable ( row1, row2 ) values ( 12, 'Microsoft stuff' )
+
+
+
+
+
+
\ No newline at end of file
diff --git a/adodb/toexport.inc.php b/adodb/toexport.inc.php
index 5ede9ce..66bbf54 100644
--- a/adodb/toexport.inc.php
+++ b/adodb/toexport.inc.php
@@ -1,14 +1,6 @@
-*/
+/**
+ * RecordSet to HTML Table
+ *
+ * Convert a recordset to a html table. Multiple tables are generated
+ * if the number of rows is > $gSQLBlockRows. This is because
+ * web browsers normally require the whole table to be downloaded
+ * before it can be rendered, so we break the output into several
+ * smaller, faster rendering tables.
+ *
+ * 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
+ */
// specific code for tohtml
GLOBAL $gSQLMaxRows,$gSQLBlockRows,$ADODB_ROUND;
@@ -17,14 +32,6 @@
$gSQLMaxRows = 1000; // max no of rows to download
$gSQLBlockRows=20; // max no of rows per table block
-// RecordSet to HTML Table
-//------------------------------------------------------------
-// Convert a recordset to a html table. Multiple tables are generated
-// if the number of rows is > $gSQLBlockRows. This is because
-// web browsers normally require the whole table to be downloaded
-// before it can be rendered, so we break the output into several
-// smaller faster rendering tables.
-//
// $rs: the recordset
// $ztabhtml: the table tag attributes (optional)
// $zheaderarray: contains the replacement strings for the headers (optional)
diff --git a/adodb/xmlschema03.dtd b/adodb/xmlschema03.dtd
index 97850bc..351ea44 100644
--- a/adodb/xmlschema03.dtd
+++ b/adodb/xmlschema03.dtd
@@ -1,17 +1,22 @@
-
-
-
+
-
+
-
+
-
+
@@ -24,20 +29,25 @@
-
+
-
+
-
-
+
+
-
-
+
+
-]>
\ No newline at end of file
From 6fd5ed4a720650ecd81154f8ca011dafdcd1517f Mon Sep 17 00:00:00 2001
From: Ruben Barkow-Kuder
Date: Fri, 9 Sep 2022 16:14:58 +0200
Subject: [PATCH 6/6] fix CVE-2020-13565: sanitize URL more cleanly
---
admin/gacl_admin_api.class.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/admin/gacl_admin_api.class.php b/admin/gacl_admin_api.class.php
index 83e8469..5c27f94 100644
--- a/admin/gacl_admin_api.class.php
+++ b/admin/gacl_admin_api.class.php
@@ -82,7 +82,7 @@ function return_page($url="") {
if (!$debug OR $debug==0) {
# fix CVE-2020-13565: sanitize URL
- $url=str_replace('://','',$url);
+ $url=preg_replace('/^([a-z0-9\s%;\+]+:\/\/+)+/i','',$url);
header("Location: $url\n\n");
} else {
$this->debug_text("return_page(): URL: $url -- Referer: $_SERVER[HTTP_REFERRER]");