diff --git a/lib/adodb/LICENSE.md b/lib/adodb/LICENSE.md
index 26956d30392..d00e2b1f2d6 100644
--- a/lib/adodb/LICENSE.md
+++ b/lib/adodb/LICENSE.md
@@ -10,7 +10,7 @@ In plain English, you do not need to distribute your application in source code
nor do you need to distribute ADOdb source code, provided you follow the rest of
terms of the BSD license.
-For more information about ADOdb, visit http://adodb.org/
+For more information about ADOdb, visit https://adodb.org/
BSD 3-Clause License
--------------------
diff --git a/lib/adodb/README.md b/lib/adodb/README.md
index 273c24ce3e5..e432b2fb0af 100644
--- a/lib/adodb/README.md
+++ b/lib/adodb/README.md
@@ -1,4 +1,4 @@
-ADOdb Library for PHP5
+ADOdb Library for PHP
======================
[](https://gitter.im/adodb/adodb?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -16,7 +16,7 @@ or, at your option, any later version.
This means you can use it in proprietary products;
see [License](https://github.com/ADOdb/ADOdb/blob/master/LICENSE.md) for details.
-Home page: http://adodb.org/
+Home page: https://adodb.org/
Introduction
@@ -27,8 +27,8 @@ need for a database class library to hide the differences between the
different databases (encapsulate the differences) so we can easily
switch databases.
-The library currently supports MySQL, Interbase, Sybase, PostgreSQL, Oracle,
-Microsoft SQL server, Foxpro ODBC, Access ODBC, Informix, DB2,
+The library currently supports MySQL, Firebird & Interbase, PostgreSQL, SQLite3, Oracle,
+Microsoft SQL Server, Foxpro ODBC, Access ODBC, Informix, DB2, Sybase,
Sybase SQL Anywhere, generic ODBC and Microsoft's ADO.
We hope more people will contribute drivers to support other databases.
@@ -48,12 +48,12 @@ You can debug using:
debug = true;
-$db->Connect($server, $user, $password, $database);
-$rs = $db->Execute('select * from some_small_table');
+$db->connect($server, $user, $password, $database);
+$rs = $db->execute('select * from some_small_table');
print "
';
- $first = true;
- foreach($fieldArray as $k => $v) {
- if ($has_autoinc && in_array($k,$keyCol)) continue; // skip autoinc col
-
- if ($first) {
- $first = false;
- $iCols = "$k";
- $iVals = "$v";
+ // 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 {
- $iCols .= ",$k";
- $iVals .= ",$v";
+ if (($zthis->Affected_Rows()>0)) return 1;
}
- }
- $insert = "INSERT INTO $table ($iCols) VALUES ($iVals)";
- $rs = $zthis->Execute($insert);
- return ($rs) ? 2 : 0;
+ } else
+ return 0;
+ }
+
+ $iCols = $iVals = '';
+ 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, ',');
+
+ $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,
@@ -441,7 +428,7 @@ function _adodb_getcount(&$zthis, $sql,$inputarr=false,$secs2cache=0)
}
// 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 http://phplens.com/lens/lensforum/msgs.php?id=12752
+ // also see PHPLens Issue No: 12752
$rewritesql = adodb_strip_order_by($rewritesql);
}
@@ -476,18 +463,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,58 +630,59 @@ 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)
+function _adodb_getupdatesql(&$zthis, &$rs, $arrFields, $forceUpdate=false, $force=2)
{
global $ADODB_QUOTE_FIELDNAMES;
- if (!$rs) {
- printf(ADODB_BAD_RS,'GetUpdateSQL');
- return false;
- }
+ if (!$rs) {
+ printf(ADODB_BAD_RS,'GetUpdateSQL');
+ return false;
+ }
- $fieldUpdatedCount = 0;
- $arrFields = _array_change_key_case($arrFields);
+ $fieldUpdatedCount = 0;
+ if (is_array($arrFields))
+ $arrFields = array_change_key_case($arrFields,CASE_UPPER);
- $hasnumeric = isset($rs->fields[0]);
- $setFields = '';
+ $hasnumeric = isset($rs->fields[0]);
+ $setFields = '';
- // Loop through all of the fields in the recordset
- for ($i=0, $max=$rs->FieldCount(); $i < $max; $i++) {
- // Get the field from the recordset
- $field = $rs->FetchField($i);
+ // Loop through all of the fields in the recordset
+ for ($i=0, $max=$rs->fieldCount(); $i < $max; $i++) {
+ // Get the field from the recordset
+ $field = $rs->fetchField($i);
- // If the recordset field is one
- // of the fields passed in then process.
- $upperfname = strtoupper($field->name);
- if (adodb_key_exists($upperfname,$arrFields,$force)) {
+ // 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 the existing field value in the recordset
+ // is different from the value passed in then
+ // go ahead and append the field name and new value to
+ // the update query.
- if ($hasnumeric) $val = $rs->fields[$i];
- else if (isset($rs->fields[$upperfname])) $val = $rs->fields[$upperfname];
- else if (isset($rs->fields[$field->name])) $val = $rs->fields[$field->name];
- else if (isset($rs->fields[strtolower($upperfname)])) $val = $rs->fields[strtolower($upperfname)];
- else $val = '';
+ if ($hasnumeric) $val = $rs->fields[$i];
+ else if (isset($rs->fields[$upperfname])) $val = $rs->fields[$upperfname];
+ else if (isset($rs->fields[$field->name])) $val = $rs->fields[$field->name];
+ else if (isset($rs->fields[strtolower($upperfname)])) $val = $rs->fields[strtolower($upperfname)];
+ else $val = '';
+ if ($forceUpdate || strcmp($val, $arrFields[$upperfname])) {
+ // Set the counter for the number of fields that will be updated.
+ $fieldUpdatedCount++;
- 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);
- // 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) {
+ if ((strpos($upperfname,' ') !== false) || ($ADODB_QUOTE_FIELDNAMES)) {
+ switch ($ADODB_QUOTE_FIELDNAMES) {
+ case 'BRACKETS':
+ $fnameq = $zthis->leftBracket.$upperfname.$zthis->rightBracket;break;
case 'LOWER':
$fnameq = $zthis->nameQuote.strtolower($field->name).$zthis->nameQuote;break;
case 'NATIVE':
@@ -709,89 +690,107 @@ function _adodb_getupdatesql(&$zthis,&$rs, $arrFields,$forceUpdate=false,$magicq
case 'UPPER':
default:
$fnameq = $zthis->nameQuote.$upperfname.$zthis->nameQuote;break;
- }
- } else
- $fnameq = $upperfname;
-
- //********************************************************//
- if (is_null($arrFields[$upperfname])
- || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
- || $arrFields[$upperfname] === $zthis->null2null
- )
- {
- switch ($force) {
-
- //case 0:
- // //Ignore empty values. This is allready handled in "adodb_key_exists" function.
- //break;
-
- case 1:
- //Set null
- $setFields .= $field->name . " = null, ";
- 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);
}
+ } else {
+ $fnameq = $upperfname;
+ }
+
+ //********************************************************//
+ if (is_null($arrFields[$upperfname])
+ || (empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0)
+ || $arrFields[$upperfname] === $zthis->null2null
+ ) {
+
+ switch ($force) {
+
+ //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;
+
+ 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 .= $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 ($discard)
- $whereClause[1] = substr($whereClause[1], 0, strlen($whereClause[1]) - strlen($discard[1]));
-
- $sql = 'UPDATE '.$tableName.' SET '.substr($setFields, 0, -2);
- if (strlen($whereClause[1]) > 0)
- $sql .= ' WHERE '.$whereClause[1];
-
- return $sql;
-
+ // 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 {
- return false;
+ 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 ($discard) {
+ $whereClause[1] = substr($whereClause[1], 0, strlen($whereClause[1]) - strlen($discard[1]));
+ }
+
+ $sql = 'UPDATE '.$tableName.' SET '.substr($setFields, 0, -2);
+ if (strlen($whereClause[1]) > 0) {
+ $sql .= ' WHERE '.$whereClause[1];
+ }
+ return $sql;
+ } else {
+ return false;
}
}
@@ -802,10 +801,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,7 +814,7 @@ 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;
@@ -826,7 +825,8 @@ static $cacheCols;
$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)) {
@@ -872,6 +872,8 @@ static $cacheCols;
$bad = false;
if ((strpos($upperfname,' ') !== false) || ($ADODB_QUOTE_FIELDNAMES)) {
switch ($ADODB_QUOTE_FIELDNAMES) {
+ case 'BRACKETS':
+ $fnameq = $zthis->leftBracket.$upperfname.$zthis->rightBracket;break;
case 'LOWER':
$fnameq = $zthis->nameQuote.strtolower($field->name).$zthis->nameQuote;break;
case 'NATIVE':
@@ -893,29 +895,44 @@ static $cacheCols;
{
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 +941,7 @@ static $cacheCols;
//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 +992,7 @@ static $cacheCols;
* @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 +1024,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 +1047,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 +1068,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 +1077,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 +1107,7 @@ function _adodb_column_sql(&$zthis, $action, $type, $fname, $fnameq, $arrFields,
if ($action == 'I') return $val . ", ";
-
return $fnameq . "=" . $val . ", ";
-
}
diff --git a/lib/adodb/adodb-loadbalancer.inc.php b/lib/adodb/adodb-loadbalancer.inc.php
new file mode 100644
index 00000000000..c0e3de00b1d
--- /dev/null
+++ b/lib/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/lib/adodb/adodb-memcache.lib.inc.php b/lib/adodb/adodb-memcache.lib.inc.php
index 394ce08983e..f143e8cb47b 100644
--- a/lib/adodb/adodb-memcache.lib.inc.php
+++ b/lib/adodb/adodb-memcache.lib.inc.php
@@ -11,7 +11,7 @@ if (empty($ADODB_INCLUDED_CSV)) include_once(ADODB_DIR.'/adodb-csvlib.inc.php');
/*
- @version v5.20.16 12-Jan-2020
+ @version v5.21.0 2021-02-27
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
@@ -19,7 +19,7 @@ if (empty($ADODB_INCLUDED_CSV)) include_once(ADODB_DIR.'/adodb-csvlib.inc.php');
the BSD license will take precedence. See License.txt.
Set tabs to 4 for best viewing.
- Latest version is available at http://adodb.org/
+ Latest version is available at https://adodb.org/
Usage:
@@ -28,11 +28,14 @@ $db->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)
+ /// Note; compression is not supported w/the memcached library
$db->Connect(...);
$db->CacheExecute($sql);
- Note the memcache class is shared by all connections, is created during the first call to Connect/PConnect.
+ Notes; The memcache class is shared by all connections, is created during the first call to Connect/PConnect.
+ We'll look for both the memcache library (https://pecl.php.net/package/memcache) and the memcached
+ library (https://pecl.php.net/package/memcached). If both exist, the memcache library will be used.
Class instance is stored in $ADODB_CACHE
*/
@@ -40,6 +43,11 @@ $db->CacheExecute($sql);
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 +68,23 @@ $db->CacheExecute($sql);
// 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 +106,25 @@ $db->CacheExecute($sql);
}
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 +140,7 @@ $db->CacheExecute($sql);
$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 +206,8 @@ $db->CacheExecute($sql);
$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/lib/adodb/adodb-pager.inc.php b/lib/adodb/adodb-pager.inc.php
index 5d0ca6d2829..ec6aba4649c 100644
--- a/lib/adodb/adodb-pager.inc.php
+++ b/lib/adodb/adodb-pager.inc.php
@@ -1,7 +1,7 @@
",
diff --git a/lib/adodb/adodb-pear.inc.php b/lib/adodb/adodb-pear.inc.php
index d1037c04a37..e0ee74bac96 100644
--- a/lib/adodb/adodb-pear.inc.php
+++ b/lib/adodb/adodb-pear.inc.php
@@ -1,6 +1,6 @@
database
if (!empty($dsn)) {
$parsed['database'] = $dsn;
diff --git a/lib/adodb/adodb-perf.inc.php b/lib/adodb/adodb-perf.inc.php
index 05a413bd74a..6bce7354d5b 100644
--- a/lib/adodb/adodb-perf.inc.php
+++ b/lib/adodb/adodb-perf.inc.php
@@ -1,6 +1,6 @@
_queryID);
}
$ok = $conn->Execute($isql,$arr);
+ if($conn instanceof ADODB_mysqli && $conn->_queryID){
+ mysqli_free_result($conn->_queryID);
+ }
} else
$ok = true;
@@ -229,7 +232,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 +266,6 @@ processes 69293
// 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 +590,7 @@ Committed_AS: 348732 kB
}
/*
- Raw function returning array of poll paramters
+ Raw function returning array of poll parameters
*/
function PollParameters()
{
@@ -694,12 +691,6 @@ Committed_AS: 348732 kB
}
$this->conn->LogSQL($savelog);
- // magic quotes
-
- if (isset($_GET['sql']) && 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'];
@@ -724,7 +715,7 @@ Committed_AS: 348732 kB
if (empty($_GET['hidem']))
echo "|
- ADOdb Performance Monitor for $app | |
+ ADOdb Performance Monitor for $app |
Performance Stats View SQL
View Tables Poll Stats",
$allowsql ? ' Run SQL' : '',
@@ -767,7 +758,6 @@ Committed_AS: 348732 kB
echo $this->Tables(); break;
}
global $ADODB_vers;
- echo "";
}
/*
@@ -956,7 +946,7 @@ Committed_AS: 348732 kB
undomq(trim($sql));
+ $sql = trim($sql);
if (substr($sql,strlen($sql)-1) === ';') {
$print = true;
$sqla = $this->SplitSQL($sql);
@@ -1000,18 +990,6 @@ Committed_AS: 348732 kB
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/lib/adodb/adodb-php4.inc.php b/lib/adodb/adodb-php4.inc.php
index 69f8149631f..eea5818b28f 100644
--- a/lib/adodb/adodb-php4.inc.php
+++ b/lib/adodb/adodb-php4.inc.php
@@ -1,7 +1,7 @@
= 5.2);
-
/*
This code was originally for windows. But apparently this problem happens
also with Linux, RH 7.3 and later!
@@ -532,8 +523,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);
@@ -737,13 +728,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)) {
@@ -1035,20 +1025,20 @@ global $_month_table_normal,$_month_table_leaf, $_adodb_last_date_call_failed;
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);
}
@@ -1081,10 +1071,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');
@@ -1093,7 +1081,15 @@ static $jan1_1971;
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);
@@ -1116,8 +1112,6 @@ static $jan1_1971;
$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
@@ -1128,12 +1122,9 @@ static $jan1_1971;
$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;
@@ -1152,14 +1143,16 @@ static $jan1_1971;
$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;
@@ -1167,6 +1160,9 @@ static $jan1_1971;
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;
@@ -1185,7 +1181,7 @@ static $jan1_1971;
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':
@@ -1389,7 +1385,7 @@ global $ADODB_DATE_LOCALE;
$sep = substr($tstr,2,1);
$hasAM = strrpos($tstr,'M') !== false;
*/
- # see http://phplens.com/lens/lensforum/msgs.php?id=14865 for reasoning, and changelog for version 0.24
+ # see PHPLens Issue No: 14865 for reasoning, and changelog for version 0.24
$dstr = gmstrftime('%x',31366800); // 30 Dec 1970, 1 am
$sep = substr($dstr,2,1);
$tstr = strtoupper(gmstrftime('%X',31366800)); // 30 Dec 1970, 1 am
diff --git a/lib/adodb/adodb-xmlschema.inc.php b/lib/adodb/adodb-xmlschema.inc.php
index b53d4e284bd..0961b4dbf50 100644
--- a/lib/adodb/adodb-xmlschema.inc.php
+++ b/lib/adodb/adodb-xmlschema.inc.php
@@ -1254,12 +1254,6 @@ class adoSchema {
*/
var $objectPrefix = '';
- /**
- * @var long Original Magic Quotes Runtime value
- * @access private
- */
- var $mgq;
-
/**
* @var long System debug
* @access private
@@ -1303,12 +1297,6 @@ class adoSchema {
* @param object $db ADOdb database connection object.
*/
function __construct( $db ) {
- // Initialize the environment
- $this->mgq = 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 );
@@ -2195,11 +2183,7 @@ class adoSchema {
* 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/lib/adodb/adodb-xmlschema03.inc.php b/lib/adodb/adodb-xmlschema03.inc.php
index 4d1faad3651..9fb8272cab9 100644
--- a/lib/adodb/adodb-xmlschema03.inc.php
+++ b/lib/adodb/adodb-xmlschema03.inc.php
@@ -145,7 +145,7 @@ class dbObject {
*
* @access private
*/
- function _tag_open( &$parser, $tag, $attributes ) {
+ function _tag_open( $parser, $tag, $attributes ) {
}
@@ -154,7 +154,7 @@ class dbObject {
*
* @access private
*/
- function _tag_cdata( &$parser, $cdata ) {
+ function _tag_cdata( $parser, $cdata ) {
}
@@ -163,7 +163,7 @@ class dbObject {
*
* @access private
*/
- function _tag_close( &$parser, $tag ) {
+ function _tag_close( $parser, $tag ) {
}
@@ -204,7 +204,7 @@ class dbObject {
* @param string $field Field.
* @return string Field ID.
*/
- function FieldID( $field ) {
+ function fieldID( $field ) {
return strtoupper( preg_replace( '/^`(.+)`$/', '$1', $field ) );
}
}
@@ -283,7 +283,7 @@ class dbTable extends dbObject {
*
* @access private
*/
- function _tag_open( &$parser, $tag, $attributes ) {
+ function _tag_open( $parser, $tag, $attributes ) {
$this->currentElement = strtoupper( $tag );
switch( $this->currentElement ) {
@@ -345,8 +345,16 @@ class dbTable extends dbObject {
*
* @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 +381,7 @@ class dbTable extends dbObject {
*
* @access private
*/
- function _tag_close( &$parser, $tag ) {
+ function _tag_close( $parser, $tag ) {
$this->currentElement = '';
switch( strtoupper( $tag ) ) {
@@ -449,7 +457,7 @@ class dbTable extends dbObject {
* @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 +514,15 @@ class dbTable extends dbObject {
*/
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 +534,9 @@ class dbTable extends dbObject {
$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 +546,10 @@ class dbTable extends dbObject {
}
// 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 +557,7 @@ class dbTable extends dbObject {
// 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 +603,21 @@ class dbTable extends dbObject {
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 +710,7 @@ class dbIndex extends dbObject {
*
* @access private
*/
- function _tag_open( &$parser, $tag, $attributes ) {
+ function _tag_open( $parser, $tag, $attributes ) {
$this->currentElement = strtoupper( $tag );
switch( $this->currentElement ) {
@@ -725,7 +737,7 @@ class dbIndex extends dbObject {
*
* @access private
*/
- function _tag_cdata( &$parser, $cdata ) {
+ function _tag_cdata( $parser, $cdata ) {
switch( $this->currentElement ) {
// Index field name
case 'COL':
@@ -741,7 +753,7 @@ class dbIndex extends dbObject {
*
* @access private
*/
- function _tag_close( &$parser, $tag ) {
+ function _tag_close( $parser, $tag ) {
$this->currentElement = '';
switch( strtoupper( $tag ) ) {
@@ -758,7 +770,7 @@ class dbIndex extends dbObject {
* @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 +807,7 @@ class dbIndex extends dbObject {
}
}
- 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 +853,7 @@ class dbData extends dbObject {
*
* @access private
*/
- function _tag_open( &$parser, $tag, $attributes ) {
+ function _tag_open( $parser, $tag, $attributes ) {
$this->currentElement = strtoupper( $tag );
switch( $this->currentElement ) {
@@ -863,7 +875,7 @@ class dbData extends dbObject {
*
* @access private
*/
- function _tag_cdata( &$parser, $cdata ) {
+ function _tag_cdata( $parser, $cdata ) {
switch( $this->currentElement ) {
// Index field name
case 'F':
@@ -879,7 +891,7 @@ class dbData extends dbObject {
*
* @access private
*/
- function _tag_close( &$parser, $tag ) {
+ function _tag_close( $parser, $tag ) {
$this->currentElement = '';
switch( strtoupper( $tag ) ) {
@@ -903,7 +915,7 @@ class dbData extends dbObject {
// 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 +947,12 @@ class dbData extends dbObject {
* @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 +1039,19 @@ class dbData extends dbObject {
$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 +1127,7 @@ class dbQuerySet extends dbObject {
*
* @access private
*/
- function _tag_open( &$parser, $tag, $attributes ) {
+ function _tag_open( $parser, $tag, $attributes ) {
$this->currentElement = strtoupper( $tag );
switch( $this->currentElement ) {
@@ -1137,7 +1149,7 @@ class dbQuerySet extends dbObject {
/**
* 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 +1165,7 @@ class dbQuerySet extends dbObject {
*
* @access private
*/
- function _tag_close( &$parser, $tag ) {
+ function _tag_close( $parser, $tag ) {
$this->currentElement = '';
switch( strtoupper( $tag ) ) {
@@ -1353,12 +1365,6 @@ class adoSchema {
*/
var $objectPrefix = '';
- /**
- * @var long Original Magic Quotes Runtime value
- * @access private
- */
- var $mgq;
-
/**
* @var long System debug
* @access private
@@ -1407,12 +1413,6 @@ class adoSchema {
* @param object $db ADOdb database connection object.
*/
function __construct( $db ) {
- // Initialize the environment
- $this->mgq = 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 );
@@ -1440,7 +1440,7 @@ class adoSchema {
* @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;
}
@@ -1488,7 +1488,7 @@ class adoSchema {
* @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:
@@ -1523,7 +1523,7 @@ class adoSchema {
*
* @see ParseSchema(), ExecuteSchema()
*/
- function ExecuteInline( $mode = NULL ) {
+ function executeInline( $mode = NULL ) {
if( is_bool( $mode ) ) {
$this->executeInline = $mode;
}
@@ -1544,7 +1544,7 @@ class adoSchema {
*
* @see addSQL(), ExecuteSchema()
*/
- function ContinueOnError( $mode = NULL ) {
+ function continueOnError( $mode = NULL ) {
if( is_bool( $mode ) ) {
$this->continueOnError = $mode;
}
@@ -1565,8 +1565,8 @@ class adoSchema {
* @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 );
}
/**
@@ -1575,22 +1575,22 @@ class adoSchema {
* 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' );
@@ -1598,7 +1598,7 @@ class adoSchema {
}
// do version detection here
- if( $this->SchemaFileVersion( $filename ) != $this->schemaVersion ) {
+ if( $this->schemaFileVersion( $filename ) != $this->schemaVersion ) {
logMsg( 'Invalid Schema Version' );
return FALSE;
}
@@ -1636,13 +1636,13 @@ class adoSchema {
*
* 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;
@@ -1686,8 +1686,8 @@ class adoSchema {
* @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 );
}
/**
@@ -1695,38 +1695,38 @@ class adoSchema {
*
* 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 ) ) {
@@ -1736,7 +1736,7 @@ class adoSchema {
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;
@@ -1746,12 +1746,12 @@ class adoSchema {
* 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 );
}
@@ -1765,7 +1765,7 @@ class adoSchema {
* @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;
@@ -1806,7 +1806,7 @@ class adoSchema {
*
* @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'] ) ) {
@@ -1831,7 +1831,7 @@ class adoSchema {
*
* @access private
*/
- function _tag_cdata( &$parser, $cdata ) {
+ function _tag_cdata( $parser, $cdata ) {
}
/**
@@ -1840,7 +1840,7 @@ class adoSchema {
* @access private
* @internal
*/
- function _tag_close( &$parser, $tag ) {
+ function _tag_close( $parser, $tag ) {
}
@@ -1853,17 +1853,17 @@ class adoSchema {
* 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;
}
@@ -1874,7 +1874,7 @@ class adoSchema {
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' ) ) ) {
@@ -1902,17 +1902,17 @@ class adoSchema {
* 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;
}
@@ -1928,7 +1928,7 @@ class adoSchema {
$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' ) ) ) {
@@ -1939,7 +1939,7 @@ class adoSchema {
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' ) ) {
@@ -2050,7 +2050,7 @@ class adoSchema {
* @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' );
@@ -2076,7 +2076,7 @@ class adoSchema {
* @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;
}
@@ -2093,20 +2093,20 @@ class adoSchema {
*
* 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 -1' );
+ $fields = $this->db->metaColumns( $table );
+ $indexes = $this->db->metaIndexes( $table );
if( is_array( $fields ) ) {
foreach( $fields as $details ) {
@@ -2148,7 +2148,7 @@ class adoSchema {
// 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] = '';
@@ -2202,7 +2202,7 @@ class adoSchema {
}
}
- $this->db->SetFetchMode( $old_mode );
+ $this->db->setFetchMode( $old_mode );
$schema .= '';
return $schema;
@@ -2218,7 +2218,7 @@ class adoSchema {
* @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 ):
@@ -2377,10 +2377,7 @@ class adoSchema {
* 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/lib/adodb/adodb.inc.php b/lib/adodb/adodb.inc.php
index 74c52e002e1..080a8df9cdd 100644
--- a/lib/adodb/adodb.inc.php
+++ b/lib/adodb/adodb.inc.php
@@ -2,7 +2,7 @@
/*
* Set tabs to 4 for best viewing.
*
- * Latest version is available at http://adodb.org/
+ * Latest version is available at https://adodb.org/
*
* This is the main include file for ADOdb.
* Database specific drivers are stored in the adodb/drivers/adodb-*.inc.php
@@ -14,7 +14,7 @@
/**
\mainpage
- @version v5.20.16 12-Jan-2020
+ @version v5.21.0 2021-02-27
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
@@ -72,7 +72,6 @@ if (!defined('_ADODB_LAYER')) {
$ADODB_CACHE_DIR, // directory to cache recordsets
$ADODB_CACHE,
$ADODB_CACHE_CLASS,
- $ADODB_EXTENSION, // ADODB extension installed
$ADODB_COMPAT_FETCH, // If $ADODB_COUNTRECS and this is true, $rs->fields is available on EOF
$ADODB_FETCH_MODE, // DEFAULT, NUM, ASSOC or BOTH. Default follows native driver default...
$ADODB_GETONE_EOF,
@@ -82,35 +81,52 @@ if (!defined('_ADODB_LAYER')) {
// 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 +141,10 @@ if (!defined('_ADODB_LAYER')) {
* - 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,54 +161,24 @@ if (!defined('_ADODB_LAYER')) {
* 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);
+ 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);
-
-
- // 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
$ADODB_vers, // database version
@@ -224,7 +210,7 @@ if (!defined('_ADODB_LAYER')) {
/**
* ADODB version as a string.
*/
- $ADODB_vers = 'v5.20.16 12-Jan-2020';
+ $ADODB_vers = 'v5.21.0 2021-02-27';
/**
* Determines whether recordset->RecordCount() is used.
@@ -302,8 +288,8 @@ if (!defined('_ADODB_LAYER')) {
//print "Errorno ($fn errno=$errno m=$errmsg) ";
$thisConnection->_transOK = false;
if ($thisConnection->_oldRaiseFn) {
- $fn = $thisConnection->_oldRaiseFn;
- $fn($dbms, $fn, $errno, $errmsg, $p1, $p2,$thisConnection);
+ $errfn = $thisConnection->_oldRaiseFn;
+ $errfn($dbms, $fn, $errno, $errmsg, $p1, $p2,$thisConnection);
}
}
@@ -439,6 +425,8 @@ if (!defined('_ADODB_LAYER')) {
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 = '';
@@ -457,7 +445,10 @@ if (!defined('_ADODB_LAYER')) {
var $hasTransactions = true; /// has transactions
//--
var $genID = 0; /// sequence id used by GenID();
- var $raiseErrorFn = 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
@@ -465,7 +456,7 @@ if (!defined('_ADODB_LAYER')) {
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
@@ -483,8 +474,12 @@ if (!defined('_ADODB_LAYER')) {
var $autoRollback = false; // autoRollback on PConnect().
var $poorAffectedRows = false; // affectedRows not working or unreliable
+ /** @var bool|callable Execute function to call */
var $fnExecute = false;
+
+ /** @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
var $rsPrefix = "ADORecordSet_";
@@ -514,6 +509,17 @@ if (!defined('_ADODB_LAYER')) {
var $_logsql = false;
var $_transmode = ''; // transaction mode
+
+ /**
+ * 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()
+ {
+ }
+
/*
* Additional parameters that may be passed to drivers in the connect string
* Driver must be coded to accept the parameters
@@ -533,13 +539,17 @@ if (!defined('_ADODB_LAYER')) {
*
* @example, for mssqlnative driver ('CharacterSet','UTF-8')
*/
- final public function setConnectionParameter($parameter,$value)
- {
+ final public function setConnectionParameter($parameter,$value) {
- $this->connectionParameters[$parameter] = $value;
+ $this->connectionParameters[] = array($parameter=>$value);
}
+ /**
+ * ADOdb version.
+ *
+ * @return string
+ */
static function Version() {
global $ADODB_vers;
@@ -561,15 +571,20 @@ if (!defined('_ADODB_LAYER')) {
}
/**
- 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);
}
@@ -583,9 +598,13 @@ if (!defined('_ADODB_LAYER')) {
}
/**
- * 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;
@@ -594,8 +613,7 @@ if (!defined('_ADODB_LAYER')) {
$fn($msg,$newline);
return;
} else if (isset($ADODB_OUTP)) {
- $fn = $ADODB_OUTP;
- $fn($msg,$newline);
+ call_user_func($ADODB_OUTP,$msg,$newline);
return;
}
@@ -616,6 +634,10 @@ if (!defined('_ADODB_LAYER')) {
}
+ /**
+ * Return the database server's current date and time.
+ * @return int|false
+ */
function Time() {
$rs = $this->_Execute("select $this->sysTimeStamp");
if ($rs && !$rs->EOF) {
@@ -646,15 +668,15 @@ if (!defined('_ADODB_LAYER')) {
}
/**
- * 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 != "") {
@@ -709,30 +731,31 @@ if (!defined('_ADODB_LAYER')) {
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.
*
- * @param [argHostname] Host to connect to
- * @param [argUsername] Userid to login
- * @param [argPassword] Associated password
- * @param [argDatabaseName] database
+ * Currently this only works with Oracle.
*
- * @return true or false
+ * @param string $argHostname Host to connect to
+ * @param string $argUsername Userid to login
+ * @param string $argPassword Associated password
+ * @param string $argDatabaseName Database name
+ *
+ * @return bool
*/
function NConnect($argHostname = "", $argUsername = "", $argPassword = "", $argDatabaseName = "") {
return $this->Connect($argHostname, $argUsername, $argPassword, $argDatabaseName, 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 = "") {
@@ -769,7 +792,7 @@ if (!defined('_ADODB_LAYER')) {
$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);
@@ -790,7 +813,11 @@ if (!defined('_ADODB_LAYER')) {
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;
@@ -806,8 +833,16 @@ if (!defined('_ADODB_LAYER')) {
}
}
- // 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;
}
@@ -815,7 +850,8 @@ if (!defined('_ADODB_LAYER')) {
}
/**
- * 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:
*
@@ -823,53 +859,47 @@ if (!defined('_ADODB_LAYER')) {
* $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:
+ * For databases that do not support this, we return the $sql.
*
- * @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
+ * @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"
+ * PEAR DB Compat - alias for qStr.
+ * @param $s
+ * @return string
*/
- function QMagic($s) {
- return $this->qstr($s,get_magic_quotes_gpc());
+ 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);
}
/**
@@ -891,17 +921,26 @@ if (!defined('_ADODB_LAYER')) {
* 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();
}
@@ -912,8 +951,9 @@ if (!defined('_ADODB_LAYER')) {
* 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;
@@ -929,6 +969,11 @@ if (!defined('_ADODB_LAYER')) {
/**
* 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);
@@ -940,8 +985,8 @@ if (!defined('_ADODB_LAYER')) {
/**
- * 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')) {
@@ -952,22 +997,26 @@ if (!defined('_ADODB_LAYER')) {
/**
- * 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
*/
@@ -1115,11 +1164,14 @@ if (!defined('_ADODB_LAYER')) {
/**
* 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);
@@ -1250,13 +1302,13 @@ if (!defined('_ADODB_LAYER')) {
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 );
+ $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 {
@@ -1287,8 +1339,17 @@ if (!defined('_ADODB_LAYER')) {
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();
@@ -1325,12 +1386,14 @@ if (!defined('_ADODB_LAYER')) {
}
/**
- * 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) {
@@ -1365,9 +1428,15 @@ if (!defined('_ADODB_LAYER')) {
}
/**
- * @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) {
@@ -1387,8 +1456,12 @@ if (!defined('_ADODB_LAYER')) {
/**
* Portable Insert ID. Pablo Roca
*
- * @return the last inserted ID. All databases support this. But aware possible
- * problems in multiuser environments. Heavy test this before deploying.
+ * @param string $table
+ * @param string $id
+
+ * @return mixed The last inserted ID. All databases support this, but be
+ * aware of possible problems in multiuser environments.
+ * Heavily test this before deploying.
*/
function PO_Insert_ID($table="", $id="") {
if ($this->hasInsertID){
@@ -1420,7 +1493,7 @@ if (!defined('_ADODB_LAYER')) {
/**
- * @return the last error message
+ * @return string the last error message
*/
function ErrorMsg() {
if ($this->_errorMsg) {
@@ -1432,7 +1505,7 @@ if (!defined('_ADODB_LAYER')) {
/**
- * @return the last error number. Normally 0 means no error.
+ * @return int the last error number. Normally 0 means no error.
*/
function ErrorNo() {
return ($this->_errorMsg) ? -1 : 0;
@@ -1483,13 +1556,15 @@ if (!defined('_ADODB_LAYER')) {
/**
* Choose a database to connect to. Many databases do not support this.
*
- * @param dbName is the name of the database to select
- * @return true or false
+ * @param string $dbName the name of the database to select
+ * @return bool
*/
function SelectDB($dbName) {return false;}
/**
+ * Select a limited number of rows.
+ *
* Will select, getting rows from $offset (1-based), for $nrows.
* This simulates the MySQL "select * from table limit $offset,$nrows" , and
* the PostgreSQL "select * from table limit $nrows offset $offset". Note that
@@ -1501,12 +1576,13 @@ if (!defined('_ADODB_LAYER')) {
* Uses SELECT TOP for Microsoft databases (when $this->hasTop is set)
* BUG: Currently SelectLimit fails with $sql with LIMIT or TOP clause already set
*
- * @param sql
- * @param [offset] is the row to start calculations from (1-based)
- * @param [nrows] is the number of rows to get
- * @param [inputarr] array of bind variables
- * @param [secs2cache] is a private parameter only used by jlim
- * @return the recordset ($rs->databaseType == 'array')
+ * @param string $sql
+ * @param int $offset Row to start calculations from (1-based)
+ * @param int $nrows Number of rows to get
+ * @param array|bool $inputarr Array of bind variables
+ * @param int $secs2cache Private parameter only used by jlim
+ *
+ * @return ADORecordSet The recordset ($rs->databaseType == 'array')
*/
function SelectLimit($sql,$nrows=-1,$offset=-1, $inputarr=false,$secs2cache=0) {
$nrows = (int)$nrows;
@@ -1523,32 +1599,47 @@ if (!defined('_ADODB_LAYER')) {
}
if ($offset <= 0) {
- // access includes ties in result
- if ($isaccess) {
- $sql = preg_replace(
- '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop.' '.$nrows.' ',$sql);
+ // access includes ties in result
+ if ($isaccess) {
+ $sql = preg_replace(
+ '/(^\s*select\s+(distinctrow|distinct)?)/i',
+ '\\1 '.$this->hasTop.' '.$nrows.' ',
+ $sql
+ );
- if ($secs2cache != 0) {
- $ret = $this->CacheExecute($secs2cache, $sql,$inputarr);
- } else {
- $ret = $this->Execute($sql,$inputarr);
- }
- return $ret; // PHP5 fix
- } else if ($ismssql){
- $sql = preg_replace(
- '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop.' '.$nrows.' ',$sql);
+ if ($secs2cache != 0) {
+ $ret = $this->CacheExecute($secs2cache, $sql,$inputarr);
} else {
- $sql = preg_replace(
- '/(^\s*select\s)/i','\\1 '.$this->hasTop.' '.$nrows.' ',$sql);
+ $ret = $this->Execute($sql,$inputarr);
}
+ return $ret; // PHP5 fix
+ } else if ($ismssql){
+ $sql = preg_replace(
+ '/(^\s*select\s+(distinctrow|distinct)?)/i',
+ '\\1 '.$this->hasTop.' '.$nrows.' ',
+ $sql
+ );
+ } else {
+ $sql = preg_replace(
+ '/(^\s*select\s)/i',
+ '\\1 '.$this->hasTop.' '.$nrows.' ',
+ $sql
+ );
+ }
} else {
$nn = $nrows + $offset;
if ($isaccess || $ismssql) {
$sql = preg_replace(
- '/(^\s*select\s+(distinctrow|distinct)?)/i','\\1 '.$this->hasTop.' '.$nn.' ',$sql);
+ '/(^\s*select\s+(distinctrow|distinct)?)/i',
+ '\\1 '.$this->hasTop.' '.$nn.' ',
+ $sql
+ );
} else {
$sql = preg_replace(
- '/(^\s*select\s)/i','\\1 '.$this->hasTop.' '.$nn.' ',$sql);
+ '/(^\s*select\s)/i',
+ '\\1 '.$this->hasTop.' '.$nn.' ',
+ $sql
+ );
}
}
}
@@ -1578,7 +1669,9 @@ if (!defined('_ADODB_LAYER')) {
/**
* Create serializable recordset. Breaks rs link to connection.
*
- * @param rs the recordset to serialize
+ * @param ADORecordSet $rs the recordset to serialize
+ *
+ * @return ADORecordSet_array|bool the new recordset
*/
function SerializableRS(&$rs) {
$rs2 = $this->_rs2rs($rs);
@@ -1589,18 +1682,21 @@ if (!defined('_ADODB_LAYER')) {
}
/**
- * Convert database recordset to an array recordset
- * input recordset's cursor should be at beginning, and
- * old $rs will be closed.
+ * Convert a database recordset to an array recordset.
+ *
+ * Input recordset's cursor should be at beginning, and old $rs will be closed.
*
- * @param rs the recordset to copy
- * @param [nrows] number of rows to retrieve (optional)
- * @param [offset] offset by number of rows (optional)
- * @return the new recordset
+ * @param ADORecordSet $rs the recordset to copy
+ * @param int $nrows number of rows to retrieve (optional)
+ * @param int $offset offset by number of rows (optional)
+ * @param bool $close
+ *
+ * @return ADORecordSet_array|ADORecordSet|bool the new recordset
*/
function &_rs2rs(&$rs,$nrows=-1,$offset=-1,$close=true) {
if (! $rs) {
- return false;
+ $ret = false;
+ return $ret;
}
$dbtype = $rs->databaseType;
if (!$dbtype) {
@@ -1635,23 +1731,58 @@ if (!defined('_ADODB_LAYER')) {
}
/*
- * Return all rows. Compat with PEAR DB
+ * Return all rows.
+ *
+ * Compat with PEAR DB.
+ *
+ * @param string $sql SQL statement
+ * @param array|bool $inputarr Input bind array
+ *
+ * @return array|false
*/
function GetAll($sql, $inputarr=false) {
- $arr = $this->GetArray($sql,$inputarr);
- return $arr;
+ return $this->GetArray($sql,$inputarr);
}
- function GetAssoc($sql, $inputarr=false,$force_array = false, $first2cols = false) {
+ /**
+ * Execute statement and return rows in an array.
+ *
+ * The function executes a statement and returns all of the returned rows in
+ * an array, or false if the statement execution fails or if only 1 column
+ * is requested in the SQL statement.
+ * If no records match the provided SQL statement, an empty array is returned.
+ *
+ * @param string $sql SQL statement
+ * @param array|bool $inputarr input bind array
+ * @param bool $force_array
+ * @param bool $first2cols
+ *
+ * @return array|bool
+ */
+ public function GetAssoc($sql, $inputarr = false, $force_array = false, $first2cols = false) {
$rs = $this->Execute($sql, $inputarr);
+
if (!$rs) {
+ /*
+ * Execution failure
+ */
return false;
}
- $arr = $rs->GetAssoc($force_array,$first2cols);
- return $arr;
+ return $rs->GetAssoc($force_array, $first2cols);
}
- function CacheGetAssoc($secs2cache, $sql=false, $inputarr=false,$force_array = false, $first2cols = false) {
+ /**
+ * Search for the results of an executed query in the cache.
+ *
+ * @param int $secs2cache
+ * @param string|bool $sql SQL statement
+ * @param array|bool $inputarr input bind array
+ * @param bool $force_array
+ * @param bool $first2cols
+ *
+ * @return false|array
+ */
+ public function CacheGetAssoc($secs2cache, $sql = false, $inputarr = false,$force_array = false, $first2cols = false) {
if (!is_numeric($secs2cache)) {
$first2cols = $force_array;
$force_array = $inputarr;
@@ -1660,18 +1791,18 @@ if (!defined('_ADODB_LAYER')) {
if (!$rs) {
return false;
}
- $arr = $rs->GetAssoc($force_array,$first2cols);
- return $arr;
+ return $rs->GetAssoc($force_array, $first2cols);
}
/**
- * Return first element of first row of sql statement. Recordset is disposed
- * for you.
- *
- * @param sql SQL statement
- * @param [inputarr] input bind array
- */
- function GetOne($sql,$inputarr=false) {
+ * Return first element of first row of sql statement. Recordset is disposed
+ * for you.
+ *
+ * @param string $sql SQL statement
+ * @param array|bool $inputarr input bind array
+ * @return mixed
+ */
+ public function GetOne($sql, $inputarr=false) {
global $ADODB_COUNTRECS,$ADODB_GETONE_EOF;
$crecs = $ADODB_COUNTRECS;
@@ -1725,6 +1856,17 @@ if (!defined('_ADODB_LAYER')) {
return $ret;
}
+ /**
+ * Executes a statement and returns each row's first column in an array.
+ *
+ * @param string $sql SQL statement
+ * @param array|bool $inputarr input bind array
+ * @param bool $trim enables space trimming of the returned value.
+ * This is only relevant if the returned string
+ * is coming from a CHAR type field.
+ *
+ * @return array|bool 1D array containning the first row of the query
+ */
function GetCol($sql, $inputarr = false, $trim = false) {
$rs = $this->Execute($sql, $inputarr);
@@ -1796,10 +1938,13 @@ if (!defined('_ADODB_LAYER')) {
/**
- *
- * @param sql SQL statement
- * @param [inputarr] input bind array
- */
+ * Executes a statement and returns a the entire recordset in an array.
+ *
+ * @param string $sql SQL statement
+ * @param array|bool $inputarr input bind array
+ *
+ * @return array|false
+ */
function GetArray($sql,$inputarr=false) {
global $ADODB_COUNTRECS;
@@ -1809,8 +1954,7 @@ if (!defined('_ADODB_LAYER')) {
$ADODB_COUNTRECS = $savec;
if (!$rs)
if (defined('ADODB_PEAR')) {
- $cls = ADODB_PEAR_Error();
- return $cls;
+ return ADODB_PEAR_Error();
} else {
return false;
}
@@ -1820,8 +1964,7 @@ if (!defined('_ADODB_LAYER')) {
}
function CacheGetAll($secs2cache,$sql=false,$inputarr=false) {
- $arr = $this->CacheGetArray($secs2cache,$sql,$inputarr);
- return $arr;
+ return $this->CacheGetArray($secs2cache,$sql,$inputarr);
}
function CacheGetArray($secs2cache,$sql=false,$inputarr=false) {
@@ -1834,8 +1977,7 @@ if (!defined('_ADODB_LAYER')) {
if (!$rs)
if (defined('ADODB_PEAR')) {
- $cls = ADODB_PEAR_Error();
- return $cls;
+ return ADODB_PEAR_Error();
} else {
return false;
}
@@ -1854,8 +1996,10 @@ if (!defined('_ADODB_LAYER')) {
* Return one row of sql statement. Recordset is disposed for you.
* Note that SelectLimit should not be called.
*
- * @param sql SQL statement
- * @param [inputarr] input bind array
+ * @param string $sql SQL statement
+ * @param array|bool $inputarr input bind array
+ *
+ * @return array|false Array containing the first row of the query
*/
function GetRow($sql,$inputarr=false) {
global $ADODB_COUNTRECS;
@@ -1879,6 +2023,12 @@ if (!defined('_ADODB_LAYER')) {
return false;
}
+ /**
+ * @param int $secs2cache
+ * @param string|false $sql
+ * @param mixed[]|bool $inputarr
+ * @return mixed[]|bool
+ */
function CacheGetRow($secs2cache,$sql=false,$inputarr=false) {
$rs = $this->CacheExecute($secs2cache,$sql,$inputarr);
if ($rs) {
@@ -1905,7 +2055,7 @@ if (!defined('_ADODB_LAYER')) {
* $table table name
* $fieldArray associative array of data (you must quote strings yourself).
* $keyCol the primary key field name or if compound key, array of field names
- * autoQuote set to true to use a hueristic to quote strings. Works with nulls and numbers
+ * autoQuote set to true to use a heuristic to quote strings. Works with nulls and numbers
* but does not work with dates nor SQL functions.
* has_autoinc the primary key is an auto-inc field, so skip in insert.
*
@@ -1917,7 +2067,7 @@ if (!defined('_ADODB_LAYER')) {
function Replace($table, $fieldArray, $keyCol, $autoQuote=false, $has_autoinc=false) {
global $ADODB_INCLUDED_LIB;
if (empty($ADODB_INCLUDED_LIB)) {
- include(ADODB_DIR.'/adodb-lib.inc.php');
+ include_once(ADODB_DIR.'/adodb-lib.inc.php');
}
return _adodb_replace($this, $table, $fieldArray, $keyCol, $autoQuote, $has_autoinc);
@@ -1935,12 +2085,13 @@ if (!defined('_ADODB_LAYER')) {
*
* BUG: Currently CacheSelectLimit fails with $sql with LIMIT or TOP clause already set
*
- * @param [secs2cache] seconds to cache data, set to 0 to force query. This is optional
- * @param sql
- * @param [offset] is the row to start calculations from (1-based)
- * @param [nrows] is the number of rows to get
- * @param [inputarr] array of bind variables
- * @return the recordset ($rs->databaseType == 'array')
+ * @param int $secs2cache Seconds to cache data, set to 0 to force query. This is optional
+ * @param string $sql
+ * @param int $offset Row to start calculations from (1-based)
+ * @param int $nrows Number of rows to get
+ * @param array $inputarr Array of bind variables
+ *
+ * @return ADORecordSet The recordset ($rs->databaseType == 'array')
*/
function CacheSelectLimit($secs2cache,$sql,$nrows=-1,$offset=-1,$inputarr=false) {
if (!is_numeric($secs2cache)) {
@@ -2023,11 +2174,12 @@ if (!defined('_ADODB_LAYER')) {
/**
* Execute SQL, caching recordsets.
*
- * @param [secs2cache] seconds to cache data, set to 0 to force query.
- * This is an optional parameter.
- * @param sql SQL statement to execute
- * @param [inputarr] holds the input data to bind to
- * @return RecordSet or false
+ * @param int $secs2cache Seconds to cache data, set to 0 to force query.
+ * This is an optional parameter.
+ * @param string|bool $sql SQL statement to execute
+ * @param array|bool $inputarr Holds the input data to bind
+ *
+ * @return ADORecordSet RecordSet or false
*/
function CacheExecute($secs2cache,$sql=false,$inputarr=false) {
global $ADODB_CACHE;
@@ -2062,11 +2214,8 @@ if (!defined('_ADODB_LAYER')) {
}
if (!$rs) {
- // no cached rs found
+ // no cached rs found
if ($this->debug) {
- if (get_magic_quotes_runtime() && !$this->memCache) {
- ADOConnection::outp("Please disable magic_quotes_runtime - it corrupts cache files :(");
- }
if ($this->debug !== -1) {
ADOConnection::outp( " $md5file cache failure: $err (this is a notice and not an error)");
}
@@ -2137,13 +2286,32 @@ if (!defined('_ADODB_LAYER')) {
/*
- Similar to PEAR DB's autoExecute(), except that
- $mode can be 'INSERT' or 'UPDATE' or DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE
- If $mode == 'UPDATE', then $where is compulsory as a safety measure.
- $forceUpdate means that even if the data has not changed, perform update.
+
+ $forceUpdate .
*/
- function AutoExecute($table, $fields_values, $mode = 'INSERT', $where = false, $forceUpdate = true, $magicq = false) {
+ /**
+ * Similar to PEAR DB's autoExecute(), except that $mode can be 'INSERT'
+ * or 'UPDATE' or DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE.
+ * If $mode == 'UPDATE', then $where is compulsory as a safety measure.
+ *
+ * @param $table
+ * @param $fields_values
+ * @param string $mode
+ * @param false $where
+ * @param bool $forceUpdate If true, perform update even if the data has not changed.
+ * @param bool $magic_quotes This param is not used since 5.21.0.
+ * It remains for backwards compatibility.
+ *
+ * @return bool
+ *
+ * @noinspection PhpUnusedParameterInspection
+ */
+ function AutoExecute($table, $fields_values, $mode = 'INSERT', $where = false, $forceUpdate = true, $magic_quotes = false) {
+ if (empty($fields_values)) {
+ $this->outp_throw('AutoExecute: Empty fields array', 'AutoExecute');
+ return false;
+ }
if ($where === false && ($mode == 'UPDATE' || $mode == 2 /* DB_AUTOQUERY_UPDATE */) ) {
$this->outp_throw('AutoExecute: Illegal mode=UPDATE with empty WHERE clause', 'AutoExecute');
return false;
@@ -2164,11 +2332,11 @@ if (!defined('_ADODB_LAYER')) {
switch($mode) {
case 'UPDATE':
case DB_AUTOQUERY_UPDATE:
- $sql = $this->GetUpdateSQL($rs, $fields_values, $forceUpdate, $magicq);
+ $sql = $this->GetUpdateSQL($rs, $fields_values, $forceUpdate);
break;
case 'INSERT':
case DB_AUTOQUERY_INSERT:
- $sql = $this->GetInsertSQL($rs, $fields_values, $magicq);
+ $sql = $this->GetInsertSQL($rs, $fields_values);
break;
default:
$this->outp_throw("AutoExecute: Unknown mode=$mode", 'AutoExecute');
@@ -2180,16 +2348,27 @@ if (!defined('_ADODB_LAYER')) {
/**
* Generates an Update Query based on an existing recordset.
+ *
* $arrFields is an associative array of fields with the value
* that should be assigned.
*
* Note: This function should only be used on a recordset
- * that is run against a single table and sql should only
- * be a simple select stmt with no groupby/orderby/limit
+ * that is run against a single table and sql should only
+ * be a simple select stmt with no groupby/orderby/limit
+ * @author "Jonathan Younger"
*
- * "Jonathan Younger"
+ * @param $rs
+ * @param $arrFields
+ * @param bool $forceUpdate
+ * @param bool $magic_quotes This param is not used since 5.21.0.
+ * It remains for backwards compatibility.
+ * @param null $force
+ *
+ * @return false|string
+ *
+ * @noinspection PhpUnusedParameterInspection
*/
- function GetUpdateSQL(&$rs, $arrFields,$forceUpdate=false,$magicq=false,$force=null) {
+ function GetUpdateSQL(&$rs, $arrFields, $forceUpdate=false, $magic_quotes=false, $force=null) {
global $ADODB_INCLUDED_LIB;
// ********************************************************
@@ -2202,29 +2381,40 @@ if (!defined('_ADODB_LAYER')) {
// ********************************************************
if (empty($ADODB_INCLUDED_LIB)) {
- include(ADODB_DIR.'/adodb-lib.inc.php');
+ include_once(ADODB_DIR.'/adodb-lib.inc.php');
}
- return _adodb_getupdatesql($this,$rs,$arrFields,$forceUpdate,$magicq,$force);
+ return _adodb_getupdatesql($this, $rs, $arrFields, $forceUpdate, $force);
}
/**
* Generates an Insert Query based on an existing recordset.
+ *
* $arrFields is an associative array of fields with the value
* that should be assigned.
*
* Note: This function should only be used on a recordset
* that is run against a single table.
+ *
+ * @param $rs
+ * @param $arrFields
+ * @param bool $magic_quotes This param is not used since 5.21.0.
+ * It remains for backwards compatibility.
+ * @param null $force
+ *
+ * @return false|string
+ *
+ * @noinspection PhpUnusedParameterInspection
*/
- function GetInsertSQL(&$rs, $arrFields,$magicq=false,$force=null) {
+ function GetInsertSQL(&$rs, $arrFields, $magic_quotes=false, $force=null) {
global $ADODB_INCLUDED_LIB;
if (!isset($force)) {
global $ADODB_FORCE_TYPE;
$force = $ADODB_FORCE_TYPE;
}
if (empty($ADODB_INCLUDED_LIB)) {
- include(ADODB_DIR.'/adodb-lib.inc.php');
+ include_once(ADODB_DIR.'/adodb-lib.inc.php');
}
- return _adodb_getinsertsql($this,$rs,$arrFields,$magicq,$force);
+ return _adodb_getinsertsql($this, $rs, $arrFields, $force);
}
@@ -2415,7 +2605,7 @@ if (!defined('_ADODB_LAYER')) {
/**
* Begin a Transaction. Must be followed by CommitTrans() or RollbackTrans().
*
- * @return true if succeeded or false if database does not support transactions
+ * @return bool true if succeeded or false if database does not support transactions
*/
function BeginTrans() {
if ($this->debug) {
@@ -2475,9 +2665,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
/**
- * If database does not support transactions, always return true as data always commited
+ * If database does not support transactions, always return true as data always committed
*
- * @param $ok set to false to rollback transaction, true to commit
+ * @param bool $ok set to false to rollback transaction, true to commit
*
* @return true/false.
*/
@@ -2489,7 +2679,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* If database does not support transactions, rollbacks always fail, so return false
*
- * @return true/false.
+ * @return bool
*/
function RollbackTrans() {
return false;
@@ -2500,7 +2690,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* return the databases that the driver can connect to.
* Some databases will return an empty array.
*
- * @return an array of database names.
+ * @return array|bool an array of database names.
*/
function MetaDatabases() {
global $ADODB_FETCH_MODE;
@@ -2724,14 +2914,16 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
/**
+ * Concatenate strings.
+ *
* Different SQL databases used different methods to combine strings together.
* This function provides a wrapper.
*
- * param s variable number of string parameters
- *
* Usage: $db->Concat($str1,$str2);
*
- * @return concatenated string
+ * @param string $s Variable number of string parameters
+ *
+ * @return string concatenated string
*/
function Concat() {
$arr = func_get_args();
@@ -2742,9 +2934,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Converts a date "d" to a string that the database can understand.
*
- * @param d a date in Unix date time format.
+ * @param mixed $d a date in Unix date time format.
*
- * @return date string in database date format
+ * @return string date string in database date format
*/
function DBDate($d, $isfld=false) {
if (empty($d) && $d !== 0) {
@@ -2796,9 +2988,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Converts a timestamp "ts" to a string that the database can understand.
*
- * @param ts a timestamp in Unix date time format.
+ * @param int|object $ts A timestamp in Unix date time format.
*
- * @return timestamp string in database timestamp format
+ * @return string $timestamp string in database timestamp format
*/
function DBTimeStamp($ts,$isfld=false) {
if (empty($ts) && $ts !== 0) {
@@ -2829,9 +3021,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Also in ADORecordSet.
- * @param $v is a date string in YYYY-MM-DD format
+ * @param mixed $v is a date string in YYYY-MM-DD format
*
- * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
+ * @return int|false Date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
*/
static function UnixDate($v) {
if (is_object($v)) {
@@ -2858,9 +3050,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Also in ADORecordSet.
- * @param $v is a timestamp string in YYYY-MM-DD HH-NN-SS format
+ * @param string|object $v is a timestamp string in YYYY-MM-DD HH-NN-SS format
*
- * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
+ * @return int|false Date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
*/
static function UnixTimeStamp($v) {
if (is_object($v)) {
@@ -2885,14 +3077,15 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
/**
- * Also in ADORecordSet.
- *
* Format database date based on user defined format.
*
- * @param v is the character date in YYYY-MM-DD format, returned by database
- * @param fmt is the format to apply to it, using date()
+ * Also in ADORecordSet.
*
- * @return a date formated as user desires
+ * @param mixed $v Date in YYYY-MM-DD format, returned by database
+ * @param string $fmt Format to apply, using date()
+ * @param bool $gmt
+ *
+ * @return string Formatted date
*/
function UserDate($v,$fmt='Y-m-d',$gmt=false) {
$tt = $this->UnixDate($v);
@@ -2911,11 +3104,13 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
/**
+ * Format timestamp based on user defined format.
*
- * @param v is the character timestamp in YYYY-MM-DD hh:mm:ss format
- * @param fmt is the format to apply to it, using date()
+ * @param mixed $v Date in YYYY-MM-DD hh:mm:ss format
+ * @param string $fmt Format to apply, using date()
+ * @param bool $gmt
*
- * @return a timestamp formated as user desires
+ * @return string Formatted timestamp
*/
function UserTimeStamp($v,$fmt='Y-m-d H:i:s',$gmt=false) {
if (!isset($v)) {
@@ -2936,92 +3131,80 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
return ($gmt) ? adodb_gmdate($fmt,$tt) : adodb_date($fmt,$tt);
}
- function escape($s,$magic_quotes=false) {
- return $this->addq($s,$magic_quotes);
- }
-
/**
- * Quotes a string, without prefixing nor appending quotes.
- */
- function addq($s,$magic_quotes=false) {
- if (!$magic_quotes) {
- if ($this->replaceQuote[0] == '\\') {
- // only since php 4.0.5
- $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
- //$s = str_replace("\0","\\\0", str_replace('\\','\\\\',$s));
- }
- return str_replace("'",$this->replaceQuote,$s);
- }
-
- // undo magic quotes for "
- $s = str_replace('\\"','"',$s);
-
- if ($this->replaceQuote == "\\'" || ini_get('magic_quotes_sybase')) {
- // ' already quoted, no need to change anything
- return $s;
- } else {
- // change \' to '' for sybase/mssql
- $s = str_replace('\\\\','\\',$s);
- return str_replace("\\'",$this->replaceQuote,$s);
- }
- }
-
- /**
- * 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",magic_quotes_runtime());
+ * Alias for addQ()
+ * @param string $s
+ * @param bool [$magic_quotes]
+ * @return mixed
*
- * @param s the string to quote
- * @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc().
- * This undoes the stupidity of magic quotes for GPC.
- *
- * @return quoted string to be sent back to database
+ * @deprecated 5.21.0
+ * @noinspection PhpUnusedParameterInspection
*/
- function qstr($s,$magic_quotes=false) {
- if (!$magic_quotes) {
- if ($this->replaceQuote[0] == '\\'){
- // only since php 4.0.5
- $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
- //$s = str_replace("\0","\\\0", str_replace('\\','\\\\',$s));
- }
- return "'".str_replace("'",$this->replaceQuote,$s)."'";
- }
+ function escape($s,$magic_quotes=false) {
+ return $this->addQ($s);
+ }
- // undo magic quotes for "
- $s = str_replace('\\"','"',$s);
-
- if ($this->replaceQuote == "\\'" || ini_get('magic_quotes_sybase')) {
- // ' already quoted, no need to change anything
- return "'$s'";
- } else {
- // change \' to '' for sybase/mssql
- $s = str_replace('\\\\','\\',$s);
- return "'".str_replace("\\'",$this->replaceQuote,$s)."'";
+ /**
+ * Quotes a string, without prefixing nor appending quotes.
+ *
+ * @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
+ *
+ * @noinspection PhpUnusedParameterInspection
+ */
+ function addQ($s, $magic_quotes=false) {
+ if ($this->replaceQuote[0] == '\\') {
+ $s = str_replace(
+ array('\\', "\0"),
+ array('\\\\', "\\\0"),
+ $s
+ );
}
+ return str_replace("'", $this->replaceQuote, $s);
+ }
+
+ /**
+ * 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");
+ * @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 to be sent back to database
+ *
+ * @noinspection PhpUnusedParameterInspection
+ */
+ function qStr($s, $magic_quotes=false) {
+ return "'" . $this->addQ($s) . "'";
}
/**
- * Will select the supplied $page number from a recordset, given that it is paginated in pages of
- * $nrows rows per page. It also saves two boolean values saying if the given page is the first
- * and/or last one of the recordset. Added by Iván Oliva to provide recordset pagination.
- *
- * See docs-adodb.htm#ex8 for an example of usage.
- *
- * @param sql
- * @param nrows is the number of rows per page to get
- * @param page is the page number to get (1-based)
- * @param [inputarr] array of bind variables
- * @param [secs2cache] is a private parameter only used by jlim
- * @return the recordset ($rs->databaseType == 'array')
- *
- * NOTE: phpLens uses a different algorithm and does not use PageExecute().
- *
- */
+ * Will select the supplied $page number from a recordset, given that it is paginated in pages of
+ * $nrows rows per page. It also saves two boolean values saying if the given page is the first
+ * and/or last one of the recordset. Added by Iván Oliva to provide recordset pagination.
+ *
+ * See docs-adodb.htm#ex8 for an example of usage.
+ * NOTE: phpLens uses a different algorithm and does not use PageExecute().
+ *
+ * @param string $sql
+ * @param int $nrows Number of rows per page to get
+ * @param int $page Page number to get (1-based)
+ * @param mixed[]|bool $inputarr Array of bind variables
+ * @param int $secs2cache Private parameter only used by jlim
+ *
+ * @return mixed the recordset ($rs->databaseType == 'array')
+ */
function PageExecute($sql, $nrows, $page, $inputarr=false, $secs2cache=0) {
global $ADODB_INCLUDED_LIB;
if (empty($ADODB_INCLUDED_LIB)) {
- include(ADODB_DIR.'/adodb-lib.inc.php');
+ include_once(ADODB_DIR.'/adodb-lib.inc.php');
}
if ($this->pageExecuteCountRows) {
$rs = _adodb_pageexecute_all_rows($this, $sql, $nrows, $page, $inputarr, $secs2cache);
@@ -3037,12 +3220,12 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* $nrows rows per page. It also saves two boolean values saying if the given page is the first
* and/or last one of the recordset. Added by Iván Oliva to provide recordset pagination.
*
- * @param secs2cache seconds to cache data, set to 0 to force query
- * @param sql
- * @param nrows is the number of rows per page to get
- * @param page is the page number to get (1-based)
- * @param [inputarr] array of bind variables
- * @return the recordset ($rs->databaseType == 'array')
+ * @param int $secs2cache seconds to cache data, set to 0 to force query
+ * @param string $sql
+ * @param int $nrows is the number of rows per page to get
+ * @param int $page is the page number to get (1-based)
+ * @param mixed[]|bool $inputarr array of bind variables
+ * @return mixed the recordset ($rs->databaseType == 'array')
*/
function CachePageExecute($secs2cache, $sql, $nrows, $page,$inputarr=false) {
/*switch($this->dataProvider) {
@@ -3051,8 +3234,79 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
break;
default: $secs2cache = 0; break;
}*/
- $rs = $this->PageExecute($sql,$nrows,$page,$inputarr,$secs2cache);
- return $rs;
+ return $this->PageExecute($sql,$nrows,$page,$inputarr,$secs2cache);
+ }
+
+ /**
+ * Returns the maximum size of a MetaType C field. If the method
+ * is not defined in the driver returns ADODB_STRINGMAX_NOTSET
+ *
+ * @return int
+ */
+ function charMax() {
+ return ADODB_STRINGMAX_NOTSET;
+ }
+
+ /**
+ * Returns the maximum size of a MetaType X field. If the method
+ * is not defined in the driver returns ADODB_STRINGMAX_NOTSET
+ *
+ * @return int
+ */
+ function textMax() {
+ return ADODB_STRINGMAX_NOTSET;
+ }
+
+ /**
+ * Returns a substring of a varchar type field
+ *
+ * Some databases have variations of the parameters, which is why
+ * we have an ADOdb function for it
+ *
+ * @param string $fld The field to sub-string
+ * @param int $start The start point
+ * @param int $length An optional length
+ *
+ * @return string The SQL text
+ */
+ function substr($fld,$start,$length=0) {
+ $text = "{$this->substr}($fld,$start";
+ if ($length > 0)
+ $text .= ",$length";
+ $text .= ')';
+ return $text;
+ }
+
+ /*
+ * Formats the date into Month only format MM with leading zeroes
+ *
+ * @param string $fld The name of the date to format
+ *
+ * @return string The SQL text
+ */
+ function month($fld) {
+ return $this->sqlDate('m',$fld);
+ }
+
+ /*
+ * Formats the date into Day only format DD with leading zeroes
+ *
+ * @param string $fld The name of the date to format
+ * @return string The SQL text
+ */
+ function day($fld) {
+ return $this->sqlDate('d',$fld);
+ }
+
+ /*
+ * Formats the date into year only format YYYY
+ *
+ * @param string $fld The name of the date to format
+ *
+ * @return string The SQL text
+ */
+ function year($fld) {
+ return $this->sqlDate('Y',$fld);
}
/**
@@ -3061,7 +3315,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* By clearing the message, it becomes possible to detect whether a new error
* has occurred, even when it is the same error as before being repeated.
*
- * @return array|null Array if an error has previously occurred. Null otherwise.
+ * @return mixed[]|null Array if an error has previously occurred. Null otherwise.
*/
protected function resetLastError() {
$error = error_get_last();
@@ -3075,18 +3329,18 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Compare a previously stored error message with the last error recorded by PHP
- * to determine whether a new error has occured.
+ * to determine whether a new error has occurred.
*
- * @param array|null $old Optional. Previously stored return value of error_get_last().
+ * @param mixed[]|null $old Optional. Previously stored return value of error_get_last().
*
- * @return string The error message if a new error has occured
- * or an empty string if no (new) errors have occured..
+ * @return string The error message if a new error has occurred
+ * or an empty string if no (new) errors have occurred..
*/
protected function getChangedErrorMsg($old = null) {
$new = error_get_last();
if (is_null($new)) {
- // No error has occured yet at all.
+ // No error has occurred yet at all.
return '';
}
@@ -3172,6 +3426,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
var $databaseType = false;
var $EOF = true;
var $_numOfRows = 0;
+ /** @var bool|array */
var $fields = false;
var $connection = false;
@@ -3246,7 +3501,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
// DATE AND TIME FUNCTIONS
//==============================================================================================
if (!defined('ADODB_DATE_VERSION')) {
- include(ADODB_DIR.'/adodb-time.inc.php');
+ include_once(ADODB_DIR.'/adodb-time.inc.php');
}
//==============================================================================================
@@ -3304,6 +3559,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* public variables
*/
var $dataProvider = "native";
+ /** @var bool|array */
var $fields = false; /// holds the current row data
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 editing.
@@ -3342,7 +3598,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Constructor
*
- * @param queryID this is the queryID returned by ADOConnection->_query()
+ * @param resource|int queryID this is the queryID returned by ADOConnection->_query()
*
*/
function __construct($queryID) {
@@ -3410,7 +3666,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
{
global $ADODB_INCLUDED_LIB;
if (empty($ADODB_INCLUDED_LIB)) {
- include(ADODB_DIR.'/adodb-lib.inc.php');
+ include_once(ADODB_DIR.'/adodb-lib.inc.php');
}
return _adodb_getmenu($this, $name, $defstr, $blank1stItem, $multiple,
$size, $selectAttr, $compareFirstCol);
@@ -3442,7 +3698,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
{
global $ADODB_INCLUDED_LIB;
if (empty($ADODB_INCLUDED_LIB)) {
- include(ADODB_DIR.'/adodb-lib.inc.php');
+ include_once(ADODB_DIR.'/adodb-lib.inc.php');
}
return _adodb_getmenu_gp($this, $name, $defstr, $blank1stItem, $multiple,
$size, $selectAttr, $compareFirstCol);
@@ -3503,15 +3759,11 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* return recordset as a 2-dimensional array.
*
- * @param [nRows] is the number of rows to return. -1 means every row.
+ * @param int $nRows Number of rows to return. -1 means every row.
*
- * @return an array indexed by the rows (0-based) from the recordset
+ * @return array indexed by the rows (0-based) from the recordset
*/
function GetArray($nRows = -1) {
- global $ADODB_EXTENSION; if ($ADODB_EXTENSION) {
- $results = adodb_getall($this,$nRows);
- return $results;
- }
$results = array();
$cnt = 0;
while (!$this->EOF && $nRows != $cnt) {
@@ -3523,8 +3775,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
function GetAll($nRows = -1) {
- $arr = $this->GetArray($nRows);
- return $arr;
+ return $this->GetArray($nRows);
}
/*
@@ -3542,12 +3793,11 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* @param offset is the row to start calculations from (1-based)
* @param [nrows] is the number of rows to return
*
- * @return an array indexed by the rows (0-based) from the recordset
+ * @return array an array indexed by the rows (0-based) from the recordset
*/
function GetArrayLimit($nrows,$offset=-1) {
if ($offset <= 0) {
- $arr = $this->GetArray($nrows);
- return $arr;
+ return $this->GetArray($nrows);
}
$this->Move($offset);
@@ -3568,137 +3818,163 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
*
* @param [nRows] is the number of rows to return. -1 means every row.
*
- * @return an array indexed by the rows (0-based) from the recordset
+ * @return array an array indexed by the rows (0-based) from the recordset
*/
function GetRows($nRows = -1) {
- $arr = $this->GetArray($nRows);
- return $arr;
+ return $this->GetArray($nRows);
}
/**
- * return whole recordset as a 2-dimensional associative array if there are more than 2 columns.
- * The first column is treated as the key and is not included in the array.
- * If there is only 2 columns, it will return a 1 dimensional array of key-value pairs unless
- * $force_array == true.
+ * return whole recordset as a 2-dimensional associative array if
+ * there are more than 2 columns. The first column is treated as the
+ * key and is not included in the array. If there is only 2 columns,
+ * it will return a 1 dimensional array of key-value pairs unless
+ * $force_array == true. This recordset method is currently part of
+ * the API, but may not be in later versions of ADOdb. By preference, use
+ * ADOconnnection::getAssoc()
*
- * @param [force_array] has only meaning if we have 2 data columns. If false, a 1 dimensional
- * array is returned, otherwise a 2 dimensional array is returned. If this sounds confusing,
- * read the source.
+ * @param bool $force_array (optional) Has only meaning if we have 2 data
+ * columns. If false, a 1 dimensional
+ * array is returned, otherwise a 2 dimensional
+ * array is returned. If this sounds confusing,
+ * read the source.
*
- * @param [first2cols] means if there are more than 2 cols, ignore the remaining cols and
- * instead of returning array[col0] => array(remaining cols), return array[col0] => col1
+ * @param bool $first2cols (optional) Means if there are more than
+ * 2 cols, ignore the remaining cols and
+ * instead of returning
+ * array[col0] => array(remaining cols),
+ * return array[col0] => col1
+ *
+ * @return mixed[]|false
*
- * @return an associative array indexed by the first column of the array,
- * or false if the data has less than 2 cols.
*/
- function GetAssoc($force_array = false, $first2cols = false) {
- global $ADODB_EXTENSION;
+ function getAssoc($force_array = false, $first2cols = false)
+ {
+ /*
+ * Insufficient rows to show data
+ */
+ if ($this->_numOfFields < 2)
+ return;
- $cols = $this->_numOfFields;
- if ($cols < 2) {
- return false;
- }
-
- // Empty recordset
+ /*
+ * Empty recordset
+ */
if (!$this->fields) {
return array();
}
- // Determine whether the array is associative or 0-based numeric
- $numIndex = array_keys($this->fields) == range(0, count($this->fields) - 1);
+ /*
+ * The number of fields is half the actual returned in BOTH mode
+ */
+ $numberOfFields = $this->_numOfFields;
- $results = array();
-
- if (!$first2cols && ($cols > 2 || $force_array)) {
- if ($ADODB_EXTENSION) {
- if ($numIndex) {
- while (!$this->EOF) {
- $results[trim($this->fields[0])] = array_slice($this->fields, 1);
- adodb_movenext($this);
- }
- } else {
- while (!$this->EOF) {
- // Fix for array_slice re-numbering numeric associative keys
- $keys = array_slice(array_keys($this->fields), 1);
- $sliced_array = array();
-
- foreach($keys as $key) {
- $sliced_array[$key] = $this->fields[$key];
- }
-
- $results[trim(reset($this->fields))] = $sliced_array;
- adodb_movenext($this);
- }
- }
- } else {
- if ($numIndex) {
- while (!$this->EOF) {
- $results[trim($this->fields[0])] = array_slice($this->fields, 1);
- $this->MoveNext();
- }
- } else {
- while (!$this->EOF) {
- // Fix for array_slice re-numbering numeric associative keys
- $keys = array_slice(array_keys($this->fields), 1);
- $sliced_array = array();
-
- foreach($keys as $key) {
- $sliced_array[$key] = $this->fields[$key];
- }
-
- $results[trim(reset($this->fields))] = $sliced_array;
- $this->MoveNext();
- }
- }
- }
- } else {
- if ($ADODB_EXTENSION) {
- // return scalar values
- if ($numIndex) {
- while (!$this->EOF) {
- // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string
- $results[trim(($this->fields[0]))] = $this->fields[1];
- adodb_movenext($this);
- }
- } else {
- while (!$this->EOF) {
- // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string
- $v1 = trim(reset($this->fields));
- $v2 = ''.next($this->fields);
- $results[$v1] = $v2;
- adodb_movenext($this);
- }
- }
- } else {
- if ($numIndex) {
- while (!$this->EOF) {
- // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string
- $results[trim(($this->fields[0]))] = $this->fields[1];
- $this->MoveNext();
- }
- } else {
- while (!$this->EOF) {
- // some bug in mssql PHP 4.02 -- doesn't handle references properly so we FORCE creating a new string
- $v1 = trim(reset($this->fields));
- $v2 = ''.next($this->fields);
- $results[$v1] = $v2;
- $this->MoveNext();
- }
- }
- }
+ /*
+ * Get the fetch mode when the call was executed, this may be
+ * different than ADODB_FETCH_MODE
+ */
+ $fetchMode = $this->connection->fetchMode;
+ if ($fetchMode == ADODB_FETCH_BOTH) {
+ /*
+ * If we are using BOTH, we present the data as if it
+ * was in ASSOC mode. This could be enhanced by adding
+ * a BOTH_ASSOC_MODE class property
+ * We build a template of numeric keys. you could improve the
+ * speed by caching this, indexed by number of keys
+ */
+ $testKeys = array_fill(0,$numberOfFields,0);
}
- $ref = $results; # workaround accelerator incompat with PHP 4.4 :(
- return $ref;
- }
+ $showArrayMethod = 0;
+ if ($numberOfFields == 2)
+ /*
+ * Key is always value of first element
+ * Value is always value of second element
+ */
+ $showArrayMethod = 1;
+
+ if ($force_array)
+ $showArrayMethod = 0;
+
+ if ($first2cols)
+ $showArrayMethod = 1;
+
+ $results = array();
+
+ while (!$this->EOF){
+
+ $myFields = $this->fields;
+
+ if ($fetchMode == ADODB_FETCH_BOTH) {
+ /*
+ * extract the associative keys
+ */
+ $myFields = array_diff_key($myFields,$testKeys);
+ }
+
+ /*
+ * key is value of first element, rest is data,
+ * The key is not case processed
+ */
+ $key = array_shift($myFields);
+
+ switch ($showArrayMethod) {
+ case 0:
+
+ if ($fetchMode == ADODB_FETCH_ASSOC
+ || $fetchMode == ADODB_FETCH_BOTH)
+ {
+ /*
+ * The driver should have already handled the key
+ * casing, but in case it did not. We will check and force
+ * this in later versions of ADOdb
+ */
+ if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_UPPER)
+ $myFields = array_change_key_case($myFields,CASE_UPPER);
+
+ elseif (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_LOWER)
+ $myFields = array_change_key_case($myFields,CASE_LOWER);
+
+ /*
+ * We have already shifted the key off
+ * the front, so the rest is the value
+ */
+ $results[$key] = $myFields;
+
+ }
+ else
+ /*
+ * I want the values in a numeric array,
+ * nicely re-indexed from zero
+ */
+ $results[$key] = array_values($myFields);
+ break;
+
+ case 1:
+
+ /*
+ * Don't care how long the array is,
+ * I just want value of second column, and it doesn't
+ * matter whether the array is associative or numeric
+ */
+ $results[$key] = array_shift($myFields);
+ break;
+ }
+
+ $this->MoveNext();
+ }
+ /*
+ * Done
+ */
+ return $results;
+ }
/**
*
- * @param v is the character timestamp in YYYY-MM-DD hh:mm:ss format
- * @param fmt is the format to apply to it, using date()
+ * @param mixed $v is the character timestamp in YYYY-MM-DD hh:mm:ss format
+ * @param string [$fmt] is the format to apply to it, using date()
*
- * @return a timestamp formated as user desires
+ * @return string a timestamp formated as user desires
*/
function UserTimeStamp($v,$fmt='Y-m-d H:i:s') {
if (is_numeric($v) && strlen($v)<14) {
@@ -3717,10 +3993,10 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
- * @param v is the character date in YYYY-MM-DD format, returned by database
- * @param fmt is the format to apply to it, using date()
+ * @param mixed $v is the character date in YYYY-MM-DD format, returned by database
+ * @param string $fmt is the format to apply to it, using date()
*
- * @return a date formated as user desires
+ * @return string a date formatted as user desires
*/
function UserDate($v,$fmt='Y-m-d') {
$tt = $this->UnixDate($v);
@@ -3737,9 +4013,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
- * @param $v is a date string in YYYY-MM-DD format
+ * @param mixed $v is a date string in YYYY-MM-DD format
*
- * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
+ * @return string date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
*/
static function UnixDate($v) {
return ADOConnection::UnixDate($v);
@@ -3747,9 +4023,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
- * @param $v is a timestamp string in YYYY-MM-DD HH-NN-SS format
+ * @param string|object $v is a timestamp string in YYYY-MM-DD HH-NN-SS format
*
- * @return date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
+ * @return mixed date in unix timestamp format, or 0 if before TIMESTAMP_FIRST_YEAR, or false if invalid date format
*/
static function UnixTimeStamp($v) {
return ADOConnection::UnixTimeStamp($v);
@@ -3765,26 +4041,30 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
- * PEAR DB compat, number of rows
- */
+ * PEAR DB compat, number of rows
+ *
+ * @return int
+ */
function NumRows() {
return $this->_numOfRows;
}
/**
- * PEAR DB compat, number of cols
- */
+ * PEAR DB compat, number of cols
+ *
+ * @return int
+ */
function NumCols() {
return $this->_numOfFields;
}
/**
- * Fetch a row, returning false if no more rows.
- * This is PEAR DB compat mode.
- *
- * @return false or array containing the current record
- */
+ * Fetch a row, returning false if no more rows.
+ * This is PEAR DB compat mode.
+ *
+ * @return mixed[]|false false or array containing the current record
+ */
function FetchRow() {
if ($this->EOF) {
return false;
@@ -3802,7 +4082,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* Fetch a row, returning PEAR_Error if no more rows.
* This is PEAR DB compat mode.
*
- * @return DB_OK or error object
+ * @param mixed[]|false $arr
+ *
+ * @return mixed DB_OK or error object
*/
function FetchInto(&$arr) {
if ($this->EOF) {
@@ -3817,7 +4099,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Move to the first row in the recordset. Many databases do NOT support this.
*
- * @return true or false
+ * @return bool true or false
*/
function MoveFirst() {
if ($this->_currentRow == 0) {
@@ -3830,7 +4112,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Move to the last row in the recordset.
*
- * @return true or false
+ * @return bool true or false
*/
function MoveLast() {
if ($this->_numOfRows >= 0) {
@@ -3852,7 +4134,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Move to next record in the recordset.
*
- * @return true if there still rows available, or false if there are no more rows (EOF).
+ * @return bool true if there still rows available, or false if there are no more rows (EOF).
*/
function MoveNext() {
if (!$this->EOF) {
@@ -3877,9 +4159,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* Random access to a specific row in the recordset. Some databases do not support
* access to previous rows in the databases (no scrolling backwards).
*
- * @param rowNumber is the row to move to (0-based)
+ * @param int $rowNumber is the row to move to (0-based)
*
- * @return true if there still rows available, or false if there are no more rows (EOF).
+ * @return bool true if there still rows available, or false if there are no more rows (EOF).
*/
function Move($rowNumber = 0) {
$this->EOF = false;
@@ -3911,18 +4193,11 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
if ($rowNumber < $this->_currentRow) {
return false;
}
- global $ADODB_EXTENSION;
- if ($ADODB_EXTENSION) {
- while (!$this->EOF && $this->_currentRow < $rowNumber) {
- adodb_movenext($this);
- }
- } else {
- while (! $this->EOF && $this->_currentRow < $rowNumber) {
- $this->_currentRow++;
+ while (! $this->EOF && $this->_currentRow < $rowNumber) {
+ $this->_currentRow++;
- if (!$this->_fetch()) {
- $this->EOF = true;
- }
+ if (!$this->_fetch()) {
+ $this->EOF = true;
}
}
return !($this->EOF);
@@ -3938,9 +4213,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* Get the value of a field in the current row by column name.
* Will not work if ADODB_FETCH_MODE is set to ADODB_FETCH_NUM.
*
- * @param colname is the field to access
+ * @param string $colname is the field to access
*
- * @return the value of $colname column
+ * @return mixed the value of $colname column
*/
function Fields($colname) {
return $this->fields[$colname];
@@ -3949,6 +4224,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Defines the function to use for table fields case conversion
* depending on ADODB_ASSOC_CASE
+ *
+ * @param int [$case]
+ *
* @return string strtolower/strtoupper or false if no conversion needed
*/
protected function AssocCaseConvertFunction($case = ADODB_ASSOC_CASE) {
@@ -3966,7 +4244,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Builds the bind array associating keys to recordset fields
*
- * @param int $upper Case for the array keys, defaults to uppercase
+ * @param int [$upper] Case for the array keys, defaults to uppercase
* (see ADODB_ASSOC_CASE_xxx constants)
*/
function GetAssocKeys($upper = ADODB_ASSOC_CASE) {
@@ -4003,7 +4281,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* Use associative array to get fields array for databases that do not support
* associative arrays. Submitted by Paolo S. Asioli paolo.asioli#libero.it
*
- * @param int $upper Case for the array keys, defaults to uppercase
+ * @param int [$upper] Case for the array keys, defaults to uppercase
* (see ADODB_ASSOC_CASE_xxx constants)
*/
function GetRowAssoc($upper = ADODB_ASSOC_CASE) {
@@ -4026,7 +4304,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Clean up recordset
*
- * @return true or false
+ * @return bool
*/
function Close() {
// free connection object - this seems to globally free the object
@@ -4040,19 +4318,21 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
/**
- * synonyms RecordCount and RowCount
+ * Synonyms RecordCount and RowCount
*
- * @return the number of rows or -1 if this is not supported
+ * @return int Number of rows or -1 if this is not supported
*/
function RecordCount() {
return $this->_numOfRows;
}
- /*
- * If we are using PageExecute(), this will return the maximum possible rows
- * that can be returned when paging a recordset.
- */
+ /**
+ * If we are using PageExecute(), this will return the maximum possible rows
+ * that can be returned when paging a recordset.
+ *
+ * @return int
+ */
function MaxRecordCount() {
return ($this->_maxRecordCount) ? $this->_maxRecordCount : $this->RecordCount();
}
@@ -4118,7 +4398,6 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
return $this->_numOfFields;
}
-
/**
* Get the ADOFieldObject of a specific column.
*
@@ -4137,9 +4416,12 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
*
*/
function FieldTypesArray() {
- $arr = array();
- for ($i=0, $max=$this->_numOfFields; $i < $max; $i++)
- $arr[] = $this->FetchField($i);
+ static $arr = array();
+ if (empty($arr)) {
+ for ($i=0, $max=$this->_numOfFields; $i < $max; $i++) {
+ $arr[] = $this->FetchField($i);
+ }
+ }
return $arr;
}
@@ -4150,8 +4432,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* @return the object with the properties set to the fields of the current row
*/
function FetchObj() {
- $o = $this->FetchObject(false);
- return $o;
+ return $this->FetchObject(false);
}
/**
@@ -4172,11 +4453,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
}
$i = 0;
- if (PHP_VERSION >= 5) {
- $o = clone($this->_obj);
- } else {
- $o = $this->_obj;
- }
+ $o = clone($this->_obj);
for ($i=0; $i <$this->_numOfFields; $i++) {
$name = $this->_names[$i];
@@ -4201,8 +4478,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
* Fixed bug reported by tim@orotech.net
*/
function FetchNextObj() {
- $o = $this->FetchNextObject(false);
- return $o;
+ return $this->FetchNextObject(false);
}
@@ -4261,6 +4537,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
$len = $fieldobj->max_length;
}
+
// changed in 2.32 to hashing instead of switch stmt for speed...
static $typeMap = array(
'VARCHAR' => 'C',
@@ -4367,9 +4644,10 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
"SQLBOOL" => 'L'
);
+
$tmap = false;
$t = strtoupper($t);
- $tmap = (isset($typeMap[$t])) ? $typeMap[$t] : 'N';
+ $tmap = (isset($typeMap[$t])) ? $typeMap[$t] : ADODB_DEFAULT_METATYPE;
switch ($tmap) {
case 'C':
// is the char field is too long, return as text field...
@@ -4522,7 +4800,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
global $ADODB_INCLUDED_LIB;
if (empty($ADODB_INCLUDED_LIB)) {
- include(ADODB_DIR.'/adodb-lib.inc.php');
+ include_once(ADODB_DIR.'/adodb-lib.inc.php');
}
$hdr = true;
@@ -4556,10 +4834,10 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
*
* @param array is a 2-dimensional array holding the data.
* The first row should hold the column names
- * unless paramter $colnames is used.
+ * unless parameter $colnames is used.
* @param typearr holds an array of types. These are the same types
* used in MetaTypes (C,B,L,I,N).
- * @param [colnames] array of column names. If set, then the first row of
+ * @param string[]|false [$colnames] array of column names. If set, then the first row of
* $array should not hold the column names.
*/
function InitArray($array,$typearr,$colnames=false) {
@@ -4577,10 +4855,10 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
/**
* Setup the Array and datatype file objects
*
- * @param array is a 2-dimensional array holding the data.
+ * @param array $array 2-dimensional array holding the data
* The first row should hold the column names
- * unless paramter $colnames is used.
- * @param fieldarr holds an array of ADOFieldObject's.
+ * unless parameter $colnames is used.
+ * @param array $fieldarr Array of ADOFieldObject's.
*/
function InitArrayFields(&$array,&$fieldarr) {
$this->_array = $array;
@@ -4591,12 +4869,15 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
$this->Init();
}
+ /**
+ * @param int [$nRows]
+ * @return array
+ */
function GetArray($nRows=-1) {
if ($nRows == -1 && $this->_currentRow <= 0 && !$this->_skiprow1) {
return $this->_array;
} else {
- $arr = ADORecordSet::GetArray($nRows);
- return $arr;
+ return ADORecordSet::GetArray($nRows);
}
}
@@ -4611,7 +4892,12 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
: sizeof($this->_types);
}
- /* Use associative array to get fields array */
+ /**
+ * Use associative array to get fields array
+ *
+ * @param string $colname
+ * @return mixed
+ */
function Fields($colname) {
$mode = isset($this->adodbFetchMode) ? $this->adodbFetchMode : $this->fetchMode;
@@ -4631,6 +4917,11 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
return $this->fields[$this->bind[strtoupper($colname)]];
}
+ /**
+ * @param int [$fieldOffset]
+ *
+ * @return \ADOFieldObject
+ */
function FetchField($fieldOffset = -1) {
if (isset($this->_fieldobjects)) {
return $this->_fieldobjects[$fieldOffset];
@@ -4643,6 +4934,10 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
return $o;
}
+ /**
+ * @param int $row
+ * @return bool
+ */
function _seek($row) {
if (sizeof($this->_array) && 0 <= $row && $row < $this->_numOfRows) {
$this->_currentRow = $row;
@@ -4655,6 +4950,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
return false;
}
+ /**
+ * @return bool
+ */
function MoveNext() {
if (!$this->EOF) {
$this->_currentRow++;
@@ -4678,6 +4976,9 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
return false;
}
+ /**
+ * @return bool
+ */
function _fetch() {
$pos = $this->_currentRow;
@@ -4725,9 +5026,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
$db = strtolower($dbType);
switch ($db) {
case 'ado':
- if (PHP_VERSION >= 5) {
- $db = 'ado5';
- }
+ $db = 'ado5';
$class = 'ado';
break;
@@ -4738,11 +5037,26 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
case 'pgsql':
case 'postgres':
- $class = $db = 'postgres8';
+ $class = $db = 'postgres9';
+ break;
+
+ case 'mysql':
+ // mysql driver deprecated since 5.5, removed in 7.0
+ // automatically switch to mysqli
+ if(version_compare(PHP_VERSION, '7.0.0', '>=')) {
+ $db = 'mysqli';
+ }
+ $class = $db;
break;
default:
- $class = $db; break;
+ if (substr($db, 0, 4) === 'pdo_') {
+ ADOConnection::outp("Invalid database type: $db");
+ return false;
+ }
+
+ $class = $db;
+ break;
}
$file = "drivers/adodb-$db.inc.php";
@@ -4762,20 +5076,24 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
}
/**
- * synonym for ADONewConnection for people like me who cannot remember the correct name
+ * Synonym for ADONewConnection for people like me who cannot remember the correct name
+ *
+ * @param string [$db]
+ *
+ * @return ADOConnection|false
*/
function NewADOConnection($db='') {
- $tmp = ADONewConnection($db);
- return $tmp;
+ return ADONewConnection($db);
}
/**
* Instantiate a new Connection class for a specific database driver.
*
- * @param [db] is the database Connection object to create. If undefined,
+ * @param string $db Database Connection object to create. If undefined,
* use the last database driver that was loaded by ADOLoadCode().
*
- * @return the freshly created instance of the Connection class.
+ * @return ADOConnection|false The freshly created instance of the Connection class
+ * or false in case of error.
*/
function ADONewConnection($db='') {
global $ADODB_NEWCONNECTION, $ADODB_LASTDB;
@@ -4783,6 +5101,13 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
if (!defined('ADODB_ASSOC_CASE')) {
define('ADODB_ASSOC_CASE', ADODB_ASSOC_CASE_NATIVE);
}
+
+ /*
+ * Are there special characters in the dsn password
+ * that disrupt parse_url
+ */
+ $needsSpecialCharacterHandling = false;
+
$errorfn = (defined('ADODB_ERROR_HANDLER')) ? ADODB_ERROR_HANDLER : false;
if (($at = strpos($db,'://')) !== FALSE) {
$origdsn = $db;
@@ -4804,9 +5129,28 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
$path = substr($path,0,$qmark);
}
$dsna['path'] = '/' . urlencode($path);
- } else
- $dsna = @parse_url($fakedsn);
-
+ } else {
+ /*
+ * Stop # character breaking parse_url
+ */
+ $cFakedsn = str_replace('#','\035',$fakedsn);
+ if (strcmp($fakedsn,$cFakedsn) != 0)
+ {
+ /*
+ * There is a # in the string
+ */
+ $needsSpecialCharacterHandling = true;
+
+ /*
+ * This allows us to successfully parse the url
+ */
+ $fakedsn = $cFakedsn;
+
+ }
+
+ $dsna = parse_url($fakedsn);
+ }
+
if (!$dsna) {
return false;
}
@@ -4832,11 +5176,20 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
if (!$db) {
return false;
}
+
$dsna['host'] = isset($dsna['host']) ? rawurldecode($dsna['host']) : '';
$dsna['user'] = isset($dsna['user']) ? rawurldecode($dsna['user']) : '';
$dsna['pass'] = isset($dsna['pass']) ? rawurldecode($dsna['pass']) : '';
$dsna['path'] = isset($dsna['path']) ? rawurldecode(substr($dsna['path'],1)) : ''; # strip off initial /
+ if ($needsSpecialCharacterHandling)
+ {
+ /*
+ * Revert back to the original string
+ */
+ $dsna = str_replace('\035','#',$dsna);
+ }
+
if (isset($dsna['query'])) {
$opt1 = explode('&',$dsna['query']);
foreach($opt1 as $k => $v) {
@@ -4846,6 +5199,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
} else {
$opt = array();
}
+
}
/*
* phptype: Database backend used in PHP (mysql, odbc etc.)
@@ -5030,9 +5384,8 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
if (!class_exists($class)) {
return false;
}
- $perf = new $class($conn);
- return $perf;
+ return new $class($conn);
}
function NewDataDictionary(&$conn,$drivername=false) {
@@ -5094,7 +5447,7 @@ http://www.stanford.edu/dept/itss/docs/oracle/10g/server.101/b10759/statements_1
function adodb_backtrace($printOrArr=true,$levels=9999,$ishtml=null) {
global $ADODB_INCLUDED_LIB;
if (empty($ADODB_INCLUDED_LIB)) {
- include(ADODB_DIR.'/adodb-lib.inc.php');
+ include_once(ADODB_DIR.'/adodb-lib.inc.php');
}
return _adodb_backtrace($printOrArr,$levels,0,$ishtml);
}
diff --git a/lib/adodb/datadict/datadict-access.inc.php b/lib/adodb/datadict/datadict-access.inc.php
index 6f68eb5779f..2291f01d8ea 100644
--- a/lib/adodb/datadict/datadict-access.inc.php
+++ b/lib/adodb/datadict/datadict-access.inc.php
@@ -1,7 +1,7 @@
debug) ADOConnection::outp("AlterColumnSQL not supported");
- return array();
+ $tabname = $this->TableName ($tabname);
+ $sql = array();
+ list($lines,$pkey,$idxs) = $this->_GenFields($flds);
+ // genfields can return FALSE at times
+ if ($lines == null) $lines = array();
+ $alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' ';
+
+ $dataTypeWords = array('SET','DATA','TYPE');
+
+ foreach($lines as $v)
+ {
+ /*
+ * We must now post-process the line to insert the 'SET DATA TYPE'
+ * text into the alter statement
+ */
+ $e = explode(' ',$v);
+
+ array_splice($e,1,0,$dataTypeWords);
+
+ $v = implode(' ',$e);
+
+ $sql[] = $alter . $v;
+ }
+ if (is_array($idxs))
+ {
+ foreach($idxs as $idx => $idxdef) {
+ $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
+ $sql = array_merge($sql, $sql_idxs);
+ }
+
+ }
+ return $sql;
}
- function DropColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
+
+ function dropColumnSql($tabname, $flds, $tableflds='',$tableoptions='')
{
- if ($this->debug) ADOConnection::outp("DropColumnSQL not supported");
- return array();
+
+
+ $tabname = $this->connection->getMetaCasedValue($tabname);
+ $flds = $this->connection->getMetaCasedValue($flds);
+
+ if (ADODB_ASSOC_CASE == ADODB_ASSOC_CASE_NATIVE )
+ {
+ /*
+ * METACASE_NATIVE
+ */
+ $tabname = $this->connection->nameQuote . $tabname . $this->connection->nameQuote;
+ $flds = $this->connection->nameQuote . $flds . $this->connection->nameQuote;
+ }
+ $sql = sprintf($this->dropCol,$tabname,$flds);
+ return (array)$sql;
+
}
+
-
- function ChangeTableSQL($tablename, $flds, $tableoptions = false)
+ function changeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFields=false)
{
/**
@@ -86,17 +135,25 @@ class ADODB2_db2 extends ADODB_DataDict {
$validTypes = array("CHAR","VARC");
$invalidTypes = array("BIGI","BLOB","CLOB","DATE", "DECI","DOUB", "INTE", "REAL","SMAL", "TIME");
// check table exists
- $cols = $this->MetaColumns($tablename);
+
+
+ $cols = $this->metaColumns($tablename);
if ( empty($cols)) {
- return $this->CreateTableSQL($tablename, $flds, $tableoptions);
+ return $this->createTableSQL($tablename, $flds, $tableoptions);
}
// already exists, alter table instead
list($lines,$pkey) = $this->_GenFields($flds);
- $alter = 'ALTER TABLE ' . $this->TableName($tablename);
+ $alter = 'ALTER TABLE ' . $this->tableName($tablename);
$sql = array();
foreach ( $lines as $id => $v ) {
+ /*
+ * If the metaCasing was NATIVE the col returned with nameQuotes
+ * around the field. We need to remove this for the metaColumn
+ * match
+ */
+ $id = str_replace($this->connection->nameQuote,'',$id);
if ( isset($cols[$id]) && is_object($cols[$id]) ) {
/**
If the first field of $v is the fieldname, and
diff --git a/lib/adodb/datadict/datadict-firebird.inc.php b/lib/adodb/datadict/datadict-firebird.inc.php
index 77a954eb76f..e5306fe266b 100644
--- a/lib/adodb/datadict/datadict-firebird.inc.php
+++ b/lib/adodb/datadict/datadict-firebird.inc.php
@@ -1,7 +1,7 @@
seqField = $fname;
+ $fconstraint = preg_replace("/``/", "\"", $fconstraint);
if ($fconstraint) $suffix .= ' '.$fconstraint;
return $suffix;
}
+ /**
+ Generate the SQL to create table. Returns an array of sql strings.
+ */
+ function CreateTableSQL($tabname, $flds, $tableoptions=array())
+ {
+ 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);
+
+ if ($this->autoIncrement && !isset($taboptions['DROP']))
+ { $tsql = $this->_Triggers($tabname,$taboptions);
+ foreach($tsql as $s) $sql[] = $s;
+ }
+
+ if (is_array($idxs)) {
+ foreach($idxs as $idx => $idxdef) {
+ $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
+ $sql = array_merge($sql, $sql_idxs);
+ }
+ }
+
+ return $sql;
+ }
+
+
/*
CREATE or replace TRIGGER jaddress_insert
before insert on jaddress
@@ -128,24 +167,60 @@ end;
else $tab = $tab1;
$seqField = $this->seqField;
$seqname = $this->schema.'.'.$this->seqPrefix.$tab;
- $trigname = $this->schema.'.trig_'.$this->seqPrefix.$tab;
+ $trigname = $this->schema.'.t_'.$this->seqPrefix.$tab;
} else {
$seqField = $this->seqField;
$seqname = $this->seqPrefix.$tab1;
- $trigname = 'trig_'.$seqname;
+ $trigname = 't_'.$seqname;
}
- if (isset($tableoptions['REPLACE']))
+
+ if (isset($tableoptions['DROP']))
+ { $sql[] = "DROP GENERATOR $seqname";
+ }
+ elseif (isset($tableoptions['REPLACE']))
{ $sql[] = "DROP GENERATOR \"$seqname\"";
$sql[] = "CREATE GENERATOR \"$seqname\"";
$sql[] = "ALTER TRIGGER \"$trigname\" BEFORE INSERT OR UPDATE AS BEGIN IF ( NEW.$seqField IS NULL OR NEW.$seqField = 0 ) THEN NEW.$seqField = GEN_ID(\"$seqname\", 1); END";
}
else
- { $sql[] = "CREATE GENERATOR \"$seqname\"";
- $sql[] = "CREATE TRIGGER \"$trigname\" FOR $tabname BEFORE INSERT OR UPDATE AS BEGIN IF ( NEW.$seqField IS NULL OR NEW.$seqField = 0 ) THEN NEW.$seqField = GEN_ID(\"$seqname\", 1); END";
+ { $sql[] = "CREATE GENERATOR $seqname";
+ $sql[] = "CREATE TRIGGER $trigname FOR $tabname BEFORE INSERT OR UPDATE AS BEGIN IF ( NEW.$seqField IS NULL OR NEW.$seqField = 0 ) THEN NEW.$seqField = GEN_ID($seqname, 1); END";
}
$this->seqField = false;
return $sql;
}
+ /**
+ * Change the definition of one column
+ *
+ * As some DBM's can't do that on there own, you need to supply the complete definition of the new table,
+ * to allow, recreating the table and copying the content over to the new table
+ * @param string $tabname table-name
+ * @param string $flds column-name and type for the changed column
+ * @param string $tableflds='' complete definition of the new table, eg. for postgres, default ''
+ * @param array/string $tableoptions='' options for the new table see CreateTableSQL, default ''
+ * @return array with SQL strings
+ */
+ function AlterColumnSQL($tabname, $flds, $tableflds='',$tableoptions='')
+ {
+ $tabname = $this->TableName ($tabname);
+ $sql = array();
+ list($lines,$pkey,$idxs) = $this->_GenFields($flds);
+ // genfields can return FALSE at times
+ if ($lines == null) $lines = array();
+ $alter = 'ALTER TABLE ' . $tabname . $this->alterCol . ' ';
+ foreach($lines as $v) {
+ $sql[] = $alter . $v;
+ }
+ if (is_array($idxs)) {
+ foreach($idxs as $idx => $idxdef) {
+ $sql_idxs = $this->CreateIndexSql($idx, $tabname, $idxdef['cols'], $idxdef['opts']);
+ $sql = array_merge($sql, $sql_idxs);
+ }
+
+ }
+ return $sql;
+ }
+
}
diff --git a/lib/adodb/datadict/datadict-generic.inc.php b/lib/adodb/datadict/datadict-generic.inc.php
index 7247544ed6f..f59b6de0dbc 100644
--- a/lib/adodb/datadict/datadict-generic.inc.php
+++ b/lib/adodb/datadict/datadict-generic.inc.php
@@ -1,7 +1,7 @@
'X'
);
- return $_typeConversion($t);
+ if (isset($_typeConversion[$t]))
+ return $_typeConversion[$t];
+
+ return ADODB_DEFAULT_METATYPE;
}
@@ -126,7 +132,6 @@ class ADODB2_mssqlnative extends ADODB_DataDict {
case 'F': return 'REAL';
case 'N': return 'NUMERIC';
default:
- print "RETURN $meta";
return $meta;
}
}
@@ -353,7 +358,7 @@ CREATE TABLE
}
- function _GetSize($ftype, $ty, $fsize, $fprec)
+ function _GetSize($ftype, $ty, $fsize, $fprec,$options=false)
{
switch ($ftype) {
case 'INT':
@@ -363,7 +368,7 @@ CREATE TABLE
return $ftype;
}
if ($ty == 'T') return $ftype;
- return parent::_GetSize($ftype, $ty, $fsize, $fprec);
+ return parent::_GetSize($ftype, $ty, $fsize, $fprec, $options);
}
}
diff --git a/lib/adodb/datadict/datadict-mysql.inc.php b/lib/adodb/datadict/datadict-mysql.inc.php
index e4f6e66e6d9..58f1110265b 100644
--- a/lib/adodb/datadict/datadict-mysql.inc.php
+++ b/lib/adodb/datadict/datadict-mysql.inc.php
@@ -1,7 +1,7 @@
type;
@@ -74,7 +77,7 @@ class ADODB2_mysql extends ADODB_DataDict {
case 'SMALLINT': return $is_serial ? 'R' : 'I2';
case 'MEDIUMINT': return $is_serial ? 'R' : 'I4';
case 'BIGINT': return $is_serial ? 'R' : 'I8';
- default: return 'N';
+ default: return ADODB_DEFAULT_METATYPE;
}
}
diff --git a/lib/adodb/datadict/datadict-oci8.inc.php b/lib/adodb/datadict/datadict-oci8.inc.php
index b09fed5eb1c..b330951a7b5 100644
--- a/lib/adodb/datadict/datadict-oci8.inc.php
+++ b/lib/adodb/datadict/datadict-oci8.inc.php
@@ -1,7 +1,7 @@
seqField) return array();
- if ($this->schema) {
+ if ($this->schema)
+ {
$t = strpos($tabname,'.');
- if ($t !== false) $tab = substr($tabname,$t+1);
- else $tab = $tabname;
+ if ($t !== false)
+ $tab = substr($tabname,$t+1);
+ else
+ $tab = $tabname;
+
+ if ($this->connection->useCompactAutoIncrements)
+ $id = sprintf('%u',crc32(strtolower($tab)));
+ else
+ $id = $tab;
+
$seqname = $this->schema.'.'.$this->seqPrefix.$tab;
$trigname = $this->schema.'.'.$this->trigPrefix.$this->seqPrefix.$tab;
- } else {
- $seqname = $this->seqPrefix.$tabname;
- $trigname = $this->trigPrefix.$seqname;
+
+ }
+ else
+ {
+ if ($this->connection->useCompactAutoIncrements)
+ $id = sprintf('%u',crc32(strtolower($tabname)));
+ else
+ $id = $tabname;
+
+ $seqname = $this->seqPrefix.$id;
+ $trigname = $this->trigPrefix.$id;
}
if (strlen($seqname) > 30) {
$seqname = $this->seqPrefix.uniqid('');
} // end if
+
if (strlen($trigname) > 30) {
$trigname = $this->trigPrefix.uniqid('');
} // end if
@@ -221,8 +251,8 @@ end;
$seqIncr = '';
if (isset($tableoptions['SEQUENCE_INCREMENT'])){$seqIncr = ' INCREMENT BY '.$tableoptions['SEQUENCE_INCREMENT'];}
$seqStart = '';
- if (isset($tableoptions['SEQUENCE_START'])){$seqIncr = ' START WITH '.$tableoptions['SEQUENCE_START'];}
- $sql[] = "CREATE SEQUENCE $seqname $seqStart $seqIncr $seqCache";
+ if (isset($tableoptions['SEQUENCE_START'])){$seqStart = ' START WITH '.$tableoptions['SEQUENCE_START'];}
+ $sql[] = "CREATE SEQUENCE $seqname MINVALUE 1 $seqStart $seqIncr $seqCache";
$sql[] = "CREATE OR REPLACE TRIGGER $trigname BEFORE insert ON $tabname FOR EACH ROW WHEN (NEW.$this->seqField IS NULL OR NEW.$this->seqField = 0) BEGIN select $seqname.nextval into :new.$this->seqField from dual; END;";
$this->seqField = false;
diff --git a/lib/adodb/datadict/datadict-postgres.inc.php b/lib/adodb/datadict/datadict-postgres.inc.php
index 7641e33917c..84136175cb6 100644
--- a/lib/adodb/datadict/datadict-postgres.inc.php
+++ b/lib/adodb/datadict/datadict-postgres.inc.php
@@ -1,7 +1,7 @@
MetaColumns($tabname) as $fld) {
- if (!$dropflds || !in_array($fld->name,$dropflds)) {
- // we need to explicit convert varchar to a number to be able to do an AlterColumn of a char column to a nummeric one
- if (preg_match('/'.$fld->name.' (I|I2|I4|I8|N|F)/i',$tableflds,$matches) &&
- in_array($fld->type,array('varchar','char','text','bytea'))) {
+ if (preg_match('/'.$fld->name.' (\w+)/i', $tableflds, $matches)) {
+ $new_type = strtoupper($matches[1]);
+ // AlterColumn of a char column to a nummeric one needs an explicit conversation
+ if (in_array($new_type, array('I', 'I2', 'I4', 'I8', 'N', 'F')) &&
+ in_array($fld->type, array('varchar','char','text','bytea'))
+ ) {
$copyflds[] = "to_number($fld->name,'S9999999999999D99')";
} else {
- $copyflds[] = $fld->name;
- }
- // identify the sequence name and the fld its on
- if ($fld->primary_key && $fld->has_default &&
- preg_match("/nextval\('([^']+)'::text\)/",$fld->default_value,$matches)) {
- $seq_name = $matches[1];
- $seq_fld = $fld->name;
+ // other column-type changes needs explicit decode, encode for bytea or cast otherwise
+ $new_actual_type = $this->ActualType($new_type);
+ if (strtoupper($fld->type) != $new_actual_type) {
+ if ($new_actual_type == 'BYTEA' && $fld->type == 'text') {
+ $copyflds[] = "DECODE($fld->name, 'escape')";
+ } elseif ($fld->type == 'bytea' && $new_actual_type == 'TEXT') {
+ $copyflds[] = "ENCODE($fld->name, 'escape')";
+ } else {
+ $copyflds[] = "CAST($fld->name AS $new_actual_type)";
+ }
+ }
}
+ } else {
+ $copyflds[] = $fld->name;
+ }
+ // identify the sequence name and the fld its on
+ if ($fld->primary_key && $fld->has_default &&
+ preg_match("/nextval\('([^']+)'::(text|regclass)\)/",$fld->default_value,$matches)) {
+ $seq_name = $matches[1];
+ $seq_fld = $fld->name;
}
}
$copyflds = implode(', ',$copyflds);
@@ -341,7 +358,7 @@ class ADODB2_postgres extends ADODB_DataDict {
$aSql[] = "SELECT setval('$seq_name',MAX($seq_fld)) FROM $tabname";
}
$aSql[] = "DROP TABLE $tempname";
- // recreate the indexes, if they not contain one of the droped columns
+ // recreate the indexes, if they not contain one of the dropped columns
foreach($this->MetaIndexes($tabname) as $idx_name => $idx_data)
{
if (substr($idx_name,-5) != '_pkey' && (!$dropflds || !count(array_intersect($dropflds,$idx_data['columns'])))) {
@@ -377,7 +394,7 @@ class ADODB2_postgres extends ADODB_DataDict {
return $suffix;
}
- // search for a sequece for the given table (asumes the seqence-name contains the table-name!)
+ // search for a sequence for the given table (asumes the seqence-name contains the table-name!)
// if yes return sql to drop it
// this is still necessary if postgres < 7.3 or the SERIAL was created on an earlier version!!!
function _DropAutoIncrement($tabname)
@@ -386,7 +403,7 @@ class ADODB2_postgres extends ADODB_DataDict {
$seq = $this->connection->GetOne("SELECT relname FROM pg_class WHERE NOT relname ~ 'pg_.*' AND relname LIKE $tabname AND relkind='S'");
- // check if a tables depends on the sequenz and it therefor cant and dont need to be droped separatly
+ // check if a tables depends on the sequence and it therefore can't and don't need to be dropped separately
if (!$seq || $this->connection->GetOne("SELECT relname FROM pg_class JOIN pg_depend ON pg_class.relfilenode=pg_depend.objid WHERE relname='$seq' AND relkind='S' AND deptype='i'")) {
return False;
}
@@ -472,13 +489,75 @@ CREATE [ UNIQUE ] INDEX index_name ON table
return $sql;
}
- function _GetSize($ftype, $ty, $fsize, $fprec)
+ function _GetSize($ftype, $ty, $fsize, $fprec, $options=false)
{
if (strlen($fsize) && $ty != 'X' && $ty != 'B' && $ty != 'I' && 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;
}
+
+ function ChangeTableSQL($tablename, $flds, $tableoptions = false, $dropOldFlds=false){
+ global $ADODB_FETCH_MODE;
+ parent::ChangeTableSQL($tablename, $flds);
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
+ if ($this->connection->fetchMode !== false)
+ $savem = $this->connection->SetFetchMode(false);
+
+ // check table exists
+ $save_handler = $this->connection->raiseErrorFn;
+ $this->connection->raiseErrorFn = '';
+ $cols = $this->MetaColumns($tablename);
+ $this->connection->raiseErrorFn = $save_handler;
+
+ if (isset($savem))
+ $this->connection->SetFetchMode($savem);
+ $ADODB_FETCH_MODE = $save;
+
+ $sqlResult=array();
+ if ( empty($cols)) {
+ $sqlResult=$this->CreateTableSQL($tablename, $flds, $tableoptions);
+ } else {
+ $sqlResultAdd = $this->AddColumnSQL($tablename, $flds);
+ $sqlResultAlter = $this->AlterColumnSQL($tablename, $flds, '', $tableoptions);
+ $sqlResult = array_merge((array)$sqlResultAdd, (array)$sqlResultAlter);
+
+ if ($dropOldFlds) {
+ // already exists, alter table instead
+ list($lines,$pkey,$idxs) = $this->_GenFields($flds);
+ // genfields can return FALSE at times
+ if ($lines == null)
+ $lines = array();
+ $alter = 'ALTER TABLE ' . $this->TableName($tablename);
+ foreach ( $cols as $id => $v ){
+ if ( !isset($lines[$id]) ){
+ $sqlResult[] = $alter . $this->dropCol . ' ' . $v->name;
+ }
+ }
+ }
+
+ }
+ return $sqlResult;
+ }
}
diff --git a/lib/adodb/datadict/datadict-sapdb.inc.php b/lib/adodb/datadict/datadict-sapdb.inc.php
index 6b6b15ca114..392d174c065 100644
--- a/lib/adodb/datadict/datadict-sapdb.inc.php
+++ b/lib/adodb/datadict/datadict-sapdb.inc.php
@@ -1,7 +1,7 @@
'F',
'FIXED' => 'N',
);
- $type = isset($maxdb_type2adodb[$t]) ? $maxdb_type2adodb[$t] : 'C';
+ $type = isset($maxdb_type2adodb[$t]) ? $maxdb_type2adodb[$t] : ADODB_DEFAULT_METATYPE;
// convert integer-types simulated with fixed back to integer
if ($t == 'FIXED' && !$fieldobj->scale && ($len == 20 || $len == 3)) {
diff --git a/lib/adodb/datadict/datadict-sqlite.inc.php b/lib/adodb/datadict/datadict-sqlite.inc.php
index c67ee3a6a28..12a68d1fa65 100644
--- a/lib/adodb/datadict/datadict-sqlite.inc.php
+++ b/lib/adodb/datadict/datadict-sqlite.inc.php
@@ -1,7 +1,7 @@
_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
-
$arr = $rs->GetArray();
//print_pre($arr);
$arr2 = array();
@@ -80,9 +71,6 @@ class ADORecordSet_access extends ADORecordSet_odbc {
var $databaseType = "access";
- function __construct($id,$mode=false)
- {
- return parent::__construct($id,$mode);
- }
-}// class
+} // class
+
}
diff --git a/lib/adodb/drivers/adodb-ado.inc.php b/lib/adodb/drivers/adodb-ado.inc.php
index 3363876835d..7c67a416cdb 100644
--- a/lib/adodb/drivers/adodb-ado.inc.php
+++ b/lib/adodb/drivers/adodb-ado.inc.php
@@ -1,6 +1,6 @@
= 5) return $this->_affectedRows;
-
- return $this->_affectedRows->value;
+ return $this->_affectedRows;
}
// you can also pass a connection string like this:
@@ -81,7 +79,7 @@ class ADODB_ado extends ADOConnection {
// not yet
//if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename";
- //use trusted conection for SQL if username not specified
+ //use trusted connection for SQL if username not specified
if (!$argUsername) $argHostname .= ";Trusted_Connection=Yes";
} else if ($argProvider=='access')
$argProvider = "Microsoft.Jet.OLEDB.4.0"; // Microsoft Jet Provider
@@ -350,7 +348,7 @@ class ADORecordSet_ado extends ADORecordSet {
$mode = $ADODB_FETCH_MODE;
}
$this->fetchMode = $mode;
- return parent::__construct($id,$mode);
+ parent::__construct($id);
}
@@ -538,7 +536,7 @@ class ADORecordSet_ado extends ADORecordSet {
case 19://adUnsignedInt = 19,
case 20://adUnsignedBigInt = 21,
return 'I';
- default: return 'N';
+ default: return ADODB_DEFAULT_METATYPE;
}
}
diff --git a/lib/adodb/drivers/adodb-ado5.inc.php b/lib/adodb/drivers/adodb-ado5.inc.php
index 014432732b0..0189e1264f5 100644
--- a/lib/adodb/drivers/adodb-ado5.inc.php
+++ b/lib/adodb/drivers/adodb-ado5.inc.php
@@ -1,6 +1,6 @@
= 5) return $this->_affectedRows;
-
- return $this->_affectedRows->value;
+ return $this->_affectedRows;
}
// you can also pass a connection string like this:
@@ -97,7 +95,7 @@ class ADODB_ado extends ADOConnection {
// not yet
//if ($argDatabasename) $argHostname .= ";Initial Catalog=$argDatabasename";
- //use trusted conection for SQL if username not specified
+ //use trusted connection for SQL if username not specified
if (!$argUsername) $argHostname .= ";Trusted_Connection=Yes";
} else if ($argProvider=='access')
$argProvider = "Microsoft.Jet.OLEDB.4.0"; // Microsoft Jet Provider
@@ -384,7 +382,7 @@ class ADORecordSet_ado extends ADORecordSet {
$mode = $ADODB_FETCH_MODE;
}
$this->fetchMode = $mode;
- return parent::__construct($id,$mode);
+ parent::__construct($id);
}
@@ -579,7 +577,7 @@ class ADORecordSet_ado extends ADORecordSet {
case 19://adUnsignedInt = 19,
case 20://adUnsignedBigInt = 21,
return 'I';
- default: return 'N';
+ default: return ADODB_DEFAULT_METATYPE;
}
}
diff --git a/lib/adodb/drivers/adodb-ado_access.inc.php b/lib/adodb/drivers/adodb-ado_access.inc.php
index 58dd0c85d12..7eb18e4ae2c 100644
--- a/lib/adodb/drivers/adodb-ado_access.inc.php
+++ b/lib/adodb/drivers/adodb-ado_access.inc.php
@@ -1,6 +1,6 @@
= 5) include(ADODB_DIR."/drivers/adodb-ado5.inc.php");
- else include(ADODB_DIR."/drivers/adodb-ado.inc.php");
+ include_once(ADODB_DIR . "/drivers/adodb-ado5.inc.php");
}
class ADODB_ado_access extends ADODB_ado {
@@ -43,8 +42,4 @@ class ADORecordSet_ado_access extends ADORecordSet_ado {
var $databaseType = "ado_access";
- function __construct($id,$mode=false)
- {
- return parent::__construct($id,$mode);
- }
}
diff --git a/lib/adodb/drivers/adodb-ado_mssql.inc.php b/lib/adodb/drivers/adodb-ado_mssql.inc.php
index d2ae2a4a544..f461c943113 100644
--- a/lib/adodb/drivers/adodb-ado_mssql.inc.php
+++ b/lib/adodb/drivers/adodb-ado_mssql.inc.php
@@ -1,6 +1,6 @@
= 5) include(ADODB_DIR."/drivers/adodb-ado5.inc.php");
- else include(ADODB_DIR."/drivers/adodb-ado.inc.php");
+ include_once(ADODB_DIR . "/drivers/adodb-ado5.inc.php");
}
@@ -43,12 +42,12 @@ class ADODB_ado_mssql extends ADODB_ado {
function _insertid()
{
- return $this->GetOne('select SCOPE_IDENTITY()');
+ return $this->GetOne('select SCOPE_IDENTITY()');
}
function _affectedrows()
{
- return $this->GetOne('select @@rowcount');
+ return $this->GetOne('select @@rowcount');
}
function SetTransactionMode( $transaction_mode )
@@ -62,40 +61,40 @@ class ADODB_ado_mssql extends ADODB_ado {
$this->Execute("SET TRANSACTION ".$transaction_mode);
}
- function qstr($s,$magic_quotes=false)
+ function qStr($s, $magic_quotes=false)
{
- $s = ADOConnection::qstr($s, $magic_quotes);
+ $s = ADOConnection::qStr($s);
return str_replace("\0", "\\\\000", $s);
}
function MetaColumns($table, $normalize=true)
{
- $table = strtoupper($table);
- $arr= array();
- $dbc = $this->_connectionID;
+ $table = strtoupper($table);
+ $arr= array();
+ $dbc = $this->_connectionID;
- $osoptions = array();
- $osoptions[0] = null;
- $osoptions[1] = null;
- $osoptions[2] = $table;
- $osoptions[3] = null;
+ $osoptions = array();
+ $osoptions[0] = null;
+ $osoptions[1] = null;
+ $osoptions[2] = $table;
+ $osoptions[3] = null;
- $adors=@$dbc->OpenSchema(4, $osoptions);//tables
+ $adors=@$dbc->OpenSchema(4, $osoptions);//tables
- if ($adors){
- while (!$adors->EOF){
- $fld = new ADOFieldObject();
- $c = $adors->Fields(3);
- $fld->name = $c->Value;
- $fld->type = 'CHAR'; // cannot discover type in ADO!
- $fld->max_length = -1;
- $arr[strtoupper($fld->name)]=$fld;
+ if ($adors){
+ while (!$adors->EOF){
+ $fld = new ADOFieldObject();
+ $c = $adors->Fields(3);
+ $fld->name = $c->Value;
+ $fld->type = 'CHAR'; // cannot discover type in ADO!
+ $fld->max_length = -1;
+ $arr[strtoupper($fld->name)]=$fld;
- $adors->MoveNext();
- }
- $adors->Close();
- }
- $false = false;
+ $adors->MoveNext();
+ }
+ $adors->Close();
+ }
+ $false = false;
return empty($arr) ? $false : $arr;
}
@@ -137,14 +136,10 @@ class ADODB_ado_mssql extends ADODB_ado {
//return $this->GetOne("SELECT CONVERT(varchar(255), NEWID()) AS 'Char'");
}
- } // end class
+} // end class
- class ADORecordSet_ado_mssql extends ADORecordSet_ado {
+class ADORecordSet_ado_mssql extends ADORecordSet_ado {
var $databaseType = 'ado_mssql';
- function __construct($id,$mode=false)
- {
- return parent::__construct($id,$mode);
- }
}
diff --git a/lib/adodb/drivers/adodb-ads.inc.php b/lib/adodb/drivers/adodb-ads.inc.php
index 8d31b2192b5..c87f5e25661 100644
--- a/lib/adodb/drivers/adodb-ads.inc.php
+++ b/lib/adodb/drivers/adodb-ads.inc.php
@@ -36,601 +36,630 @@ DELPHI FOR PHP USERS:
*/
// security - hide paths
-if (!defined('ADODB_DIR')) die();
+if (!defined('ADODB_DIR')) {
+ die();
+}
- define("_ADODB_ADS_LAYER", 2 );
+define("_ADODB_ADS_LAYER", 2);
/*--------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------*/
-class ADODB_ads extends ADOConnection {
- var $databaseType = "ads";
- var $fmt = "'m-d-Y'";
- var $fmtTimeStamp = "'Y-m-d H:i:s'";
- var $concat_operator = '';
- var $replaceQuote = "''"; // string to use to replace quotes
- var $dataProvider = "ads";
- var $hasAffectedRows = true;
- var $binmode = ODBC_BINMODE_RETURN;
- var $useFetchArray = false; // setting this to true will make array elements in FETCH_ASSOC mode case-sensitive
- // breaking backward-compat
- //var $longreadlen = 8000; // default number of chars to return for a Blob/Long field
- var $_bindInputArray = false;
- var $curmode = SQL_CUR_USE_DRIVER; // See sqlext.h, SQL_CUR_DEFAULT == SQL_CUR_USE_DRIVER == 2L
- var $_genSeqSQL = "create table %s (id integer)";
- var $_autocommit = true;
- var $_haserrorfunctions = true;
- var $_has_stupid_odbc_fetch_api_change = true;
- var $_lastAffectedRows = 0;
- var $uCaseTables = true; // for meta* functions, uppercase table names
-
-
- function __construct()
- {
- $this->_haserrorfunctions = ADODB_PHPVER >= 0x4050;
- $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
- }
-
- // returns true or false
- function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
- {
- if (!function_exists('ads_connect')) return null;
-
- if ($this->debug && $argDatabasename && $this->databaseType != 'vfp') {
- ADOConnection::outp("For Advantage Connect(), $argDatabasename is not used. Place dsn in 1st parameter.");
- }
- $last_php_error = $this->resetLastError();
- if ($this->curmode === false) $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword);
- else $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword,$this->curmode);
- $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
- if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
-
- return $this->_connectionID != false;
- }
-
- // returns true or false
- function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
- {
- if (!function_exists('ads_connect')) return null;
-
- $last_php_error = $this->resetLastError();
- $this->_errorMsg = '';
- if ($this->debug && $argDatabasename) {
- ADOConnection::outp("For PConnect(), $argDatabasename is not used. Place dsn in 1st parameter.");
- }
- // print "dsn=$argDSN u=$argUsername p=$argPassword "; flush();
- if ($this->curmode === false) $this->_connectionID = ads_connect($argDSN,$argUsername,$argPassword);
- else $this->_connectionID = ads_pconnect($argDSN,$argUsername,$argPassword,$this->curmode);
-
- $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
- if ($this->_connectionID && $this->autoRollback) @ads_rollback($this->_connectionID);
- if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
-
- return $this->_connectionID != false;
- }
-
- // returns the Server version and Description
- function ServerInfo()
- {
-
- if (!empty($this->host) && ADODB_PHPVER >= 0x4300) {
- $stmt = $this->Prepare('EXECUTE PROCEDURE sp_mgGetInstallInfo()');
- $res = $this->Execute($stmt);
- if(!$res)
- print $this->ErrorMsg();
- else{
- $ret["version"]= $res->fields[3];
- $ret["description"]="Advantage Database Server";
- return $ret;
- }
- }
- else {
- return ADOConnection::ServerInfo();
- }
- }
-
-
- // returns true or false
- function CreateSequence($seqname = 'adodbseq', $start = 1)
- {
- $res = $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE");
- if(!$res){
- print $this->ErrorMsg();
- return false;
- }
- else
- return true;
-
- }
-
- // returns true or false
- function DropSequence($seqname = 'adodbseq')
- {
- $res = $this->Execute("DROP TABLE $seqname");
- if(!$res){
- print $this->ErrorMsg();
- return false;
- }
- else
- return true;
- }
-
-
- // returns the generated ID or false
- // checks if the table already exists, else creates the table and inserts a record into the table
- // and gets the ID number of the last inserted record.
- function GenID($seqname = 'adodbseq', $start = 1)
- {
- $go = $this->Execute("select * from $seqname");
- if (!$go){
- $res = $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE");
- if(!res){
- print $this->ErrorMsg();
- return false;
- }
- }
- $res = $this->Execute("INSERT INTO $seqname VALUES( DEFAULT )");
- if(!$res){
- print $this->ErrorMsg();
- return false;
- }
- else{
- $gen = $this->Execute("SELECT LastAutoInc( STATEMENT ) FROM system.iota");
- $ret = $gen->fields[0];
- return $ret;
- }
-
- }
-
-
-
-
- function ErrorMsg()
- {
- if ($this->_haserrorfunctions) {
- if ($this->_errorMsg !== false) return $this->_errorMsg;
- if (empty($this->_connectionID)) return @ads_errormsg();
- return @ads_errormsg($this->_connectionID);
- } else return ADOConnection::ErrorMsg();
- }
-
-
- function ErrorNo()
- {
-
- if ($this->_haserrorfunctions) {
- if ($this->_errorCode !== false) {
- // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
- return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode;
- }
-
- if (empty($this->_connectionID)) $e = @ads_error();
- else $e = @ads_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();
- }
-
-
-
- function BeginTrans()
- {
- if (!$this->hasTransactions) return false;
- if ($this->transOff) return true;
- $this->transCnt += 1;
- $this->_autocommit = false;
- return ads_autocommit($this->_connectionID,false);
- }
-
- function CommitTrans($ok=true)
- {
- if ($this->transOff) return true;
- if (!$ok) return $this->RollbackTrans();
- if ($this->transCnt) $this->transCnt -= 1;
- $this->_autocommit = true;
- $ret = ads_commit($this->_connectionID);
- ads_autocommit($this->_connectionID,true);
- return $ret;
- }
-
- function RollbackTrans()
- {
- if ($this->transOff) return true;
- if ($this->transCnt) $this->transCnt -= 1;
- $this->_autocommit = true;
- $ret = ads_rollback($this->_connectionID);
- ads_autocommit($this->_connectionID,true);
- return $ret;
- }
-
-
- // Returns tables,Views or both on succesfull execution. Returns
- // tables by default on succesfull execustion.
- function &MetaTables($ttype = false, $showSchema = false, $mask = false)
- {
- $recordSet1 = $this->Execute("select * from system.tables");
- if(!$recordSet1){
- print $this->ErrorMsg();
- return false;
- }
- $recordSet2 = $this->Execute("select * from system.views");
- if(!$recordSet2){
- print $this->ErrorMsg();
- return false;
- }
- $i=0;
- while (!$recordSet1->EOF){
- $arr["$i"] = $recordSet1->fields[0];
- $recordSet1->MoveNext();
- $i=$i+1;
- }
- if($ttype=='FALSE'){
- while (!$recordSet2->EOF){
- $arr["$i"] = $recordSet2->fields[0];
- $recordSet2->MoveNext();
- $i=$i+1;
- }
- return $arr;
- }
- elseif($ttype=='VIEWS'){
- while (!$recordSet2->EOF){
- $arrV["$i"] = $recordSet2->fields[0];
- $recordSet2->MoveNext();
- $i=$i+1;
- }
- return $arrV;
- }
- else{
- return $arr;
- }
-
- }
-
- function &MetaPrimaryKeys($table, $owner = false)
- {
- $recordSet = $this->Execute("select table_primary_key from system.tables where name='$table'");
- if(!$recordSet){
- print $this->ErrorMsg();
- return false;
- }
- $i=0;
- while (!$recordSet->EOF){
- $arr["$i"] = $recordSet->fields[0];
- $recordSet->MoveNext();
- $i=$i+1;
- }
- return $arr;
- }
-
-/*
-See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcdatetime_data_type_changes.asp
-/ SQL data type codes /
-#define SQL_UNKNOWN_TYPE 0
-#define SQL_CHAR 1
-#define SQL_NUMERIC 2
-#define SQL_DECIMAL 3
-#define SQL_INTEGER 4
-#define SQL_SMALLINT 5
-#define SQL_FLOAT 6
-#define SQL_REAL 7
-#define SQL_DOUBLE 8
-#if (ODBCVER >= 0x0300)
-#define SQL_DATETIME 9
-#endif
-#define SQL_VARCHAR 12
-
-
-/ One-parameter shortcuts for date/time data types /
-#if (ODBCVER >= 0x0300)
-#define SQL_TYPE_DATE 91
-#define SQL_TYPE_TIME 92
-#define SQL_TYPE_TIMESTAMP 93
-
-#define SQL_UNICODE (-95)
-#define SQL_UNICODE_VARCHAR (-96)
-#define SQL_UNICODE_LONGVARCHAR (-97)
-*/
- function ODBCTypes($t)
- {
- switch ((integer)$t) {
- case 1:
- case 12:
- case 0:
- case -95:
- case -96:
- return 'C';
- case -97:
- case -1: //text
- return 'X';
- case -4: //image
- return 'B';
-
- case 9:
- case 91:
- return 'D';
-
- case 10:
- case 11:
- case 92:
- case 93:
- return 'T';
-
- case 4:
- case 5:
- case -6:
- return 'I';
-
- case -11: // uniqidentifier
- return 'R';
- case -7: //bit
- return 'L';
-
- default:
- return 'N';
- }
- }
-
- function &MetaColumns($table, $normalize = true)
- {
- global $ADODB_FETCH_MODE;
-
- $false = false;
- if ($this->uCaseTables) $table = strtoupper($table);
- $schema = '';
- $this->_findschema($table,$schema);
-
- $savem = $ADODB_FETCH_MODE;
- $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
-
- /*if (false) { // after testing, confirmed that the following does not work becoz of a bug
- $qid2 = ads_tables($this->_connectionID);
- $rs = new ADORecordSet_ads($qid2);
- $ADODB_FETCH_MODE = $savem;
- if (!$rs) return false;
- $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
- $rs->_fetch();
-
- while (!$rs->EOF) {
- if ($table == strtoupper($rs->fields[2])) {
- $q = $rs->fields[0];
- $o = $rs->fields[1];
- break;
- }
- $rs->MoveNext();
- }
- $rs->Close();
-
- $qid = ads_columns($this->_connectionID,$q,$o,strtoupper($table),'%');
- } */
-
- switch ($this->databaseType) {
- case 'access':
- case 'vfp':
- $qid = ads_columns($this->_connectionID);#,'%','',strtoupper($table),'%');
- break;
-
-
- case 'db2':
- $colname = "%";
- $qid = ads_columns($this->_connectionID, "", $schema, $table, $colname);
- break;
-
- default:
- $qid = @ads_columns($this->_connectionID,'%','%',strtoupper($table),'%');
- if (empty($qid)) $qid = ads_columns($this->_connectionID);
- break;
- }
- if (empty($qid)) return $false;
-
- $rs = new ADORecordSet_ads($qid);
- $ADODB_FETCH_MODE = $savem;
-
- if (!$rs) return $false;
- $rs->_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
- $rs->_fetch();
-
- $retarr = array();
-
- /*
- $rs->fields indices
- 0 TABLE_QUALIFIER
- 1 TABLE_SCHEM
- 2 TABLE_NAME
- 3 COLUMN_NAME
- 4 DATA_TYPE
- 5 TYPE_NAME
- 6 PRECISION
- 7 LENGTH
- 8 SCALE
- 9 RADIX
- 10 NULLABLE
- 11 REMARKS
- */
- while (!$rs->EOF) {
- // adodb_pr($rs->fields);
- if (strtoupper(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]);
-
- // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp
- // access uses precision to store length for char/varchar
- if ($fld->type == 'C' or $fld->type == 'X') {
- if ($this->databaseType == 'access')
- $fld->max_length = $rs->fields[6];
- else if ($rs->fields[4] <= -95) // UNICODE
- $fld->max_length = $rs->fields[7]/2;
- else
- $fld->max_length = $rs->fields[7];
- } else
- $fld->max_length = $rs->fields[7];
- $fld->not_null = !empty($rs->fields[10]);
- $fld->scale = $rs->fields[8];
- $retarr[strtoupper($fld->name)] = $fld;
- } else if (sizeof($retarr)>0)
- break;
- $rs->MoveNext();
- }
- $rs->Close(); //-- crashes 4.03pl1 -- why?
-
- if (empty($retarr)) $retarr = false;
- return $retarr;
- }
-
- // Returns an array of columns names for a given table
- function &MetaColumnNames($table, $numIndexes = false, $useattnum = false)
- {
- $recordSet = $this->Execute("select name from system.columns where parent='$table'");
- if(!$recordSet){
- print $this->ErrorMsg();
- return false;
- }
- else{
- $i=0;
- while (!$recordSet->EOF){
- $arr["FIELD$i"] = $recordSet->fields[0];
- $recordSet->MoveNext();
- $i=$i+1;
- }
- return $arr;
- }
- }
-
-
- function Prepare($sql)
- {
- if (! $this->_bindInputArray) return $sql; // no binding
- $stmt = ads_prepare($this->_connectionID,$sql);
- if (!$stmt) {
- // we don't know whether odbc driver is parsing prepared stmts, so just return sql
- return $sql;
- }
- return array($sql,$stmt,false);
- }
-
- /* returns queryID or false */
- function _query($sql,$inputarr=false)
- {
- $last_php_error = $this->resetLastError();
- $this->_errorMsg = '';
-
- if ($inputarr) {
- if (is_array($sql)) {
- $stmtid = $sql[1];
- } else {
- $stmtid = ads_prepare($this->_connectionID,$sql);
-
- if ($stmtid == false) {
- $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
- return false;
- }
- }
-
- if (! ads_execute($stmtid,$inputarr)) {
- //@ads_free_result($stmtid);
- if ($this->_haserrorfunctions) {
- $this->_errorMsg = ads_errormsg();
- $this->_errorCode = ads_error();
- }
- return false;
- }
-
- } else if (is_array($sql)) {
- $stmtid = $sql[1];
- if (!ads_execute($stmtid)) {
- //@ads_free_result($stmtid);
- if ($this->_haserrorfunctions) {
- $this->_errorMsg = ads_errormsg();
- $this->_errorCode = ads_error();
- }
- return false;
- }
- } else
- {
-
- $stmtid = ads_exec($this->_connectionID,$sql);
-
- }
-
- $this->_lastAffectedRows = 0;
-
- if ($stmtid) {
-
- if (@ads_num_fields($stmtid) == 0) {
- $this->_lastAffectedRows = ads_num_rows($stmtid);
- $stmtid = true;
-
- } else {
-
- $this->_lastAffectedRows = 0;
- ads_binmode($stmtid,$this->binmode);
- ads_longreadlen($stmtid,$this->maxblobsize);
-
- }
-
- if ($this->_haserrorfunctions) {
- $this->_errorMsg = '';
- $this->_errorCode = 0;
- } else {
- $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
- }
- } else {
- if ($this->_haserrorfunctions) {
- $this->_errorMsg = ads_errormsg();
- $this->_errorCode = ads_error();
- } else {
- $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
- }
- }
-
- return $stmtid;
-
- }
-
- /*
- Insert a null into the blob field of the table first.
- Then use UpdateBlob to store the blob.
-
- Usage:
-
- $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
- $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
- */
- function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
- {
- $last_php_error = $this->resetLastError();
- $sql = "UPDATE $table SET $column=? WHERE $where";
- $stmtid = ads_prepare($this->_connectionID,$sql);
- if ($stmtid == false){
- $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
- return false;
- }
- if (! ads_execute($stmtid,array($val),array(SQL_BINARY) )){
- if ($this->_haserrorfunctions){
- $this->_errorMsg = ads_errormsg();
- $this->_errorCode = ads_error();
- }
- return false;
- }
- return TRUE;
- }
-
- // returns true or false
- function _close()
- {
- $ret = @ads_close($this->_connectionID);
- $this->_connectionID = false;
- return $ret;
- }
-
- function _affectedrows()
- {
- return $this->_lastAffectedRows;
- }
+class ADODB_ads extends ADOConnection
+{
+ var $databaseType = "ads";
+ var $fmt = "'m-d-Y'";
+ var $fmtTimeStamp = "'Y-m-d H:i:s'";
+ var $concat_operator = '';
+ var $replaceQuote = "''"; // string to use to replace quotes
+ var $dataProvider = "ads";
+ var $hasAffectedRows = true;
+ var $binmode = ODBC_BINMODE_RETURN;
+ var $useFetchArray = false; // setting this to true will make array elements in FETCH_ASSOC mode case-sensitive
+ // breaking backward-compat
+ //var $longreadlen = 8000; // default number of chars to return for a Blob/Long field
+ var $_bindInputArray = false;
+ var $curmode = SQL_CUR_USE_DRIVER; // See sqlext.h, SQL_CUR_DEFAULT == SQL_CUR_USE_DRIVER == 2L
+ var $_genSeqSQL = "create table %s (id integer)";
+ var $_autocommit = true;
+ var $_lastAffectedRows = 0;
+ var $uCaseTables = true; // for meta* functions, uppercase table names
+
+ function __construct()
+ {
+ }
+
+ // returns true or false
+ function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('ads_connect')) {
+ return null;
+ }
+
+ if ($this->debug && $argDatabasename && $this->databaseType != 'vfp') {
+ ADOConnection::outp("For Advantage Connect(), $argDatabasename is not used. Place dsn in 1st parameter.");
+ }
+ $last_php_error = $this->resetLastError();
+ if ($this->curmode === false) {
+ $this->_connectionID = ads_connect($argDSN, $argUsername, $argPassword);
+ } else {
+ $this->_connectionID = ads_connect($argDSN, $argUsername, $argPassword, $this->curmode);
+ }
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ if (isset($this->connectStmt)) {
+ $this->Execute($this->connectStmt);
+ }
+
+ return $this->_connectionID != false;
+ }
+
+ // returns true or false
+ function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
+ {
+ if (!function_exists('ads_connect')) {
+ return null;
+ }
+
+ $last_php_error = $this->resetLastError();
+ $this->_errorMsg = '';
+ if ($this->debug && $argDatabasename) {
+ ADOConnection::outp("For PConnect(), $argDatabasename is not used. Place dsn in 1st parameter.");
+ }
+ // print "dsn=$argDSN u=$argUsername p=$argPassword "; flush();
+ if ($this->curmode === false) {
+ $this->_connectionID = ads_connect($argDSN, $argUsername, $argPassword);
+ } else {
+ $this->_connectionID = ads_pconnect($argDSN, $argUsername, $argPassword, $this->curmode);
+ }
+
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ if ($this->_connectionID && $this->autoRollback) {
+ @ads_rollback($this->_connectionID);
+ }
+ if (isset($this->connectStmt)) {
+ $this->Execute($this->connectStmt);
+ }
+
+ return $this->_connectionID != false;
+ }
+
+ // returns the Server version and Description
+ function ServerInfo()
+ {
+
+ if (!empty($this->host)) {
+ $stmt = $this->Prepare('EXECUTE PROCEDURE sp_mgGetInstallInfo()');
+ $res = $this->Execute($stmt);
+ if (!$res) {
+ print $this->ErrorMsg();
+ } else {
+ $ret["version"] = $res->fields[3];
+ $ret["description"] = "Advantage Database Server";
+ return $ret;
+ }
+ } else {
+ return ADOConnection::ServerInfo();
+ }
+ }
+
+
+ // returns true or false
+ function CreateSequence($seqname = 'adodbseq', $start = 1)
+ {
+ $res = $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE");
+ if (!$res) {
+ print $this->ErrorMsg();
+ return false;
+ } else {
+ return true;
+ }
+
+ }
+
+ // returns true or false
+ function DropSequence($seqname = 'adodbseq')
+ {
+ $res = $this->Execute("DROP TABLE $seqname");
+ if (!$res) {
+ print $this->ErrorMsg();
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+
+ // returns the generated ID or false
+ // checks if the table already exists, else creates the table and inserts a record into the table
+ // and gets the ID number of the last inserted record.
+ function GenID($seqname = 'adodbseq', $start = 1)
+ {
+ $go = $this->Execute("select * from $seqname");
+ if (!$go) {
+ $res = $this->Execute("CREATE TABLE $seqname ( ID autoinc( 1 ) ) IN DATABASE");
+ if (!$res) {
+ print $this->ErrorMsg();
+ return false;
+ }
+ }
+ $res = $this->Execute("INSERT INTO $seqname VALUES( DEFAULT )");
+ if (!$res) {
+ print $this->ErrorMsg();
+ return false;
+ } else {
+ $gen = $this->Execute("SELECT LastAutoInc( STATEMENT ) FROM system.iota");
+ $ret = $gen->fields[0];
+ return $ret;
+ }
+
+ }
+
+
+ function ErrorMsg()
+ {
+ if ($this->_errorMsg !== false) {
+ return $this->_errorMsg;
+ }
+ if (empty($this->_connectionID)) {
+ return @ads_errormsg();
+ }
+ return @ads_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 (empty($this->_connectionID)) {
+ $e = @ads_error();
+ } else {
+ $e = @ads_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;
+ }
+
+
+ function BeginTrans()
+ {
+ if (!$this->hasTransactions) {
+ return false;
+ }
+ if ($this->transOff) {
+ return true;
+ }
+ $this->transCnt += 1;
+ $this->_autocommit = false;
+ return ads_autocommit($this->_connectionID, false);
+ }
+
+ function CommitTrans($ok = true)
+ {
+ if ($this->transOff) {
+ return true;
+ }
+ if (!$ok) {
+ return $this->RollbackTrans();
+ }
+ if ($this->transCnt) {
+ $this->transCnt -= 1;
+ }
+ $this->_autocommit = true;
+ $ret = ads_commit($this->_connectionID);
+ ads_autocommit($this->_connectionID, true);
+ return $ret;
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) {
+ return true;
+ }
+ if ($this->transCnt) {
+ $this->transCnt -= 1;
+ }
+ $this->_autocommit = true;
+ $ret = ads_rollback($this->_connectionID);
+ ads_autocommit($this->_connectionID, true);
+ return $ret;
+ }
+
+
+ // Returns tables,Views or both on successful execution. Returns
+ // tables by default on successful execution.
+ function &MetaTables($ttype = false, $showSchema = false, $mask = false)
+ {
+ $recordSet1 = $this->Execute("select * from system.tables");
+ if (!$recordSet1) {
+ print $this->ErrorMsg();
+ return false;
+ }
+ $recordSet2 = $this->Execute("select * from system.views");
+ if (!$recordSet2) {
+ print $this->ErrorMsg();
+ return false;
+ }
+ $i = 0;
+ while (!$recordSet1->EOF) {
+ $arr["$i"] = $recordSet1->fields[0];
+ $recordSet1->MoveNext();
+ $i = $i + 1;
+ }
+ if ($ttype == 'FALSE') {
+ while (!$recordSet2->EOF) {
+ $arr["$i"] = $recordSet2->fields[0];
+ $recordSet2->MoveNext();
+ $i = $i + 1;
+ }
+ return $arr;
+ } elseif ($ttype == 'VIEWS') {
+ while (!$recordSet2->EOF) {
+ $arrV["$i"] = $recordSet2->fields[0];
+ $recordSet2->MoveNext();
+ $i = $i + 1;
+ }
+ return $arrV;
+ } else {
+ return $arr;
+ }
+
+ }
+
+ function &MetaPrimaryKeys($table, $owner = false)
+ {
+ $recordSet = $this->Execute("select table_primary_key from system.tables where name='$table'");
+ if (!$recordSet) {
+ print $this->ErrorMsg();
+ return false;
+ }
+ $i = 0;
+ while (!$recordSet->EOF) {
+ $arr["$i"] = $recordSet->fields[0];
+ $recordSet->MoveNext();
+ $i = $i + 1;
+ }
+ return $arr;
+ }
+
+ /*
+ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcdatetime_data_type_changes.asp
+ / SQL data type codes /
+ #define SQL_UNKNOWN_TYPE 0
+ #define SQL_CHAR 1
+ #define SQL_NUMERIC 2
+ #define SQL_DECIMAL 3
+ #define SQL_INTEGER 4
+ #define SQL_SMALLINT 5
+ #define SQL_FLOAT 6
+ #define SQL_REAL 7
+ #define SQL_DOUBLE 8
+ #if (ODBCVER >= 0x0300)
+ #define SQL_DATETIME 9
+ #endif
+ #define SQL_VARCHAR 12
+
+
+ / One-parameter shortcuts for date/time data types /
+ #if (ODBCVER >= 0x0300)
+ #define SQL_TYPE_DATE 91
+ #define SQL_TYPE_TIME 92
+ #define SQL_TYPE_TIMESTAMP 93
+
+ #define SQL_UNICODE (-95)
+ #define SQL_UNICODE_VARCHAR (-96)
+ #define SQL_UNICODE_LONGVARCHAR (-97)
+ */
+ function ODBCTypes($t)
+ {
+ switch ((integer)$t) {
+ case 1:
+ case 12:
+ case 0:
+ case -95:
+ case -96:
+ return 'C';
+ case -97:
+ case -1: //text
+ return 'X';
+ case -4: //image
+ return 'B';
+
+ case 9:
+ case 91:
+ return 'D';
+
+ case 10:
+ case 11:
+ case 92:
+ case 93:
+ return 'T';
+
+ case 4:
+ case 5:
+ case -6:
+ return 'I';
+
+ case -11: // uniqidentifier
+ return 'R';
+ case -7: //bit
+ return 'L';
+
+ default:
+ return 'N';
+ }
+ }
+
+ function &MetaColumns($table, $normalize = true)
+ {
+ global $ADODB_FETCH_MODE;
+
+ $false = false;
+ if ($this->uCaseTables) {
+ $table = strtoupper($table);
+ }
+ $schema = '';
+ $this->_findschema($table, $schema);
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ /*if (false) { // after testing, confirmed that the following does not work because of a bug
+ $qid2 = ads_tables($this->_connectionID);
+ $rs = new ADORecordSet_ads($qid2);
+ $ADODB_FETCH_MODE = $savem;
+ if (!$rs) return false;
+ $rs->_fetch();
+
+ while (!$rs->EOF) {
+ if ($table == strtoupper($rs->fields[2])) {
+ $q = $rs->fields[0];
+ $o = $rs->fields[1];
+ break;
+ }
+ $rs->MoveNext();
+ }
+ $rs->Close();
+
+ $qid = ads_columns($this->_connectionID,$q,$o,strtoupper($table),'%');
+ } */
+
+ switch ($this->databaseType) {
+ case 'access':
+ case 'vfp':
+ $qid = ads_columns($this->_connectionID);#,'%','',strtoupper($table),'%');
+ break;
+
+
+ case 'db2':
+ $colname = "%";
+ $qid = ads_columns($this->_connectionID, "", $schema, $table, $colname);
+ break;
+
+ default:
+ $qid = @ads_columns($this->_connectionID, '%', '%', strtoupper($table), '%');
+ if (empty($qid)) {
+ $qid = ads_columns($this->_connectionID);
+ }
+ break;
+ }
+ if (empty($qid)) {
+ return $false;
+ }
+
+ $rs = new ADORecordSet_ads($qid);
+ $ADODB_FETCH_MODE = $savem;
+
+ if (!$rs) {
+ return $false;
+ }
+ $rs->_fetch();
+
+ $retarr = array();
+
+ /*
+ $rs->fields indices
+ 0 TABLE_QUALIFIER
+ 1 TABLE_SCHEM
+ 2 TABLE_NAME
+ 3 COLUMN_NAME
+ 4 DATA_TYPE
+ 5 TYPE_NAME
+ 6 PRECISION
+ 7 LENGTH
+ 8 SCALE
+ 9 RADIX
+ 10 NULLABLE
+ 11 REMARKS
+ */
+ while (!$rs->EOF) {
+ // adodb_pr($rs->fields);
+ if (strtoupper(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]);
+
+ // ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp
+ // access uses precision to store length for char/varchar
+ if ($fld->type == 'C' or $fld->type == 'X') {
+ if ($this->databaseType == 'access') {
+ $fld->max_length = $rs->fields[6];
+ } else {
+ if ($rs->fields[4] <= -95) // UNICODE
+ {
+ $fld->max_length = $rs->fields[7] / 2;
+ } else {
+ $fld->max_length = $rs->fields[7];
+ }
+ }
+ } else {
+ $fld->max_length = $rs->fields[7];
+ }
+ $fld->not_null = !empty($rs->fields[10]);
+ $fld->scale = $rs->fields[8];
+ $retarr[strtoupper($fld->name)] = $fld;
+ } else {
+ if (sizeof($retarr) > 0) {
+ break;
+ }
+ }
+ $rs->MoveNext();
+ }
+ $rs->Close(); //-- crashes 4.03pl1 -- why?
+
+ if (empty($retarr)) {
+ $retarr = false;
+ }
+ return $retarr;
+ }
+
+ // Returns an array of columns names for a given table
+ function &MetaColumnNames($table, $numIndexes = false, $useattnum = false)
+ {
+ $recordSet = $this->Execute("select name from system.columns where parent='$table'");
+ if (!$recordSet) {
+ print $this->ErrorMsg();
+ return false;
+ } else {
+ $i = 0;
+ while (!$recordSet->EOF) {
+ $arr["FIELD$i"] = $recordSet->fields[0];
+ $recordSet->MoveNext();
+ $i = $i + 1;
+ }
+ return $arr;
+ }
+ }
+
+
+ function Prepare($sql)
+ {
+ if (!$this->_bindInputArray) {
+ return $sql;
+ } // no binding
+ $stmt = ads_prepare($this->_connectionID, $sql);
+ if (!$stmt) {
+ // we don't know whether odbc driver is parsing prepared stmts, so just return sql
+ return $sql;
+ }
+ return array($sql, $stmt, false);
+ }
+
+ /* returns queryID or false */
+ function _query($sql, $inputarr = false)
+ {
+ $last_php_error = $this->resetLastError();
+ $this->_errorMsg = '';
+
+ if ($inputarr) {
+ if (is_array($sql)) {
+ $stmtid = $sql[1];
+ } else {
+ $stmtid = ads_prepare($this->_connectionID, $sql);
+
+ if ($stmtid == false) {
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ return false;
+ }
+ }
+
+ if (!ads_execute($stmtid, $inputarr)) {
+ //@ads_free_result($stmtid);
+ $this->_errorMsg = ads_errormsg();
+ $this->_errorCode = ads_error();
+ return false;
+ }
+
+ } else {
+ if (is_array($sql)) {
+ $stmtid = $sql[1];
+ if (!ads_execute($stmtid)) {
+ //@ads_free_result($stmtid);
+ $this->_errorMsg = ads_errormsg();
+ $this->_errorCode = ads_error();
+ return false;
+ }
+ } else {
+
+ $stmtid = ads_exec($this->_connectionID, $sql);
+
+ }
+ }
+
+ $this->_lastAffectedRows = 0;
+
+ if ($stmtid) {
+
+ if (@ads_num_fields($stmtid) == 0) {
+ $this->_lastAffectedRows = ads_num_rows($stmtid);
+ $stmtid = true;
+
+ } else {
+
+ $this->_lastAffectedRows = 0;
+ ads_binmode($stmtid, $this->binmode);
+ ads_longreadlen($stmtid, $this->maxblobsize);
+
+ }
+
+ $this->_errorMsg = '';
+ $this->_errorCode = 0;
+ } else {
+ $this->_errorMsg = ads_errormsg();
+ $this->_errorCode = ads_error();
+ }
+
+ return $stmtid;
+
+ }
+
+ /*
+ Insert a null into the blob field of the table first.
+ Then use UpdateBlob to store the blob.
+
+ Usage:
+
+ $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
+ $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
+ */
+ function UpdateBlob($table, $column, $val, $where, $blobtype = 'BLOB')
+ {
+ $last_php_error = $this->resetLastError();
+ $sql = "UPDATE $table SET $column=? WHERE $where";
+ $stmtid = ads_prepare($this->_connectionID, $sql);
+ if ($stmtid == false) {
+ $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ return false;
+ }
+ if (!ads_execute($stmtid, array($val), array(SQL_BINARY))) {
+ $this->_errorMsg = ads_errormsg();
+ $this->_errorCode = ads_error();
+ return false;
+ }
+ return true;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ $ret = @ads_close($this->_connectionID);
+ $this->_connectionID = false;
+ return $ret;
+ }
+
+ function _affectedrows()
+ {
+ return $this->_lastAffectedRows;
+ }
}
@@ -638,139 +667,142 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/od
Class Name: Recordset
--------------------------------------------------------------------------------------*/
-class ADORecordSet_ads extends ADORecordSet {
+class ADORecordSet_ads extends ADORecordSet
+{
- var $bind = false;
- var $databaseType = "ads";
- var $dataProvider = "ads";
- var $useFetchArray;
- var $_has_stupid_odbc_fetch_api_change;
+ var $bind = false;
+ var $databaseType = "ads";
+ var $dataProvider = "ads";
+ var $useFetchArray;
- function __construct($id,$mode=false)
- {
- if ($mode === false) {
- global $ADODB_FETCH_MODE;
- $mode = $ADODB_FETCH_MODE;
- }
- $this->fetchMode = $mode;
+ function __construct($id, $mode = false)
+ {
+ if ($mode === false) {
+ global $ADODB_FETCH_MODE;
+ $mode = $ADODB_FETCH_MODE;
+ }
+ $this->fetchMode = $mode;
- $this->_queryID = $id;
+ $this->_queryID = $id;
- // the following is required for mysql odbc driver in 4.3.1 -- why?
- $this->EOF = false;
- $this->_currentRow = -1;
- //parent::__construct($id);
- }
+ // the following is required for mysql odbc driver in 4.3.1 -- why?
+ $this->EOF = false;
+ $this->_currentRow = -1;
+ //parent::__construct($id);
+ }
- // returns the field object
- function &FetchField($fieldOffset = -1)
- {
+ // returns the field object
+ function &FetchField($fieldOffset = -1)
+ {
- $off=$fieldOffset+1; // offsets begin at 1
+ $off = $fieldOffset + 1; // offsets begin at 1
- $o= new ADOFieldObject();
- $o->name = @ads_field_name($this->_queryID,$off);
- $o->type = @ads_field_type($this->_queryID,$off);
- $o->max_length = @ads_field_len($this->_queryID,$off);
- if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
- else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
- return $o;
- }
+ $o = new ADOFieldObject();
+ $o->name = @ads_field_name($this->_queryID, $off);
+ $o->type = @ads_field_type($this->_queryID, $off);
+ $o->max_length = @ads_field_len($this->_queryID, $off);
+ if (ADODB_ASSOC_CASE == 0) {
+ $o->name = strtolower($o->name);
+ } else {
+ if (ADODB_ASSOC_CASE == 1) {
+ $o->name = strtoupper($o->name);
+ }
+ }
+ return $o;
+ }
- /* Use associative array to get fields array */
- function Fields($colname)
- {
- if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
- if (!$this->bind) {
- $this->bind = array();
- for ($i=0; $i < $this->_numOfFields; $i++) {
- $o = $this->FetchField($i);
- $this->bind[strtoupper($o->name)] = $i;
- }
- }
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ return $this->fields[$colname];
+ }
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i = 0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
- return $this->fields[$this->bind[strtoupper($colname)]];
- }
+ return $this->fields[$this->bind[strtoupper($colname)]];
+ }
- function _initrs()
- {
- global $ADODB_COUNTRECS;
- $this->_numOfRows = ($ADODB_COUNTRECS) ? @ads_num_rows($this->_queryID) : -1;
- $this->_numOfFields = @ads_num_fields($this->_queryID);
- // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0
- if ($this->_numOfRows == 0) $this->_numOfRows = -1;
- //$this->useFetchArray = $this->connection->useFetchArray;
- $this->_has_stupid_odbc_fetch_api_change = ADODB_PHPVER >= 0x4200;
- }
+ function _initrs()
+ {
+ global $ADODB_COUNTRECS;
+ $this->_numOfRows = ($ADODB_COUNTRECS) ? @ads_num_rows($this->_queryID) : -1;
+ $this->_numOfFields = @ads_num_fields($this->_queryID);
+ // some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0
+ if ($this->_numOfRows == 0) {
+ $this->_numOfRows = -1;
+ }
+ //$this->useFetchArray = $this->connection->useFetchArray;
+ }
- function _seek($row)
- {
- return false;
- }
+ function _seek($row)
+ {
+ return false;
+ }
- // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated
- function &GetArrayLimit($nrows,$offset=-1)
- {
- if ($offset <= 0) {
- $rs =& $this->GetArray($nrows);
- return $rs;
- }
- $savem = $this->fetchMode;
- $this->fetchMode = ADODB_FETCH_NUM;
- $this->Move($offset);
- $this->fetchMode = $savem;
+ // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated
+ function &GetArrayLimit($nrows, $offset = -1)
+ {
+ if ($offset <= 0) {
+ $rs =& $this->GetArray($nrows);
+ return $rs;
+ }
+ $savem = $this->fetchMode;
+ $this->fetchMode = ADODB_FETCH_NUM;
+ $this->Move($offset);
+ $this->fetchMode = $savem;
- if ($this->fetchMode & ADODB_FETCH_ASSOC) {
- $this->fields =& $this->GetRowAssoc();
- }
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ $this->fields =& $this->GetRowAssoc();
+ }
- $results = array();
- $cnt = 0;
- while (!$this->EOF && $nrows != $cnt) {
- $results[$cnt++] = $this->fields;
- $this->MoveNext();
- }
+ $results = array();
+ $cnt = 0;
+ while (!$this->EOF && $nrows != $cnt) {
+ $results[$cnt++] = $this->fields;
+ $this->MoveNext();
+ }
- return $results;
- }
+ return $results;
+ }
- function MoveNext()
- {
- if ($this->_numOfRows != 0 && !$this->EOF) {
- $this->_currentRow++;
- if( $this->_fetch() ) {
- return true;
- }
- }
- $this->fields = false;
- $this->EOF = true;
- return false;
- }
+ function MoveNext()
+ {
+ if ($this->_numOfRows != 0 && !$this->EOF) {
+ $this->_currentRow++;
+ if ($this->_fetch()) {
+ return true;
+ }
+ }
+ $this->fields = false;
+ $this->EOF = true;
+ return false;
+ }
- function _fetch()
- {
- $this->fields = false;
- if ($this->_has_stupid_odbc_fetch_api_change)
- $rez = @ads_fetch_into($this->_queryID,$this->fields);
- else {
- $row = 0;
- $rez = @ads_fetch_into($this->_queryID,$row,$this->fields);
- }
- if ($rez) {
- if ($this->fetchMode & ADODB_FETCH_ASSOC) {
- $this->fields =& $this->GetRowAssoc();
- }
- return true;
- }
- return false;
- }
+ function _fetch()
+ {
+ $this->fields = false;
+ $rez = @ads_fetch_into($this->_queryID, $this->fields);
+ if ($rez) {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ $this->fields =& $this->GetRowAssoc();
+ }
+ return true;
+ }
+ return false;
+ }
- function _close()
- {
- return @ads_free_result($this->_queryID);
- }
+ function _close()
+ {
+ return @ads_free_result($this->_queryID);
+ }
}
diff --git a/lib/adodb/drivers/adodb-borland_ibase.inc.php b/lib/adodb/drivers/adodb-borland_ibase.inc.php
index 45fdcbfdc55..922796beaf7 100644
--- a/lib/adodb/drivers/adodb-borland_ibase.inc.php
+++ b/lib/adodb/drivers/adodb-borland_ibase.inc.php
@@ -1,6 +1,6 @@
_insertid;
+ return $this->_insertid;
}
function _affectedrows()
{
- return $this->_affectedrows;
+ return $this->_affectedrows;
}
function MetaDatabases()
@@ -178,7 +174,7 @@ class ADODB_csv extends ADOConnection {
/* Returns: the last error message from previous database operation */
function ErrorMsg()
{
- return $this->_errorMsg;
+ return $this->_errorMsg;
}
/* Returns: the last error number from previous database operation */
@@ -195,10 +191,6 @@ class ADODB_csv extends ADOConnection {
} // class
class ADORecordset_csv extends ADORecordset {
- function __construct($id,$mode=false)
- {
- parent::__construct($id,$mode);
- }
function _close()
{
diff --git a/lib/adodb/drivers/adodb-db2.inc.php b/lib/adodb/drivers/adodb-db2.inc.php
index 20a1ecf55f9..6618c87aade 100644
--- a/lib/adodb/drivers/adodb-db2.inc.php
+++ b/lib/adodb/drivers/adodb-db2.inc.php
@@ -1,20 +1,27 @@
_haserrorfunctions = ADODB_PHPVER >= 0x4050;
+ return $this->doDB2Connect($argDSN, $argUsername, $argPassword, $argDatabasename);
}
-
- // returns true or false
- function _connect($argDSN, $argUsername, $argPassword, $argDatabasename)
+
+ public function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
{
+ return $this->doDB2Connect($argDSN, $argUsername, $argPassword, $argDatabasename,true);
+ }
+
+ private function doDB2Connect($argDSN, $argUsername, $argPassword, $argDatabasename, $persistent=false)
+ {
+ global $php_errormsg;
+
if (!function_exists('db2_connect')) {
- ADOConnection::outp("Warning: The old ODBC based DB2 driver has been renamed 'odbc_db2'. This ADOdb driver calls PHP's native db2 extension which is not installed.");
+ ADOConnection::outp("DB2 extension not installed.");
return null;
}
- // This needs to be set before the connect().
- // Replaces the odbc_binmode() call that was in Execute()
+
+ $connectionParameters = $this->unpackParameters($argDSN,
+ $argUsername,
+ $argPassword,
+ $argDatabasename);
+
+ if ($connectionParameters == null)
+ {
+ /*
+ * Error thrown
+ */
+ return null;
+ }
+
+ $argDSN = $connectionParameters['dsn'];
+ $argUsername = $connectionParameters['uid'];
+ $argPassword = $connectionParameters['pwd'];
+ $argDatabasename = $connectionParameters['database'];
+ $useCataloguedConnection = $connectionParameters['catalogue'];
+
+ if ($this->debug){
+ if ($useCataloguedConnection){
+ $connectMessage = "Catalogued connection using parameters: ";
+ $connectMessage .= "DB=$argDatabasename / ";
+ $connectMessage .= "UID=$argUsername / ";
+ $connectMessage .= "PWD=$argPassword";
+ }
+ else
+ {
+ $connectMessage = "Uncatalogued connection using DSN: $argDSN";
+ }
+ ADOConnection::outp($connectMessage);
+ }
+ /*
+ * This needs to be set before the connect().
+ */
ini_set('ibm_db2.binmode', $this->binmode);
- if ($argDatabasename && empty($argDSN)) {
+ if ($persistent)
+ $db2Function = 'db2_pconnect';
+ else
+ $db2Function = 'db2_connect';
+
+ /*
+ * We need to flatten out the connectionParameters
+ */
- if (stripos($argDatabasename,'UID=') && stripos($argDatabasename,'PWD=')) $this->_connectionID = db2_connect($argDatabasename,null,null);
- else $this->_connectionID = db2_connect($argDatabasename,$argUsername,$argPassword);
- } else {
- if ($argDatabasename) $schema = $argDatabasename;
- if (stripos($argDSN,'UID=') && stripos($argDSN,'PWD=')) $this->_connectionID = db2_connect($argDSN,null,null);
- else $this->_connectionID = db2_connect($argDSN,$argUsername,$argPassword);
+ $db2Options = array();
+ if ($this->connectionParameters)
+ {
+ foreach($this->connectionParameters as $p)
+ foreach($p as $k=>$v)
+ $db2Options[$k] = $v;
}
-
- // For db2_connect(), there is an optional 4th arg. If present, it must be
- // an array of valid options. So far, we don't use them.
+
+ if ($useCataloguedConnection)
+ $this->_connectionID = $db2Function($argDatabasename,
+ $argUsername,
+ $argPassword,
+ $db2Options);
+ else
+ $this->_connectionID = $db2Function($argDSN,
+ null,
+ null,
+ $db2Options);
+
+ $php_errormsg = '';
$this->_errorMsg = @db2_conn_errormsg();
- if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
+
+ if ($this->_connectionID && $this->connectStmt)
+ $this->execute($this->connectStmt);
- if ($this->_connectionID && isset($schema)) $this->Execute("SET SCHEMA=$schema");
return $this->_connectionID != false;
- }
-
- // returns true or false
- function _pconnect($argDSN, $argUsername, $argPassword, $argDatabasename)
+
+ }
+
+ /**
+ * Validates and preprocesses the passed parameters for consistency
+ *
+ * @param string $argDSN Either DSN or database
+ * @param string $argUsername User name or null
+ * @param string $argPassword Password or null
+ * @param string $argDatabasename Either DSN or database
+ *
+ * @return mixed array if correct, null if not
+ */
+ private function unpackParameters($argDSN, $argUsername, $argPassword, $argDatabasename)
{
- if (!function_exists('db2_connect')) return null;
-
- // This needs to be set before the connect().
- // Replaces the odbc_binmode() call that was in Execute()
- ini_set('ibm_db2.binmode', $this->binmode);
-
- $this->_errorMsg = '';
-
- if ($argDatabasename && empty($argDSN)) {
-
- if (stripos($argDatabasename,'UID=') && stripos($argDatabasename,'PWD=')) $this->_connectionID = db2_pconnect($argDatabasename,null,null);
- else $this->_connectionID = db2_pconnect($argDatabasename,$argUsername,$argPassword);
- } else {
- if ($argDatabasename) $schema = $argDatabasename;
- if (stripos($argDSN,'UID=') && stripos($argDSN,'PWD=')) $this->_connectionID = db2_pconnect($argDSN,null,null);
- else $this->_connectionID = db2_pconnect($argDSN,$argUsername,$argPassword);
+
+ global $php_errormsg;
+
+ $connectionParameters = array('dsn'=>'',
+ 'uid'=>'',
+ 'pwd'=>'',
+ 'database'=>'',
+ 'catalogue'=>true
+ );
+
+ /*
+ * Uou can either connect to a catalogued connection
+ * with a database name e.g. 'SAMPLE'
+ * or an uncatalogued connection with a DSN like connection
+ * DATABASE=database;HOSTNAME=hostname;PORT=port;PROTOCOL=TCPIP;UID=username;PWD=password;
+ */
+
+ if (!$argDSN && !$argDatabasename)
+ {
+ $errorMessage = 'Supply either catalogued or uncatalogued connection parameters';
+ $this->_errorMsg = $errorMessage;
+ if ($this->debug)
+ ADOConnection::outp($errorMessage);
+ return null;
}
+
+ $useCataloguedConnection = true;
+ $schemaName = '';
+
+ if ($argDSN && $argDatabasename)
+ {
+ /*
+ * If a catalogued connection if provided,
+ * as well as user and password
+ * that will take priority
+ */
+ if ($argUsername && $argPassword && !$this->isDsn($argDatabasename))
+ {
+ if ($this->debug){
+ $errorMessage = 'Warning: Because you provided user,';
+ $errorMessage.= 'password and database, DSN connection ';
+ $errorMessage.= 'parameters were discarded';
+ ADOConnection::outp($errorMessage);
+
+ }
+ $argDSN = '';
+ }
+ else if ($this->isDsn($argDSN) && $this->isDsn($argDatabasename))
+ {
+ $errorMessage = 'Supply uncatalogued connection parameters ';
+ $errorMessage.= 'in either the database or DSN arguments, ';
+ $errorMessage.= 'but not both';
+ $php_errormsg = $errorMessage;
+ if ($this->debug)
+ ADOConnection::outp($errorMessage);
+ return null;
+ }
+ }
+
+ if (!$this->isDsn($argDSN) && $this->isDsn($argDatabasename))
+ {
+ /*
+ * Switch them around for next test
+ */
+ $temp = $argDSN;
+ $argDsn = $argDatabasename;
+ $argDatabasenME = $temp;
+ }
+
+ if ($this->isDsn($argDSN))
+ {
+
+ if (!preg_match('/uid=/i',$argDSN)
+ || !preg_match('/pwd=/i',$argDSN))
+ {
+ $errorMessage = 'For uncatalogued connections, provide ';
+ $errorMessage.= 'both UID and PWD in the connection string';
+ $php_errormsg = $errorMessage;
+ if ($this->debug)
+ ADOConnection::outp($errorMessage);
+ return null;
+ }
+
+ if (preg_match('/database=/i',$argDSN))
+ {
+ if ($argDatabasename)
+ {
+ $argDatabasename = '';
+ if ($this->debug)
+ {
+ $errorMessage = 'Warning: Because you provided ';
+ $errorMessage.= 'database information in the DSN ';
+ $errorMessage.= 'parameters, the supplied database ';
+ $errorMessage.= 'name was discarded';
+ ADOConnection::outp($errorMessage);
+ }
+ }
+ $useCataloguedConnection = false;
+
+ }
+ elseif ($argDatabasename)
+ {
+ $this->databaseName = $argDatabasename;
+ $argDSN .= ';database=' . $argDatabasename;
+ $argDatabasename = '';
+ $useCataloguedConnection = false;
+
+ }
+ else
+ {
+ $errorMessage = 'Uncatalogued connection parameters ';
+ $errorMessage.= 'must contain a database= argument';
+ $php_errormsg = $errorMessage;
+ if ($this->debug)
+ ADOConnection::outp($errorMessage);
+ return null;
+ }
+ }
+
+ if ($argDSN && !$argDatabasename && $useCataloguedConnection)
+ {
+ $argDatabasename = $argDSN;
+ $argDSN = '';
+ }
+
- $this->_errorMsg = @db2_conn_errormsg();
- if ($this->_connectionID && $this->autoRollback) @db2_rollback($this->_connectionID);
- if (isset($this->connectStmt)) $this->Execute($this->connectStmt);
-
- if ($this->_connectionID && isset($schema)) $this->Execute("SET SCHEMA=$schema");
- return $this->_connectionID != false;
+ if ($useCataloguedConnection
+ && (!$argDatabasename
+ || !$argUsername
+ || !$argPassword))
+ {
+
+ $errorMessage = 'For catalogued connections, provide ';
+ $errorMessage.= 'database, username and password';
+ $this->_errorMsg = $errorMessage;
+ if ($this->debug)
+ ADOConnection::outp($errorMessage);
+ return null;
+
+ }
+
+ if ($argDatabasename)
+ $this->databaseName = $argDatabasename;
+ elseif (!$this->databaseName)
+ $this->databaseName = $this->getDatabasenameFromDsn($argDSN);
+
+
+ $connectionParameters = array('dsn'=>$argDSN,
+ 'uid'=>$argUsername,
+ 'pwd'=>$argPassword,
+ 'database'=>$argDatabasename,
+ 'catalogue'=>$useCataloguedConnection
+ );
+
+ return $connectionParameters;
+
}
- // format and return date string in database timestamp format
- function DBTimeStamp($ts, $isfld = false)
+ /**
+ * Does the provided string look like a DSN
+ *
+ * @param string $dsnString
+ *
+ * @return bool
+ */
+ private function isDsn($dsnString){
+ $dsnArray = preg_split('/[;=]+/',$dsnString);
+ if (count($dsnArray) > 2)
+ return true;
+ return false;
+ }
+
+
+ /**
+ * Gets the database name from the DSN
+ *
+ * @param string $dsnString
+ *
+ * @return string
+ */
+ private function getDatabasenameFromDsn($dsnString){
+
+ $dsnArray = preg_split('/[;=]+/',$dsnString);
+ $dbIndex = array_search('database',$dsnArray);
+
+ return $dsnArray[$dbIndex + 1];
+ }
+
+
+ /**
+ * format and return date string in database timestamp format
+ *
+ * @param mixed $ts either a string or a unixtime
+ * @param bool $isField discarded
+ *
+ * @return string
+ */
+ function dbTimeStamp($ts,$isField=false)
{
if (empty($ts) && $ts !== 0) return 'null';
- if (is_string($ts)) $ts = ADORecordSet::UnixTimeStamp($ts);
+ if (is_string($ts)) $ts = ADORecordSet::unixTimeStamp($ts);
return 'TO_DATE('.adodb_date($this->fmtTimeStamp,$ts).",'YYYY-MM-DD HH24:MI:SS')";
}
- // 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 given an input format that understands Y M D
+ *
+ * @param string $fmt
+ * @param bool $col
+ *
+ * @return string
+ */
+ function sqlDate($fmt, $col=false)
{
- // use right() and replace() ?
if (!$col) $col = $this->sysDate;
/* use TO_CHAR() if $fmt is TO_CHAR() allowed fmt */
@@ -203,10 +481,12 @@ class ADODB_db2 extends ADOConnection {
}
- function ServerInfo()
+ function serverInfo()
{
- $row = $this->GetRow("SELECT service_level, fixpack_num FROM TABLE(sysproc.env_get_inst_info())
- as INSTANCEINFO");
+ $sql = "SELECT service_level, fixpack_num
+ FROM TABLE(sysproc.env_get_inst_info())
+ AS INSTANCEINFO";
+ $row = $this->GetRow($sql);
if ($row) {
@@ -214,108 +494,119 @@ class ADODB_db2 extends ADOConnection {
$info['fixpack'] = $row[1];
$info['description'] = '';
} else {
- return ADOConnection::ServerInfo();
+ return ADOConnection::serverInfo();
}
return $info;
}
- function CreateSequence($seqname='adodbseq',$start=1)
+ function createSequence($seqname='adodbseq',$start=1)
{
- if (empty($this->_genSeqSQL)) return false;
- $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname,$start));
- if (!$ok) return false;
+ if (empty($this->_genSeqSQL))
+ return false;
+
+ $ok = $this->execute(sprintf($this->_genSeqSQL,$seqname,$start));
+ if (!$ok)
+ return false;
return true;
}
- function DropSequence($seqname = 'adodbseq')
+ function dropSequence($seqname='adodbseq')
{
if (empty($this->_dropSeqSQL)) return false;
- return $this->Execute(sprintf($this->_dropSeqSQL,$seqname));
+ return $this->execute(sprintf($this->_dropSeqSQL,$seqname));
}
- function SelectLimit($sql, $nrows = -1, $offset = -1, $inputArr = false, $secs2cache = 0)
+ function selectLimit($sql,$nrows=-1,$offset=-1,$inputArr=false,$secs2cache=0)
{
- $nrows = (int) $nrows;
- $offset = (int) $offset;
- if ($offset <= 0) {
- // could also use " OPTIMIZE FOR $nrows ROWS "
- if ($nrows >= 0) $sql .= " FETCH FIRST $nrows ROWS ONLY ";
- $rs = $this->Execute($sql,$inputArr);
- } else {
+ $nrows = (integer) $nrows;
+
+ if ($offset <= 0)
+ {
+ if ($nrows >= 0)
+ $sql .= " FETCH FIRST $nrows ROWS ONLY ";
+
+ $rs = $this->execute($sql,$inputArr);
+
+ }
+ else
+ {
if ($offset > 0 && $nrows < 0);
- else {
+
+ else
+ {
$nrows += $offset;
$sql .= " FETCH FIRST $nrows ROWS ONLY ";
}
- $rs = ADOConnection::SelectLimit($sql,-1,$offset,$inputArr);
+
+ /*
+ * DB2 has no native support for mid table offset
+ */
+ $rs = ADOConnection::selectLimit($sql,$nrows,$offset,$inputArr);
+
}
-
+
return $rs;
}
- /*
- This algorithm is not very efficient, but works even if table locking
- is not available.
-
- Will return false if unable to generate an ID after $MAXLOOPS attempts.
- */
- function GenID($seq='adodbseq',$start=1)
+
+ function errorMsg()
{
- // if you have to modify the parameter below, your database is overloaded,
- // or you need to implement generation of id's yourself!
- $num = $this->GetOne("VALUES NEXTVAL FOR $seq");
- return $num;
+ if ($this->_errorMsg !== false)
+ return $this->_errorMsg;
+
+ if (empty($this->_connectionID))
+ return @db2_conn_errormsg();
+
+ return @db2_conn_errormsg($this->_connectionID);
}
-
- function ErrorMsg()
- {
- if ($this->_haserrorfunctions) {
- if ($this->_errorMsg !== false) return $this->_errorMsg;
- if (empty($this->_connectionID)) return @db2_conn_errormsg();
- return @db2_conn_errormsg($this->_connectionID);
- } else return ADOConnection::ErrorMsg();
- }
-
- function ErrorNo()
+ function errorNo()
{
- if ($this->_haserrorfunctions) {
- if ($this->_errorCode !== false) {
- // bug in 4.0.6, error number can be corrupted string (should be 6 digits)
- return (strlen($this->_errorCode)<=2) ? 0 : $this->_errorCode;
- }
+ if ($this->_errorCode !== false)
+ return $this->_errorCode;
+
- if (empty($this->_connectionID)) $e = @db2_conn_error();
- else $e = @db2_conn_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();
+ if (empty($this->_connectionID))
+ $e = @db2_conn_error();
+
+ else
+ $e = @db2_conn_error($this->_connectionID);
+
+ return $e;
}
- function BeginTrans()
+ function beginTrans()
{
- if (!$this->hasTransactions) return false;
- if ($this->transOff) return true;
+ if (!$this->hasTransactions)
+ return false;
+ if ($this->transOff)
+ return true;
+
$this->transCnt += 1;
+
$this->_autocommit = false;
+
return db2_autocommit($this->_connectionID,false);
}
function CommitTrans($ok=true)
{
- if ($this->transOff) return true;
- if (!$ok) return $this->RollbackTrans();
- if ($this->transCnt) $this->transCnt -= 1;
+ if ($this->transOff)
+ return true;
+
+ if (!$ok)
+ return $this->RollbackTrans();
+
+ if ($this->transCnt)
+ $this->transCnt -= 1;
+
$this->_autocommit = true;
- $ret = db2_commit($this->_connectionID);
- db2_autocommit($this->_connectionID,true);
+ $ret = @db2_commit($this->_connectionID);
+ @db2_autocommit($this->_connectionID,true);
return $ret;
}
@@ -324,123 +615,400 @@ class ADODB_db2 extends ADOConnection {
if ($this->transOff) return true;
if ($this->transCnt) $this->transCnt -= 1;
$this->_autocommit = true;
- $ret = db2_rollback($this->_connectionID);
- db2_autocommit($this->_connectionID,true);
+ $ret = @db2_rollback($this->_connectionID);
+ @db2_autocommit($this->_connectionID,true);
return $ret;
}
- function MetaPrimaryKeys($table, $owner = false)
+ /**
+ * Return a list of Primary Keys for a specified table
+ *
+ * We don't use db2_statistics as the function does not seem to play
+ * well with mixed case table names
+ *
+ * @param string $table
+ * @param bool $primary (optional) only return primary keys
+ * @param bool $owner (optional) not used in this driver
+ *
+ * @return string[] Array of indexes
+ */
+ public function metaPrimaryKeys($table,$owner=false)
{
- global $ADODB_FETCH_MODE;
+
+ $primaryKeys = array();
+
+ global $ADODB_FETCH_MODE;
- if ($this->uCaseTables) $table = strtoupper($table);
$schema = '';
$this->_findschema($table,$schema);
+
+ $table = $this->getTableCasedValue($table);
- $savem = $ADODB_FETCH_MODE;
+ $savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
- $qid = @db2_primarykeys($this->_connectionID,'',$schema,$table);
+ $this->setFetchMode(ADODB_FETCH_NUM);
- if (!$qid) {
- $ADODB_FETCH_MODE = $savem;
- return false;
- }
- $rs = new ADORecordSet_db2($qid);
+
+ $sql = "SELECT *
+ FROM syscat.indexes
+ WHERE tabname='$table'";
+
+ $rows = $this->getAll($sql);
+
+ $this->setFetchMode($savem);
$ADODB_FETCH_MODE = $savem;
- if (!$rs) return false;
-
- $arr = $rs->GetArray();
- $rs->Close();
- $arr2 = array();
- for ($i=0; $i < sizeof($arr); $i++) {
- if ($arr[$i][3]) $arr2[] = $arr[$i][3];
- }
- return $arr2;
- }
-
- function MetaForeignKeys($table, $owner = FALSE, $upper = FALSE, $asociative = FALSE )
- {
- global $ADODB_FETCH_MODE;
-
- if ($this->uCaseTables) $table = strtoupper($table);
- $schema = '';
- $this->_findschema($table,$schema);
-
- $savem = $ADODB_FETCH_MODE;
- $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
- $qid = @db2_foreign_keys($this->_connectionID,'',$schema,$table);
- if (!$qid) {
- $ADODB_FETCH_MODE = $savem;
+ if (empty($rows))
return false;
- }
- $rs = new ADORecordSet_db2($qid);
-
- $ADODB_FETCH_MODE = $savem;
- /*
- $rs->fields indices
- 0 PKTABLE_CAT
- 1 PKTABLE_SCHEM
- 2 PKTABLE_NAME
- 3 PKCOLUMN_NAME
- 4 FKTABLE_CAT
- 5 FKTABLE_SCHEM
- 6 FKTABLE_NAME
- 7 FKCOLUMN_NAME
- */
- if (!$rs) return false;
-
- $foreign_keys = array();
- while (!$rs->EOF) {
- if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
- if (!is_array($foreign_keys[$rs->fields[5].'.'.$rs->fields[6]]))
- $foreign_keys[$rs->fields[5].'.'.$rs->fields[6]] = array();
- $foreign_keys[$rs->fields[5].'.'.$rs->fields[6]][$rs->fields[7]] = $rs->fields[3];
+
+ foreach ($rows as $r)
+ {
+ if ($r[7] != 'P')
+ continue;
+
+ $cols = explode('+',$r[6]);
+ foreach ($cols as $colIndex=>$col)
+ {
+ if ($colIndex == 0)
+ continue;
+ $columnName = $this->getMetaCasedValue($col);
+ $primaryKeys[] = $columnName;
}
- $rs->MoveNext();
+ break;
}
-
- $rs->Close();
- return $foreign_key;
+ return $primaryKeys;
}
-
- function MetaTables($ttype = false, $schema = false, $mask = false)
+ /**
+ * returns assoc array where keys are tables, and values are foreign keys
+ *
+ * @param string $table
+ * @param string $owner [optional][discarded]
+ * @param bool $upper [optional][discarded]
+ * @param bool $associative[optional][discarded]
+ *
+ * @return mixed[] Array of foreign key information
+ */
+ public function metaForeignKeys($table, $owner = FALSE, $upper = FALSE, $asociative = FALSE )
{
- global $ADODB_FETCH_MODE;
+
+ global $ADODB_FETCH_MODE;
+
+ $schema = '';
+ $this->_findschema($table,$schema);
$savem = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
- $qid = db2_tables($this->_connectionID);
+
+ $this->setFetchMode(ADODB_FETCH_NUM);
+
+ $sql = "SELECT SUBSTR(tabname,1,20) table_name,
+ SUBSTR(constname,1,20) fk_name,
+ SUBSTR(REFTABNAME,1,12) parent_table,
+ SUBSTR(refkeyname,1,20) pk_orig_table,
+ fk_colnames
+ FROM syscat.references
+ WHERE tabname = '$table'";
+
+ $results = $this->getAll($sql);
+
+ $ADODB_FETCH_MODE = $savem;
+ $this->setFetchMode($savem);
+
+ if (empty($results))
+ return false;
+
+ $foreignKeys = array();
+
+ foreach ($results as $r)
+ {
+ $parentTable = trim($this->getMetaCasedValue($r[2]));
+ $keyName = trim($this->getMetaCasedValue($r[1]));
+ $foreignKeys[$parentTable] = $keyName;
+ }
+
+ return $foreignKeys;
+ }
+
+ /**
+ * Returns a list of tables
+ *
+ * @param string $ttype (optional)
+ * @param string $schema (optional)
+ * @param string $mask (optional)
+ *
+ * @return array
+ */
+ public function metaTables($ttype=false,$schema=false,$mask=false)
+ {
+
+ global $ADODB_FETCH_MODE;
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ /*
+ * Values for TABLE_TYPE
+ * ---------------------------
+ * ALIAS, HIERARCHY TABLE, INOPERATIVE VIEW, NICKNAME,
+ * MATERIALIZED QUERY TABLE, SYSTEM TABLE, TABLE,
+ * TYPED TABLE, TYPED VIEW, and VIEW
+ *
+ * If $ttype passed as '', match 'TABLE' and 'VIEW'
+ * If $ttype passed as 'T' it is assumed to be 'TABLE'
+ * if $ttype passed as 'V' it is assumed to be 'VIEW'
+ */
+ $ttype = strtoupper($ttype);
+ if ($ttype) {
+ /*
+ * @todo We could do valid type checking or array type
+ */
+ if ($ttype == 'V')
+ $ttype = 'VIEW';
+ if ($ttype == 'T')
+ $ttype = 'TABLE';
+ }
+
+ if (!$schema)
+ $schema = '%';
+
+ if (!$mask)
+ $mask = '%';
+
+ $qid = @db2_tables($this->_connectionID,NULL,$schema,$mask,$ttype);
$rs = new ADORecordSet_db2($qid);
-
+
$ADODB_FETCH_MODE = $savem;
- if (!$rs) {
- $false = false;
- return $false;
- }
-
- $arr = $rs->GetArray();
+
+ if (!$rs)
+ return false;
+
+ $arr = $rs->getArray();
+
$rs->Close();
- $arr2 = array();
+
+ $tableList = array();
- if ($ttype) {
- $isview = strncmp($ttype,'V',1) === 0;
+ /*
+ * Array items
+ * ---------------------------------
+ * 0 TABLE_CAT The catalog that contains the table.
+ * The value is NULL if this table does not have catalogs.
+ * 1 TABLE_SCHEM Name of the schema that contains the table.
+ * 2 TABLE_NAME Name of the table.
+ * 3 TABLE_TYPE Table type identifier for the table.
+ * 4 REMARKS Description of the table.
+ */
+
+ for ($i=0; $i < sizeof($arr); $i++)
+ {
+
+ $tableRow = $arr[$i];
+ $tableName = $tableRow[2];
+ $tableType = $tableRow[3];
+
+ if (!$tableName)
+ continue;
+
+ if ($ttype == '' && (strcmp($tableType,'TABLE') <> 0 && strcmp($tableType,'VIEW') <> 0))
+ continue;
+
+ /*
+ * Set metacasing if required
+ */
+ $tableName = $this->getMetaCasedValue($tableName);
+
+ /*
+ * If we requested a schema, we prepend the schema
+ name to the table name
+ */
+ if (strcmp($schema,'%') <> 0)
+ $tableName = $schema . '.' . $tableName;
+
+ $tableList[] = $tableName;
+
}
- for ($i=0; $i < sizeof($arr); $i++) {
- if (!$arr[$i][2]) continue;
- $type = $arr[$i][3];
- $owner = $arr[$i][1];
- $schemaval = ($schema) ? $arr[$i][1].'.' : '';
- if ($ttype) {
- if ($isview) {
- if (strncmp($type,'V',1) === 0) $arr2[] = $schemaval.$arr[$i][2];
- } else if (strncmp($owner,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2];
- } else if (strncmp($owner,'SYS',3) !== 0) $arr2[] = $schemaval.$arr[$i][2];
- }
- return $arr2;
+ return $tableList;
}
+
+ /**
+ * Return a list of indexes for a specified table
+ *
+ * We don't use db2_statistics as the function does not seem to play
+ * well with mixed case table names
+ *
+ * @param string $table
+ * @param bool $primary (optional) only return primary keys
+ * @param bool $owner (optional) not used in this driver
+ *
+ * @return string[] Array of indexes
+ */
+ public function metaIndexes($table, $primary = false, $owner = false) {
+
+ global $ADODB_FETCH_MODE;
+
+ /* Array(
+ * [name_of_index] => Array(
+ * [unique] => true or false
+ * [columns] => Array(
+ * [0] => firstcol
+ * [1] => nextcol
+ * [2] => etc........
+ * )
+ * )
+ * )
+ */
+ $indices = array();
+ $primaryKeyName = '';
+
+ $table = $this->getTableCasedValue($table);
+
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ $this->setFetchMode(ADODB_FETCH_NUM);
+
+ $sql = "SELECT *
+ FROM syscat.indexes
+ WHERE tabname='$table'";
+
+ $rows = $this->getAll($sql);
+
+ $this->setFetchMode($savem);
+ $ADODB_FETCH_MODE = $savem;
+
+ if (empty($rows))
+ return false;
+
+ foreach ($rows as $r)
+ {
+
+ $primaryIndex = $r[7] == 'P'?1:0;
+ if (!$primary)
+ /*
+ * Primary key not requested, ignore that one
+ */
+ if ($r[7] == 'P')
+ continue;
+
+ $indexName = $this->getMetaCasedValue($r[1]);
+ if (!isset($indices[$indexName]))
+ {
+ $unique = ($r[7] == 'U')?1:0;
+ $indices[$indexName] = array('unique'=>$unique,
+ 'primary'=>$primaryIndex,
+ 'columns'=>array()
+ );
+ }
+ $cols = explode('+',$r[6]);
+ foreach ($cols as $colIndex=>$col)
+ {
+ if ($colIndex == 0)
+ continue;
+ $columnName = $this->getMetaCasedValue($col);
+ $indices[$indexName]['columns'][] = $columnName;
+ }
+
+ }
+
+ return $indices;
+
+ }
+
+ /**
+ * List procedures or functions in an array.
+ *
+ * We interrogate syscat.routines instead of calling the PHP
+ * function procedures because ADOdb requires the type of procedure
+ * this is not available in the php function
+ *
+ * @param string $procedureNamePattern (optional)
+ * @param string $catalog (optional)
+ * @param string $schemaPattern (optional)
+
+ * @return array of procedures on current database.
+ *
+ */
+ public function metaProcedures($procedureNamePattern = null, $catalog = null, $schemaPattern = null) {
+
+
+ global $ADODB_FETCH_MODE;
+
+ $metaProcedures = array();
+ $procedureSQL = '';
+ $catalogSQL = '';
+ $schemaSQL = '';
+
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ if ($procedureNamePattern)
+ $procedureSQL = "AND ROUTINENAME LIKE " . strtoupper($this->qstr($procedureNamePattern));
+
+ if ($catalog)
+ $catalogSQL = "AND OWNER=" . strtoupper($this->qstr($catalog));
+
+ if ($schemaPattern)
+ $schemaSQL = "AND ROUTINESCHEMA LIKE {$this->qstr($schemaPattern)}";
+
+
+ $fields = "
+ ROUTINENAME,
+ CASE ROUTINETYPE
+ WHEN 'P' THEN 'PROCEDURE'
+ WHEN 'F' THEN 'FUNCTION'
+ ELSE 'METHOD'
+ END AS ROUTINETYPE_NAME,
+ ROUTINESCHEMA,
+ REMARKS";
+
+ $SQL = "SELECT $fields
+ FROM syscat.routines
+ WHERE OWNER IS NOT NULL
+ $procedureSQL
+ $catalogSQL
+ $schemaSQL
+ ORDER BY ROUTINENAME
+ ";
+
+ $result = $this->execute($SQL);
+
+ $ADODB_FETCH_MODE = $savem;
+
+ if (!$result)
+ return false;
+
+ while ($r = $result->fetchRow()){
+ $procedureName = $this->getMetaCasedValue($r[0]);
+ $schemaName = $this->getMetaCasedValue($r[2]);
+ $metaProcedures[$procedureName] = array('type'=> $r[1],
+ 'catalog' => '',
+ 'schema' => $schemaName,
+ 'remarks' => $r[3]
+ );
+ }
+
+ return $metaProcedures;
+
+ }
+
+ /**
+ * Lists databases. Because instances are independent, we only know about
+ * the current database name
+ *
+ * @return string[]
+ */
+ public function metaDatabases(){
+
+ $dbName = $this->getMetaCasedValue($this->databaseName);
+
+ return (array)$dbName;
+
+ }
+
+
+
/*
See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2datetime_data_type_changes.asp
@@ -510,26 +1078,32 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2
}
}
- function MetaColumns($table, $normalize=true)
+ public function metaColumns($table, $normalize=true)
{
- global $ADODB_FETCH_MODE;
-
- $false = false;
- if ($this->uCaseTables) $table = strtoupper($table);
- $schema = '';
- $this->_findschema($table,$schema);
-
+ global $ADODB_FETCH_MODE;
+
$savem = $ADODB_FETCH_MODE;
- $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
- $colname = "%";
- $qid = db2_columns($this->_connectionID, "", $schema, $table, $colname);
- if (empty($qid)) return $false;
+ $schema = '%';
+ $this->_findschema($table,$schema);
+ $table = $this->getTableCasedValue($table);
+ $colname = "%";
+ $qid = db2_columns($this->_connectionID, null, $schema, $table, $colname);
+ if (empty($qid))
+ {
+ if ($this->debug)
+ {
+ $errorMessage = @db2_conn_errormsg($this->_connectionID);
+ ADOConnection::outp($errorMessage);
+ }
+ return false;
+ }
$rs = new ADORecordSet_db2($qid);
- $ADODB_FETCH_MODE = $savem;
- if (!$rs) return $false;
+ if (!$rs)
+ return false;
+
$rs->_fetch();
$retarr = array();
@@ -548,15 +1122,25 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2
9 RADIX
10 NULLABLE
11 REMARKS
+ 12 Column Default
+ 13 SQL Data Type
+ 14 SQL DateTime SubType
+ 15 Max length in Octets
+ 16 Ordinal Position
+ 17 Is NULLABLE
*/
- while (!$rs->EOF) {
- if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
- $fld = new ADOFieldObject();
+ while (!$rs->EOF)
+ {
+ if ($rs->fields[2] == $table)
+ {
+
+ $fld = new ADOFieldObject();
$fld->name = $rs->fields[3];
$fld->type = $this->DB2Types($rs->fields[4]);
// ref: http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraccgen/html/msdn_odk.asp
// access uses precision to store length for char/varchar
+
if ($fld->type == 'C' or $fld->type == 'X') {
if ($rs->fields[4] <= -95) // UNICODE
$fld->max_length = $rs->fields[7]/2;
@@ -564,24 +1148,42 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2
$fld->max_length = $rs->fields[7];
} else
$fld->max_length = $rs->fields[7];
- $fld->not_null = !empty($rs->fields[10]);
- $fld->scale = $rs->fields[8];
- $fld->primary_key = false;
- $retarr[strtoupper($fld->name)] = $fld;
- } else if (sizeof($retarr)>0)
+
+ $fld->not_null = !empty($rs->fields[10]);
+ $fld->scale = $rs->fields[8];
+ $fld->primary_key = false;
+
+ //$columnName = $this->getMetaCasedValue($fld->name);
+ $columnName = strtoupper($fld->name);
+ $retarr[$columnName] = $fld;
+
+ }
+ else if (sizeof($retarr)>0)
break;
+
$rs->MoveNext();
+
}
+
$rs->Close();
- if (empty($retarr)) $retarr = false;
+ if (empty($retarr))
+ $retarr = false;
- $qid = db2_primary_keys($this->_connectionID, "", $schema, $table);
- if (empty($qid)) return $false;
+ /*
+ * Now we find out if the column is part of a primary key
+ */
+
+ $qid = @db2_primary_keys($this->_connectionID, "", $schema, $table);
+ if (empty($qid))
+ return false;
$rs = new ADORecordSet_db2($qid);
- $ADODB_FETCH_MODE = $savem;
- if (!$rs) return $retarr;
+ if (!$rs)
+ {
+ $ADODB_FETCH_MODE = $savem;
+ return $retarr;
+ }
$rs->_fetch();
/*
@@ -594,23 +1196,371 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2
5 PK_NAME
*/
while (!$rs->EOF) {
- if (strtoupper(trim($rs->fields[2])) == $table && (!$schema || strtoupper($rs->fields[1]) == $schema)) {
+ if (strtoupper(trim($rs->fields[2])) == $table
+ && (!$schema || strtoupper($rs->fields[1]) == $schema))
+ {
$retarr[strtoupper($rs->fields[3])]->primary_key = true;
- } else if (sizeof($retarr)>0)
+ }
+ else if (sizeof($retarr)>0)
break;
+
$rs->MoveNext();
}
$rs->Close();
- if (empty($retarr)) $retarr = false;
+ $ADODB_FETCH_MODE = $savem;
+
+ if (empty($retarr))
+ return false;
+
+ /*
+ * If the fetch mode is numeric, return as numeric array
+ */
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM)
+ $retarr = array_values($retarr);
+
return $retarr;
}
+ /**
+ * In this version if prepareSp, we just check to make sure
+ * that the name of the stored procedure is correct
+ * If true, we returns an array
+ * else false
+ *
+ * @param string $procedureName
+ * @param mixed $parameters (not used in db2 connections)
+ * @return mixed[]
+ */
+ function prepareSp($procedureName,$parameters=false) {
+
+ global $ADODB_FETCH_MODE;
+
+ $this->storedProcedureParameters = array('name'=>'',
+ 'resource'=>false,
+ 'in'=>array(),
+ 'out'=>array(),
+ 'index'=>array(),
+ 'parameters'=>array(),
+ 'keyvalue' => array());
+
+ //$procedureName = strtoupper($procedureName);
+ //$procedureName = $this->getTableCasedValue($procedureName);
- function Prepare($sql)
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ $qid = db2_procedures($this->_connectionID, NULL , '%' , $procedureName );
+
+ $ADODB_FETCH_MODE = $savem;
+
+ if (!$qid)
+ {
+ if ($this->debug)
+ ADOConnection::outp(sprintf('No Procedure of name %s available',$procedureName));
+ return false;
+ }
+
+
+
+ $this->storedProcedureParameters['name'] = $procedureName;
+ /*
+ * Now we know we have a valid procedure name, lets see if it requires
+ * parameters
+ */
+ $savem = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+
+ $qid = db2_procedure_columns($this->_connectionID, NULL , '%' , $procedureName , NULL );
+
+ $ADODB_FETCH_MODE = $savem;
+
+ if (!$qid)
+ {
+ if ($this->debug)
+ ADOConnection::outp(sprintf('No columns of name %s available',$procedureName));
+ return false;
+ }
+ $rs = new ADORecordSet_db2($qid);
+ if (!$rs)
+ return false;
+
+ $preparedStatement = 'CALL %s(%s)';
+ $parameterMarkers = array();
+ while (!$rs->EOF)
+ {
+ $parameterName = $rs->fields[3];
+ if ($parameterName == '')
+ {
+ $rs->moveNext();
+ continue;
+ }
+ $parameterType = $rs->fields[4];
+ $ordinalPosition = $rs->fields[17];
+ switch($parameterType)
+ {
+ case DB2_PARAM_IN:
+ case DB2_PARAM_INOUT:
+ $this->storedProcedureParameters['in'][$parameterName] = '';
+ break;
+ case DB2_PARAM_INOUT:
+ case DB2_PARAM_OUT:
+ $this->storedProcedureParameters['out'][$parameterName] = '';
+ break;
+ }
+ $this->storedProcedureParameters['index'][$parameterName] = $ordinalPosition;
+ $this->storedProcedureParameters['parameters'][$ordinalPosition] = $rs->fields;
+ $rs->moveNext();
+
+ }
+ $parameterCount = count($this->storedProcedureParameters['index']);
+ $parameterMarkers = array_fill(0,$parameterCount,'?');
+
+ /*
+ * We now know how many parameters to bind to the stored procedure
+ */
+ $parameterList = implode(',',$parameterMarkers);
+
+ $sql = sprintf($preparedStatement,$procedureName,$parameterList);
+
+ $spResource = @db2_prepare($this->_connectionID,$sql);
+
+ if (!$spResource)
+ {
+ $errorMessage = @db2_conn_errormsg($this->_connectionID);
+ $this->_errorMsg = $errorMessage;
+
+ if ($this->debug)
+ ADOConnection::outp($errorMessage);
+
+ return false;
+ }
+
+ $this->storedProcedureParameters['resource'] = $spResource;
+
+ if ($this->debug)
+ {
+
+ ADOConnection::outp('The following parameters will be used in the SP call');
+ ADOConnection::outp(print_r($this->storedProcedureParameters));
+ }
+ /*
+ * We now have a stored parameter resource
+ * to bind to. The spResource and sql that is returned are
+ * not usable, its for dummy compatibility. Everything
+ * will be handled by the storedProcedureParameters
+ * array
+ */
+ return array($sql,$spResource);
+
+ }
+
+ private function storedProcedureParameter(&$stmt,
+ &$var,
+ $name,
+ $isOutput=false,
+ $maxLen=4000,
+ $type=false)
{
+
+
+ $name = strtoupper($name);
+
+ /*
+ * Must exist in the list of parameter names for the type
+ */
+ if ($isOutput
+ && !isset( $this->storedProcedureParameters['out'][$name]))
+ {
+ $errorMessage = sprintf('%s is not a valid OUT parameter name',$name);
+
+ $this->_errorMsg = $errorMessage;
+ if ($this->debug)
+ ADOConnection::outp($errorMessage);
+ return false;
+ }
+
+ if (!$isOutput
+ && !isset( $this->storedProcedureParameters['in'][$name]))
+ {
+ $errorMessage = sprintf('%s is not a valid IN parameter name',$name);
+
+ $this->_errorMsg = $errorMessage;
+ if ($this->debug)
+ ADOConnection::outp($errorMessage);
+ return false;
+ }
+
+ /*
+ * We will use these values to bind to when we execute
+ * the query
+ */
+ $this->storedProcedureParameters['keyvalue'][$name] = &$var;
+
+ return true;
+
+ }
+
+ /**
+ * Executes a prepared stored procedure.
+ *
+ * The function uses the previously accumulated information and
+ * resources in the $storedProcedureParameters array
+ *
+ * @return mixed The statement id if successful, or false
+ */
+ private function executeStoredProcedure()
+ {
+
+ /*
+ * Get the previously built resource
+ */
+ $stmtid = $this->storedProcedureParameters['resource'];
+
+ /*
+ * Bind our variables to the DB2 procedure
+ */
+ foreach ($this->storedProcedureParameters['keyvalue'] as $spName=>$spValue){
+
+ /*
+ * Get the ordinal position, required for binding
+ */
+ $ordinalPosition = $this->storedProcedureParameters['index'][$spName];
+
+ /*
+ * Get the db2 column dictionary for the parameter
+ */
+ $columnDictionary = $this->storedProcedureParameters['parameters'][$ordinalPosition];
+ $parameterType = $columnDictionary[4];
+ $dataType = $columnDictionary[5];
+ $precision = $columnDictionary[10];
+ $scale = $columnDictionary[9];
+
+ $ok = @db2_bind_param ($this->storedProcedureParameters['resource'],
+ $ordinalPosition ,
+ $spName,
+ $parameterType,
+ $dataType,
+ $precision,
+ $scale
+ );
+
+ if (!$ok)
+ {
+ $this->_errorMsg = @db2_stmt_errormsg();
+ $this->_errorCode = @db2_stmt_error();
+
+ if ($this->debug)
+ ADOConnection::outp($this->_errorMsg);
+ return false;
+ }
+
+ if ($this->debug)
+ ADOConnection::outp("Correctly Bound parameter $spName to procedure");
+
+ /*
+ * Build a variable in the current environment that matches
+ * the parameter name
+ */
+ ${$spName} = $spValue;
+
+ }
+
+ /*
+ * All bound, execute
+ */
+
+ if (!@db2_execute($stmtid))
+ {
+ $this->_errorMsg = @db2_stmt_errormsg();
+ $this->_errorCode = @db2_stmt_error();
+
+ if ($this->debug)
+ ADOConnection::outp($this->_errorMsg);
+ return false;
+ }
+
+ /*
+ * We now take the changed parameters back into the
+ * stored procedures array where we can query them later
+ * Remember that $spValue was passed in by reference, so we
+ * can access the value in the variable that was originally
+ * passed to inParameter or outParameter
+ */
+ foreach ($this->storedProcedureParameters['keyvalue'] as $spName=>$spValue)
+ {
+ /*
+ * We make it available to the environment
+ */
+ $spValue = ${$spName};
+ $this->storedProcedureParameters['keyvalue'][$spName] = $spValue;
+ }
+
+ return $stmtid;
+ }
+
+ /**
+ *
+ * Accepts an input or output parameter to bind to either a stored
+ * or prepared statements. For DB2, this should not be called as an
+ * API. always wrap with inParameter and outParameter
+ *
+ * @param mixed[] $stmt Statement returned by Prepare() or PrepareSP().
+ * @param mixed $var PHP variable to bind to. Can set to null (for isNull support).
+ * @param string $name Name of stored procedure variable name to bind to.
+ * @param int $isOutput optional) Indicates direction of parameter
+ * 0/false=IN 1=OUT 2= IN/OUT
+ * This is ignored for Stored Procedures
+ * @param int $maxLen (optional)Holds an maximum length of the variable.
+ * This is ignored for Stored Procedures
+ * @param int $type (optional) The data type of $var.
+ * This is ignored for Stored Procedures
+ *
+ * @return bool Success of the operation
+ */
+ public function parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=false)
+ {
+
+ /*
+ * If the $stmt is the name of a stored procedure we are
+ * setting up, we will process it one way, otherwise
+ * we assume we are setting up a prepared statement
+ */
+ if (is_array($stmt))
+ {
+ if ($this->debug)
+ ADOConnection::outp("Adding parameter to stored procedure");
+ if ($stmt[1] == $this->storedProcedureParameters['resource'])
+ return $this->storedProcedureParameter($stmt[1],
+ $var,
+ $name,
+ $isOutput,
+ $maxLen,
+ $type);
+
+ }
+
+ /*
+ * We are going to add a parameter to a prepared statement
+ */
+ if ($this->debug)
+ ADOConnection::outp("Adding parameter to prepared statement");
+ }
+
+
+ /**
+ * Prepares a prepared SQL statement, not used for stored procedures
+ *
+ * @param string $sql
+ *
+ * @return mixed
+ */
+ function prepare($sql)
+ {
+
if (! $this->_bindInputArray) return $sql; // no binding
- $stmt = db2_prepare($this->_connectionID,$sql);
+
+ $stmt = @db2_prepare($this->_connectionID,$sql);
if (!$stmt) {
// we don't know whether db2 driver is parsing prepared stmts, so just return sql
return $sql;
@@ -618,66 +1568,158 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2
return array($sql,$stmt,false);
}
- /* returns queryID or false */
- function _query($sql,$inputarr=false)
+ /**
+ * Executes a query
+ *
+ * @param mixed $sql
+ * @param mixed $inputarr An optional array of parameters
+ *
+ * @return mixed either the queryID or false
+ */
+ function _query(&$sql,$inputarr=false)
{
- $last_php_error = $this->resetLastError();
- $this->_errorMsg = '';
+
+ GLOBAL $php_errormsg;
+
+ if (isset($php_errormsg))
+ $php_errormsg = '';
+ $this->_error = '';
- if ($inputarr) {
- if (is_array($sql)) {
+ $db2Options = array();
+ /*
+ * Use DB2 Internal case handling for best speed
+ */
+ switch(ADODB_ASSOC_CASE)
+ {
+ case ADODB_ASSOC_CASE_UPPER:
+ $db2Options = array('db2_attr_case'=>DB2_CASE_UPPER);
+ $setOption = @db2_set_option($this->_connectionID,$db2Options,1);
+ break;
+
+ case ADODB_ASSOC_CASE_LOWER:
+ $db2Options = array('db2_attr_case'=>DB2_CASE_LOWER);
+ $setOption = @db2_set_option($this->_connectionID,$db2Options,1);
+ break;
+
+ default:
+ $db2Options = array('db2_attr_case'=>DB2_CASE_NATURAL);
+ $setOption = @db2_set_option($this->_connectionID,$db2Options,1);
+ }
+
+ $db2Options = array('db2_attr_case'=>DB2_CASE_LOWER);
+ $setOption = @db2_set_option($this->_connectionID,$db2Options,1);
+
+ if ($inputarr)
+ {
+ if (is_array($sql))
+ {
$stmtid = $sql[1];
- } else {
- $stmtid = db2_prepare($this->_connectionID,$sql);
+ }
+ else
+ {
+ $stmtid = @db2_prepare($this->_connectionID,$sql);
- if ($stmtid == false) {
- $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
+ if ($stmtid == false)
+ {
+ $this->_errorMsg = isset($php_errormsg) ? $php_errormsg : '';
return false;
}
}
- if (! db2_execute($stmtid,$inputarr)) {
- if ($this->_haserrorfunctions) {
- $this->_errorMsg = db2_stmt_errormsg();
- $this->_errorCode = db2_stmt_error();
- }
+ if (! @db2_execute($stmtid,$inputarr))
+ {
+ $this->_errorMsg = @db2_stmt_errormsg();
+ $this->_errorCode = @db2_stmt_error();
+ if ($this->debug)
+ ADOConnection::outp($this->_errorMsg);
return false;
}
- } else if (is_array($sql)) {
- $stmtid = $sql[1];
- if (!db2_execute($stmtid)) {
- if ($this->_haserrorfunctions) {
- $this->_errorMsg = db2_stmt_errormsg();
- $this->_errorCode = db2_stmt_error();
- }
+ }
+ else if (is_array($sql))
+ {
+
+ /*
+ * Either a prepared statement or a stored procedure
+ */
+
+ if (is_array($this->storedProcedureParameters)
+ && is_resource($this->storedProcedureParameters['resource']
+ ))
+ /*
+ * This is all handled in the separate method for
+ * readability
+ */
+ return $this->executeStoredProcedure();
+
+ /*
+ * First, we prepare the statement
+ */
+ $stmtid = @db2_prepare($this->_connectionID,$sql[0]);
+ if (!$stmtid){
+ $this->_errorMsg = @db2_stmt_errormsg();
+ $this->_errorCode = @db2_stmt_error();
+ if ($this->debug)
+ ADOConnection::outp("Prepare failed: " . $this->_errorMsg);
+
return false;
}
- } else
+ /*
+ * We next bind some input parameters
+ */
+ $ordinal = 1;
+ foreach ($sql[1] as $psVar=>$psVal){
+ ${$psVar} = $psVal;
+ $ok = @db2_bind_param($stmtid, $ordinal, $psVar, DB2_PARAM_IN);
+ if (!$ok)
+ {
+ $this->_errorMsg = @db2_stmt_errormsg();
+ $this->_errorCode = @db2_stmt_error();
+ if ($this->debug)
+ ADOConnection::outp("Bind failed: " . $this->_errorMsg);
+ return false;
+ }
+ }
+
+ if (!@db2_execute($stmtid))
+ {
+ $this->_errorMsg = @db2_stmt_errormsg();
+ $this->_errorCode = @db2_stmt_error();
+ if ($this->debug)
+ ADOConnection::outp($this->_errorMsg);
+ return false;
+ }
+
+ return $stmtid;
+ }
+ else
+ {
+
$stmtid = @db2_exec($this->_connectionID,$sql);
-
+ }
$this->_lastAffectedRows = 0;
- if ($stmtid) {
- if (@db2_num_fields($stmtid) == 0) {
+ if ($stmtid)
+ {
+ if (@db2_num_fields($stmtid) == 0)
+ {
$this->_lastAffectedRows = db2_num_rows($stmtid);
$stmtid = true;
- } else {
+ }
+ else
+ {
$this->_lastAffectedRows = 0;
}
- if ($this->_haserrorfunctions) {
- $this->_errorMsg = '';
- $this->_errorCode = 0;
- } else {
- $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
- }
- } else {
- if ($this->_haserrorfunctions) {
- $this->_errorMsg = db2_stmt_errormsg();
- $this->_errorCode = db2_stmt_error();
- } else {
- $this->_errorMsg = $this->getChangedErrorMsg($last_php_error);
- }
+ $this->_errorMsg = '';
+ $this->_errorCode = 0;
+
+ }
+ else
+ {
+
+ $this->_errorMsg = @db2_stmt_errormsg();
+ $this->_errorCode = @db2_stmt_error();
+
}
return $stmtid;
}
@@ -688,12 +1730,12 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2
Usage:
- $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
+ $conn->execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
$conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
*/
- function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ function updateBlob($table,$column,$val,$where,$blobtype='BLOB')
{
- return $this->Execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false;
+ return $this->execute("UPDATE $table SET $column=? WHERE $where",array($val)) != false;
}
// returns true or false
@@ -708,6 +1750,87 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/db2/htm/db2
{
return $this->_lastAffectedRows;
}
+
+ /**
+ * Gets a meta cased parameter
+ *
+ * Receives an input variable to be processed per the metaCasing
+ * rule, and returns the same value, processed
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ final public function getMetaCasedValue($value)
+ {
+ global $ADODB_ASSOC_CASE;
+
+ switch($ADODB_ASSOC_CASE)
+ {
+ case ADODB_ASSOC_CASE_LOWER:
+ $value = strtolower($value);
+ break;
+ case ADODB_ASSOC_CASE_UPPER:
+ $value = strtoupper($value);
+ break;
+ }
+ return $value;
+ }
+
+
+ const TABLECASE_LOWER = 0;
+ const TABLECASE_UPPER = 1;
+ const TABLECASE_DEFAULT = 2;
+
+ /*
+ * Controls the casing of the table provided to the meta functions
+ */
+ private $tableCase = 2;
+
+ /**
+ * Sets the table case parameter
+ *
+ * @param int $caseOption
+ * @return null
+ */
+ final public function setTableCasing($caseOption)
+ {
+ $this->tableCase = $caseOption;
+ }
+
+ /**
+ * Gets the table casing parameter
+ *
+ * @return int $caseOption
+ */
+ final public function getTableCasing()
+ {
+ return $this->tableCase;
+ }
+
+ /**
+ * Gets a table cased parameter
+ *
+ * Receives an input variable to be processed per the tableCasing
+ * rule, and returns the same value, processed
+ *
+ * @param string $value
+ *
+ * @return string
+ */
+ final public function getTableCasedValue($value)
+ {
+ switch($this->tableCase)
+ {
+ case self::TABLECASE_LOWER:
+ $value = strtolower($value);
+ break;
+ case self::TABLECASE_UPPER:
+ $value = strtoupper($value);
+ break;
+ }
+ return $value;
+ }
}
@@ -735,21 +1858,30 @@ class ADORecordSet_db2 extends ADORecordSet {
// returns the field object
- function FetchField($offset = -1)
+ function fetchField($offset = 0)
{
- $o= new ADOFieldObject();
- $o->name = @db2_field_name($this->_queryID,$offset);
- $o->type = @db2_field_type($this->_queryID,$offset);
- $o->max_length = db2_field_width($this->_queryID,$offset);
- if (ADODB_ASSOC_CASE == 0) $o->name = strtolower($o->name);
- else if (ADODB_ASSOC_CASE == 1) $o->name = strtoupper($o->name);
+ $o = new ADOFieldObject();
+ $o->name = @db2_field_name($this->_queryID,$offset);
+ $o->type = @db2_field_type($this->_queryID,$offset);
+ $o->max_length = @db2_field_width($this->_queryID,$offset);
+
+ /*
+ if (ADODB_ASSOC_CASE == 0)
+ $o->name = strtolower($o->name);
+ else if (ADODB_ASSOC_CASE == 1)
+ $o->name = strtoupper($o->name);
+ */
return $o;
}
/* Use associative array to get fields array */
- function Fields($colname)
+ function fields($colname)
{
- if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
+
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) {
+ return $this->fields[$colname];
+ }
+
if (!$this->bind) {
$this->bind = array();
for ($i=0; $i < $this->_numOfFields; $i++) {
@@ -764,11 +1896,15 @@ class ADORecordSet_db2 extends ADORecordSet {
function _initrs()
{
- global $ADODB_COUNTRECS;
+ global $ADODB_COUNTRECS;
$this->_numOfRows = ($ADODB_COUNTRECS) ? @db2_num_rows($this->_queryID) : -1;
+
$this->_numOfFields = @db2_num_fields($this->_queryID);
+
// some silly drivers such as db2 as/400 and intersystems cache return _numOfRows = 0
- if ($this->_numOfRows == 0) $this->_numOfRows = -1;
+
+ if ($this->_numOfRows == 0)
+ $this->_numOfRows = -1;
}
function _seek($row)
@@ -776,21 +1912,15 @@ class ADORecordSet_db2 extends ADORecordSet {
return false;
}
- // speed up SelectLimit() by switching to ADODB_FETCH_NUM as ADODB_FETCH_ASSOC is emulated
- function GetArrayLimit($nrows,$offset=-1)
+ function getArrayLimit($nrows,$offset=0)
{
if ($offset <= 0) {
$rs = $this->GetArray($nrows);
return $rs;
}
- $savem = $this->fetchMode;
- $this->fetchMode = ADODB_FETCH_NUM;
+
$this->Move($offset);
- $this->fetchMode = $savem;
- if ($this->fetchMode & ADODB_FETCH_ASSOC) {
- $this->fields = $this->GetRowAssoc();
- }
$results = array();
$cnt = 0;
@@ -798,46 +1928,81 @@ class ADORecordSet_db2 extends ADORecordSet {
$results[$cnt++] = $this->fields;
$this->MoveNext();
}
-
+
return $results;
}
-
- function MoveNext()
+ function moveNext()
{
- if ($this->_numOfRows != 0 && !$this->EOF) {
- $this->_currentRow++;
-
- $this->fields = @db2_fetch_array($this->_queryID);
- if ($this->fields) {
- if ($this->fetchMode & ADODB_FETCH_ASSOC) {
- $this->fields = $this->GetRowAssoc();
- }
- return true;
- }
- }
- $this->fields = false;
- $this->EOF = true;
- return false;
+ if ($this->EOF || $this->_numOfRows == 0)
+ return false;
+
+ $this->_currentRow++;
+
+ $this->processCoreFetch();
+ return $this->processMoveRecord();
+
}
-
- function _fetch()
- {
-
- $this->fields = db2_fetch_array($this->_queryID);
- if ($this->fields) {
- if ($this->fetchMode & ADODB_FETCH_ASSOC) {
- $this->fields = $this->GetRowAssoc();
- }
- return true;
+
+ private function processCoreFetch()
+ {
+ switch ($this->fetchMode){
+ case ADODB_FETCH_ASSOC:
+
+ /*
+ * Associative array
+ */
+ $this->fields = @db2_fetch_assoc($this->_queryID);
+ break;
+
+ case ADODB_FETCH_BOTH:
+ /*
+ * Fetch both numeric and Associative array
+ */
+ $this->fields = @db2_fetch_both($this->_queryID);
+ break;
+ default:
+ /*
+ * Numeric array
+ */
+ $this->fields = @db2_fetch_array($this->_queryID);
+ break;
}
+ }
+
+ private function processMoveRecord()
+ {
+ if (!$this->fields){
+ $this->EOF = true;
+ return false;
+ }
+
+ return true;
+ }
+
+ function _fetch()
+ {
+ $this->processCoreFetch();
+ if ($this->fields)
+ return true;
+
$this->fields = false;
return false;
}
function _close()
{
- return @db2_free_result($this->_queryID);
+ $ok = @db2_free_result($this->_queryID);
+ if (!$ok)
+ {
+ $this->_errorMsg = @db2_stmt_errormsg($this->_queryId);
+ $this->_errorCode = @db2_stmt_error();
+
+ if ($this->debug)
+ ADOConnection::outp($this->_errorMsg);
+ return false;
+ }
+
}
}
diff --git a/lib/adodb/drivers/adodb-db2oci.inc.php b/lib/adodb/drivers/adodb-db2oci.inc.php
index c5fc168875a..ab3bc406c94 100644
--- a/lib/adodb/drivers/adodb-db2oci.inc.php
+++ b/lib/adodb/drivers/adodb-db2oci.inc.php
@@ -1,6 +1,6 @@
$_COLONSZ) return $p;
- $_COLONARR[] = $v;
- return '?';
-}
-
-// smart remapping of :0, :1 bind vars to ? ?
-function _colonscope($sql,$arr)
-{
-global $_COLONARR,$_COLONSZ;
-
- $_COLONARR = array();
- $_COLONSZ = sizeof($arr);
-
- $sql2 = preg_replace("/(:[0-9]+)/e","_colontrack('\\1')",$sql);
-
- if (empty($_COLONARR)) return array($sql,$arr);
-
- foreach($_COLONARR as $k => $v) {
- $arr2[] = $arr[$v];
- }
-
- return array($sql2,$arr2);
-}
-*/
-
-/*
- Smart remapping of :0, :1 bind vars to ? ?
-
- Handles colons in comments -- and / * * / and in quoted strings.
-*/
-
+/**
+ * Smart remapping of :0, :1 bind vars to ? ?
+ * Handles colons in comments -- and / * * / and in quoted strings.
+ * @param string $sql SQL statement
+ * @param array $arr parameters
+ * @return array
+ */
function _colonparser($sql,$arr)
{
$lensql = strlen($sql);
@@ -217,10 +187,6 @@ class ADORecordSet_db2oci extends ADORecordSet_db2 {
var $databaseType = "db2oci";
- function __construct($id,$mode=false)
- {
- return parent::__construct($id,$mode);
- }
}
} //define
diff --git a/lib/adodb/drivers/adodb-db2ora.inc.php b/lib/adodb/drivers/adodb-db2ora.inc.php
index 2dc330c55e1..b701f7eeddb 100644
--- a/lib/adodb/drivers/adodb-db2ora.inc.php
+++ b/lib/adodb/drivers/adodb-db2ora.inc.php
@@ -1,6 +1,6 @@
_connectionID);
@@ -177,7 +173,7 @@ class ADORecordSet_fbsql extends ADORecordSet{
default:
$this->fetchMode = FBSQL_BOTH; break;
}
- return parent::__construct($queryID);
+ parent::__construct($queryID);
}
function _initrs()
@@ -259,7 +255,7 @@ class ADORecordSet_fbsql extends ADORecordSet{
if (!empty($fieldobj->primary_key)) return 'R';
else return 'I';
- default: return 'N';
+ default: return ADODB_DEFAULT_METATYPE;
}
}
diff --git a/lib/adodb/drivers/adodb-firebird.inc.php b/lib/adodb/drivers/adodb-firebird.inc.php
index 06eabe5e92e..f125563158e 100644
--- a/lib/adodb/drivers/adodb-firebird.inc.php
+++ b/lib/adodb/drivers/adodb-firebird.inc.php
@@ -1,6 +1,6 @@
ibasetrans = IBASE_DEFAULT;
+ // else
+ $this->ibasetrans = IBASE_WAIT | IBASE_REC_VERSION | IBASE_COMMITTED;
+ }
+
+
+ // returns true or false
+ function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$persist=false)
+ {
+ if (!function_exists('fbird_pconnect')) return null;
+ if ($argDatabasename) $argHostname .= ':'.$argDatabasename;
+ $fn = ($persist) ? 'fbird_pconnect':'fbird_connect';
+ if ($this->role)
+ $this->_connectionID = $fn($argHostname,$argUsername,$argPassword,
+ $this->charSet,$this->buffers,$this->dialect,$this->role);
+ else
+ $this->_connectionID = $fn($argHostname,$argUsername,$argPassword,
+ $this->charSet,$this->buffers,$this->dialect);
+
+ if ($this->dialect != 1) { // http://www.ibphoenix.com/ibp_60_del_id_ds.html
+ $this->replaceQuote = "''";
+ }
+ if ($this->_connectionID === false) {
+ $this->_handleerror();
+ return false;
+ }
+
+ // PHP5 change.
+ if (function_exists('fbird_timefmt')) {
+ fbird_timefmt($this->fbird_datefmt,fbird_DATE );
+ if ($this->dialect == 1) {
+ fbird_timefmt($this->fbird_datefmt,fbird_TIMESTAMP );
+ } else {
+ fbird_timefmt($this->fbird_timestampfmt,fbird_TIMESTAMP );
+ }
+ fbird_timefmt($this->fbird_timefmt,fbird_TIME );
+
+ } else {
+ ini_set("ibase.timestampformat", $this->fbird_timestampfmt);
+ ini_set("ibase.dateformat", $this->fbird_datefmt);
+ ini_set("ibase.timeformat", $this->fbird_timefmt);
+ }
+ return true;
+ }
+
+ // returns true or false
+ function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
+ {
+ return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename,true);
+ }
+
+
+ function MetaPrimaryKeys($table,$owner_notused=false,$internalKey=false)
+ {
+ if ($internalKey) {
+ return array('RDB$DB_KEY');
+ }
+
+ $table = strtoupper($table);
+
+ $sql = 'SELECT S.RDB$FIELD_NAME AFIELDNAME
+ FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON I.RDB$INDEX_NAME=S.RDB$INDEX_NAME
+ WHERE I.RDB$RELATION_NAME=\''.$table.'\' and I.RDB$INDEX_NAME like \'RDB$PRIMARY%\'
+ ORDER BY I.RDB$INDEX_NAME,S.RDB$FIELD_POSITION';
+
+ $a = $this->GetCol($sql,false,true);
+ if ($a && sizeof($a)>0) return $a;
+ return false;
+ }
function ServerInfo()
{
@@ -38,10 +134,597 @@ class ADODB_firebird extends ADODB_ibase {
return $arr;
}
+ function BeginTrans()
+ {
+ if ($this->transOff) return true;
+ $this->transCnt += 1;
+ $this->autoCommit = false;
+ $this->_transactionID = fbird_trans( $this->ibasetrans, $this->_connectionID );
+ return $this->_transactionID;
+ }
+
+ function CommitTrans($ok=true)
+ {
+ if (!$ok) {
+ return $this->RollbackTrans();
+ }
+ if ($this->transOff) {
+ return true;
+ }
+ if ($this->transCnt) {
+ $this->transCnt -= 1;
+ }
+ $ret = false;
+ $this->autoCommit = true;
+ if ($this->_transactionID) {
+ //print ' commit ';
+ $ret = fbird_commit($this->_transactionID);
+ }
+ $this->_transactionID = false;
+ return $ret;
+ }
+
+ function _affectedrows()
+ {
+ return fbird_affected_rows( $this->_transactionID ? $this->_transactionID : $this->_connectionID );
+ }
+
+ // there are some compat problems with ADODB_COUNTRECS=false and $this->_logsql currently.
+ // it appears that ibase extension cannot support multiple concurrent queryid's
+ function _Execute($sql,$inputarr=false) {
+ global $ADODB_COUNTRECS;
+
+ if ($this->_logsql) {
+ $savecrecs = $ADODB_COUNTRECS;
+ $ADODB_COUNTRECS = true; // force countrecs
+ $ret =& ADOConnection::_Execute($sql,$inputarr);
+ $ADODB_COUNTRECS = $savecrecs;
+ } else {
+ $ret = ADOConnection::_Execute($sql,$inputarr);
+ }
+ return $ret;
+ }
+
+ function RollbackTrans()
+ {
+ if ($this->transOff) return true;
+ if ($this->transCnt) $this->transCnt -= 1;
+ $ret = false;
+ $this->autoCommit = true;
+ if ($this->_transactionID) {
+ $ret = fbird_rollback($this->_transactionID);
+ }
+ $this->_transactionID = false;
+
+ return $ret;
+ }
+
+ function &MetaIndexes ($table, $primary = FALSE, $owner=false)
+ {
+ // save old fetch mode
+ global $ADODB_FETCH_MODE;
+ $false = false;
+ $save = $ADODB_FETCH_MODE;
+ $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
+ if ($this->fetchMode !== FALSE) {
+ $savem = $this->SetFetchMode(FALSE);
+ }
+ $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;
+ }
+
+
+ // See http://community.borland.com/article/0,1410,25844,00.html
+ function RowLock($tables,$where,$col=false)
+ {
+ if ($this->autoCommit) {
+ $this->BeginTrans();
+ }
+ $this->Execute("UPDATE $table SET $col=$col WHERE $where "); // is this correct - jlim?
+ return 1;
+ }
+
+
+ function CreateSequence($seqname = 'adodbseq', $startID = 1)
+ {
+ $ok = $this->Execute(("CREATE GENERATOR $seqname" ));
+ if (!$ok) return false;
+ return $this->Execute("SET GENERATOR $seqname TO ".($startID-1));
+ }
+
+ function DropSequence($seqname = 'adodbseq')
+ {
+ $seqname = strtoupper($seqname);
+ return $this->Execute("DROP GENERATOR $seqname");
+ }
+
+ function GenID($seqname='adodbseq',$startID=1)
+ {
+ $getnext = ("SELECT Gen_ID($seqname,1) FROM RDB\$DATABASE");
+ $rs = @$this->Execute($getnext);
+ if (!$rs) {
+ $this->Execute(("CREATE GENERATOR $seqname" ));
+ $this->Execute("SET GENERATOR $seqname TO ".($startID-1).';');
+ $rs = $this->Execute($getnext);
+ }
+ if ($rs && !$rs->EOF) {
+ $this->genID = (integer) reset($rs->fields);
+ }
+ else {
+ $this->genID = 0; // false
+ }
+
+ if ($rs) {
+ $rs->Close();
+ }
+
+ return $this->genID;
+ }
+
+ function SelectDB($dbName)
+ {
+ return false;
+ }
+
+ function _handleerror()
+ {
+ $this->_errorMsg = fbird_errmsg();
+ }
+
+ function ErrorNo()
+ {
+ if (preg_match('/error code = ([\-0-9]*)/i', $this->_errorMsg,$arr)) return (integer) $arr[1];
+ else return 0;
+ }
+
+ function ErrorMsg()
+ {
+ return $this->_errorMsg;
+ }
+
+ function Prepare($sql)
+ {
+ $stmt = fbird_prepare($this->_connectionID,$sql);
+ if (!$stmt) return false;
+ return array($sql,$stmt);
+ }
+
+ // returns query ID if successful, otherwise false
+ // there have been reports of problems with nested queries - the code is probably not re-entrant?
+ function _query($sql,$iarr=false)
+ {
+ if ( !$this->isConnected() ) return false;
+ if (!$this->autoCommit && $this->_transactionID) {
+ $conn = $this->_transactionID;
+ $docommit = false;
+ } else {
+ $conn = $this->_connectionID;
+ $docommit = true;
+ }
+ if (is_array($sql)) {
+ $fn = 'fbird_execute';
+ $sql = $sql[1];
+ if (is_array($iarr)) {
+ if ( !isset($iarr[0]) )
+ $iarr[0] = ''; // PHP5 compat hack
+ $fnarr = array_merge( array($sql) , $iarr);
+ $ret = call_user_func_array($fn,$fnarr);
+ }
+ else {
+ $ret = $fn($sql);
+ }
+ } else {
+ $fn = 'fbird_query';
+ if (is_array($iarr))
+ {
+ if (sizeof($iarr) == 0)
+ $iarr[0] = ''; // PHP5 compat hack
+ $fnarr = array_merge( array($conn,$sql) , $iarr);
+ $ret = call_user_func_array($fn,$fnarr);
+ }
+ else {
+ $ret = $fn($conn, $sql);
+ }
+ }
+ if ($docommit && $ret === true) {
+ fbird_commit($this->_connectionID);
+ }
+
+ $this->_handleerror();
+ return $ret;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ if (!$this->autoCommit) {
+ @fbird_rollback($this->_connectionID);
+ }
+ return @fbird_close($this->_connectionID);
+ }
+
+ //OPN STUFF start
+ function _ConvertFieldType(&$fld, $ftype, $flen, $fscale, $fsubtype, $fprecision, $dialect3)
+ {
+ $fscale = abs($fscale);
+ $fld->max_length = $flen;
+ $fld->scale = null;
+ switch($ftype){
+ case 7:
+ case 8:
+ if ($dialect3) {
+ switch($fsubtype){
+ case 0:
+ $fld->type = ($ftype == 7 ? 'smallint' : 'integer');
+ break;
+ case 1:
+ $fld->type = 'numeric';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ case 2:
+ $fld->type = 'decimal';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ } // switch
+ } else {
+ if ($fscale !=0) {
+ $fld->type = 'decimal';
+ $fld->scale = $fscale;
+ $fld->max_length = ($ftype == 7 ? 4 : 9);
+ } else {
+ $fld->type = ($ftype == 7 ? 'smallint' : 'integer');
+ }
+ }
+ break;
+ case 16:
+ if ($dialect3) {
+ switch($fsubtype){
+ case 0:
+ $fld->type = 'decimal';
+ $fld->max_length = 18;
+ $fld->scale = 0;
+ break;
+ case 1:
+ $fld->type = 'numeric';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ case 2:
+ $fld->type = 'decimal';
+ $fld->max_length = $fprecision;
+ $fld->scale = $fscale;
+ break;
+ } // switch
+ }
+ break;
+ case 10:
+ $fld->type = 'float';
+ break;
+ case 14:
+ $fld->type = 'char';
+ break;
+ case 27:
+ if ($fscale !=0) {
+ $fld->type = 'decimal';
+ $fld->max_length = 15;
+ $fld->scale = 5;
+ } else {
+ $fld->type = 'double';
+ }
+ break;
+ case 35:
+ if ($dialect3) {
+ $fld->type = 'timestamp';
+ } else {
+ $fld->type = 'date';
+ }
+ break;
+ case 12:
+ $fld->type = 'date';
+ break;
+ case 13:
+ $fld->type = 'time';
+ break;
+ case 37:
+ $fld->type = 'varchar';
+ break;
+ case 40:
+ $fld->type = 'cstring';
+ break;
+ case 261:
+ $fld->type = 'blob';
+ $fld->max_length = -1;
+ break;
+ } // switch
+ }
+ //OPN STUFF end
+
+ // returns array of ADOFieldObjects for current table
+ function MetaColumns($table, $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;
+ $false = false;
+ if ($rs === false) {
+ return $false;
+ }
+
+ $retarr = array();
+ //OPN STUFF start
+ $dialect3 = ($this->dialect==3 ? true : false);
+ //OPN STUFF end
+ while (!$rs->EOF) { //print_r($rs->fields);
+ $fld = new ADOFieldObject();
+ $fld->name = trim($rs->fields[0]);
+ //OPN STUFF start
+ $this->_ConvertFieldType($fld, $rs->fields[7], $rs->fields[3], $rs->fields[4], $rs->fields[5], $rs->fields[6], $dialect3);
+ if (isset($rs->fields[1]) && $rs->fields[1]) {
+ $fld->not_null = true;
+ }
+ if (isset($rs->fields[2])) {
+
+ $fld->has_default = true;
+ $d = substr($rs->fields[2],strlen('default '));
+ switch ($fld->type)
+ {
+ case 'smallint':
+ case 'integer': $fld->default_value = (int) $d; break;
+ case 'char':
+ case 'blob':
+ case 'text':
+ case 'varchar': $fld->default_value = (string) substr($d,1,strlen($d)-2); break;
+ case 'double':
+ case 'float': $fld->default_value = (float) $d; break;
+ default: $fld->default_value = $d; break;
+ }
+ // case 35:$tt = 'TIMESTAMP'; break;
+ }
+ if ((isset($rs->fields[5])) && ($fld->type == 'blob')) {
+ $fld->sub_type = $rs->fields[5];
+ } else {
+ $fld->sub_type = null;
+ }
+ //OPN STUFF end
+ if ($ADODB_FETCH_MODE == ADODB_FETCH_NUM) $retarr[] = $fld;
+ else $retarr[strtoupper($fld->name)] = $fld;
+
+ $rs->MoveNext();
+ }
+ $rs->Close();
+ if ( empty($retarr)) return $false;
+ else return $retarr;
+ }
+
+ function BlobEncode( $blob )
+ {
+ $blobid = fbird_blob_create( $this->_connectionID);
+ fbird_blob_add( $blobid, $blob );
+ return fbird_blob_close( $blobid );
+ }
+
+ // since we auto-decode all blob's since 2.42,
+ // BlobDecode should not do any transforms
+ function BlobDecode($blob)
+ {
+ return $blob;
+ }
+
+ // old blobdecode function
+ // still used to auto-decode all blob's
+ function _BlobDecode_old( $blob )
+ {
+ $blobid = fbird_blob_open($this->_connectionID, $blob );
+ $realblob = fbird_blob_get( $blobid,$this->maxblobsize); // 2nd param is max size of blob -- Kevin Boillet
+ while($string = fbird_blob_get($blobid, 8192)){
+ $realblob .= $string;
+ }
+ fbird_blob_close( $blobid );
+
+ return( $realblob );
+ }
+
+ function _BlobDecode( $blob )
+ {
+ $blob_data = fbird_blob_info($this->_connectionID, $blob );
+ $blobid = fbird_blob_open($this->_connectionID, $blob );
+
+ if( $blob_data[0] > $this->maxblobsize ) {
+ $realblob = fbird_blob_get($blobid, $this->maxblobsize);
+
+ while($string = fbird_blob_get($blobid, 8192)) {
+ $realblob .= $string;
+ }
+ } else {
+ $realblob = fbird_blob_get($blobid, $blob_data[0]);
+ }
+
+ fbird_blob_close( $blobid );
+ return( $realblob );
+ }
+
+ function UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')
+ {
+ $fd = fopen($path,'rb');
+ if ($fd === false) return false;
+ $blob_id = fbird_blob_create($this->_connectionID);
+
+ /* fill with data */
+
+ while ($val = fread($fd,32768)){
+ fbird_blob_add($blob_id, $val);
+ }
+
+ /* close and get $blob_id_str for inserting into table */
+ $blob_id_str = fbird_blob_close($blob_id);
+
+ fclose($fd);
+ return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
+ }
+
+ /*
+ Insert a null into the blob field of the table first.
+ Then use UpdateBlob to store the blob.
+
+ Usage:
+
+ $conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
+ $conn->UpdateBlob('blobtable','blobcol',$blob,'id=1');
+ */
+ function UpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ {
+ $blob_id = fbird_blob_create($this->_connectionID);
+
+ // fbird_blob_add($blob_id, $val);
+
+ // replacement that solves the problem by which only the first modulus 64K /
+ // of $val are stored at the blob field ////////////////////////////////////
+ // Thx Abel Berenstein aberenstein#afip.gov.ar
+ $len = strlen($val);
+ $chunk_size = 32768;
+ $tail_size = $len % $chunk_size;
+ $n_chunks = ($len - $tail_size) / $chunk_size;
+
+ for ($n = 0; $n < $n_chunks; $n++) {
+ $start = $n * $chunk_size;
+ $data = substr($val, $start, $chunk_size);
+ fbird_blob_add($blob_id, $data);
+ }
+
+ if ($tail_size) {
+ $start = $n_chunks * $chunk_size;
+ $data = substr($val, $start, $tail_size);
+ fbird_blob_add($blob_id, $data);
+ }
+ // end replacement /////////////////////////////////////////////////////////
+
+ $blob_id_str = fbird_blob_close($blob_id);
+
+ return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
+
+ }
+
+
+ function OldUpdateBlob($table,$column,$val,$where,$blobtype='BLOB')
+ {
+ $blob_id = fbird_blob_create($this->_connectionID);
+ fbird_blob_add($blob_id, $val);
+ $blob_id_str = fbird_blob_close($blob_id);
+ return $this->Execute("UPDATE $table SET $column=(?) WHERE $where",array($blob_id_str)) != false;
+ }
+
+ // Format date column in sql string given an input format that understands Y M D
+ // Only since Interbase 6.0 - uses EXTRACT
+ // problem - does not zero-fill the day and month yet
+ function SQLDate($fmt, $col=false)
+ {
+ if (!$col) $col = $this->sysDate;
+ $s = '';
+
+ $len = strlen($fmt);
+ for ($i=0; $i < $len; $i++) {
+ if ($s) $s .= '||';
+ $ch = $fmt[$i];
+ switch($ch) {
+ case 'Y':
+ case 'y':
+ $s .= "extract(year from $col)";
+ break;
+ case 'M':
+ case 'm':
+ $s .= "extract(month from $col)";
+ break;
+ case 'W':
+ case 'w':
+ // The more accurate way of doing this is with a stored procedure
+ // See http://wiki.firebirdsql.org/wiki/index.php?page=DATE+Handling+Functions for details
+ $s .= "((extract(yearday from $col) - extract(weekday from $col - 1) + 7) / 7)";
+ break;
+ case 'Q':
+ case 'q':
+ $s .= "cast(((extract(month from $col)+2) / 3) as integer)";
+ break;
+ case 'D':
+ case 'd':
+ $s .= "(extract(day from $col))";
+ break;
+ case 'H':
+ case 'h':
+ $s .= "(extract(hour from $col))";
+ break;
+ case 'I':
+ case 'i':
+ $s .= "(extract(minute from $col))";
+ break;
+ case 'S':
+ case 's':
+ $s .= "CAST((extract(second from $col)) AS INTEGER)";
+ break;
+
+ default:
+ if ($ch == '\\') {
+ $i++;
+ $ch = substr($fmt,$i,1);
+ }
+ $s .= $this->qstr($ch);
+ break;
+ }
+ }
+ return $s;
+ }
+
// Note that Interbase 6.5 uses this ROWS instead - don't you love forking wars!
// SELECT col1, col2 FROM table ROWS 5 -- get 5 rows
// SELECT col1, col2 FROM TABLE ORDER BY col1 ROWS 3 TO 7 -- first 5 skip 2
- function SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false, $secs=0)
+ function &SelectLimit($sql,$nrows=-1,$offset=-1,$inputarr=false, $secs=0)
{
$nrows = (integer) $nrows;
$offset = (integer) $offset;
@@ -58,16 +741,173 @@ class ADODB_firebird extends ADODB_ibase {
return $rs;
}
+}
-};
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
-
-class ADORecordSet_firebird extends ADORecordSet_ibase {
+class ADORecordset_firebird extends ADORecordSet
+{
var $databaseType = "firebird";
+ var $bind=false;
+ var $_cacheType;
function __construct($id,$mode=false)
{
- parent::__construct($id,$mode);
+ global $ADODB_FETCH_MODE;
+
+ $this->fetchMode = ($mode === false) ? $ADODB_FETCH_MODE : $mode;
+ parent::__construct($id);
}
+
+ /**
+ * Get column information in the Recordset object.
+ * fetchField() can be used in order to obtain information about fields in
+ * a certain query result. If the field offset isn't specified, the next
+ * field that wasn't yet retrieved by fetchField() is retrieved.
+ * @return object containing field information.
+ */
+ function FetchField($fieldOffset = -1)
+ {
+ $fld = new ADOFieldObject;
+ $ibf = fbird_field_info($this->_queryID,$fieldOffset);
+
+ $name = empty($ibf['alias']) ? $ibf['name'] : $ibf['alias'];
+
+ switch (ADODB_ASSOC_CASE) {
+ case ADODB_ASSOC_CASE_UPPER:
+ $fld->name = strtoupper($name);
+ break;
+ case ADODB_ASSOC_CASE_LOWER:
+ $fld->name = strtolower($name);
+ break;
+ case ADODB_ASSOC_CASE_NATIVE:
+ default:
+ $fld->name = $name;
+ break;
+ }
+
+ $fld->type = $ibf['type'];
+ $fld->max_length = $ibf['length'];
+
+ /* This needs to be populated from the metadata */
+ $fld->not_null = false;
+ $fld->has_default = false;
+ $fld->default_value = 'null';
+ return $fld;
+ }
+
+ function _initrs()
+ {
+ $this->_numOfRows = -1;
+ $this->_numOfFields = @fbird_num_fields($this->_queryID);
+
+ // cache types for blob decode check
+ for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
+ $f1 = $this->FetchField($i);
+ $this->_cacheType[] = $f1->type;
+ }
+ }
+
+ function _seek($row)
+ {
+ return false;
+ }
+
+ function _fetch()
+ {
+ $f = @fbird_fetch_row($this->_queryID);
+ if ($f === false) {
+ $this->fields = false;
+ return false;
+ }
+ // OPN stuff start - optimized
+ // fix missing nulls and decode blobs automatically
+
+ global $ADODB_ANSI_PADDING_OFF;
+ //$ADODB_ANSI_PADDING_OFF=1;
+ $rtrim = !empty($ADODB_ANSI_PADDING_OFF);
+
+ for ($i=0, $max = $this->_numOfFields; $i < $max; $i++) {
+ if ($this->_cacheType[$i]=="BLOB") {
+ if (isset($f[$i])) {
+ $f[$i] = $this->connection->_BlobDecode($f[$i]);
+ } else {
+ $f[$i] = null;
+ }
+ } else {
+ if (!isset($f[$i])) {
+ $f[$i] = null;
+ } else if ($rtrim && is_string($f[$i])) {
+ $f[$i] = rtrim($f[$i]);
+ }
+ }
+ }
+ // OPN stuff end
+
+ $this->fields = $f;
+ if ($this->fetchMode == ADODB_FETCH_ASSOC) {
+ $this->fields = $this->GetRowAssoc();
+ } else if ($this->fetchMode == ADODB_FETCH_BOTH) {
+ $this->fields = array_merge($this->fields,$this->GetRowAssoc());
+ }
+ return true;
+ }
+
+ /* Use associative array to get fields array */
+ function Fields($colname)
+ {
+ if ($this->fetchMode & ADODB_FETCH_ASSOC) return $this->fields[$colname];
+ if (!$this->bind) {
+ $this->bind = array();
+ for ($i=0; $i < $this->_numOfFields; $i++) {
+ $o = $this->FetchField($i);
+ $this->bind[strtoupper($o->name)] = $i;
+ }
+ }
+
+ return $this->fields[$this->bind[strtoupper($colname)]];
+
+ }
+
+
+ function _close()
+ {
+ return @fbird_free_result($this->_queryID);
+ }
+
+ function MetaType($t,$len=-1,$fieldobj=false)
+ {
+ if (is_object($t)) {
+ $fieldobj = $t;
+ $t = $fieldobj->type;
+ $len = $fieldobj->max_length;
+ }
+ switch (strtoupper($t)) {
+ case 'CHAR':
+ return 'C';
+
+ case 'TEXT':
+ case 'VARCHAR':
+ case 'VARYING':
+ if ($len <= $this->blobSize) return 'C';
+ return 'X';
+ case 'BLOB':
+ return 'B';
+
+ case 'TIMESTAMP':
+ case 'DATE': return 'D';
+ case 'TIME': return 'T';
+ //case 'T': return 'T';
+
+ //case 'L': return 'L';
+ case 'INT':
+ case 'SHORT':
+ case 'INTEGER': return 'I';
+ default: return ADODB_DEFAULT_METATYPE;
+ }
+ }
+
}
diff --git a/lib/adodb/drivers/adodb-ibase.inc.php b/lib/adodb/drivers/adodb-ibase.inc.php
index 95c1e7aba88..96a30cdfa8a 100644
--- a/lib/adodb/drivers/adodb-ibase.inc.php
+++ b/lib/adodb/drivers/adodb-ibase.inc.php
@@ -1,13 +1,13 @@
= 0x4050) { // actually 4.0.4
- if ( !isset($iarr[0]) ) $iarr[0] = ''; // PHP5 compat hack
- $fnarr = array_merge( array($sql) , $iarr);
- $ret = call_user_func_array($fn,$fnarr);
- } else {
- switch(sizeof($iarr)) {
- case 1: $ret = $fn($sql,$iarr[0]); break;
- case 2: $ret = $fn($sql,$iarr[0],$iarr[1]); break;
- case 3: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2]); break;
- case 4: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3]); break;
- case 5: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4]); break;
- case 6: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5]); break;
- case 7: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6]); break;
- default: ADOConnection::outp( "Too many parameters to ibase query $sql");
- case 8: $ret = $fn($sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6],$iarr[7]); break;
- }
- }
- } else $ret = $fn($sql);
+ if ( !isset($iarr[0]) )
+ $iarr[0] = ''; // PHP5 compat hack
+ $fnarr = array_merge( array($sql) , $iarr);
+ $ret = call_user_func_array($fn,$fnarr);
+ }
+ else {
+ $ret = $fn($sql);
+ }
} else {
$fn = 'ibase_query';
if (is_array($iarr)) {
- if (ADODB_PHPVER >= 0x4050) { // actually 4.0.4
- if (sizeof($iarr) == 0) $iarr[0] = ''; // PHP5 compat hack
- $fnarr = array_merge( array($conn,$sql) , $iarr);
- $ret = call_user_func_array($fn,$fnarr);
- } else {
- switch(sizeof($iarr)) {
- case 1: $ret = $fn($conn,$sql,$iarr[0]); break;
- case 2: $ret = $fn($conn,$sql,$iarr[0],$iarr[1]); break;
- case 3: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2]); break;
- case 4: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3]); break;
- case 5: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4]); break;
- case 6: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5]); break;
- case 7: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6]); break;
- default: ADOConnection::outp( "Too many parameters to ibase query $sql");
- case 8: $ret = $fn($conn,$sql,$iarr[0],$iarr[1],$iarr[2],$iarr[3],$iarr[4],$iarr[5],$iarr[6],$iarr[7]); break;
- }
- }
- } else $ret = $fn($conn,$sql);
+ if (sizeof($iarr) == 0)
+ $iarr[0] = ''; // PHP5 compat hack
+ $fnarr = array_merge( array($conn,$sql) , $iarr);
+ $ret = call_user_func_array($fn,$fnarr);
+ }
+ else {
+ $ret = $fn($conn, $sql);
+ }
}
if ($docommit && $ret === true) {
ibase_commit($this->_connectionID);
@@ -601,14 +581,8 @@ class ADODB_ibase extends ADOConnection {
function _BlobDecode( $blob )
{
- if (ADODB_PHPVER >= 0x5000) {
- $blob_data = ibase_blob_info($this->_connectionID, $blob );
- $blobid = ibase_blob_open($this->_connectionID, $blob );
- } else {
-
- $blob_data = ibase_blob_info( $blob );
- $blobid = ibase_blob_open( $blob );
- }
+ $blob_data = ibase_blob_info($this->_connectionID, $blob );
+ $blobid = ibase_blob_open($this->_connectionID, $blob );
if( $blob_data[0] > $this->maxblobsize ) {
@@ -911,7 +885,7 @@ class ADORecordset_ibase extends ADORecordSet
case 'INT':
case 'SHORT':
case 'INTEGER': return 'I';
- default: return 'N';
+ default: return ADODB_DEFAULT_METATYPE;
}
}
diff --git a/lib/adodb/drivers/adodb-informix.inc.php b/lib/adodb/drivers/adodb-informix.inc.php
index 15e9dda1cba..07f4e2831dc 100644
--- a/lib/adodb/drivers/adodb-informix.inc.php
+++ b/lib/adodb/drivers/adodb-informix.inc.php
@@ -1,6 +1,6 @@
fetchMode = $mode;
- return parent::__construct($id);
+ parent::__construct($id);
}
@@ -501,7 +501,7 @@ class ADORecordset_informix72 extends ADORecordSet {
}
/** !Eos
-* Auxiliar function to Parse coltype,collength. Used by Metacolumns
+* Auxiliary function to Parse coltype,collength. Used by Metacolumns
* return: array ($mtype,$length,$precision,$nullable) (similar to ifx_fieldpropierties)
*/
function ifx_props($coltype,$collength){
diff --git a/lib/adodb/drivers/adodb-ldap.inc.php b/lib/adodb/drivers/adodb-ldap.inc.php
index 67491449ecd..1337314bfb9 100644
--- a/lib/adodb/drivers/adodb-ldap.inc.php
+++ b/lib/adodb/drivers/adodb-ldap.inc.php
@@ -1,6 +1,6 @@
_numOfRows;
$results = array();
diff --git a/lib/adodb/drivers/adodb-mssql.inc.php b/lib/adodb/drivers/adodb-mssql.inc.php
index 6f88939b86b..be20620ebfa 100644
--- a/lib/adodb/drivers/adodb-mssql.inc.php
+++ b/lib/adodb/drivers/adodb-mssql.inc.php
@@ -1,6 +1,6 @@
= 0x4300) {
-// docs say 4.2.0, but testing shows only since 4.3.0 does it work!
- ini_set('mssql.datetimeconvert',0);
-} else {
-global $ADODB_mssql_mths; // array, months must be upper-case
-
-
- $ADODB_mssql_date_order = 'mdy';
- $ADODB_mssql_mths = array(
- 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,
- 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
-}
-
-//---------------------------------------------------------------------------
-// Call this to autoset $ADODB_mssql_date_order at the beginning of your code,
-// just after you connect to the database. Supports mdy and dmy only.
-// Not required for PHP 4.2.0 and above.
-function AutoDetect_MSSQL_Date_Order($conn)
-{
-global $ADODB_mssql_date_order;
- $adate = $conn->GetOne('select getdate()');
- if ($adate) {
- $anum = (int) $adate;
- if ($anum > 0) {
- if ($anum > 31) {
- //ADOConnection::outp( "MSSQL: YYYY-MM-DD date format not supported currently");
- } else
- $ADODB_mssql_date_order = 'dmy';
- } else
- $ADODB_mssql_date_order = 'mdy';
- }
-}
+ini_set('mssql.datetimeconvert',0);
class ADODB_mssql extends ADOConnection {
var $databaseType = "mssql";
@@ -94,7 +62,6 @@ class ADODB_mssql extends ADOConnection {
var $hasGenID = true;
var $sysDate = 'convert(datetime,convert(char,GetDate(),102),102)';
var $sysTimeStamp = 'GetDate()';
- var $_has_mssql_init;
var $maxParameterLen = 4000;
var $arrayClass = 'ADORecordSet_array_mssql';
var $uniqueSort = true;
@@ -107,11 +74,6 @@ class ADODB_mssql extends ADOConnection {
var $_bindInputArray = true;
var $forceNewConnect = false;
- function __construct()
- {
- $this->_has_mssql_init = (strnatcmp(PHP_VERSION,'4.1.0')>=0);
- }
-
function ServerInfo()
{
global $ADODB_FETCH_MODE;
@@ -155,9 +117,9 @@ class ADODB_mssql extends ADOConnection {
// the same scope. A scope is a module -- a stored procedure, trigger,
// function, or batch. Thus, two statements are in the same scope if
// they are in the same stored procedure, function, or batch.
- if ($this->lastInsID !== false) {
- return $this->lastInsID; // InsID from sp_executesql call
- } else {
+ if ($this->lastInsID !== false) {
+ return $this->lastInsID; // InsID from sp_executesql call
+ } else {
return $this->GetOne($this->identitySQL);
}
}
@@ -165,37 +127,22 @@ class ADODB_mssql extends ADOConnection {
/**
- * 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",magic_quotes_runtime());
- *
- * @param s the string to quote
- * @param [magic_quotes] if $s is GET/POST var, set to get_magic_quotes_gpc().
- * This undoes the stupidity of magic quotes for GPC.
- *
- * @return quoted string to be sent back to database
- */
- function qstr($s,$magic_quotes=false)
+ * 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.
+ *
+ * @return string Quoted string to be sent back to database
+ *
+ * @noinspection PhpUnusedParameterInspection
+ */
+ function qStr($s, $magic_quotes=false)
{
- if (!$magic_quotes) {
- return "'".str_replace("'",$this->replaceQuote,$s)."'";
- }
-
- // undo magic quotes for " unless sybase is on
- $sybase = ini_get('magic_quotes_sybase');
- if (!$sybase) {
- $s = str_replace('\\"','"',$s);
- if ($this->replaceQuote == "\\'") // ' already quoted, no need to change anything
- return "'$s'";
- else {// change \' to '' for sybase/mssql
- $s = str_replace('\\\\','\\',$s);
- return "'".str_replace("\\'",$this->replaceQuote,$s)."'";
- }
- } else {
- return "'".$s."'";
- }
+ return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
}
-// moodle change end - see readme_moodle.txt
function _affectedrows()
{
@@ -309,7 +256,9 @@ class ADODB_mssql extends ADOConnection {
case 'A':
$s .= "substring(convert(char(19),$col,0),18,2)";
break;
-
+ case 'l':
+ $s .= "datename(dw,$col)";
+ break;
default:
if ($ch == '\\') {
$i++;
@@ -327,8 +276,8 @@ class ADODB_mssql extends ADOConnection {
{
if ($this->transOff) return true;
$this->transCnt += 1;
- $ok = $this->Execute('BEGIN TRAN');
- return $ok;
+ $ok = $this->Execute('BEGIN TRAN');
+ return $ok;
}
function CommitTrans($ok=true)
@@ -451,29 +400,29 @@ class ADODB_mssql extends ADOConnection {
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()) {
if ($primary && !$row[5]) continue;
- $indexes[$row[0]]['unique'] = $row[6];
- $indexes[$row[0]]['columns'][] = $row[1];
- }
- return $indexes;
+ $indexes[$row[0]]['unique'] = $row[6];
+ $indexes[$row[0]]['columns'][] = $row[1];
+ }
+ return $indexes;
}
function MetaForeignKeys($table, $owner=false, $upper=false)
@@ -488,7 +437,7 @@ class ADODB_mssql extends ADOConnection {
"select object_name(constid) as constraint_name,
col_name(fkeyid, fkey) as column_name,
object_name(rkeyid) as referenced_table_name,
- col_name(rkeyid, rkey) as referenced_column_name
+ col_name(rkeyid, rkey) as referenced_column_name
from sysforeignkeys
where upper(object_name(fkeyid)) = $table
order by constraint_name, referenced_table_name, keyno";
@@ -509,7 +458,11 @@ order by constraint_name, referenced_table_name, keyno";
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;
@@ -519,22 +472,24 @@ order by constraint_name, referenced_table_name, keyno";
function MetaDatabases()
{
if(@mssql_select_db("master")) {
- $qry=$this->metaDatabasesSQL;
- if($rs=@mssql_query($qry,$this->_connectionID)){
- $tmpAr=$ar=array();
- while($tmpAr=@mssql_fetch_row($rs))
- $ar[]=$tmpAr[0];
- @mssql_select_db($this->database);
- if(sizeof($ar))
- return($ar);
- else
- return(false);
- } else {
- @mssql_select_db($this->database);
- return(false);
- }
- }
- return(false);
+ $qry = $this->metaDatabasesSQL;
+ if($rs = @mssql_query($qry,$this->_connectionID)) {
+ $tmpAr = $ar = array();
+ while($tmpAr = @mssql_fetch_row($rs)) {
+ $ar[]=$tmpAr[0];
+ }
+ @mssql_select_db($this->database);
+ if(sizeof($ar)) {
+ return($ar);
+ } else {
+ return(false);
+ }
+ } else {
+ @mssql_select_db($this->database);
+ return(false);
+ }
+ }
+ return(false);
}
// "Stein-Aksel Basma"
@@ -607,14 +562,18 @@ order by constraint_name, referenced_table_name, keyno";
if (!$id) return false;
$arr = mssql_fetch_array($id);
@mssql_free_result($id);
- if (is_array($arr)) return $arr[0];
- else return -1;
+ if (is_array($arr)) {
+ return $arr[0];
+ } else {
+ return -1;
+ }
}
// returns true or false, newconnect supported since php 5.1.0.
function _connect($argHostname, $argUsername, $argPassword, $argDatabasename,$newconnect=false)
{
if (!function_exists('mssql_pconnect')) return null;
+ if (!empty($this->port)) $argHostname .= ":".$this->port;
$this->_connectionID = mssql_connect($argHostname,$argUsername,$argPassword,$newconnect);
if ($this->_connectionID === false) return false;
if ($argDatabasename) return $this->SelectDB($argDatabasename);
@@ -626,6 +585,7 @@ order by constraint_name, referenced_table_name, keyno";
function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
if (!function_exists('mssql_pconnect')) return null;
+ if (!empty($this->port)) $argHostname .= ":".$this->port;
$this->_connectionID = mssql_pconnect($argHostname,$argUsername,$argPassword);
if ($this->_connectionID === false) return false;
@@ -639,9 +599,9 @@ order by constraint_name, referenced_table_name, keyno";
}
function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
- {
+ {
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true);
- }
+ }
function Prepare($sql)
{
@@ -656,31 +616,27 @@ order by constraint_name, referenced_table_name, keyno";
function PrepareSP($sql,$param=true)
{
- if (!$this->_has_mssql_init) {
- ADOConnection::outp( "PrepareSP: mssql_init only available since PHP 4.1.0");
- return $sql;
- }
$stmt = mssql_init($sql,$this->_connectionID);
if (!$stmt) return $sql;
return array($sql,$stmt);
}
// 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();
+ // 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;
- }
+ // Split single record on commas, if possible
+ if (sizeof($arr) == 1) {
+ foreach ($arr as $arg) {
+ $args = explode(',', $arg);
+ }
+ $arr = $args;
+ }
array_walk(
$arr,
@@ -688,11 +644,11 @@ order by constraint_name, referenced_table_name, keyno";
$value = "CAST(" . $value . " AS VARCHAR(255))";
}
);
- $s = implode('+',$arr);
- if (sizeof($arr) > 0) return "$s";
+ $s = implode('+',$arr);
+ if (sizeof($arr) > 0) return "$s";
return '';
- }
+ }
/*
Usage:
@@ -714,11 +670,6 @@ order by constraint_name, referenced_table_name, keyno";
*/
function Parameter(&$stmt, &$var, $name, $isOutput=false, $maxLen=4000, $type=false)
{
- if (!$this->_has_mssql_init) {
- ADOConnection::outp( "Parameter: mssql_bind only available since PHP 4.1.0");
- return false;
- }
-
$isNull = is_null($var); // php 4.0.4 and above...
if ($type === false)
@@ -728,7 +679,7 @@ order by constraint_name, referenced_table_name, keyno";
case 'double': $type = SQLFLT8; break;
case 'integer': $type = SQLINT4; break;
case 'boolean': $type = SQLINT1; break; # SQLBIT not supported in 4.1.0
- }
+ }
if ($this->debug) {
$prefix = ($isOutput) ? 'Out' : 'In';
@@ -736,7 +687,7 @@ order by constraint_name, referenced_table_name, keyno";
ADOConnection::outp( "{$prefix}Parameter(\$stmt, \$php_var='$var', \$name='$name', \$maxLen=$maxLen, \$type=$ztype);");
}
/*
- See http://phplens.com/lens/lensforum/msgs.php?id=7231
+ See PHPLens Issue No: 7231
RETVAL is HARD CODED into php_mssql extension:
The return value (a long integer value) is treated like a special OUTPUT parameter,
@@ -780,11 +731,11 @@ order by constraint_name, referenced_table_name, keyno";
# bind input params with sp_executesql:
# see http://www.quest-pipelines.com/newsletter-v3/0402_F.htm
# works only with sql server 7 and newer
- $getIdentity = false;
- if (!is_array($sql) && preg_match('/^\\s*insert/i', $sql)) {
- $getIdentity = true;
- $sql .= (preg_match('/;\\s*$/i', $sql) ? ' ' : '; ') . $this->identitySQL;
- }
+ $getIdentity = false;
+ if (!is_array($sql) && preg_match('/^\\s*insert/i', $sql)) {
+ $getIdentity = true;
+ $sql .= (preg_match('/;\\s*$/i', $sql) ? ' ' : '; ') . $this->identitySQL;
+ }
if (!is_array($sql)) $sql = $this->Prepare($sql);
$params = '';
$decl = '';
@@ -805,16 +756,16 @@ order by constraint_name, referenced_table_name, keyno";
$decl .= "@P$i NVARCHAR($len)";
}
-
- if (substr($v,0,1) == "'" && substr($v,-1,1) == "'")
+ if(substr($v,0,1) == "'" && substr($v,-1,1) == "'")
/*
* String is already fully quoted
*/
$inputVar = $v;
else
- $inputVar = $this->qstr($v);
+ $inputVar = $db->this($v);
- $params .= "@P$i=N" . $inputVar;
+ $params .= "@P$i=N" . $inputVar;
+
} else if (is_integer($v)) {
$decl .= "@P$i INT";
$params .= "@P$i=".$v;
@@ -833,20 +784,20 @@ order by constraint_name, referenced_table_name, keyno";
$decl = $this->qstr($decl);
if ($this->debug) ADOConnection::outp("sp_executesql N{$sql[1]},N$decl,$params");
$rez = mssql_query("sp_executesql N{$sql[1]},N$decl,$params", $this->_connectionID);
- if ($getIdentity) {
- $arr = @mssql_fetch_row($rez);
- $this->lastInsID = isset($arr[0]) ? $arr[0] : false;
- @mssql_data_seek($rez, 0);
- }
+ if ($getIdentity) {
+ $arr = @mssql_fetch_row($rez);
+ $this->lastInsID = isset($arr[0]) ? $arr[0] : false;
+ @mssql_data_seek($rez, 0);
+ }
} else if (is_array($sql)) {
# PrepareSP()
$rez = mssql_execute($sql[1]);
- $this->lastInsID = false;
+ $this->lastInsID = false;
} else {
$rez = mssql_query($sql,$this->_connectionID);
- $this->lastInsID = false;
+ $this->lastInsID = false;
}
return $rez;
}
@@ -854,33 +805,54 @@ order by constraint_name, referenced_table_name, keyno";
// returns true or false
function _close()
{
- if ($this->transCnt) $this->RollbackTrans();
- $rez = @mssql_close($this->_connectionID);
+ if ($this->transCnt) {
+ $this->RollbackTrans();
+ }
+ if($this->_connectionID) {
+ $rez = mssql_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_mssql::UnixDate($v);
- }
+
- static function UnixTimeStamp($v)
+ /**
+ * 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)
{
- return ADORecordSet_array_mssql::UnixTimeStamp($v);
+ 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;
}
}
/*--------------------------------------------------------------------------------------
- Class Name: Recordset
+ Class Name: Recordset
--------------------------------------------------------------------------------------*/
class ADORecordset_mssql extends ADORecordSet {
var $databaseType = "mssql";
var $canSeek = true;
- var $hasFetchAssoc; // see http://phplens.com/lens/lensforum/msgs.php?id=6083
+ var $hasFetchAssoc; // see PHPLens Issue No: 6083
// _mths works only in non-localised system
function __construct($id,$mode=false)
@@ -894,7 +866,7 @@ class ADORecordset_mssql extends ADORecordSet {
}
$this->fetchMode = $mode;
- return parent::__construct($id,$mode);
+ return parent::__construct($id);
}
@@ -930,7 +902,7 @@ class ADORecordset_mssql extends ADORecordSet {
}
}
- return $this->fields[$this->bind[strtoupper($colname)]];
+ return $this->fields[$this->bind[strtoupper($colname)]];
}
/* Returns: an object containing field information.
@@ -970,7 +942,7 @@ class ADORecordset_mssql extends ADORecordSet {
}
else {
if ($this->hasFetchAssoc) {// only for PHP 4.2.0 or later
- $this->fields = @mssql_fetch_assoc($this->_queryID);
+ $this->fields = @mssql_fetch_assoc($this->_queryID);
} else {
$flds = @mssql_fetch_array($this->_queryID);
if (is_array($flds)) {
@@ -1027,9 +999,9 @@ class ADORecordset_mssql extends ADORecordSet {
$this->fields = @mssql_fetch_assoc($this->_queryID);
else {
$this->fields = @mssql_fetch_array($this->_queryID);
- if (@is_array($$this->fields)) {
+ if (@is_array($this->fields)) {
$fassoc = array();
- foreach($$this->fields as $k => $v) {
+ foreach($this->fields as $k => $v) {
if (is_integer($k)) continue;
$fassoc[$k] = $v;
}
@@ -1075,108 +1047,43 @@ class ADORecordset_mssql extends ADORecordSet {
return true;
}
- // mssql uses a default date like Dec 30 2000 12:00AM
- static function UnixDate($v)
+ /**
+ * 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 ADORecordSet_array_mssql::UnixDate($v);
+ return ADODB_STRINGMAX_NOLIMIT;
}
- static function UnixTimeStamp($v)
+ /**
+ * 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 ADORecordSet_array_mssql::UnixTimeStamp($v);
+ return ADODB_STRINGMAX_NOLIMIT;
}
}
-class ADORecordSet_array_mssql 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 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 mktime($rr[4],$rr[5],0,$themth,$theday,$rr[3]);
- }
-}
+class ADORecordSet_array_mssql extends ADORecordSet_array {}
/*
Code Example 1:
-select object_name(constid) as constraint_name,
- object_name(fkeyid) as table_name,
- col_name(fkeyid, fkey) as column_name,
+select object_name(constid) as constraint_name,
+ object_name(fkeyid) as table_name,
+ col_name(fkeyid, fkey) as column_name,
object_name(rkeyid) as referenced_table_name,
- col_name(rkeyid, rkey) as referenced_column_name
+ col_name(rkeyid, rkey) as referenced_column_name
from sysforeignkeys
where object_name(fkeyid) = x
order by constraint_name, table_name, referenced_table_name, keyno
diff --git a/lib/adodb/drivers/adodb-mssql_n.inc.php b/lib/adodb/drivers/adodb-mssql_n.inc.php
index 28b29bb2aff..b8c650f1235 100644
--- a/lib/adodb/drivers/adodb-mssql_n.inc.php
+++ b/lib/adodb/drivers/adodb-mssql_n.inc.php
@@ -8,7 +8,7 @@
// //
// ADOdb - Database Abstraction Library for PHP //
// //
-// Latest version is available at http://adodb.org //
+// Latest version is available at https://adodb.org //
// //
// Copyright (c) 2000-2014 John Lim (jlim\@natsoft.com.my) //
// All rights reserved. //
@@ -66,12 +66,12 @@ class ADODB_mssql_n extends ADODB_mssql {
* and ODBTP) keeping SQL compatibility at ADOdb level (instead of hacking every project to add
* the "N" notation when working against MSSQL.
*
- * The orginal note indicated that this hack should only be used if ALL the char-based columns
+ * The original note indicated that this hack should only be used if ALL the char-based columns
* in your DB are of type nchar, nvarchar and ntext, but testing seems to indicate that SQL server
* doesn't seem to care if the statement is used against char etc fields.
*
* @todo This function should raise an ADOdb error if one of the transformations fail
- *
+ *
* @param mixed $inboundData Either a string containing an SQL statement
* or an array with resources from prepared statements
*
@@ -80,22 +80,22 @@ class ADODB_mssql_n extends ADODB_mssql {
function _appendN($inboundData) {
$inboundIsArray = false;
-
+
if (is_array($inboundData))
{
$inboundIsArray = true;
$inboundArray = $inboundData;
} else
$inboundArray = (array)$inboundData;
-
+
/*
* All changes will be placed here
*/
$outboundArray = $inboundArray;
-
+
foreach($inboundArray as $inboundKey=>$inboundValue)
{
-
+
if (is_resource($inboundValue))
{
/*
@@ -106,7 +106,7 @@ class ADODB_mssql_n extends ADODB_mssql {
continue;
}
-
+
if (strpos($inboundValue, SINGLEQUOTE) === false)
{
/*
@@ -121,11 +121,11 @@ class ADODB_mssql_n extends ADODB_mssql {
* Check we haven't an odd number of single quotes (this can cause problems below
* and should be considered one wrong SQL). Exit with debug info.
*/
- if ((substr_count($inboundValue, SINGLEQUOTE) & 1))
+ if ((substr_count($inboundValue, SINGLEQUOTE) & 1))
{
if ($this->debug)
ADOConnection::outp("{$this->databaseType} internal transformation: not converted. Wrong number of quotes (odd)");
-
+
break;
}
@@ -136,9 +136,9 @@ class ADODB_mssql_n extends ADODB_mssql {
$regexp = '/(\\\\' . SINGLEQUOTE . '[^' . SINGLEQUOTE . '])/';
if (preg_match($regexp, $inboundValue))
{
- if ($this->debug)
+ if ($this->debug)
ADOConnection::outp("{$this->databaseType} internal transformation: not converted. Found bad use of backslash + single quote");
-
+
break;
}
@@ -148,16 +148,16 @@ class ADODB_mssql_n extends ADODB_mssql {
$pairs = array();
$regexp = '/(' . SINGLEQUOTE . SINGLEQUOTE . ')/';
preg_match_all($regexp, $inboundValue, $list_of_pairs);
-
+
if ($list_of_pairs)
{
foreach (array_unique($list_of_pairs[0]) as $key=>$value)
$pairs['<@#@#@PAIR-'.$key.'@#@#@>'] = $value;
-
-
+
+
if (!empty($pairs))
$inboundValue = str_replace($pairs, array_keys($pairs), $inboundValue);
-
+
}
/*
@@ -166,13 +166,13 @@ class ADODB_mssql_n extends ADODB_mssql {
$literals = array();
$regexp = '/(N?' . SINGLEQUOTE . '.*?' . SINGLEQUOTE . ')/is';
preg_match_all($regexp, $inboundValue, $list_of_literals);
-
+
if ($list_of_literals)
{
foreach (array_unique($list_of_literals[0]) as $key=>$value)
$literals['<#@#@#LITERAL-'.$key.'#@#@#>'] = $value;
-
-
+
+
if (!empty($literals))
$inboundValue = str_replace($literals, array_keys($literals), $inboundValue);
}
@@ -185,11 +185,11 @@ class ADODB_mssql_n extends ADODB_mssql {
foreach ($literals as $key=>$value) {
if (!is_numeric(trim($value, SINGLEQUOTE)))
/*
- * Non numeric string, prepend our dear N, whilst
+ * Non numeric string, prepend our dear N, whilst
* Trimming potentially existing previous "N"
*/
- $literals[$key] = 'N' . trim($value, 'N');
-
+ $literals[$key] = 'N' . trim($value, 'N');
+
}
}
@@ -198,7 +198,7 @@ class ADODB_mssql_n extends ADODB_mssql {
*/
if (!empty($literals))
$inboundValue = str_replace(array_keys($literals), $literals, $inboundValue);
-
+
/*
* Any pairs followed by N' must be switched to N' followed by those pairs
@@ -211,40 +211,36 @@ class ADODB_mssql_n extends ADODB_mssql {
*/
if (!empty($pairs))
$inboundValue = str_replace(array_keys($pairs), $pairs, $inboundValue);
-
+
/*
* Print transformation if debug = on
*/
if (strcmp($inboundValue,$inboundArray[$inboundKey]) <> 0 && $this->debug)
ADOConnection::outp("{$this->databaseType} internal transformation: {$inboundArray[$inboundKey]} to {$inboundValue}");
-
+
if (strcmp($inboundValue,$inboundArray[$inboundKey]) <> 0)
/*
* Place the transformed value into the outbound array
*/
$outboundArray[$inboundKey] = $inboundValue;
}
-
+
/*
* Any transformations are in the $outboundArray
*/
if ($inboundIsArray)
return $outboundArray;
-
+
/*
* We passed a string in originally
*/
return $outboundArray[0];
-
+
}
}
class ADORecordset_mssql_n extends ADORecordset_mssql {
var $databaseType = "mssql_n";
- function __construct($id,$mode=false)
- {
- parent::__construct($id,$mode);
- }
}
diff --git a/lib/adodb/drivers/adodb-mssqlnative.inc.php b/lib/adodb/drivers/adodb-mssqlnative.inc.php
index 72f1d7eed85..10a344af22d 100644
--- a/lib/adodb/drivers/adodb-mssqlnative.inc.php
+++ b/lib/adodb/drivers/adodb-mssqlnative.inc.php
@@ -1,6 +1,6 @@
= 0x4300) {
-// docs say 4.2.0, but testing shows only since 4.3.0 does it work!
- ini_set('mssql.datetimeconvert',0);
-} else {
- global $ADODB_mssql_mths; // array, months must be upper-case
- $ADODB_mssql_date_order = 'mdy';
- $ADODB_mssql_mths = array(
- 'JAN'=>1,'FEB'=>2,'MAR'=>3,'APR'=>4,'MAY'=>5,'JUN'=>6,
- 'JUL'=>7,'AUG'=>8,'SEP'=>9,'OCT'=>10,'NOV'=>11,'DEC'=>12);
-}
-
class ADODB_mssqlnative extends ADOConnection {
var $databaseType = "mssqlnative";
var $dataProvider = "mssqlnative";
@@ -124,8 +87,10 @@ class ADODB_mssqlnative extends ADOConnection {
var $uniqueOrderBy = true;
var $_bindInputArray = true;
var $_dropSeqSQL = "drop table %s";
- var $connectionInfo = array();
+
+ var $connectionInfo = array('ReturnDatesAsStrings'=>true);
var $cachedSchemaFlush = false;
+
var $sequences = false;
var $mssql_version = '';
@@ -163,7 +128,7 @@ class ADODB_mssqlnative extends ADOConnection {
}
function ServerInfo() {
- global $ADODB_FETCH_MODE;
+ global $ADODB_FETCH_MODE;
static $arr = false;
if (is_array($arr))
return $arr;
@@ -189,11 +154,9 @@ class ADODB_mssqlnative extends ADOConnection {
function _insertid()
{
- // SCOPE_IDENTITY()
- // Returns the last IDENTITY value inserted into an IDENTITY column in
- // the same scope. A scope is a module -- a stored procedure, trigger,
- // function, or batch. Thus, two statements are in the same scope if
- // they are in the same stored procedure, function, or batch.
+ $rez = sqlsrv_query($this->_connectionID,$this->identitySQL);
+ sqlsrv_fetch($rez);
+ $this->lastInsertID = sqlsrv_get_field($rez, 0);
return $this->lastInsertID;
}
@@ -204,8 +167,6 @@ class ADODB_mssqlnative extends ADOConnection {
}
function GenID($seq='adodbseq',$start=1) {
- if (!$this->mssql_version)
- $this->ServerVersion();
switch($this->mssql_version){
case 9:
case 10:
@@ -219,9 +180,6 @@ class ADODB_mssqlnative extends ADOConnection {
function CreateSequence($seq='adodbseq',$start=1)
{
- if (!$this->mssql_version)
- $this->ServerVersion();
-
switch($this->mssql_version){
case 9:
case 10:
@@ -231,7 +189,6 @@ class ADODB_mssqlnative extends ADOConnection {
return $this->CreateSequence2012($seq, $start);
break;
}
-
}
/**
@@ -324,6 +281,20 @@ class ADODB_mssqlnative extends ADOConnection {
if (!$col) $col = $this->sysTimeStamp;
$s = '';
+ $ConvertableFmt=array(
+ "m/d/Y"=>101,"m/d/y"=>101 // US
+ ,"Y.m.d"=>102,"y/m/d"=>102 // ANSI
+ ,"d/m/Y"=>103,"d/m/y"=>103 // French /english
+ ,"d.m.Y"=>104,"d.m.y"=>104 // German
+ ,"d-m-Y"=>105,"d-m-y"=>105 // Italian
+ ,"m-d-Y"=>110,"m-d-y"=>110 // US Dash
+ ,"Y/m/d"=>111,"y/m/d"=>111 // Japan
+ ,"Ymd"=>112,"ymd"=>112 // ISO
+ ,"H:i:s"=>108 // Time
+ );
+ if(key_exists($fmt,$ConvertableFmt))
+ return "convert (varchar ,$col,".$ConvertableFmt[$fmt].")";
+
$len = strlen($fmt);
for ($i=0; $i < $len; $i++) {
if ($s) $s .= '+';
@@ -365,7 +336,9 @@ class ADODB_mssqlnative extends ADOConnection {
case 'A':
$s .= "substring(convert(char(19),$col,0),18,2)";
break;
-
+ case 'l':
+ $s .= "datename(dw,$col)";
+ break;
default:
if ($ch == '\\') {
$i++;
@@ -397,6 +370,7 @@ class ADODB_mssqlnative extends ADOConnection {
sqlsrv_commit($this->_connectionID);
return true;
}
+
function RollbackTrans()
{
if ($this->transOff) return true;
@@ -465,30 +439,75 @@ class ADODB_mssqlnative extends ADOConnection {
function ErrorNo()
{
$err = sqlsrv_errors(SQLSRV_ERR_ALL);
- if($err[0]) return $err[0]['code'];
- else return 0;
+ if ($err && $err[0])
+ return $err[0]['code'];
+ else
+ return 0;
}
// returns true or false
function _connect($argHostname, $argUsername, $argPassword, $argDatabasename)
{
- if (!function_exists('sqlsrv_connect')) return null;
- $connectionInfo = $this->connectionInfo;
- $connectionInfo["Database"]=$argDatabasename;
- $connectionInfo["UID"]=$argUsername;
- $connectionInfo["PWD"]=$argPassword;
+ if (!function_exists('sqlsrv_connect'))
+ {
+ if ($this->debug)
+ ADOConnection::outp('Microsoft SQL Server native driver (mssqlnative) not installed');
+ return null;
+ }
+
+ if (!empty($this->port))
+ /*
+ * Port uses a comma
+ */
+ $argHostname .= ",".$this->port;
+
+ $connectionInfo = $this->connectionInfo;
+ $connectionInfo["Database"] = $argDatabasename;
+ if ((string)$argUsername != '' || (string)$argPassword != '')
+ {
+ /*
+ * If they pass either a userid or password, we assume
+ * SQL Server authentication
+ */
+ $connectionInfo["UID"] = $argUsername;
+ $connectionInfo["PWD"] = $argPassword;
+
+ if ($this->debug)
+ ADOConnection::outp('userid or password supplied, attempting connection with SQL Server Authentication');
+
+ }
+ else
+ {
+ /*
+ * If they don't pass either value, we won't add them to the
+ * connection parameters. This will then force an attempt
+ * to use windows authentication
+ */
+ if ($this->debug)
+
+ ADOConnection::outp('No userid or password supplied, attempting connection with Windows Authentication');
+ }
+
- foreach ($this->connectionParameters as $parameter=>$value)
- $connectionInfo[$parameter] = $value;
-
- if ($this->debug) ADOConnection::outp(" connecting... hostname: $argHostname params: ".var_export($connectionInfo,true));
- //if ($this->debug) ADOConnection::outp(" _connectionID before: ".serialize($this->_connectionID));
- if(!($this->_connectionID = sqlsrv_connect($argHostname,$connectionInfo))) {
- if ($this->debug) ADOConnection::outp( " errors: ".print_r( sqlsrv_errors(), true));
+ /*
+ * Now merge in the passed connection parameters setting
+ */
+ foreach ($this->connectionParameters as $options)
+ {
+ foreach($options as $parameter=>$value)
+ $connectionInfo[$parameter] = $value;
+ }
+
+ if ($this->debug) ADOConnection::outp("connecting to host: $argHostname params: ".var_export($connectionInfo,true));
+ if(!($this->_connectionID = @sqlsrv_connect($argHostname,$connectionInfo)))
+ {
+ if ($this->debug)
+ ADOConnection::outp( 'Connection Failed: '.print_r( sqlsrv_errors(), true));
return false;
}
- //if ($this->debug) ADOConnection::outp(" _connectionID after: ".serialize($this->_connectionID));
- //if ($this->debug) ADOConnection::outp(" defined functions: ".var_export(get_defined_functions(),true)." ");
+
+ $this->ServerVersion();
+
return true;
}
@@ -502,10 +521,6 @@ class ADODB_mssqlnative extends ADOConnection {
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
@@ -565,7 +580,8 @@ class ADODB_mssqlnative extends ADOConnection {
{
$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
@@ -573,7 +589,14 @@ class ADODB_mssqlnative extends ADOConnection {
$insert = true;
$sql .= '; '.$this->identitySQL; // select scope_identity()
}
- if($inputarr) {
+ if($inputarr)
+ {
+ /*
+ * Ensure that the input array is numeric, 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);
@@ -581,38 +604,26 @@ class ADODB_mssqlnative extends ADOConnection {
if ($this->debug) ADOConnection::outp(" running query: ".var_export($sql,true)." input array: ".var_export($inputarr,true)." result: ".var_export($rez,true));
- if(!$rez) {
+ if(!$rez)
$rez = false;
- } else if ($insert) {
- // retrieve the last insert ID (where applicable)
- while ( sqlsrv_next_result($rez) ) {
- sqlsrv_fetch($rez);
- $this->lastInsertID = sqlsrv_get_field($rez, 0);
- }
- }
+
return $rez;
}
// 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)
{
$table = $this->qstr($table);
@@ -670,7 +681,7 @@ class ADODB_mssqlnative extends ADOConnection {
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;
@@ -686,7 +697,11 @@ class ADODB_mssqlnative extends ADOConnection {
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;
@@ -752,7 +767,9 @@ class ADODB_mssqlnative extends ADOConnection {
}
function MetaColumns($table, $upper=true, $schema=false){
- # start adg
+ /*
+ * A simple caching mechanism, to be replaced in ADOdb V6
+ */
static $cached_columns = array();
if ($this->cachedSchemaFlush)
$cached_columns = array();
@@ -760,10 +777,7 @@ class ADODB_mssqlnative extends ADOConnection {
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) {
@@ -797,7 +811,7 @@ class ADODB_mssqlnative extends ADOConnection {
$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];
@@ -808,7 +822,7 @@ class ADODB_mssqlnative extends ADOConnection {
$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'];
@@ -825,16 +839,130 @@ class ADODB_mssqlnative extends ADOConnection {
}
$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 {
@@ -844,6 +972,68 @@ class ADORecordset_mssqlnative extends ADORecordSet {
var $fieldOffset = 0;
// _mths works only in non-localised system
+ /*
+ * Holds a cached version of the metadata
+ */
+ private $fieldObjects = false;
+
+ /*
+ * Flags if we have retrieved the 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) {
@@ -852,29 +1042,15 @@ class ADORecordset_mssqlnative extends ADORecordSet {
}
$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();
}
@@ -894,7 +1070,14 @@ class ADORecordset_mssqlnative extends ADORecordSet {
/* Use associative array to get fields array */
function Fields($colname)
{
- if ($this->fetchMode != ADODB_FETCH_NUM) return $this->fields[$colname];
+ if (!is_array($this->fields))
+ /*
+ * Too early
+ */
+ return;
+ if ($this->fetchMode != ADODB_FETCH_NUM)
+ return $this->fields[$colname];
+
if (!$this->bind) {
$this->bind = array();
for ($i=0; $i < $this->_numOfFields; $i++) {
@@ -906,79 +1089,74 @@ class ADORecordset_mssqlnative extends ADORecordSet {
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'
- );
-
- $fa = @sqlsrv_field_metadata($this->_queryID);
- if ($fieldOffset != -1) {
- $fa = $fa[$fieldOffset];
- }
- $false = false;
- if (empty($fa)) {
- $f = false;//PHP Notice: Only variable references should be returned by reference
- }
- 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']]
- );
+ if ($this->fieldObjectsRetrieved){
+ if ($this->fieldObjects) {
+ /*
+ * Already got the information
+ */
+ if ($fieldOffset == -1)
+ return $this->fieldObjects;
+ else
+ return $this->fieldObjects[$fieldOffset];
}
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;
+ /*
+ * No metadata available
+ */
+ return false;
}
- return $f;
+
+ $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;
+
+ $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->fieldObjects[$key] = $fld;
+
+ $this->fieldObjectsIndex[$fld->name] = $key;
+
+ }
+ if ($fieldOffset == -1)
+ return $this->fieldObjects;
+
+ return $this->fieldObjects[$fieldOffset];
}
/*
@@ -986,12 +1164,16 @@ class ADORecordset_mssqlnative extends ADORecordSet {
* 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->fieldObjects[$fieldOffset];
}
function _seek($row)
@@ -1002,178 +1184,73 @@ class ADORecordset_mssqlnative extends ADORecordSet {
// 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;
- }
- }
+ 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);
+
}
- } else {
- //# KMN # if ($this->connection->debug) ADOConnection::outp("fetch mode: num");
+ }
+ else
$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($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));
+
+ 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()
{
+ /*
+ * If we are closing down a failed query, collect any
+ * error messages. This is a hack fix to the "close too early"
+ * problem so this might go away later
+ */
+ $this->connection->errorMsg();
if(is_resource($this->_queryID)) {
$rez = sqlsrv_free_stmt($this->_queryID);
$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);
- }
-
- 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/lib/adodb/drivers/adodb-mssqlpo.inc.php b/lib/adodb/drivers/adodb-mssqlpo.inc.php
index 8dd0e36fb84..86f69d87d7c 100644
--- a/lib/adodb/drivers/adodb-mssqlpo.inc.php
+++ b/lib/adodb/drivers/adodb-mssqlpo.inc.php
@@ -1,6 +1,6 @@
_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 +47,4 @@ class ADODB_mssqlpo extends ADODB_mssql {
class ADORecordset_mssqlpo extends ADORecordset_mssql {
var $databaseType = "mssqlpo";
- function __construct($id,$mode=false)
- {
- parent::__construct($id,$mode);
- }
}
diff --git a/lib/adodb/drivers/adodb-mysql.inc.php b/lib/adodb/drivers/adodb-mysql.inc.php
index 98bd31a7fc3..dae31b455f9 100644
--- a/lib/adodb/drivers/adodb-mysql.inc.php
+++ b/lib/adodb/drivers/adodb-mysql.inc.php
@@ -1,6 +1,6 @@
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_name)
{
if (!function_exists('mysql_set_charset')) {
return false;
@@ -75,19 +94,19 @@ class ADODB_mysql extends ADOConnection {
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 +172,7 @@ class ADODB_mysql extends ADOConnection {
*
* @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 +192,7 @@ class ADODB_mysql extends ADOConnection {
}
- function MetaIndexes ($table, $primary = FALSE, $owner=false)
+ function metaIndexes ($table, $primary = FALSE, $owner=false)
{
// save old fetch mode
global $ADODB_FETCH_MODE;
@@ -226,25 +245,32 @@ class ADODB_mysql extends ADOConnection {
}
- // 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 (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_null($s)) {
+ return 'NULL';
}
- // undo magic quotes for "
- $s = str_replace('\\"','"',$s);
- return "'$s'";
+ if (is_resource($this->_connectionID)) {
+ return "'" . mysql_real_escape_string($s, $this->_connectionID) . "'";
+ }
+
+ if ($this->replaceQuote[0] == '\\') {
+ $s = str_replace(array('\\', "\0"), array('\\\\', "\\\0"), $s);
+ }
+ return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
}
function _insertid()
@@ -253,7 +279,7 @@ class ADODB_mysql extends ADOConnection {
//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 +295,7 @@ class ADODB_mysql extends ADOConnection {
return false;
}
- function BeginTrans()
+ function beginTrans()
{
if ($this->debug) ADOConnection::outp("Transactions not supported in 'mysql' driver. Use 'mysqlt' or 'mysqli' driver");
}
@@ -287,7 +313,7 @@ class ADODB_mysql extends ADOConnection {
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 +324,7 @@ class ADODB_mysql extends ADOConnection {
}
- 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 +353,7 @@ class ADODB_mysql extends ADOConnection {
return $this->genID;
}
- function MetaDatabases()
+ function metaDatabases()
{
$qid = mysql_list_dbs($this->_connectionID);
$arr = array();
@@ -343,7 +369,7 @@ class ADODB_mysql extends ADOConnection {
// 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 +457,7 @@ class ADODB_mysql extends ADOConnection {
// 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 +468,7 @@ class ADODB_mysql extends ADOConnection {
else return '';
}
- function OffsetDate($dayFraction,$date=false)
+ function offsetDate($dayFraction,$date=false)
{
if (!$date) $date = $this->sysDate;
@@ -455,19 +481,23 @@ class ADODB_mysql extends ADOConnection {
// 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 +506,18 @@ class ADODB_mysql extends ADOConnection {
{
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 +527,7 @@ class ADODB_mysql extends ADOConnection {
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 +607,7 @@ class ADODB_mysql extends ADOConnection {
}
// 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,12 +618,12 @@ class ADODB_mysql extends ADOConnection {
}
// 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;
$offsetStr =($offset>=0) ? ((integer)$offset)."," : '';
- // jason judge, see http://phplens.com/lens/lensforum/msgs.php?id=9220
+ // jason judge, see PHPLens Issue No: 9220
if ($nrows < 0) $nrows = '18446744073709551615';
if ($secs)
@@ -613,7 +648,7 @@ class ADODB_mysql extends ADOConnection {
}
/* Returns: the last error message from previous database operation */
- function ErrorMsg()
+ function errorMsg()
{
if ($this->_logsql) return $this->_errorMsg;
@@ -623,7 +658,7 @@ class ADODB_mysql extends ADOConnection {
}
/* 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 +678,7 @@ class ADODB_mysql extends ADOConnection {
/*
* Maximum size of C field
*/
- function CharMax()
+ function charMax()
{
return 255;
}
@@ -651,13 +686,13 @@ class ADODB_mysql extends ADOConnection {
/*
* 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 +778,7 @@ class ADORecordSet_mysql extends ADORecordSet{
$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 +796,7 @@ class ADORecordSet_mysql extends ADORecordSet{
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 +808,7 @@ class ADORecordSet_mysql extends ADORecordSet{
}
/* 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 +829,8 @@ class ADORecordSet_mysql extends ADORecordSet{
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 +855,7 @@ class ADORecordSet_mysql extends ADORecordSet{
$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 +905,18 @@ class ADORecordSet_mysql extends ADORecordSet{
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/lib/adodb/drivers/adodb-mysqli.inc.php b/lib/adodb/drivers/adodb-mysqli.inc.php
index 63138617463..f9f16f750a7 100644
--- a/lib/adodb/drivers/adodb-mysqli.inc.php
+++ b/lib/adodb/drivers/adodb-mysqli.inc.php
@@ -1,6 +1,6 @@
_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);
}
- // 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 +125,7 @@ class ADODB_mysqli extends ADOConnection {
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 +134,29 @@ class ADODB_mysqli extends ADOConnection {
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 $options)
+ {
+ foreach($options as $k=>$v)
+ $ok = mysqli_options($this->_connectionID,$k,$v);
+ }
+
+ //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 +170,249 @@ class ADODB_mysqli extends ADOConnection {
$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 ($this->replaceQuote[0] == '\\') {
- $s = adodb_str_replace(array('\\',"\0"), array('\\\\',"\\\0") ,$s);
- }
- return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
+ if (is_null($s)) {
+ return 'NULL';
}
- // undo magic quotes for "
- $s = str_replace('\\"','"',$s);
- return "'$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) . "'";
+ }
+
+ if ($this->replaceQuote[0] == '\\') {
+ $s = str_replace(array('\\', "\0"), array('\\\\', "\\\0") ,$s);
+ }
+ return "'" . str_replace("'", $this->replaceQuote, $s) . "'";
}
+ /**
+ * Return the AUTO_INCREMENT id of the last row that has been inserted or updated in a table.
+ *
+ * @return int|string
+ */
function _insertid()
{
- $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()
{
$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 +420,96 @@ class ADODB_mysqli extends ADOConnection {
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 +518,15 @@ class ADODB_mysqli extends ADOConnection {
$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 +537,7 @@ class ADODB_mysqli extends ADOConnection {
$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 +561,17 @@ class ADODB_mysqli extends ADOConnection {
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 +648,15 @@ class ADODB_mysqli extends ADOConnection {
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 +665,17 @@ class ADODB_mysqli extends ADOConnection {
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 +685,25 @@ class ADODB_mysqli extends ADOConnection {
// 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 +714,11 @@ class ADODB_mysqli extends ADOConnection {
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 +728,10 @@ class ADODB_mysqli extends ADOConnection {
}
}
- $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 +743,7 @@ class ADODB_mysqli extends ADOConnection {
// restore fetchmode
if (isset($savem)) {
- $this->SetFetchMode($savem);
+ $this->setFetchMode($savem);
}
$ADODB_FETCH_MODE = $save;
@@ -547,13 +753,13 @@ class ADODB_mysqli extends ADOConnection {
/**
* 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 +772,43 @@ class ADODB_mysqli extends ADOConnection {
$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 +841,15 @@ class ADODB_mysqli extends ADOConnection {
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)
@@ -629,6 +860,19 @@ class ADODB_mysqli extends ADOConnection {
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== false)
$savem = $this->SetFetchMode(false);
+ /*
+ * Return assoc array where key is column name, value is column type
+ * [1] => int unsigned
+ */
+
+ $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;
@@ -640,6 +884,12 @@ class ADODB_mysqli extends ADOConnection {
$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
+ */
+ $type = $schemaArray[strtolower($fld->name)];
// split type into type(length):
$fld->scale = null;
@@ -660,6 +910,7 @@ class ADODB_mysqli extends ADOConnection {
$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);
@@ -682,14 +933,22 @@ class ADODB_mysqli extends ADOConnection {
} 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);
@@ -699,19 +958,32 @@ class ADODB_mysqli extends ADOConnection {
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;
@@ -719,30 +991,53 @@ class ADODB_mysqli extends ADOConnection {
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
@@ -763,15 +1058,30 @@ class ADODB_mysqli extends ADOConnection {
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;
}
@@ -791,13 +1101,19 @@ class ADODB_mysqli extends ADOConnection {
}
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))
@@ -807,7 +1123,11 @@ class ADODB_mysqli extends ADOConnection {
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))
@@ -816,37 +1136,48 @@ class ADODB_mysqli extends ADOConnection {
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
-
+ /**
+ * Get the name of the character set the client connection is using now.
+ *
+ * @return string|bool The name of the character set, or false if it can't be determined.
+ */
function GetCharSet()
{
//we will use ADO's builtin property charSet
@@ -861,7 +1192,15 @@ class ADODB_mysqli extends ADOConnection {
}
}
- // SetCharSet - switch the client encoding
+ /**
+ * Sets the character set for database connections (limited databases).
+ *
+ * @link https://adodb.org/dokuwiki/doku.php?id=v5:reference:connection:setcharset
+ *
+ * @param string $charset_name The character set to switch to.
+ *
+ * @return bool True if the character set was changed successfully, otherwise false.
+ */
function SetCharSet($charset_name)
{
if (!method_exists($this->_connectionID,'set_charset')) {
@@ -870,7 +1209,7 @@ class ADODB_mysqli extends ADOConnection {
if ($this->charSet !== $charset_name) {
$if = @$this->_connectionID->set_charset($charset_name);
- return ($if === true & $this->GetCharSet() == $charset_name);
+ return ($if === true & $this->getCharSet() == $charset_name);
} else {
return true;
}
@@ -878,10 +1217,9 @@ class ADODB_mysqli extends ADOConnection {
}
-/*--------------------------------------------------------------------------------------
- Class Name: Recordset
---------------------------------------------------------------------------------------*/
-
+/**
+ * Class ADORecordSet_mysqli
+ */
class ADORecordSet_mysqli extends ADORecordSet{
var $databaseType = "mysqli";
@@ -939,6 +1277,15 @@ class ADORecordSet_mysqli extends ADORecordSet{
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;
@@ -960,19 +1307,43 @@ class ADORecordSet_mysqli extends ADORecordSet{
// $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) {
@@ -982,13 +1353,20 @@ class ADORecordSet_mysqli extends ADORecordSet{
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) {
@@ -1000,10 +1378,16 @@ class ADORecordSet_mysqli extends ADORecordSet{
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;
@@ -1011,25 +1395,32 @@ class ADORecordSet_mysqli extends ADORecordSet{
// 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;
- }
- // 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) {
+ if (!mysqli_next_result($this->connection->_connectionID)) {
return false;
}
- $this->_inited = false;
- $this->bind = 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) {
+ return 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;
@@ -1044,6 +1435,11 @@ class ADORecordSet_mysqli extends ADORecordSet{
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);
@@ -1051,18 +1447,23 @@ class ADORecordSet_mysqli extends ADORecordSet{
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;
@@ -1097,6 +1498,15 @@ class ADORecordSet_mysqli extends ADORecordSet{
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)) {
@@ -1105,99 +1515,107 @@ class ADORecordSet_mysqli extends ADORecordSet{
$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 '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 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';
+ 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':
+ // 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 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 'YEAR':
+ case 'DATE':
+ case MYSQLI_TYPE_DATE :
+ case MYSQLI_TYPE_YEAR :
+ return 'D';
- case 'TIME':
- case 'DATETIME':
- case 'TIMESTAMP':
+ 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 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 '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';
+ 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';
+ // 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)) {
@@ -1206,90 +1624,89 @@ class ADORecordSet_array_mysqli extends ADORecordSet_array {
$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 '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 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';
+ 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':
+ // 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 :
+ case MYSQLI_TYPE_BLOB :
+ case MYSQLI_TYPE_LONG_BLOB :
+ case MYSQLI_TYPE_MEDIUM_BLOB :
+ return !empty($fieldobj->binary) ? 'B' : 'X';
- return !empty($fieldobj->binary) ? 'B' : 'X';
- case 'YEAR':
- case 'DATE':
- case MYSQLI_TYPE_DATE :
- case MYSQLI_TYPE_YEAR :
+ case 'YEAR':
+ case 'DATE':
+ case MYSQLI_TYPE_DATE :
+ case MYSQLI_TYPE_YEAR :
+ return 'D';
- return 'D';
+ case 'TIME':
+ case 'DATETIME':
+ case 'TIMESTAMP':
- 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 MYSQLI_TYPE_DATETIME :
- case MYSQLI_TYPE_NEWDATE :
- case MYSQLI_TYPE_TIME :
- case MYSQLI_TYPE_TIMESTAMP :
+ case 'INT':
+ case 'INTEGER':
+ case 'BIGINT':
+ case 'TINYINT':
+ case 'MEDIUMINT':
+ case 'SMALLINT':
- return 'T';
+ 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';
- 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';
+ // 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
-
+ }
}
+
+} // if defined _ADODB_MYSQLI_LAYER
diff --git a/lib/adodb/drivers/adodb-mysqlpo.inc.php b/lib/adodb/drivers/adodb-mysqlpo.inc.php
index 14e0c5ffc8e..a1f797e07c9 100644
--- a/lib/adodb/drivers/adodb-mysqlpo.inc.php
+++ b/lib/adodb/drivers/adodb-mysqlpo.inc.php
@@ -1,7 +1,7 @@
-
- This driver extends the deprecated mysql driver, and was originally designed to be a
+
+ 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.
@@ -32,11 +32,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 +111,6 @@ class ADORecordSet_mysqlt extends ADORecordSet_mysql{
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/lib/adodb/drivers/adodb-mysqlt.inc.php b/lib/adodb/drivers/adodb-mysqlt.inc.php
index 925e1aa5fe2..fd1fa3c57f8 100644
--- a/lib/adodb/drivers/adodb-mysqlt.inc.php
+++ b/lib/adodb/drivers/adodb-mysqlt.inc.php
@@ -1,7 +1,7 @@
rsPrefix .= 'ext_';
- }
-
/* set transaction mode
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
diff --git a/lib/adodb/drivers/adodb-netezza.inc.php b/lib/adodb/drivers/adodb-netezza.inc.php
index f63cc133506..b887c7cb742 100644
--- a/lib/adodb/drivers/adodb-netezza.inc.php
+++ b/lib/adodb/drivers/adodb-netezza.inc.php
@@ -1,6 +1,6 @@
@@ -89,7 +89,6 @@ END;
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 +102,20 @@ END;
// 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)
@@ -307,6 +313,43 @@ END;
{
return " NVL($field, $ifNull) "; // if Oracle
}
+
+ function _insertid($tabname,$column='')
+ {
+
+ if (!$this->seqField)
+ return false;
+
+
+ if ($this->schema)
+ {
+ $t = strpos($tabname,'.');
+ if ($t !== false)
+ $tab = substr($tabname,$t+1);
+ else
+ $tab = $tabname;
+
+ if ($this->useCompactAutoIncrements)
+ $tab = sprintf('%u',crc32(strtolower($tab)));
+
+ $seqname = $this->schema.'.'.$this->seqPrefix.$tab;
+ }
+ else
+ {
+ if ($this->useCompactAutoIncrements)
+ $tabname = sprintf('%u',crc32(strtolower($tabname)));
+
+ $seqname = $this->seqPrefix.$tabname;
+ }
+
+ 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)
@@ -947,7 +990,7 @@ END;
$element0 = reset($inputarr);
$array2d = $this->bulkBind && is_array($element0) && !is_object(reset($element0));
- # see http://phplens.com/lens/lensforum/msgs.php?id=18786
+ # see PHPLens Issue No: 18786
if ($array2d || !$this->_bindInputArray) {
# is_object check because oci8 descriptors can be passed in
@@ -1497,37 +1540,27 @@ SELECT /*+ RULE */ distinct b.column_name
}
/**
- * 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 if $s is GET/POST var, set to get_magic_quotes_gpc().
- * This undoes the stupidity of magic quotes for GPC.
+ * @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 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) . "'";
}
}
@@ -1591,7 +1624,7 @@ class ADORecordset_oci8 extends ADORecordSet {
/*
// based on idea by Gaetano Giunta to detect unusual oracle errors
- // see http://phplens.com/lens/lensforum/msgs.php?id=6771
+ // see PHPLens Issue No: 6771
$err = oci_error($this->_queryID);
if ($err && $this->connection->debug) {
ADOConnection::outp($err);
@@ -1751,7 +1784,8 @@ class ADORecordset_oci8 extends ADORecordSet {
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 +1842,12 @@ class ADORecordset_oci8 extends ADORecordSet {
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/lib/adodb/drivers/adodb-oci805.inc.php b/lib/adodb/drivers/adodb-oci805.inc.php
index bda486ca8c5..38f9c79aa0a 100644
--- a/lib/adodb/drivers/adodb-oci805.inc.php
+++ b/lib/adodb/drivers/adodb-oci805.inc.php
@@ -1,6 +1,6 @@
_hasOCIFetchStatement = ADODB_PHPVER >= 0x4200;
- # oci8po does not support adodb extension: adodb_movenext()
- }
-
function Param($name,$type='C')
{
return '?';
@@ -86,6 +80,7 @@ class ADODB_oci8po extends ADODB_oci8 {
}
return ADODB_oci8::_query($sql,$inputarr);
}
+
/**
* Replaces compatibility bind markers with oracle ones and returns a
* valid sql statement
@@ -94,13 +89,13 @@ class ADODB_oci8po extends ADODB_oci8 {
* 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 +115,7 @@ class ADODB_oci8po extends ADODB_oci8 {
/*
* find the next character of the string
*/
- $c = $sql[$i];
+ $c = $sql[$i];
if ($c == "'" && !$inString && $escaped==0)
/*
@@ -173,11 +168,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/lib/adodb/drivers/adodb-oci8quercus.inc.php b/lib/adodb/drivers/adodb-oci8quercus.inc.php
index 183ae1772b4..d2b5117b48b 100644
--- a/lib/adodb/drivers/adodb-oci8quercus.inc.php
+++ b/lib/adodb/drivers/adodb-oci8quercus.inc.php
@@ -1,13 +1,13 @@
_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 +104,7 @@ class ADODB_odbc extends ADOConnection {
function ServerInfo()
{
- if (!empty($this->host) && ADODB_PHPVER >= 0x4300) {
+ if (!empty($this->host)) {
$dsn = strtoupper($this->host);
$first = true;
$found = false;
@@ -180,30 +191,25 @@ class ADODB_odbc extends ADOConnection {
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 +264,6 @@ class ADODB_odbc extends ADOConnection {
$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 +292,6 @@ class ADODB_odbc extends ADOConnection {
$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 +394,11 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/od
$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 +437,6 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/od
$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 +461,16 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/od
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 +527,8 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/od
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 +536,8 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/od
$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 +554,11 @@ See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/od
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 +602,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 +659,6 @@ class ADORecordSet_odbc extends ADORecordSet {
// 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 +709,7 @@ class ADORecordSet_odbc extends ADORecordSet {
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/lib/adodb/drivers/adodb-odbc_db2.inc.php b/lib/adodb/drivers/adodb-odbc_db2.inc.php
index aeae3fb1504..c32033a41d7 100644
--- a/lib/adodb/drivers/adodb-odbc_db2.inc.php
+++ b/lib/adodb/drivers/adodb-odbc_db2.inc.php
@@ -1,6 +1,6 @@
_has_stupid_odbc_fetch_api_change = $this->_has_stupid_odbc_fetch_api_change;
$arr = $rs->GetArray();
//print_r($arr);
@@ -306,11 +305,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 +355,7 @@ class ADORecordSet_odbc_db2 extends ADORecordSet_odbc {
case 'I':
return 'I';
- default: return 'N';
+ default: return ADODB_DEFAULT_METATYPE;
}
}
}
diff --git a/lib/adodb/drivers/adodb-odbc_mssql.inc.php b/lib/adodb/drivers/adodb-odbc_mssql.inc.php
index 520d1c01f97..19fdd604bef 100644
--- a/lib/adodb/drivers/adodb-odbc_mssql.inc.php
+++ b/lib/adodb/drivers/adodb-odbc_mssql.inc.php
@@ -1,6 +1,6 @@
curmode = SQL_CUR_USE_ODBC;
- }
-
// crashes php...
function ServerInfo()
{
@@ -351,6 +345,85 @@ order by constraint_name, referenced_table_name, keyno";
}
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 '';
+ }
}
@@ -358,8 +431,4 @@ class ADORecordSet_odbc_mssql extends ADORecordSet_odbc {
var $databaseType = 'odbc_mssql';
- function __construct($id,$mode=false)
- {
- return parent::__construct($id,$mode);
- }
}
diff --git a/lib/adodb/drivers/adodb-odbc_mssql2012.inc.php b/lib/adodb/drivers/adodb-odbc_mssql2012.inc.php
new file mode 100644
index 00000000000..17d0bb025df
--- /dev/null
+++ b/lib/adodb/drivers/adodb-odbc_mssql2012.inc.php
@@ -0,0 +1,28 @@
+
@@ -35,10 +35,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),
@@ -792,48 +788,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/lib/adodb/drivers/adodb-odbtp_unicode.inc.php b/lib/adodb/drivers/adodb-odbtp_unicode.inc.php
index 9df039796e8..4ad997bb71a 100644
--- a/lib/adodb/drivers/adodb-odbtp_unicode.inc.php
+++ b/lib/adodb/drivers/adodb-odbtp_unicode.inc.php
@@ -1,13 +1,13 @@
@@ -26,7 +26,7 @@ if (!defined('ADODB_DIR')) die();
*/
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/lib/adodb/drivers/adodb-oracle.inc.php b/lib/adodb/drivers/adodb-oracle.inc.php
index 9f0919bbf13..d8d68b08d75 100644
--- a/lib/adodb/drivers/adodb-oracle.inc.php
+++ b/lib/adodb/drivers/adodb-oracle.inc.php
@@ -1,13 +1,13 @@
pdoOptions = [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION];
+ */
+ public $pdoParameters = array();
function _UpdatePDO()
{
@@ -102,6 +104,7 @@ class ADODB_pdo extends ADOConnection {
$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;
@@ -144,12 +147,22 @@ class ADODB_pdo extends ADOConnection {
case 'oci':
case 'pgsql':
case 'sqlite':
+ case 'firebird':
default:
$argDSN .= ';dbname='.$argDatabasename;
}
}
+ /*
+ * Configure for persistent connection if required,
+ * by adding the the pdo parameter into any provided
+ * ones
+ */
+ if ($persist) {
+ $this->pdoParameters[\PDO::ATTR_PERSISTENT] = true;
+ }
+
try {
- $this->_connectionID = new PDO($argDSN, $argUsername, $argPassword);
+ $this->_connectionID = new \PDO($argDSN, $argUsername, $argPassword, $this->pdoParameters);
} catch (Exception $e) {
$this->_connectionID = false;
$this->_errorno = -1;
@@ -175,6 +188,16 @@ class ADODB_pdo extends ADOConnection {
//$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) {
@@ -184,6 +207,8 @@ class ADODB_pdo extends ADOConnection {
case 'pgsql':
case 'sqlite':
case 'sqlsrv':
+ case 'firebird':
+ case 'dblib':
include_once(ADODB_DIR.'/drivers/adodb-pdo_'.$this->dsnType.'.inc.php');
break;
}
@@ -210,10 +235,7 @@ class ADODB_pdo extends ADOConnection {
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
@@ -251,6 +273,64 @@ class ADODB_pdo extends ADOConnection {
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];
@@ -335,16 +415,16 @@ class ADODB_pdo extends ADOConnection {
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)
{
@@ -352,13 +432,13 @@ class ADODB_pdo extends ADOConnection {
return $this->_driver->SetTransactionMode($transaction_mode);
}
- return parent::SetTransactionMode($seqname);
+ 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) {
@@ -374,10 +454,11 @@ class ADODB_pdo extends ADOConnection {
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) {
@@ -387,7 +468,7 @@ class ADODB_pdo extends ADOConnection {
return true;
}
if (!$ok) {
- return $this->RollbackTrans();
+ return $this->rollbackTrans();
}
if ($this->transCnt) {
$this->transCnt -= 1;
@@ -441,10 +522,10 @@ class ADODB_pdo extends ADOConnection {
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);
@@ -478,10 +559,11 @@ class ADODB_pdo extends ADOConnection {
} else {
$stmt = $this->_connectionID->prepare($sql);
}
- #adodb_backtrace();
- #var_dump($this->_bindInputArray);
+
if ($stmt) {
- $this->_driver->debug = $this->debug;
+ if ($this->_driver instanceof ADODB_pdo) {
+ $this->_driver->debug = $this->debug;
+ }
if ($inputarr) {
$ok = $stmt->execute($inputarr);
}
@@ -523,6 +605,9 @@ class ADODB_pdo extends ADOConnection {
function _affectedrows()
{
+ if(method_exists($this->_driver, '_affectedrows'))
+ return $this->_driver->_affectedrows();
+
return ($this->_stmt) ? $this->_stmt->rowCount() : 0;
}
@@ -533,25 +618,23 @@ class ADODB_pdo extends ADOConnection {
/**
* 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) . "'";
}
}
@@ -813,3 +896,5 @@ class ADORecordSet_pdo extends ADORecordSet {
}
}
+
+class ADORecordSet_array_pdo extends ADORecordSet_array {}
diff --git a/lib/adodb/drivers/adodb-pdo_dblib.inc.php b/lib/adodb/drivers/adodb-pdo_dblib.inc.php
new file mode 100644
index 00000000000..1a688dca1a8
--- /dev/null
+++ b/lib/adodb/drivers/adodb-pdo_dblib.inc.php
@@ -0,0 +1,182 @@
+ '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/lib/adodb/drivers/adodb-pdo_firebird.inc.php b/lib/adodb/drivers/adodb-pdo_firebird.inc.php
new file mode 100644
index 00000000000..cd7b4c73d45
--- /dev/null
+++ b/lib/adodb/drivers/adodb-pdo_firebird.inc.php
@@ -0,0 +1,447 @@
+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/lib/adodb/drivers/adodb-pdo_mssql.inc.php b/lib/adodb/drivers/adodb-pdo_mssql.inc.php
index 162cd592ee2..e78e4d8b403 100644
--- a/lib/adodb/drivers/adodb-pdo_mssql.inc.php
+++ b/lib/adodb/drivers/adodb-pdo_mssql.inc.php
@@ -2,7 +2,7 @@
/*
-@version v5.20.16 12-Jan-2020
+@version v5.21.0 2021-02-27
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
diff --git a/lib/adodb/drivers/adodb-pdo_mysql.inc.php b/lib/adodb/drivers/adodb-pdo_mysql.inc.php
index eea92aeda46..edc8634d332 100644
--- a/lib/adodb/drivers/adodb-pdo_mysql.inc.php
+++ b/lib/adodb/drivers/adodb-pdo_mysql.inc.php
@@ -1,6 +1,6 @@
=0) ? "$offset," : '';
- // jason judge, see http://phplens.com/lens/lensforum/msgs.php?id=9220
+ // jason judge, see PHPLens Issue No: 9220
if ($nrows < 0) {
$nrows = '18446744073709551615';
}
@@ -310,4 +313,41 @@ class ADODB_pdo_mysql extends ADODB_pdo {
}
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/lib/adodb/drivers/adodb-pdo_oci.inc.php b/lib/adodb/drivers/adodb-pdo_oci.inc.php
index 4584f3f6a09..8bbdf42f579 100644
--- a/lib/adodb/drivers/adodb-pdo_oci.inc.php
+++ b/lib/adodb/drivers/adodb-pdo_oci.inc.php
@@ -2,7 +2,7 @@
/*
-@version v5.20.16 12-Jan-2020
+@version v5.21.0 2021-02-27
@copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
@copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
Released under both BSD license and Lesser GPL library license.
diff --git a/lib/adodb/drivers/adodb-pdo_pgsql.inc.php b/lib/adodb/drivers/adodb-pdo_pgsql.inc.php
index b5cd221a75d..bd653bbf20d 100644
--- a/lib/adodb/drivers/adodb-pdo_pgsql.inc.php
+++ b/lib/adodb/drivers/adodb-pdo_pgsql.inc.php
@@ -1,7 +1,7 @@
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/lib/adodb/drivers/adodb-pdo_sqlite.inc.php b/lib/adodb/drivers/adodb-pdo_sqlite.inc.php
index 0694fb35e4d..7cd6ccd4aae 100644
--- a/lib/adodb/drivers/adodb-pdo_sqlite.inc.php
+++ b/lib/adodb/drivers/adodb-pdo_sqlite.inc.php
@@ -1,7 +1,7 @@
_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/lib/adodb/drivers/adodb-postgres.inc.php b/lib/adodb/drivers/adodb-postgres.inc.php
index 61e3987a11a..003ae9ebcc7 100644
--- a/lib/adodb/drivers/adodb-postgres.inc.php
+++ b/lib/adodb/drivers/adodb-postgres.inc.php
@@ -1,6 +1,6 @@
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 )
@@ -165,7 +187,7 @@ class ADODB_postgres64 extends ADOConnection{
function _insertid($table,$column)
{
if (!is_resource($this->_resultid) || get_resource_type($this->_resultid) !== 'pgsql result') return false;
- $oid = pg_getlastoid($this->_resultid);
+ $oid = pg_last_oid($this->_resultid);
// to really return the id, we need the table and column-name, else we can only return the oid != id
return empty($table) || empty($column) ? $oid : $this->GetOne("SELECT $column FROM $table WHERE oid=".(int)$oid);
}
@@ -243,31 +265,32 @@ class ADODB_postgres64 extends ADOConnection{
}
- // 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 +416,7 @@ class ADODB_postgres64 extends ADOConnection{
}
/*
- Hueristic - not guaranteed to work.
+ Heuristic - not guaranteed to work.
*/
function GuessOID($oid)
{
@@ -425,29 +448,25 @@ class ADODB_postgres64 extends ADOConnection{
}
if (!$maxsize) $maxsize = $this->maxblobsize;
$realblob = @pg_lo_read($fd,$maxsize);
- @pg_loclose($fd);
+ @pg_lo_close($fd);
if ($hastrans) pg_query($this->_connectionID,'commit');
return $realblob;
}
- /*
- See http://www.postgresql.org/idocs/index.php?datatype-binary.html
-
- NOTE: SQL string literals (input strings) must be preceded with two backslashes
- due to the fact that they must pass through two parsers in the PostgreSQL
- backend.
- */
+ /**
+ * 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
@@ -492,7 +511,7 @@ class ADODB_postgres64 extends ADOConnection{
// for schema support, pass in the $table param "$schema.$tabname".
// converts field names to lowercase, $upper is ignored
- // see http://phplens.com/lens/lensforum/msgs.php?id=14018 for more info
+ // see PHPLens Issue No: 14018 for more info
function MetaColumns($table,$normalize=true)
{
global $ADODB_FETCH_MODE;
@@ -606,15 +625,18 @@ class ADODB_postgres64 extends ADOConnection{
}
- 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 +751,9 @@ class ADODB_postgres64 extends ADOConnection{
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,8 +761,11 @@ class ADODB_postgres64 extends ADOConnection{
# 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', '>=')) {
- $this->Execute('set bytea_output=escape');
+ if (!empty($this->connection->noBlobs) && version_compare($info['version'], '9.0', '>=')) {
+ $version = pg_version($this->connectionID);
+ if (version_compare($info['client'], '9.2', '<')) {
+ $this->Execute('set bytea_output=escape');
+ }
}
return true;
@@ -848,20 +873,23 @@ class ADODB_postgres64 extends ADOConnection{
/* Returns: the last error message from previous database operation */
function ErrorMsg()
{
- if ($this->_errorMsg !== false) return $this->_errorMsg;
- if (ADODB_PHPVER >= 0x4300) {
- if (!empty($this->_resultid)) {
- $this->_errorMsg = @pg_result_error($this->_resultid);
- if ($this->_errorMsg) return $this->_errorMsg;
- }
-
- if (!empty($this->_connectionID)) {
- $this->_errorMsg = @pg_last_error($this->_connectionID);
- } else $this->_errorMsg = $this->_errconnect();
- } else {
- if (empty($this->_connectionID)) $this->_errconnect();
- else $this->_errorMsg = @pg_errormessage($this->_connectionID);
+ 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();
+ }
+
return $this->_errorMsg;
}
@@ -986,7 +1014,7 @@ class ADORecordSet_postgres64 extends ADORecordSet{
$o= new ADOFieldObject();
$o->name = @pg_field_name($this->_queryID,$off);
$o->type = @pg_field_type($this->_queryID,$off);
- $o->max_length = @pg_fieldsize($this->_queryID,$off);
+ $o->max_length = @pg_field_size($this->_queryID,$off);
return $o;
}
@@ -998,7 +1026,7 @@ class ADORecordSet_postgres64 extends ADORecordSet{
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);
}
@@ -1049,7 +1077,12 @@ class ADORecordSet_postgres64 extends ADORecordSet{
function _close()
{
- return @pg_free_result($this->_queryID);
+ if (!is_resource($this->_queryID)
+ || get_resource_type($this->_queryID) != 'pgsql result'
+ ) {
+ return true;
+ }
+ return pg_free_result($this->_queryID);
}
function MetaType($t,$len=-1,$fieldobj=false)
@@ -1068,6 +1101,7 @@ class ADORecordSet_postgres64 extends ADORecordSet{
case 'NAME':
case 'BPCHAR':
case '_VARCHAR':
+ case 'CIDR':
case 'INET':
case 'MACADDR':
if ($len <= $this->blobSize) return 'C';
@@ -1111,7 +1145,7 @@ class ADORecordSet_postgres64 extends ADORecordSet{
return 'R';
default:
- return 'N';
+ return ADODB_DEFAULT_METATYPE;
}
}
diff --git a/lib/adodb/drivers/adodb-postgres7.inc.php b/lib/adodb/drivers/adodb-postgres7.inc.php
index e5aaaa74bc4..6de6c1c6ceb 100644
--- a/lib/adodb/drivers/adodb-postgres7.inc.php
+++ b/lib/adodb/drivers/adodb-postgres7.inc.php
@@ -1,6 +1,6 @@
rsPrefix .= 'assoc_';
}
- $this->_bindInputArray = PHP_VERSION >= 5.1;
+ $this->_bindInputArray = true;
}
@@ -309,12 +309,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 +335,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/lib/adodb/drivers/adodb-postgres8.inc.php b/lib/adodb/drivers/adodb-postgres8.inc.php
index 4e3ce8de8c5..6f5859ad76c 100644
--- a/lib/adodb/drivers/adodb-postgres8.inc.php
+++ b/lib/adodb/drivers/adodb-postgres8.inc.php
@@ -1,6 +1,6 @@
curmode = SQL_CUR_USE_ODBC;
- parent::__construct();
- }
-
function ServerInfo()
{
$info = ADODB_odbc::ServerInfo();
@@ -55,7 +49,7 @@ class ADODB_SAPDB extends ADODB_odbc {
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 +59,43 @@ class ADODB_SAPDB extends ADODB_odbc {
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 +128,10 @@ class ADODB_SAPDB extends ADODB_odbc {
}
$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;
}
@@ -158,13 +152,13 @@ class ADODB_SAPDB extends ADODB_odbc {
/*
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 +166,10 @@ class ADODB_SAPDB extends ADODB_odbc {
};
-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/lib/adodb/drivers/adodb-sqlanywhere.inc.php b/lib/adodb/drivers/adodb-sqlanywhere.inc.php
index 77b5a17ef2c..ca54175646b 100644
--- a/lib/adodb/drivers/adodb-sqlanywhere.inc.php
+++ b/lib/adodb/drivers/adodb-sqlanywhere.inc.php
@@ -1,6 +1,6 @@
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,6 +193,60 @@ class ADODB_sqlite3 extends ADOConnection {
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;
@@ -160,11 +278,22 @@ class ADODB_sqlite3 extends ADOConnection {
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);
@@ -288,8 +417,8 @@ class ADODB_sqlite3 extends ADOConnection {
{
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 +428,36 @@ class ADODB_sqlite3 extends ADOConnection {
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 +467,10 @@ class ADODB_sqlite3 extends ADOConnection {
}
$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 +478,122 @@ class ADODB_sqlite3 extends ADOConnection {
);
}
/**
- * 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/lib/adodb/drivers/adodb-sqlitepo.inc.php b/lib/adodb/drivers/adodb-sqlitepo.inc.php
index 8b3ec9e47ee..4b56cbe0616 100644
--- a/lib/adodb/drivers/adodb-sqlitepo.inc.php
+++ b/lib/adodb/drivers/adodb-sqlitepo.inc.php
@@ -1,6 +1,6 @@
= 0x4300)
+ if ($ADODB_COUNTRECS == false)
return sybase_unbuffered_query($sql,$this->_connectionID);
else
return sybase_query($sql,$this->_connectionID);
@@ -320,7 +316,7 @@ class ADORecordset_sybase extends ADORecordSet {
}
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 +389,8 @@ class ADORecordset_sybase extends ADORecordSet {
}
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/lib/adodb/drivers/adodb-sybase_ase.inc.php b/lib/adodb/drivers/adodb-sybase_ase.inc.php
index 4e09f60a068..8490e8fb468 100644
--- a/lib/adodb/drivers/adodb-sybase_ase.inc.php
+++ b/lib/adodb/drivers/adodb-sybase_ase.inc.php
@@ -1,6 +1,6 @@
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.
+*/
+
+// security - hide paths
+if (!defined('ADODB_DIR')) die();
+
+if (! defined("_ADODB_TEXT_LAYER")) {
+ define("_ADODB_TEXT_LAYER", 1 );
+
+// for sorting in _query()
+function adodb_cmp($a, $b) {
+ if ($a[0] == $b[0]) return 0;
+ return ($a[0] < $b[0]) ? -1 : 1;
+}
+// for sorting in _query()
+function adodb_cmpr($a, $b) {
+ if ($a[0] == $b[0]) return 0;
+ return ($a[0] > $b[0]) ? -1 : 1;
+}
+class ADODB_text extends ADOConnection {
+ var $databaseType = 'text';
+
+ var $_origarray; // original data
+ var $_types;
+ var $_proberows = 8;
+ var $_colnames;
+ var $_skiprow1=false;
+ var $readOnly = true;
+ var $hasTransactions = false;
+
+ var $_rezarray;
+ var $_reznames;
+ var $_reztypes;
+
+ function RSRecordCount()
+ {
+ if (!empty($this->_rezarray)) return sizeof($this->_rezarray);
+
+ return sizeof($this->_origarray);
+ }
+
+ function _insertid()
+ {
+ return false;
+ }
+
+ function _affectedrows()
+ {
+ return false;
+ }
+
+ // returns true or false
+ function PConnect(&$array, $types = false, $colnames = false)
+ {
+ return $this->Connect($array, $types, $colnames);
+ }
+ // returns true or false
+ function Connect(&$array, $types = false, $colnames = false)
+ {
+ if (is_string($array) and $array === 'iluvphplens') return 'me2';
+
+ if (!$array) {
+ $this->_origarray = false;
+ return true;
+ }
+ $row = $array[0];
+ $cols = sizeof($row);
+
+
+ if ($colnames) $this->_colnames = $colnames;
+ else {
+ $this->_colnames = $array[0];
+ $this->_skiprow1 = true;
+ }
+ if (!$types) {
+ // probe and guess the type
+ $types = array();
+ $firstrow = true;
+ if ($this->_proberows > sizeof($array)) $max = sizeof($array);
+ else $max = $this->_proberows;
+ for ($j=($this->_skiprow1)?1:0;$j < $max; $j++) {
+ $row = $array[$j];
+ if (!$row) break;
+ $i = -1;
+ foreach($row as $v) {
+ $i += 1;
+ //print " ($i ".$types[$i]. "$v) ";
+ $v = trim($v);
+ if (!preg_match('/^[+-]{0,1}[0-9\.]+$/',$v)) {
+ $types[$i] = 'C'; // once C, always C
+ continue;
+ }
+ if (isset($types[$i]) && $types[$i]=='C') continue;
+ if ($firstrow) {
+ // If empty string, we presume is character
+ // test for integer for 1st row only
+ // after that it is up to testing other rows to prove
+ // that it is not an integer
+ if (strlen($v) == 0) $types[0] = 'C';
+ if (strpos($v,'.') !== false) $types[0] = 'N';
+ else $types[$i] = 'I';
+ continue;
+ }
+
+ if (strpos($v,'.') !== false) $types[$i] = 'N';
+
+ }
+ $firstrow = false;
+ }
+ }
+ //print_r($types);
+ $this->_origarray = $array;
+ $this->_types = $types;
+ return true;
+ }
+
+
+
+ // returns queryID or false
+ // We presume that the select statement is on the same table (what else?),
+ // with the only difference being the order by.
+ //You can filter by using $eval and each clause is stored in $arr .eg. $arr[1] == 'name'
+ // also supports SELECT [DISTINCT] COL FROM ... -- only 1 col supported
+ function _query($sql,$input_arr,$eval=false)
+ {
+ if ($this->_origarray === false) return false;
+
+ $eval = $this->evalAll;
+ $usql = strtoupper(trim($sql));
+ $usql = preg_replace("/[\t\n\r]/",' ',$usql);
+ $usql = preg_replace('/ *BY/i',' BY',strtoupper($usql));
+
+ $eregword ='([A-Z_0-9]*)';
+ //print " $sql $eval ";
+ if ($eval) {
+ $i = 0;
+ foreach($this->_colnames as $n) {
+ $n = strtoupper(trim($n));
+ $eval = str_replace("\$$n","\$arr[$i]",$eval);
+
+ $i += 1;
+ }
+
+ $i = 0;
+ $eval = "\$rez=($eval);";
+ //print "Eval string = $eval ";
+ $where_arr = array();
+
+ reset($this->_origarray);
+ foreach ($this->_origarray as $arr) {
+
+ if ($i == 0 && $this->_skiprow1)
+ $where_arr[] = $arr;
+ else {
+ eval($eval);
+ //print " $i: result=$rez arr[0]={$arr[0]} arr[1]={$arr[1]} \n ";
+ if ($rez) $where_arr[] = $arr;
+ }
+ $i += 1;
+ }
+ $this->_rezarray = $where_arr;
+ }else
+ $where_arr = $this->_origarray;
+
+ // THIS PROJECTION CODE ONLY WORKS FOR 1 COLUMN,
+ // OTHERWISE IT RETURNS ALL COLUMNS
+ if (substr($usql,0,7) == 'SELECT ') {
+ $at = strpos($usql,' FROM ');
+ $sel = trim(substr($usql,7,$at-7));
+
+ $distinct = false;
+ if (substr($sel,0,8) == 'DISTINCT') {
+ $distinct = true;
+ $sel = trim(substr($sel,8,$at));
+ }
+
+ // $sel holds the selection clause, comma delimited
+ // currently we only project if one column is involved
+ // this is to support popups in PHPLens
+ if (strpos(',',$sel)===false) {
+ $colarr = array();
+
+ preg_match("/$eregword/",$sel,$colarr);
+ $col = $colarr[1];
+ $i = 0;
+ $n = '';
+ reset($this->_colnames);
+ foreach ($this->_colnames as $n) {
+
+ if ($col == strtoupper(trim($n))) break;
+ $i += 1;
+ }
+
+ if ($n && $col) {
+ $distarr = array();
+ $projarray = array();
+ $projtypes = array($this->_types[$i]);
+ $projnames = array($n);
+
+ foreach ($where_arr as $a) {
+ if ($i == 0 && $this->_skiprow1) {
+ $projarray[] = array($n);
+ continue;
+ }
+
+ if ($distinct) {
+ $v = strtoupper($a[$i]);
+ if (! $distarr[$v]) {
+ $projarray[] = array($a[$i]);
+ $distarr[$v] = 1;
+ }
+ } else
+ $projarray[] = array($a[$i]);
+
+ } //foreach
+ //print_r($projarray);
+ }
+ } // check 1 column in projection
+ } // is SELECT
+
+ if (empty($projarray)) {
+ $projtypes = $this->_types;
+ $projarray = $where_arr;
+ $projnames = $this->_colnames;
+ }
+ $this->_rezarray = $projarray;
+ $this->_reztypes = $projtypes;
+ $this->_reznames = $projnames;
+
+
+ $pos = strpos($usql,' ORDER BY ');
+ if ($pos === false) return $this;
+ $orderby = trim(substr($usql,$pos+10));
+
+ preg_match("/$eregword/",$orderby,$arr);
+ if (sizeof($arr) < 2) return $this; // actually invalid sql
+ $col = $arr[1];
+ $at = (integer) $col;
+ if ($at == 0) {
+ $i = 0;
+ reset($projnames);
+ foreach ($projnames as $n) {
+ if (strtoupper(trim($n)) == $col) {
+ $at = $i+1;
+ break;
+ }
+ $i += 1;
+ }
+ }
+
+ if ($at <= 0 || $at > sizeof($projarray[0])) return $this; // cannot find sort column
+ $at -= 1;
+
+ // generate sort array consisting of (sortval1, row index1) (sortval2, row index2)...
+ $sorta = array();
+ $t = $projtypes[$at];
+ $num = ($t == 'I' || $t == 'N');
+ for ($i=($this->_skiprow1)?1:0, $max = sizeof($projarray); $i < $max; $i++) {
+ $row = $projarray[$i];
+ $val = ($num)?(float)$row[$at]:$row[$at];
+ $sorta[]=array($val,$i);
+ }
+
+ // check for desc sort
+ $orderby = substr($orderby,strlen($col)+1);
+ $arr = array();
+ preg_match('/([A-Z_0-9]*)/i',$orderby,$arr);
+
+ if (trim($arr[1]) == 'DESC') $sortf = 'adodb_cmpr';
+ else $sortf = 'adodb_cmp';
+
+ // hasta la sorta babe
+ usort($sorta, $sortf);
+
+ // rearrange original array
+ $arr2 = array();
+ if ($this->_skiprow1) $arr2[] = $projarray[0];
+ foreach($sorta as $v) {
+ $arr2[] = $projarray[$v[1]];
+ }
+
+ $this->_rezarray = $arr2;
+ return $this;
+ }
+
+ /* Returns: the last error message from previous database operation */
+ function ErrorMsg()
+ {
+ return '';
+ }
+
+ /* Returns: the last error number from previous database operation */
+ function ErrorNo()
+ {
+ return 0;
+ }
+
+ // returns true or false
+ function _close()
+ {
+ }
+
+
+}
+
+/*--------------------------------------------------------------------------------------
+ Class Name: Recordset
+--------------------------------------------------------------------------------------*/
+
+
+class ADORecordSet_text extends ADORecordSet_array
+{
+
+ var $databaseType = "text";
+
+ function __construct( $conn,$mode=false)
+ {
+ parent::__construct();
+ $this->InitArray($conn->_rezarray,$conn->_reztypes,$conn->_reznames);
+ $conn->_rezarray = false;
+ }
+
+} // class ADORecordSet_text
+
+
+} // defined
diff --git a/lib/adodb/drivers/adodb-vfp.inc.php b/lib/adodb/drivers/adodb-vfp.inc.php
index fe12f7fb78d..7369510e073 100644
--- a/lib/adodb/drivers/adodb-vfp.inc.php
+++ b/lib/adodb/drivers/adodb-vfp.inc.php
@@ -1,6 +1,6 @@
tablesSQL) return false;
@@ -302,11 +308,9 @@ class perf_mysql extends adodb_perf{
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( "%s: '%s' using of undefined mode '%s' ", __CLASS__, __FUNCTION__, $mode));
return false;
- }
}
$sql = sprintf( $sql, $table);
diff --git a/lib/adodb/perf/perf-oci8.inc.php b/lib/adodb/perf/perf-oci8.inc.php
index 4c6a39f2a60..d311e70d683 100644
--- a/lib/adodb/perf/perf-oci8.inc.php
+++ b/lib/adodb/perf/perf-oci8.inc.php
@@ -1,6 +1,6 @@
optimizeTableLow; break;
case ADODB_OPT_HIGH: $sql = $this->optimizeTableHigh; break;
default :
- {
ADOConnection::outp(sprintf("%s: '%s' using of undefined mode '%s' ", __CLASS__, 'optimizeTable', $mode));
return false;
- }
}
$sql = sprintf($sql, $table);
diff --git a/lib/adodb/pivottable.inc.php b/lib/adodb/pivottable.inc.php
index 261b30f379d..ada50687461 100644
--- a/lib/adodb/pivottable.inc.php
+++ b/lib/adodb/pivottable.inc.php
@@ -1,6 +1,6 @@
-
-
+
-
+
-
+
-
+
@@ -24,20 +29,25 @@
-
+
-
+
-
-
+
+
-
-
+
+
-]>
\ No newline at end of file
diff --git a/lib/classes/event/base.php b/lib/classes/event/base.php
index 0d7831fe731..a0cf9f6b7bf 100644
--- a/lib/classes/event/base.php
+++ b/lib/classes/event/base.php
@@ -134,7 +134,7 @@ abstract class base implements \IteratorAggregate {
/**
* Private constructor, use create() or restore() methods instead.
*/
- private final function __construct() {
+ final private function __construct() {
$this->data = array_fill_keys(self::$fields, null);
// Define some basic details.
diff --git a/lib/thirdpartylibs.xml b/lib/thirdpartylibs.xml
index d08f6208e6b..185be1cb2d4 100644
--- a/lib/thirdpartylibs.xml
+++ b/lib/thirdpartylibs.xml
@@ -3,9 +3,9 @@
adodb
AdoDB
- BSD/GPL
- 5.20.16
- 2.1+
+ BSD/LGPL
+ 5.21.0
+ 3-Clause/2.1+
behat/axe
|
|