* MySQL: got mysqli extension working and make it default for EGroupware, as mysql is now officially deprecated, existing installs need to be switched manually in header.inc.php or Setup >> Manage header

prefering mysqli for new installs
This commit is contained in:
Ralf Becker 2013-05-27 09:37:13 +00:00
parent d46bd621ae
commit e72d937e19
5 changed files with 232 additions and 219 deletions

View File

@ -24,7 +24,7 @@ $config = array(
'domain' => 'default', 'domain' => 'default',
'config_user' => 'admin', 'config_user' => 'admin',
'config_passwd' => randomstring(), 'config_passwd' => randomstring(),
'db_type' => 'mysql', 'db_type' => 'mysqli',
'db_host' => 'localhost', 'db_host' => 'localhost',
'db_port' => 3306, 'db_port' => 3306,
'db_name' => 'egroupware', 'db_name' => 'egroupware',

View File

@ -1,24 +1,24 @@
<?php <?php
/* /*
V4.65 22 July 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved. V4.65 22 July 2005 (c) 2000-2005 John Lim (jlim@natsoft.com.my). All rights reserved.
Released under both BSD license and Lesser GPL library license. Released under both BSD license and Lesser GPL library license.
Whenever there is any discrepancy between the two licenses, Whenever there is any discrepancy between the two licenses,
the BSD license will take precedence. the BSD license will take precedence.
Set tabs to 8. Set tabs to 8.
MySQL code that does not support transactions. Use mysqlt if you need transactions. MySQL code that does not support transactions. Use mysqlt if you need transactions.
Requires mysql client. Works on Windows and Unix. Requires mysql client. Works on Windows and Unix.
21 October 2003: MySQLi extension implementation by Arjen de Rijke (a.de.rijke@xs4all.nl) 21 October 2003: MySQLi extension implementation by Arjen de Rijke (a.de.rijke@xs4all.nl)
Based on adodb 3.40 Based on adodb 3.40
*/ */
// security - hide paths // security - hide paths
//if (!defined('ADODB_DIR')) die(); //if (!defined('ADODB_DIR')) die();
if (! defined("_ADODB_MYSQLI_LAYER")) { if (! defined("_ADODB_MYSQLI_LAYER")) {
define("_ADODB_MYSQLI_LAYER", 1 ); define("_ADODB_MYSQLI_LAYER", 1 );
if (!defined('MYSQLI_READ_DEFAULT_GROUP')) define('MYSQLI_READ_DEFAULT_GROUP',1); if (!defined('MYSQLI_READ_DEFAULT_GROUP')) define('MYSQLI_READ_DEFAULT_GROUP',1);
// disable adodb extension - currently incompatible. // disable adodb extension - currently incompatible.
@ -28,8 +28,8 @@ class ADODB_mysqli extends ADOConnection {
var $databaseType = 'mysqli'; var $databaseType = 'mysqli';
var $dataProvider = 'native'; var $dataProvider = 'native';
var $hasInsertID = true; var $hasInsertID = true;
var $hasAffectedRows = true; var $hasAffectedRows = true;
var $metaTablesSQL = "SHOW TABLES"; var $metaTablesSQL = "SHOW TABLES";
var $metaColumnsSQL = "SHOW COLUMNS FROM %s"; var $metaColumnsSQL = "SHOW COLUMNS FROM %s";
var $fmtTimeStamp = "'Y-m-d H:i:s'"; var $fmtTimeStamp = "'Y-m-d H:i:s'";
var $hasLimit = true; var $hasLimit = true;
@ -48,31 +48,31 @@ class ADODB_mysqli extends ADOConnection {
var $_bindInputArray = false; var $_bindInputArray = false;
var $nameQuote = '`'; /// string to use to quote identifiers and names var $nameQuote = '`'; /// string to use to quote identifiers and names
var $optionFlags = array(array(MYSQLI_READ_DEFAULT_GROUP,0)); var $optionFlags = array(array(MYSQLI_READ_DEFAULT_GROUP,0));
function ADODB_mysqli() function ADODB_mysqli()
{ {
// if(!extension_loaded("mysqli")) // if(!extension_loaded("mysqli"))
;//trigger_error("You must have the mysqli extension installed.", E_USER_ERROR); ;//trigger_error("You must have the mysqli extension installed.", E_USER_ERROR);
} }
// returns true or false // returns true or false
// To add: parameter int $port, // To add: parameter int $port,
// parameter string $socket // parameter string $socket
function _connect($argHostname = NULL, function _connect($argHostname = NULL,
$argUsername = NULL, $argUsername = NULL,
$argPassword = NULL, $argPassword = NULL,
$argDatabasename = NULL, $persist=false) $argDatabasename = NULL, $persist=false)
{ {
if(!extension_loaded("mysqli")) { if(!extension_loaded("mysqli")) {
return null; return null;
} }
$this->_connectionID = @mysqli_init(); $this->_connectionID = @mysqli_init();
if (is_null($this->_connectionID)) { if (is_null($this->_connectionID)) {
// mysqli_init only fails if insufficient memory // mysqli_init only fails if insufficient memory
if ($this->debug) if ($this->debug)
ADOConnection::outp("mysqli_init() failed : " . $this->ErrorMsg()); ADOConnection::outp("mysqli_init() failed : " . $this->ErrorMsg());
return false; return false;
} }
@ -81,7 +81,7 @@ class ADODB_mysqli extends ADOConnection {
read connection options from the standard mysql configuration file read connection options from the standard mysql configuration file
/etc/my.cnf - "Bastien Duclaux" <bduclaux#yahoo.com> /etc/my.cnf - "Bastien Duclaux" <bduclaux#yahoo.com>
*/ */
foreach($this->optionFlags as $arr) { foreach($this->optionFlags as $arr) {
mysqli_options($this->_connectionID,$arr[0],$arr[1]); mysqli_options($this->_connectionID,$arr[0],$arr[1]);
} }
@ -99,12 +99,12 @@ class ADODB_mysqli extends ADOConnection {
if ($argDatabasename) return $this->SelectDB($argDatabasename); if ($argDatabasename) return $this->SelectDB($argDatabasename);
return true; return true;
} else { } else {
if ($this->debug) if ($this->debug)
ADOConnection::outp("Could't connect : " . $this->ErrorMsg()); ADOConnection::outp("Could't connect : " . $this->ErrorMsg());
return false; return false;
} }
} }
// returns true or false // returns true or false
// How to force a persistent connection // How to force a persistent connection
function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename) function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
@ -112,48 +112,61 @@ class ADODB_mysqli extends ADOConnection {
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true); return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true);
} }
// When is this used? Close old connection first? // When is this used? Close old connection first?
// In _connect(), check $this->forceNewConnect? // In _connect(), check $this->forceNewConnect?
function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename) function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
{ {
$this->forceNewConnect = true; $this->forceNewConnect = true;
return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename); return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
} }
function IfNull( $field, $ifNull ) /**
* Check if we are connected
*
* Reimplemented as check in ADOConnection::IsConnected will allways return true, as _connectionID is mysqli object!
*
* @see ADOConnection::IsConnected()
* @return boolean
*/
function IsConnected()
{
return $this->_connectionID && @mysqli_ping($this->_connectionID);
}
function IfNull( $field, $ifNull )
{ {
return " IFNULL($field, $ifNull) "; // if MySQL return " IFNULL($field, $ifNull) "; // if MySQL
} }
function ServerInfo() function ServerInfo()
{ {
$arr['description'] = $this->GetOne("select version()"); $arr['description'] = $this->GetOne("select version()");
$arr['version'] = ADOConnection::_findvers($arr['description']); $arr['version'] = ADOConnection::_findvers($arr['description']);
return $arr; return $arr;
} }
function BeginTrans() function BeginTrans()
{ {
if ($this->transOff) return true; if ($this->transOff) return true;
$this->transCnt += 1; $this->transCnt += 1;
$this->Execute('SET AUTOCOMMIT=0'); $this->Execute('SET AUTOCOMMIT=0');
$this->Execute('BEGIN'); $this->Execute('BEGIN');
return true; return true;
} }
function CommitTrans($ok=true) function CommitTrans($ok=true)
{ {
if ($this->transOff) return true; if ($this->transOff) return true;
if (!$ok) return $this->RollbackTrans(); if (!$ok) return $this->RollbackTrans();
if ($this->transCnt) $this->transCnt -= 1; if ($this->transCnt) $this->transCnt -= 1;
$this->Execute('COMMIT'); $this->Execute('COMMIT');
$this->Execute('SET AUTOCOMMIT=1'); $this->Execute('SET AUTOCOMMIT=1');
return true; return true;
} }
function RollbackTrans() function RollbackTrans()
{ {
if ($this->transOff) return true; if ($this->transOff) return true;
@ -162,14 +175,14 @@ class ADODB_mysqli extends ADOConnection {
$this->Execute('SET AUTOCOMMIT=1'); $this->Execute('SET AUTOCOMMIT=1');
return true; return true;
} }
// if magic quotes disabled, use mysql_real_escape_string() // if magic quotes disabled, use mysql_real_escape_string()
// From readme.htm: // From readme.htm:
// Quotes a string to be sent to the database. The $magic_quotes_enabled // Quotes a string to be sent to the database. The $magic_quotes_enabled
// parameter may look funny, but the idea is if you are quoting a // parameter may look funny, but the idea is if you are quoting a
// string extracted from a POST/GET variable, then // string extracted from a POST/GET variable, then
// pass get_magic_quotes_gpc() as the second parameter. This will // pass get_magic_quotes_gpc() as the second parameter. This will
// ensure that the variable is not quoted twice, once by qstr and once // ensure that the variable is not quoted twice, once by qstr and once
// by the magic_quotes_gpc. // by the magic_quotes_gpc.
// //
//Eg. $s = $db->qstr(_GET['name'],get_magic_quotes_gpc()); //Eg. $s = $db->qstr(_GET['name'],get_magic_quotes_gpc());
@ -177,17 +190,17 @@ class ADODB_mysqli extends ADOConnection {
{ {
if (!$magic_quotes) { if (!$magic_quotes) {
if (PHP_VERSION >= 5 && $this->_connectionID) if (PHP_VERSION >= 5 && $this->_connectionID)
return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'"; return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'";
if ($this->replaceQuote[0] == '\\') if ($this->replaceQuote[0] == '\\')
$s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s); $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
return "'".str_replace("'",$this->replaceQuote,$s)."'"; return "'".str_replace("'",$this->replaceQuote,$s)."'";
} }
// undo magic quotes for " // undo magic quotes for "
$s = str_replace('\\"','"',$s); $s = str_replace('\\"','"',$s);
return "'$s'"; return "'$s'";
} }
function _insertid() function _insertid()
{ {
$result = @mysqli_insert_id($this->_connectionID); $result = @mysqli_insert_id($this->_connectionID);
@ -196,7 +209,7 @@ class ADODB_mysqli extends ADOConnection {
} }
return $result; return $result;
} }
// Only works for INSERT, UPDATE and DELETE query's // Only works for INSERT, UPDATE and DELETE query's
function _affectedrows() function _affectedrows()
{ {
@ -206,29 +219,29 @@ class ADODB_mysqli extends ADOConnection {
} }
return $result; return $result;
} }
// See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
// Reference on Last_Insert_ID on the recommended way to simulate sequences // Reference on Last_Insert_ID on the recommended way to simulate sequences
var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);"; var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
var $_genSeqSQL = "create table %s (id int not null)"; var $_genSeqSQL = "create table %s (id int not null)";
var $_genSeq2SQL = "insert into %s values (%s)"; var $_genSeq2SQL = "insert into %s values (%s)";
var $_dropSeqSQL = "drop table %s"; var $_dropSeqSQL = "drop table %s";
function CreateSequence($seqname='adodbseq',$startID=1) function CreateSequence($seqname='adodbseq',$startID=1)
{ {
if (empty($this->_genSeqSQL)) return false; if (empty($this->_genSeqSQL)) return false;
$u = strtoupper($seqname); $u = strtoupper($seqname);
$ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname)); $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
if (!$ok) return false; 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) function GenID($seqname='adodbseq',$startID=1)
{ {
// post-nuke sets hasGenID to false // post-nuke sets hasGenID to false
if (!$this->hasGenID) return false; if (!$this->hasGenID) return false;
$getnext = sprintf($this->_genIDSQL,$seqname); $getnext = sprintf($this->_genIDSQL,$seqname);
$holdtransOK = $this->_transOK; // save the current status $holdtransOK = $this->_transOK; // save the current status
$rs = @$this->Execute($getnext); $rs = @$this->Execute($getnext);
@ -240,12 +253,12 @@ class ADODB_mysqli extends ADOConnection {
$rs = $this->Execute($getnext); $rs = $this->Execute($getnext);
} }
$this->genID = mysqli_insert_id($this->_connectionID); $this->genID = mysqli_insert_id($this->_connectionID);
if ($rs) $rs->Close(); if ($rs) $rs->Close();
return $this->genID; return $this->genID;
} }
function &MetaDatabases() function &MetaDatabases()
{ {
$query = "SHOW DATABASES"; $query = "SHOW DATABASES";
@ -262,63 +275,63 @@ class ADODB_mysqli extends ADOConnection {
return $ret; return $ret;
} }
function &MetaIndexes ($table, $primary = FALSE) function &MetaIndexes ($table, $primary = FALSE)
{ {
// save old fetch mode // save old fetch mode
global $ADODB_FETCH_MODE; global $ADODB_FETCH_MODE;
$false = false; $false = false;
$save = $ADODB_FETCH_MODE; $save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM; $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
if ($this->fetchMode !== FALSE) { if ($this->fetchMode !== FALSE) {
$savem = $this->SetFetchMode(FALSE); $savem = $this->SetFetchMode(FALSE);
} }
// get index details // get index details
$rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table)); $rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table));
// restore fetchmode // restore fetchmode
if (isset($savem)) { if (isset($savem)) {
$this->SetFetchMode($savem); $this->SetFetchMode($savem);
} }
$ADODB_FETCH_MODE = $save; $ADODB_FETCH_MODE = $save;
if (!is_object($rs)) { if (!is_object($rs)) {
return $false; return $false;
} }
$indexes = array (); $indexes = array ();
// parse index data into array // parse index data into array
while ($row = $rs->FetchRow()) { while ($row = $rs->FetchRow()) {
if ($primary == FALSE AND $row[2] == 'PRIMARY') { if ($primary == FALSE AND $row[2] == 'PRIMARY') {
continue; continue;
} }
if (!isset($indexes[$row[2]])) { if (!isset($indexes[$row[2]])) {
$indexes[$row[2]] = array( $indexes[$row[2]] = array(
'unique' => ($row[1] == 0), 'unique' => ($row[1] == 0),
'columns' => array() 'columns' => array()
); );
} }
$indexes[$row[2]]['columns'][$row[3] - 1] = $row[4]; $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
} }
// sort columns by order in the index // sort columns by order in the index
foreach ( array_keys ($indexes) as $index ) foreach ( array_keys ($indexes) as $index )
{ {
ksort ($indexes[$index]['columns']); ksort ($indexes[$index]['columns']);
} }
return $indexes; return $indexes;
} }
// Format date column in sql string given an input format that understands Y M D // 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; if (!$col) $col = $this->sysTimeStamp;
$s = 'DATE_FORMAT('.$col.",'"; $s = 'DATE_FORMAT('.$col.",'";
$concat = false; $concat = false;
@ -333,7 +346,7 @@ class ADODB_mysqli extends ADOConnection {
case 'Q': case 'Q':
case 'q': case 'q':
$s .= "'),Quarter($col)"; $s .= "'),Quarter($col)";
if ($len > $i+1) $s .= ",DATE_FORMAT($col,'"; if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
else $s .= ",('"; else $s .= ",('";
$concat = true; $concat = true;
@ -341,7 +354,7 @@ class ADODB_mysqli extends ADOConnection {
case 'M': case 'M':
$s .= '%b'; $s .= '%b';
break; break;
case 'm': case 'm':
$s .= '%m'; $s .= '%m';
break; break;
@ -349,38 +362,38 @@ class ADODB_mysqli extends ADOConnection {
case 'd': case 'd':
$s .= '%d'; $s .= '%d';
break; break;
case 'H': case 'H':
$s .= '%H'; $s .= '%H';
break; break;
case 'h': case 'h':
$s .= '%I'; $s .= '%I';
break; break;
case 'i': case 'i':
$s .= '%i'; $s .= '%i';
break; break;
case 's': case 's':
$s .= '%s'; $s .= '%s';
break; break;
case 'a': case 'a':
case 'A': case 'A':
$s .= '%p'; $s .= '%p';
break; break;
case 'w': case 'w':
$s .= '%w'; $s .= '%w';
break; break;
case 'l': case 'l':
$s .= '%W'; $s .= '%W';
break; break;
default: default:
if ($ch == '\\') { if ($ch == '\\') {
$i++; $i++;
$ch = substr($fmt,$i,1); $ch = substr($fmt,$i,1);
@ -393,45 +406,45 @@ class ADODB_mysqli extends ADOConnection {
if ($concat) $s = "CONCAT($s)"; if ($concat) $s = "CONCAT($s)";
return $s; return $s;
} }
// returns concatenated string // returns concatenated string
// much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
function Concat() function Concat()
{ {
$s = ""; $s = "";
$arr = func_get_args(); $arr = func_get_args();
// suggestion by andrew005@mnogo.ru // suggestion by andrew005@mnogo.ru
$s = implode(',',$arr); $s = implode(',',$arr);
if (strlen($s) > 0) return "CONCAT($s)"; if (strlen($s) > 0) return "CONCAT($s)";
else return ''; else return '';
} }
// dayFraction is a day in floating point // dayFraction is a day in floating point
function OffsetDate($dayFraction,$date=false) function OffsetDate($dayFraction,$date=false)
{ {
if (!$date) if (!$date)
$date = $this->sysDate; $date = $this->sysDate;
return "from_unixtime(unix_timestamp($date)+($dayFraction)*24*3600)"; return "from_unixtime(unix_timestamp($date)+($dayFraction)*24*3600)";
} }
function &MetaTables($ttype=false,$showSchema=false,$mask=false) function &MetaTables($ttype=false,$showSchema=false,$mask=false)
{ {
$save = $this->metaTablesSQL; $save = $this->metaTablesSQL;
if ($showSchema && is_string($showSchema)) { if ($showSchema && is_string($showSchema)) {
$this->metaTablesSQL .= " from $showSchema"; $this->metaTablesSQL .= " from $showSchema";
} }
if ($mask) { if ($mask) {
$mask = $this->qstr($mask); $mask = $this->qstr($mask);
$this->metaTablesSQL .= " like $mask"; $this->metaTablesSQL .= " like $mask";
} }
$ret =& ADOConnection::MetaTables($ttype,$showSchema); $ret =& ADOConnection::MetaTables($ttype,$showSchema);
$this->metaTablesSQL = $save; $this->metaTablesSQL = $save;
return $ret; return $ret;
} }
// "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx> // "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx>
function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $asociative = FALSE ) function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $asociative = FALSE )
{ {
@ -467,13 +480,13 @@ class ADODB_mysqli extends ADOConnection {
} }
return $foreign_keys; return $foreign_keys;
} }
function &MetaColumns($table) function &MetaColumns($table)
{ {
$false = false; $false = false;
if (!$this->metaColumnsSQL) if (!$this->metaColumnsSQL)
return $false; return $false;
global $ADODB_FETCH_MODE; global $ADODB_FETCH_MODE;
$save = $ADODB_FETCH_MODE; $save = $ADODB_FETCH_MODE;
$ADODB_FETCH_MODE = ADODB_FETCH_NUM; $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
@ -484,13 +497,13 @@ class ADODB_mysqli extends ADOConnection {
$ADODB_FETCH_MODE = $save; $ADODB_FETCH_MODE = $save;
if (!is_object($rs)) if (!is_object($rs))
return $false; return $false;
$retarr = array(); $retarr = array();
while (!$rs->EOF) { while (!$rs->EOF) {
$fld = new ADOFieldObject(); $fld = new ADOFieldObject();
$fld->name = $rs->fields[0]; $fld->name = $rs->fields[0];
$type = $rs->fields[1]; $type = $rs->fields[1];
// split type into type(length): // split type into type(length):
$fld->scale = null; $fld->scale = null;
if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) { if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
@ -523,7 +536,7 @@ class ADODB_mysqli extends ADOConnection {
$fld->has_default = false; $fld->has_default = false;
} }
} }
if ($save == ADODB_FETCH_NUM) { if ($save == ADODB_FETCH_NUM) {
$retarr[] = $fld; $retarr[] = $fld;
} else { } else {
@ -531,13 +544,13 @@ class ADODB_mysqli extends ADOConnection {
} }
$rs->MoveNext(); $rs->MoveNext();
} }
$rs->Close(); $rs->Close();
return $retarr; return $retarr;
} }
// returns true or false // returns true or false
function SelectDB($dbName) function SelectDB($dbName)
{ {
// $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID); // $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);
$this->databaseName = $dbName; $this->databaseName = $dbName;
@ -546,35 +559,35 @@ class ADODB_mysqli extends ADOConnection {
if (!$result && $this->debug) { if (!$result && $this->debug) {
ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg()); ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg());
} }
return $result; return $result;
} }
return false; return false;
} }
// parameters use PostgreSQL convention, not MySQL // parameters use PostgreSQL convention, not MySQL
function &SelectLimit($sql, function &SelectLimit($sql,
$nrows = -1, $nrows = -1,
$offset = -1, $offset = -1,
$inputarr = false, $inputarr = false,
$arg3 = false, $arg3 = false,
$secs = 0) $secs = 0)
{ {
$offsetStr = ($offset >= 0) ? "$offset," : ''; $offsetStr = ($offset >= 0) ? "$offset," : '';
if ($nrows < 0) $nrows = '18446744073709551615'; if ($nrows < 0) $nrows = '18446744073709551615';
if ($secs) if ($secs)
$rs =& $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr , $arg3); $rs =& $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr , $arg3);
else else
$rs =& $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr , $arg3); $rs =& $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr , $arg3);
return $rs; return $rs;
} }
function Prepare($sql) function Prepare($sql)
{ {
return $sql; return $sql;
$stmt = $this->_connectionID->prepare($sql); $stmt = $this->_connectionID->prepare($sql);
if (!$stmt) { if (!$stmt) {
echo $this->ErrorMsg(); echo $this->ErrorMsg();
@ -582,22 +595,22 @@ class ADODB_mysqli extends ADOConnection {
} }
return array($sql,$stmt); return array($sql,$stmt);
} }
// returns queryID or false // returns queryID or false
function _query($sql, $inputarr) function _query($sql, $inputarr)
{ {
global $ADODB_COUNTRECS; global $ADODB_COUNTRECS;
if (is_array($sql)) { if (is_array($sql)) {
$stmt = $sql[1]; $stmt = $sql[1];
$a = ''; $a = '';
foreach($inputarr as $k => $v) { foreach($inputarr as $k => $v) {
if (is_string($v)) $a .= 's'; if (is_string($v)) $a .= 's';
else if (is_integer($v)) $a .= 'i'; else if (is_integer($v)) $a .= 'i';
else $a .= 'd'; else $a .= 'd';
} }
$fnarr =& array_merge( array($stmt,$a) , $inputarr); $fnarr =& array_merge( array($stmt,$a) , $inputarr);
$ret = call_user_func_array('mysqli_stmt_bind_param',$fnarr); $ret = call_user_func_array('mysqli_stmt_bind_param',$fnarr);
@ -608,29 +621,29 @@ class ADODB_mysqli extends ADOConnection {
if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg()); if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
return false; return false;
} }
return $mysql_res; return $mysql_res;
} }
/* Returns: the last error message from previous database operation */ /* Returns: the last error message from previous database operation */
function ErrorMsg() function ErrorMsg()
{ {
if (empty($this->_connectionID)) if (empty($this->_connectionID))
$this->_errorMsg = @mysqli_connect_error(); $this->_errorMsg = @mysqli_connect_error();
else else
$this->_errorMsg = @mysqli_error($this->_connectionID); $this->_errorMsg = @mysqli_error($this->_connectionID);
return $this->_errorMsg; return $this->_errorMsg;
} }
/* Returns: the last error number from previous database operation */ /* Returns: the last error number from previous database operation */
function ErrorNo() function ErrorNo()
{ {
if (empty($this->_connectionID)) if (empty($this->_connectionID))
return @mysqli_connect_errno(); return @mysqli_connect_errno();
else else
return @mysqli_errno($this->_connectionID); return @mysqli_errno($this->_connectionID);
} }
// returns true or false // returns true or false
function _close() function _close()
{ {
@ -643,15 +656,15 @@ class ADODB_mysqli extends ADOConnection {
*/ */
function CharMax() function CharMax()
{ {
return 255; return 255;
} }
/* /*
* Maximum size of X field * Maximum size of X field
*/ */
function TextMax() function TextMax()
{ {
return 4294967295; return 4294967295;
} }
/** /**
@ -686,71 +699,76 @@ class ADODB_mysqli extends ADOConnection {
} }
return $this->charSet ? $this->charSet : false; return $this->charSet ? $this->charSet : false;
} }
/** /**
* sets the client encoding from the connection * sets the client encoding from the connection
* *
* mysqli_set_charset is php5.1+, the query used here works since mysql4.1 * mysqli_set_charset is php5.1+, the query used here works since mysql4.1
* *
* mysqli_set_charset is strongly prefered, as mysqli_real_escape only uses charset set this way!
*
* @param string $charset_name * @param string $charset_name
* @return boolean true on success, false otherwise * @return boolean true on success, false otherwise
*/ */
function SetCharSet($charset_name) function SetCharSet($charset_name)
{ {
$mysql_charset = isset($this->charset2mysql[$charset_name]) ? $this->charset2mysql[$charset_name] : $charset_name; $mysql_charset = isset($this->charset2mysql[$charset_name]) ? $this->charset2mysql[$charset_name] : $charset_name;
if (!mysqli_query($this->_connectionID,'SET NAMES '.$this->qstr($mysql_charset))) return false; if (function_exists('mysqli_set_charset')) {
if (!mysqli_set_charset($this->_connectionID,$mysql_charset)) return false;
}
elseif (!mysqli_query($this->_connectionID,'SET NAMES '.$this->qstr($mysql_charset))) return false;
if ($this->GetCharSet()) { if ($this->GetCharSet()) {
return $this->charSet == $charset_name || $this->charset2mysql[$this->charSet] == $charset_name; return $this->charSet == $charset_name || $this->charset2mysql[$this->charSet] == $charset_name;
} }
return false; return false;
} }
} }
/*-------------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------------
Class Name: Recordset Class Name: Recordset
--------------------------------------------------------------------------------------*/ --------------------------------------------------------------------------------------*/
class ADORecordSet_mysqli extends ADORecordSet{ class ADORecordSet_mysqli extends ADORecordSet{
var $databaseType = "mysqli"; var $databaseType = "mysqli";
var $canSeek = true; var $canSeek = true;
function ADORecordSet_mysqli($queryID, $mode = false) function ADORecordSet_mysqli($queryID, $mode = false)
{ {
if ($mode === false) if ($mode === false)
{ {
global $ADODB_FETCH_MODE; global $ADODB_FETCH_MODE;
$mode = $ADODB_FETCH_MODE; $mode = $ADODB_FETCH_MODE;
} }
switch ($mode) switch ($mode)
{ {
case ADODB_FETCH_NUM: case ADODB_FETCH_NUM:
$this->fetchMode = MYSQLI_NUM; $this->fetchMode = MYSQLI_NUM;
break; break;
case ADODB_FETCH_ASSOC: case ADODB_FETCH_ASSOC:
$this->fetchMode = MYSQLI_ASSOC; $this->fetchMode = MYSQLI_ASSOC;
break; break;
case ADODB_FETCH_DEFAULT: case ADODB_FETCH_DEFAULT:
case ADODB_FETCH_BOTH: case ADODB_FETCH_BOTH:
default: default:
$this->fetchMode = MYSQLI_BOTH; $this->fetchMode = MYSQLI_BOTH;
break; break;
} }
$this->adodbFetchMode = $mode; $this->adodbFetchMode = $mode;
$this->ADORecordSet($queryID); $this->ADORecordSet($queryID);
} }
function _initrs() function _initrs()
{ {
global $ADODB_COUNTRECS; global $ADODB_COUNTRECS;
$this->_numOfRows = $ADODB_COUNTRECS ? @mysqli_num_rows($this->_queryID) : -1; $this->_numOfRows = $ADODB_COUNTRECS ? @mysqli_num_rows($this->_queryID) : -1;
$this->_numOfFields = @mysqli_num_fields($this->_queryID); $this->_numOfFields = @mysqli_num_fields($this->_queryID);
} }
function &FetchField($fieldOffset = -1) function &FetchField($fieldOffset = -1)
{ {
$fieldnr = $fieldOffset; $fieldnr = $fieldOffset;
if ($fieldOffset != -1) { if ($fieldOffset != -1) {
$fieldOffset = mysqli_field_seek($this->_queryID, $fieldnr); $fieldOffset = mysqli_field_seek($this->_queryID, $fieldnr);
@ -761,18 +779,18 @@ class ADORecordSet_mysqli extends ADORecordSet{
function &GetRowAssoc($upper = true) function &GetRowAssoc($upper = true)
{ {
if ($this->fetchMode == MYSQLI_ASSOC && !$upper) if ($this->fetchMode == MYSQLI_ASSOC && !$upper)
return $this->fields; return $this->fields;
$row =& ADORecordSet::GetRowAssoc($upper); $row =& ADORecordSet::GetRowAssoc($upper);
return $row; return $row;
} }
/* Use associative array to get fields array */ /* Use associative array to get fields array */
function Fields($colname) function Fields($colname)
{ {
if ($this->fetchMode != MYSQLI_NUM) if ($this->fetchMode != MYSQLI_NUM)
return @$this->fields[$colname]; return @$this->fields[$colname];
if (!$this->bind) { if (!$this->bind) {
$this->bind = array(); $this->bind = array();
for ($i = 0; $i < $this->_numOfFields; $i++) { for ($i = 0; $i < $this->_numOfFields; $i++) {
@ -782,10 +800,10 @@ class ADORecordSet_mysqli extends ADORecordSet{
} }
return $this->fields[$this->bind[strtoupper($colname)]]; return $this->fields[$this->bind[strtoupper($colname)]];
} }
function _seek($row) function _seek($row)
{ {
if ($this->_numOfRows == 0) if ($this->_numOfRows == 0)
return false; return false;
if ($row < 0) if ($row < 0)
@ -795,33 +813,33 @@ class ADORecordSet_mysqli extends ADORecordSet{
$this->EOF = false; $this->EOF = false;
return true; return true;
} }
// 10% speedup to move MoveNext to child class // 10% speedup to move MoveNext to child class
// This is the only implementation that works now (23-10-2003). // This is the only implementation that works now (23-10-2003).
// Other functions return no or the wrong results. // Other functions return no or the wrong results.
function MoveNext() function MoveNext()
{ {
if ($this->EOF) return false; if ($this->EOF) return false;
$this->_currentRow++; $this->_currentRow++;
$this->fields = @mysqli_fetch_array($this->_queryID,$this->fetchMode); $this->fields = @mysqli_fetch_array($this->_queryID,$this->fetchMode);
if (is_array($this->fields)) return true; if (is_array($this->fields)) return true;
$this->EOF = true; $this->EOF = true;
return false; return false;
} }
function _fetch() function _fetch()
{ {
$this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode); $this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode);
return is_array($this->fields); return is_array($this->fields);
} }
function _close() function _close()
{ {
mysqli_free_result($this->_queryID); mysqli_free_result($this->_queryID);
$this->_queryID = false; $this->_queryID = false;
} }
/* /*
0 = MYSQLI_TYPE_DECIMAL 0 = MYSQLI_TYPE_DECIMAL
@ -858,18 +876,18 @@ class ADORecordSet_mysqli extends ADORecordSet{
$t = $fieldobj->type; $t = $fieldobj->type;
$len = $fieldobj->max_length; $len = $fieldobj->max_length;
} }
$len = -1; // mysql max_length is not accurate $len = -1; // mysql max_length is not accurate
switch (strtoupper($t)) { switch (strtoupper($t)) {
case 'STRING': case 'STRING':
case 'CHAR': case 'CHAR':
case 'VARCHAR': case 'VARCHAR':
case 'TINYBLOB': case 'TINYBLOB':
case 'TINYTEXT': case 'TINYTEXT':
case 'ENUM': case 'ENUM':
case 'SET': case 'SET':
case MYSQLI_TYPE_TINY_BLOB : case MYSQLI_TYPE_TINY_BLOB :
case MYSQLI_TYPE_CHAR : case MYSQLI_TYPE_CHAR :
case MYSQLI_TYPE_STRING : case MYSQLI_TYPE_STRING :
@ -877,61 +895,61 @@ class ADORecordSet_mysqli extends ADORecordSet{
case MYSQLI_TYPE_SET : case MYSQLI_TYPE_SET :
case 253 : case 253 :
if ($len <= $this->blobSize) return 'C'; if ($len <= $this->blobSize) return 'C';
case 'TEXT': case 'TEXT':
case 'LONGTEXT': case 'LONGTEXT':
case 'MEDIUMTEXT': case 'MEDIUMTEXT':
return 'X'; return 'X';
// php_mysql extension always returns 'blob' even if 'text' // php_mysql extension always returns 'blob' even if 'text'
// so we have to check whether binary... // so we have to check whether binary...
case 'IMAGE': case 'IMAGE':
case 'LONGBLOB': case 'LONGBLOB':
case 'BLOB': case 'BLOB':
case 'MEDIUMBLOB': case 'MEDIUMBLOB':
case MYSQLI_TYPE_BLOB : case MYSQLI_TYPE_BLOB :
case MYSQLI_TYPE_LONG_BLOB : case MYSQLI_TYPE_LONG_BLOB :
case MYSQLI_TYPE_MEDIUM_BLOB : case MYSQLI_TYPE_MEDIUM_BLOB :
return !empty($fieldobj->binary) ? 'B' : 'X'; return !empty($fieldobj->binary) ? 'B' : 'X';
case 'YEAR': case 'YEAR':
case 'DATE': case 'DATE':
case MYSQLI_TYPE_DATE : case MYSQLI_TYPE_DATE :
case MYSQLI_TYPE_YEAR : case MYSQLI_TYPE_YEAR :
return 'D'; return 'D';
case 'TIME': case 'TIME':
case 'DATETIME': case 'DATETIME':
case 'TIMESTAMP': case 'TIMESTAMP':
case MYSQLI_TYPE_DATETIME : case MYSQLI_TYPE_DATETIME :
case MYSQLI_TYPE_NEWDATE : case MYSQLI_TYPE_NEWDATE :
case MYSQLI_TYPE_TIME : case MYSQLI_TYPE_TIME :
case MYSQLI_TYPE_TIMESTAMP : case MYSQLI_TYPE_TIMESTAMP :
return 'T'; return 'T';
case 'INT': case 'INT':
case 'INTEGER': case 'INTEGER':
case 'BIGINT': case 'BIGINT':
case 'TINYINT': case 'TINYINT':
case 'MEDIUMINT': case 'MEDIUMINT':
case 'SMALLINT': case 'SMALLINT':
case MYSQLI_TYPE_INT24 : case MYSQLI_TYPE_INT24 :
case MYSQLI_TYPE_LONG : case MYSQLI_TYPE_LONG :
case MYSQLI_TYPE_LONGLONG : case MYSQLI_TYPE_LONGLONG :
case MYSQLI_TYPE_SHORT : case MYSQLI_TYPE_SHORT :
case MYSQLI_TYPE_TINY : case MYSQLI_TYPE_TINY :
if (!empty($fieldobj->primary_key)) return 'R'; if (!empty($fieldobj->primary_key)) return 'R';
return 'I'; return 'I';
// Added floating-point types // Added floating-point types
// Maybe not necessery. // Maybe not necessery.
case 'FLOAT': case 'FLOAT':
@ -941,14 +959,14 @@ class ADORecordSet_mysqli extends ADORecordSet{
case 'DEC': case 'DEC':
case 'FIXED': case 'FIXED':
default: default:
//if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>"; //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>";
return 'N'; return 'N';
} }
} // function } // function
} // rs class } // rs class
} }
?> ?>

View File

@ -418,14 +418,10 @@ class egw_db
return null; // in case error-reporting = 'no' return null; // in case error-reporting = 'no'
} }
$connect = $GLOBALS['egw_info']['server']['db_persistent'] ? 'PConnect' : 'Connect'; $connect = $GLOBALS['egw_info']['server']['db_persistent'] ? 'PConnect' : 'Connect';
if (($Ok = $this->Link_ID->$connect($Host, $User, $Password))) if (($Ok = $this->Link_ID->$connect($Host, $User, $Password, $Database)))
{ {
$this->ServerInfo = $this->Link_ID->ServerInfo(); $this->ServerInfo = $this->Link_ID->ServerInfo();
$this->set_capabilities($type,$this->ServerInfo['version']); $this->set_capabilities($type,$this->ServerInfo['version']);
if($Database)
{
$Ok = $this->Link_ID->SelectDB($Database);
}
} }
if (!$Ok) if (!$Ok)
{ {
@ -456,8 +452,7 @@ class egw_db
$this->Link_ID =& $GLOBALS['egw']->ADOdb; $this->Link_ID =& $GLOBALS['egw']->ADOdb;
} }
} }
// next ADOdb version: if (!$this->Link_ID->isConnected()) $this->Link_ID->Connect(); if (!$this->Link_ID->isConnected()) $this->Link_ID->Connect();
if (!$this->Link_ID->_connectionID) $this->Link_ID->Connect();
if ($new_connection) if ($new_connection)
{ {

View File

@ -19,10 +19,10 @@ class setup_cmd_database extends setup_cmd
* Allow to run this command via setup-cli * Allow to run this command via setup-cli
*/ */
const SETUP_CLI_CALLABLE = true; const SETUP_CLI_CALLABLE = true;
/** /**
* Maximum length of database name (at least for MySQL this is the limit) * Maximum length of database name (at least for MySQL this is the limit)
* *
* @var int * @var int
*/ */
const MAX_DB_NAME_LEN = 16; const MAX_DB_NAME_LEN = 16;
@ -68,7 +68,7 @@ class setup_cmd_database extends setup_cmd
'db_root_pw' => $db_root_pw, 'db_root_pw' => $db_root_pw,
'sub_command' => $sub_command, 'sub_command' => $sub_command,
'db_grant_host' => $db_grant_host, 'db_grant_host' => $db_grant_host,
'make_db_name_unique' => $make_db_name_unique, 'make_db_name_unique' => $make_db_name_unique,
); );
} }
//error_log(__METHOD__.'('.array2string($domain).") make_db_name_unique=".array2string($domain['make_db_name_unique'])); //error_log(__METHOD__.'('.array2string($domain).") make_db_name_unique=".array2string($domain['make_db_name_unique']));
@ -163,7 +163,7 @@ class setup_cmd_database extends setup_cmd
* Check and if does not yet exist create the new database and user * Check and if does not yet exist create the new database and user
* *
* The check will fail if the database exists, but already contains tables * The check will fail if the database exists, but already contains tables
* *
* if $this->make_db_name_unique is set, a decrementing nummeric prefix gets * if $this->make_db_name_unique is set, a decrementing nummeric prefix gets
* added to $this->db_name AND $this->db_user, if db already exists. * added to $this->db_name AND $this->db_user, if db already exists.
* *
@ -177,7 +177,7 @@ class setup_cmd_database extends setup_cmd
// shorten db-name/-user to self::MAX_DB_NAME_LEN chars // shorten db-name/-user to self::MAX_DB_NAME_LEN chars
if ($this->make_db_name_unique && strlen($this->db_name) > self::MAX_DB_NAME_LEN) if ($this->make_db_name_unique && strlen($this->db_name) > self::MAX_DB_NAME_LEN)
{ {
$this->set_defaults['db_name'] = $this->db_name = $this->set_defaults['db_name'] = $this->db_name =
$this->set_defaults['db_user'] = $this->db_user = // change user too (otherwise existing user/db could not connect any more!) $this->set_defaults['db_user'] = $this->db_user = // change user too (otherwise existing user/db could not connect any more!)
substr($this->db_name,0,self::MAX_DB_NAME_LEN); substr($this->db_name,0,self::MAX_DB_NAME_LEN);
} }
@ -193,7 +193,7 @@ class setup_cmd_database extends setup_cmd
catch(egw_exception_db $e) { // catches failed to create database catch(egw_exception_db $e) { // catches failed to create database
// try connect as root to check if wrong root/root_pw is the problem // try connect as root to check if wrong root/root_pw is the problem
$this->connect($this->db_root,$this->db_root_pw,$this->db_meta); $this->connect($this->db_root,$this->db_root_pw,$this->db_meta);
// if we should create a db with a unique name (try it only N times, not endless!) // if we should create a db with a unique name (try it only N times, not endless!)
if ($this->make_db_name_unique && $try_make_unique++ < 20) if ($this->make_db_name_unique && $try_make_unique++ < 20)
{ {
@ -209,10 +209,10 @@ class setup_cmd_database extends setup_cmd
{ {
$num = '2'; $num = '2';
} }
$this->set_defaults['db_name'] = $this->db_name = $this->set_defaults['db_name'] = $this->db_name =
$this->set_defaults['db_user'] = $this->db_user = // change user too (otherwise existing user/db could not connect any more!) $this->set_defaults['db_user'] = $this->db_user = // change user too (otherwise existing user/db could not connect any more!)
substr($this->db_name,0,self::MAX_DB_NAME_LEN-strlen($num)).$num; substr($this->db_name,0,self::MAX_DB_NAME_LEN-strlen($num)).$num;
return $this->create(); return $this->create();
} }
catch (egw_exception_wrong_userinput $e2) catch (egw_exception_wrong_userinput $e2)
@ -270,7 +270,7 @@ class setup_cmd_database extends setup_cmd
* @param string $db_type='mysql' * @param string $db_type='mysql'
* @return array * @return array
*/ */
static function defaults($db_type='mysql') static function defaults($db_type='mysqli')
{ {
switch($db_type) switch($db_type)
{ {
@ -312,7 +312,7 @@ class setup_cmd_database extends setup_cmd
if (strpos($this->$name,'$domain') !== false) if (strpos($this->$name,'$domain') !== false)
{ {
// limit names to 16 chars (16 char is user-name limit in MySQL) // limit names to 16 chars (16 char is user-name limit in MySQL)
$this->set_defaults[$name] = $this->$name = $this->set_defaults[$name] = $this->$name =
substr(str_replace(array('$domain','.','-'),array($this->domain,'_','_'),$this->$name), substr(str_replace(array('$domain','.','-'),array($this->domain,'_','_'),$this->$name),
0,self::MAX_DB_NAME_LEN); 0,self::MAX_DB_NAME_LEN);
} }

View File

@ -26,10 +26,10 @@ class setup_header
* @var array with php-extension / ADOdb drive names => describtiv label * @var array with php-extension / ADOdb drive names => describtiv label
*/ */
var $db_fullnames = array( var $db_fullnames = array(
'mysqli' => 'MySQLi (recommended, incl. transactions)',
'mysql' => 'MySQL (deprecated)',
'mysqlt' => 'MySQL (deprecated, transactions)',
'pgsql' => 'PostgreSQL', 'pgsql' => 'PostgreSQL',
'mysql' => 'MySQL',
'mysqli' => 'MySQLi (php5)',
'mysqlt' => 'MySQL (with transactions)',
'mssql' => 'MS SQL Server', 'mssql' => 'MS SQL Server',
'odbc_mssql' => 'MS SQL Server via ODBC', 'odbc_mssql' => 'MS SQL Server via ODBC',
'oracle' => 'Oracle', 'oracle' => 'Oracle',
@ -84,7 +84,7 @@ class setup_header
function domain_defaults($user='admin',$passwd='',$supported_db=null) function domain_defaults($user='admin',$passwd='',$supported_db=null)
{ {
if (is_null($supported_db)) $supported_db = $this->check_db_support($null); if (is_null($supported_db)) $supported_db = $this->check_db_support($null);
$default_db = count($supported_db) ? $supported_db[0] : 'mysql'; $default_db = count($supported_db) ? $supported_db[0] : 'mysqli';
return array( return array(
'db_host' => 'localhost', 'db_host' => 'localhost',
@ -232,8 +232,8 @@ class setup_header
$supported_db = $detected = array(); $supported_db = $detected = array();
foreach(array( foreach(array(
// short => array(extension,func_to_check,supported_db(s)) // short => array(extension,func_to_check,supported_db(s))
'mysql' => array('mysql','mysql_connect','mysql'),
'mysqli' => array('mysql','mysqli_connect','mysqli'), 'mysqli' => array('mysql','mysqli_connect','mysqli'),
'mysql' => array('mysql','mysql_connect','mysql'),
'mysqlt' => array('mysql','mysql_connect','mysqlt'), 'mysqlt' => array('mysql','mysql_connect','mysqlt'),
'pgsql' => array('pgsql','pg_connect','pgsql'), 'pgsql' => array('pgsql','pg_connect','pgsql'),
'mssql' => array('mssql','mssql_connect','mssql'), 'mssql' => array('mssql','mssql_connect','mssql'),