Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/adodb/drivers/adodb-mysqli.inc.php
Go to the documentation of this file.
00001 <?php
00002 /*
00003 V5.14 8 Sept 2011  (c) 2000-2011 John Lim (jlim#natsoft.com). All rights reserved.
00004   Released under both BSD license and Lesser GPL library license. 
00005   Whenever there is any discrepancy between the two licenses, 
00006   the BSD license will take precedence.
00007   Set tabs to 8.
00008   
00009   MySQL code that does not support transactions. Use mysqlt if you need transactions.
00010   Requires mysql client. Works on Windows and Unix.
00011  
00012 21 October 2003: MySQLi extension implementation by Arjen de Rijke (a.de.rijke@xs4all.nl)
00013 Based on adodb 3.40
00014 */ 
00015 
00016 // security - hide paths
00017 if (!defined('ADODB_DIR')) die();
00018 
00019 if (! defined("_ADODB_MYSQLI_LAYER")) {
00020  define("_ADODB_MYSQLI_LAYER", 1 );
00021  
00022  // PHP5 compat...
00023  if (! defined("MYSQLI_BINARY_FLAG"))  define("MYSQLI_BINARY_FLAG", 128); 
00024  if (!defined('MYSQLI_READ_DEFAULT_GROUP')) define('MYSQLI_READ_DEFAULT_GROUP',1);
00025 
00026  // disable adodb extension - currently incompatible.
00027  global $ADODB_EXTENSION; $ADODB_EXTENSION = false;
00028 
00029 class ADODB_mysqli extends ADOConnection {
00030         var $databaseType = 'mysqli';
00031         var $dataProvider = 'native';
00032         var $hasInsertID = true;
00033         var $hasAffectedRows = true;    
00034         var $metaTablesSQL = "SHOW TABLES";     
00035         var $metaColumnsSQL = "SHOW COLUMNS FROM `%s`";
00036         var $fmtTimeStamp = "'Y-m-d H:i:s'";
00037         var $hasLimit = true;
00038         var $hasMoveFirst = true;
00039         var $hasGenID = true;
00040         var $isoDates = true; // accepts dates in ISO format
00041         var $sysDate = 'CURDATE()';
00042         var $sysTimeStamp = 'NOW()';
00043         var $hasTransactions = true;
00044         var $forceNewConnect = false;
00045         var $poorAffectedRows = true;
00046         var $clientFlags = 0;
00047         var $substr = "substring";
00048         var $port = false;
00049         var $socket = false;
00050         var $_bindInputArray = false;
00051         var $nameQuote = '`';           
00052         var $optionFlags = array(array(MYSQLI_READ_DEFAULT_GROUP,0));
00053         var $arrayClass = 'ADORecordSet_array_mysqli';
00054         var $multiQuery = false;
00055         
00056         function ADODB_mysqli() 
00057         {                       
00058          // if(!extension_loaded("mysqli"))
00059               ;//trigger_error("You must have the mysqli extension installed.", E_USER_ERROR);
00060             
00061         }
00062         
00063         function SetTransactionMode( $transaction_mode ) 
00064         {
00065                 $this->_transmode  = $transaction_mode;
00066                 if (empty($transaction_mode)) {
00067                         $this->Execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ');
00068                         return;
00069                 }
00070                 if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
00071                 $this->Execute("SET SESSION TRANSACTION ".$transaction_mode);
00072         }
00073 
00074         // returns true or false
00075         // To add: parameter int $port,
00076         //         parameter string $socket
00077         function _connect($argHostname = NULL, 
00078                           $argUsername = NULL, 
00079                           $argPassword = NULL, 
00080                           $argDatabasename = NULL, $persist=false)
00081           {
00082                  if(!extension_loaded("mysqli")) {
00083                         return null;
00084                  }
00085             $this->_connectionID = @mysqli_init();
00086             
00087             if (is_null($this->_connectionID)) {
00088               // mysqli_init only fails if insufficient memory
00089               if ($this->debug) 
00090                                 ADOConnection::outp("mysqli_init() failed : "  . $this->ErrorMsg());
00091               return false;
00092             }
00093                 /*
00094                 I suggest a simple fix which would enable adodb and mysqli driver to
00095                 read connection options from the standard mysql configuration file
00096                 /etc/my.cnf - "Bastien Duclaux" <bduclaux#yahoo.com>
00097                 */
00098                 foreach($this->optionFlags as $arr) {   
00099                         mysqli_options($this->_connectionID,$arr[0],$arr[1]);
00100                 }
00101 
00102                 //http ://php.net/manual/en/mysqli.persistconns.php
00103                 if ($persist && PHP_VERSION > 5.2 && strncmp($argHostname,'p:',2) != 0) $argHostname = 'p:'.$argHostname;
00104 
00105                 #if (!empty($this->port)) $argHostname .= ":".$this->port;
00106                 $ok = mysqli_real_connect($this->_connectionID,
00107                                     $argHostname,
00108                                     $argUsername,
00109                                     $argPassword,
00110                                     $argDatabasename,
00111                                         $this->port,
00112                                         $this->socket,
00113                                         $this->clientFlags);
00114              
00115                 if ($ok) {
00116                         if ($argDatabasename)  return $this->SelectDB($argDatabasename);
00117                         return true;
00118            } else {
00119                         if ($this->debug) 
00120                                 ADOConnection::outp("Could't connect : "  . $this->ErrorMsg());
00121                         $this->_connectionID = null;
00122                         return false;
00123            }
00124         }
00125         
00126         // returns true or false
00127         // How to force a persistent connection
00128         function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
00129         {
00130                 return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true);
00131 
00132         }
00133         
00134         // When is this used? Close old connection first?
00135         // In _connect(), check $this->forceNewConnect? 
00136         function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
00137           {
00138             $this->forceNewConnect = true;
00139             return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
00140           }
00141         
00142         function IfNull( $field, $ifNull ) 
00143         {
00144                 return " IFNULL($field, $ifNull) "; // if MySQL
00145         }
00146         
00147         // do not use $ADODB_COUNTRECS
00148         function GetOne($sql,$inputarr=false)
00149         {
00150         global $ADODB_GETONE_EOF;
00151         
00152                 $ret = false;
00153                 $rs = $this->Execute($sql,$inputarr);
00154                 if ($rs) {
00155                         if ($rs->EOF) $ret = $ADODB_GETONE_EOF;
00156                         else $ret = reset($rs->fields);
00157                         $rs->Close();
00158                 }
00159                 return $ret;
00160         }
00161         
00162         function ServerInfo()
00163         {
00164                 $arr['description'] = $this->GetOne("select version()");
00165                 $arr['version'] = ADOConnection::_findvers($arr['description']);
00166                 return $arr;
00167         }
00168         
00169         
00170         function BeginTrans()
00171         {         
00172                 if ($this->transOff) return true;
00173                 $this->transCnt += 1;
00174                 
00175                 //$this->Execute('SET AUTOCOMMIT=0');
00176                 mysqli_autocommit($this->_connectionID, false);
00177                 $this->Execute('BEGIN');
00178                 return true;
00179         }
00180         
00181         function CommitTrans($ok=true) 
00182         {
00183                 if ($this->transOff) return true; 
00184                 if (!$ok) return $this->RollbackTrans();
00185                 
00186                 if ($this->transCnt) $this->transCnt -= 1;
00187                 $this->Execute('COMMIT');
00188                 
00189                 //$this->Execute('SET AUTOCOMMIT=1');
00190                 mysqli_autocommit($this->_connectionID, true);
00191                 return true;
00192         }
00193         
00194         function RollbackTrans()
00195         {
00196                 if ($this->transOff) return true;
00197                 if ($this->transCnt) $this->transCnt -= 1;
00198                 $this->Execute('ROLLBACK');
00199                 //$this->Execute('SET AUTOCOMMIT=1');
00200                 mysqli_autocommit($this->_connectionID, true);
00201                 return true;
00202         }
00203         
00204         function RowLock($tables,$where='',$col='1 as adodbignore') 
00205         {
00206                 if ($this->transCnt==0) $this->BeginTrans();
00207                 if ($where) $where = ' where '.$where;
00208                 $rs = $this->Execute("select $col from $tables $where for update");
00209                 return !empty($rs); 
00210         }
00211         
00212         // if magic quotes disabled, use mysql_real_escape_string()
00213         // From readme.htm:
00214         // Quotes a string to be sent to the database. The $magic_quotes_enabled
00215         // parameter may look funny, but the idea is if you are quoting a 
00216         // string extracted from a POST/GET variable, then 
00217         // pass get_magic_quotes_gpc() as the second parameter. This will 
00218         // ensure that the variable is not quoted twice, once by qstr and once 
00219         // by the magic_quotes_gpc.
00220         //
00221         //Eg. $s = $db->qstr(_GET['name'],get_magic_quotes_gpc());
00222         function qstr($s, $magic_quotes = false)
00223         {
00224                 if (is_null($s)) return 'NULL';
00225                 if (!$magic_quotes) {
00226                 if (PHP_VERSION >= 5)
00227                         return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'";   
00228             
00229                 if ($this->replaceQuote[0] == '\\')
00230                         $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
00231             return  "'".str_replace("'",$this->replaceQuote,$s)."'"; 
00232           }
00233           // undo magic quotes for "
00234           $s = str_replace('\\"','"',$s);
00235           return "'$s'";
00236         }
00237         
00238         function _insertid()
00239         {
00240           $result = @mysqli_insert_id($this->_connectionID);
00241           if ($result == -1){
00242               if ($this->debug) ADOConnection::outp("mysqli_insert_id() failed : "  . $this->ErrorMsg());
00243           }
00244           return $result;
00245         }
00246         
00247         // Only works for INSERT, UPDATE and DELETE query's
00248         function _affectedrows()
00249         {
00250           $result =  @mysqli_affected_rows($this->_connectionID);
00251           if ($result == -1) {
00252               if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : "  . $this->ErrorMsg());
00253           }
00254           return $result;
00255         }
00256   
00257         // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
00258         // Reference on Last_Insert_ID on the recommended way to simulate sequences
00259         var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
00260         var $_genSeqSQL = "create table %s (id int not null)";
00261         var $_genSeqCountSQL = "select count(*) from %s";
00262         var $_genSeq2SQL = "insert into %s values (%s)";
00263         var $_dropSeqSQL = "drop table %s";
00264         
00265         function CreateSequence($seqname='adodbseq',$startID=1)
00266         {
00267                 if (empty($this->_genSeqSQL)) return false;
00268                 $u = strtoupper($seqname);
00269                 
00270                 $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
00271                 if (!$ok) return false;
00272                 return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
00273         }
00274         
00275         function GenID($seqname='adodbseq',$startID=1)
00276         {
00277                 // post-nuke sets hasGenID to false
00278                 if (!$this->hasGenID) return false;
00279                 
00280                 $getnext = sprintf($this->_genIDSQL,$seqname);
00281                 $holdtransOK = $this->_transOK; // save the current status
00282                 $rs = @$this->Execute($getnext);
00283                 if (!$rs) {
00284                         if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset
00285                         $u = strtoupper($seqname);
00286                         $this->Execute(sprintf($this->_genSeqSQL,$seqname));
00287                         $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname));
00288                         if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
00289                         $rs = $this->Execute($getnext);
00290                 }
00291                 
00292                 if ($rs) {
00293                         $this->genID = mysqli_insert_id($this->_connectionID);
00294                         $rs->Close();
00295                 } else
00296                         $this->genID = 0;
00297                         
00298                 return $this->genID;
00299         }
00300         
00301         function MetaDatabases()
00302         {
00303                 $query = "SHOW DATABASES";
00304                 $ret = $this->Execute($query);
00305                 if ($ret && is_object($ret)){
00306                    $arr = array();
00307                         while (!$ret->EOF){
00308                                 $db = $ret->Fields('Database');
00309                                 if ($db != 'mysql') $arr[] = $db;
00310                                 $ret->MoveNext();
00311                         }
00312                    return $arr;
00313                 }
00314         return $ret;
00315         }
00316 
00317           
00318         function MetaIndexes ($table, $primary = FALSE, $owner = false)
00319         {
00320                 // save old fetch mode
00321                 global $ADODB_FETCH_MODE;
00322                 
00323                 $false = false;
00324                 $save = $ADODB_FETCH_MODE;
00325                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00326                 if ($this->fetchMode !== FALSE) {
00327                        $savem = $this->SetFetchMode(FALSE);
00328                 }
00329                 
00330                 // get index details
00331                 $rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table));
00332                 
00333                 // restore fetchmode
00334                 if (isset($savem)) {
00335                         $this->SetFetchMode($savem);
00336                 }
00337                 $ADODB_FETCH_MODE = $save;
00338                 
00339                 if (!is_object($rs)) {
00340                         return $false;
00341                 }
00342                 
00343                 $indexes = array ();
00344                 
00345                 // parse index data into array
00346                 while ($row = $rs->FetchRow()) {
00347                         if ($primary == FALSE AND $row[2] == 'PRIMARY') {
00348                                 continue;
00349                         }
00350                         
00351                         if (!isset($indexes[$row[2]])) {
00352                                 $indexes[$row[2]] = array(
00353                                         'unique' => ($row[1] == 0),
00354                                         'columns' => array()
00355                                 );
00356                         }
00357                         
00358                         $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
00359                 }
00360                 
00361                 // sort columns by order in the index
00362                 foreach ( array_keys ($indexes) as $index )
00363                 {
00364                         ksort ($indexes[$index]['columns']);
00365                 }
00366                 
00367                 return $indexes;
00368         }
00369 
00370         
00371         // Format date column in sql string given an input format that understands Y M D
00372         function SQLDate($fmt, $col=false)
00373         {       
00374                 if (!$col) $col = $this->sysTimeStamp;
00375                 $s = 'DATE_FORMAT('.$col.",'";
00376                 $concat = false;
00377                 $len = strlen($fmt);
00378                 for ($i=0; $i < $len; $i++) {
00379                         $ch = $fmt[$i];
00380                         switch($ch) {
00381                         case 'Y':
00382                         case 'y':
00383                                 $s .= '%Y';
00384                                 break;
00385                         case 'Q':
00386                         case 'q':
00387                                 $s .= "'),Quarter($col)";
00388                                 
00389                                 if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
00390                                 else $s .= ",('";
00391                                 $concat = true;
00392                                 break;
00393                         case 'M':
00394                                 $s .= '%b';
00395                                 break;
00396                                 
00397                         case 'm':
00398                                 $s .= '%m';
00399                                 break;
00400                         case 'D':
00401                         case 'd':
00402                                 $s .= '%d';
00403                                 break;
00404                         
00405                         case 'H': 
00406                                 $s .= '%H';
00407                                 break;
00408                                 
00409                         case 'h':
00410                                 $s .= '%I';
00411                                 break;
00412                                 
00413                         case 'i':
00414                                 $s .= '%i';
00415                                 break;
00416                                 
00417                         case 's':
00418                                 $s .= '%s';
00419                                 break;
00420                                 
00421                         case 'a':
00422                         case 'A':
00423                                 $s .= '%p';
00424                                 break;
00425                         
00426                         case 'w':
00427                                 $s .= '%w';
00428                                 break;
00429                                 
00430                         case 'l':
00431                                 $s .= '%W';
00432                                 break;
00433                                 
00434                         default:
00435                                 
00436                                 if ($ch == '\\') {
00437                                         $i++;
00438                                         $ch = substr($fmt,$i,1);
00439                                 }
00440                                 $s .= $ch;
00441                                 break;
00442                         }
00443                 }
00444                 $s.="')";
00445                 if ($concat) $s = "CONCAT($s)";
00446                 return $s;
00447         }
00448         
00449         // returns concatenated string
00450         // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
00451         function Concat()
00452         {
00453                 $s = "";
00454                 $arr = func_get_args();
00455                 
00456                 // suggestion by andrew005@mnogo.ru
00457                 $s = implode(',',$arr); 
00458                 if (strlen($s) > 0) return "CONCAT($s)";
00459                 else return '';
00460         }
00461         
00462         // dayFraction is a day in floating point
00463         function OffsetDate($dayFraction,$date=false)
00464         {               
00465                 if (!$date) $date = $this->sysDate;
00466                 
00467                 $fraction = $dayFraction * 24 * 3600;
00468                 return $date . ' + INTERVAL ' .  $fraction.' SECOND';
00469                 
00470 //              return "from_unixtime(unix_timestamp($date)+$fraction)";
00471         }
00472         
00473         function MetaTables($ttype=false,$showSchema=false,$mask=false) 
00474         {       
00475                 $save = $this->metaTablesSQL;
00476                 if ($showSchema && is_string($showSchema)) {
00477                         $this->metaTablesSQL .= " from $showSchema";
00478                 }
00479                 
00480                 if ($mask) {
00481                         $mask = $this->qstr($mask);
00482                         $this->metaTablesSQL .= " like $mask";
00483                 }
00484                 $ret = ADOConnection::MetaTables($ttype,$showSchema);
00485                 
00486                 $this->metaTablesSQL = $save;
00487                 return $ret;
00488         }
00489         
00490         // "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx>
00491         function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
00492         {
00493          global $ADODB_FETCH_MODE;
00494                 
00495                 if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true;
00496                 
00497             if ( !empty($owner) ) {
00498                $table = "$owner.$table";
00499             }
00500             $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
00501                 if ($associative) {
00502                         $create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"];
00503             } else $create_sql  = $a_create_table[1];
00504         
00505             $matches = array();
00506         
00507             if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
00508                 $foreign_keys = array();                 
00509             $num_keys = count($matches[0]);
00510             for ( $i = 0;  $i < $num_keys;  $i ++ ) {
00511                 $my_field  = explode('`, `', $matches[1][$i]);
00512                 $ref_table = $matches[2][$i];
00513                 $ref_field = explode('`, `', $matches[3][$i]);
00514         
00515                 if ( $upper ) {
00516                     $ref_table = strtoupper($ref_table);
00517                 }
00518         
00519                 // see https://sourceforge.net/tracker/index.php?func=detail&aid=2287278&group_id=42718&atid=433976
00520                         if (!isset($foreign_keys[$ref_table])) {
00521                                 $foreign_keys[$ref_table] = array();
00522                         }
00523                 $num_fields = count($my_field);
00524                 for ( $j = 0;  $j < $num_fields;  $j ++ ) {
00525                     if ( $associative ) {
00526                         $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
00527                     } else {
00528                         $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
00529                     }
00530                 }
00531             }
00532             
00533             return  $foreign_keys;
00534         }
00535         
00536         function MetaColumns($table, $normalize=true) 
00537         {
00538                 $false = false;
00539                 if (!$this->metaColumnsSQL)
00540                         return $false;
00541                 
00542                 global $ADODB_FETCH_MODE;
00543                 $save = $ADODB_FETCH_MODE;
00544                 $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00545                 if ($this->fetchMode !== false)
00546                         $savem = $this->SetFetchMode(false);
00547                 $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
00548                 if (isset($savem)) $this->SetFetchMode($savem);
00549                 $ADODB_FETCH_MODE = $save;
00550                 if (!is_object($rs))
00551                         return $false;
00552                 
00553                 $retarr = array();
00554                 while (!$rs->EOF) {
00555                         $fld = new ADOFieldObject();
00556                         $fld->name = $rs->fields[0];
00557                         $type = $rs->fields[1];
00558                         
00559                         // split type into type(length):
00560                         $fld->scale = null;
00561                         if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
00562                                 $fld->type = $query_array[1];
00563                                 $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
00564                                 $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
00565                         } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
00566                                 $fld->type = $query_array[1];
00567                                 $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
00568                         } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
00569                                 $fld->type = $query_array[1];
00570                                 $arr = explode(",",$query_array[2]);
00571                                 $fld->enums = $arr;
00572                                 $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
00573                                 $fld->max_length = ($zlen > 0) ? $zlen : 1;
00574                         } else {
00575                                 $fld->type = $type;
00576                                 $fld->max_length = -1;
00577                         }
00578                         $fld->not_null = ($rs->fields[2] != 'YES');
00579                         $fld->primary_key = ($rs->fields[3] == 'PRI');
00580                         $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
00581                         $fld->binary = (strpos($type,'blob') !== false);
00582                         $fld->unsigned = (strpos($type,'unsigned') !== false);
00583                         $fld->zerofill = (strpos($type,'zerofill') !== false);
00584 
00585                         if (!$fld->binary) {
00586                                 $d = $rs->fields[4];
00587                                 if ($d != '' && $d != 'NULL') {
00588                                         $fld->has_default = true;
00589                                         $fld->default_value = $d;
00590                                 } else {
00591                                         $fld->has_default = false;
00592                                 }
00593                         }
00594                         
00595                         if ($save == ADODB_FETCH_NUM) {
00596                                 $retarr[] = $fld;
00597                         } else {
00598                                 $retarr[strtoupper($fld->name)] = $fld;
00599                         }
00600                         $rs->MoveNext();
00601                 }
00602                 
00603                 $rs->Close();
00604                 return $retarr;
00605         }
00606                 
00607         // returns true or false
00608         function SelectDB($dbName) 
00609         {
00610 //          $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);
00611             $this->database = $dbName;
00612                 $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
00613                 
00614             if ($this->_connectionID) {
00615                 $result = @mysqli_select_db($this->_connectionID, $dbName);
00616                         if (!$result) {
00617                         ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg());
00618                         }
00619                         return $result;         
00620                 }
00621             return false;       
00622         }
00623         
00624         // parameters use PostgreSQL convention, not MySQL
00625         function SelectLimit($sql,
00626                               $nrows = -1,
00627                               $offset = -1,
00628                               $inputarr = false, 
00629                               $secs = 0)
00630         {
00631                 $offsetStr = ($offset >= 0) ? "$offset," : '';
00632                 if ($nrows < 0) $nrows = '18446744073709551615';
00633                 
00634                 if ($secs)
00635                         $rs = $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr );
00636                 else
00637                         $rs = $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr );
00638                         
00639                 return $rs;
00640         }
00641         
00642         
00643         function Prepare($sql)
00644         {
00645                 return $sql;
00646                 $stmt = $this->_connectionID->prepare($sql);
00647                 if (!$stmt) {
00648                         echo $this->ErrorMsg();
00649                         return $sql;
00650                 }
00651                 return array($sql,$stmt);
00652         }
00653         
00654         
00655         // returns queryID or false
00656         function _query($sql, $inputarr)
00657         {
00658         global $ADODB_COUNTRECS;
00659                 // Move to the next recordset, or return false if there is none. In a stored proc
00660                 // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
00661                 // returns false. I think this is because the last "recordset" is actually just the
00662                 // return value of the stored proc (ie the number of rows affected).
00663                 // Commented out for reasons of performance. You should retrieve every recordset yourself.
00664                 //      if (!mysqli_next_result($this->connection->_connectionID))      return false;
00665         
00666                 if (is_array($sql)) {
00667                 
00668                         // Prepare() not supported because mysqli_stmt_execute does not return a recordset, but
00669                         // returns as bound variables.
00670                 
00671                         $stmt = $sql[1];
00672                         $a = '';
00673                         foreach($inputarr as $k => $v) {
00674                                 if (is_string($v)) $a .= 's';
00675                                 else if (is_integer($v)) $a .= 'i'; 
00676                                 else $a .= 'd';
00677                         }
00678                         
00679                         $fnarr = array_merge( array($stmt,$a) , $inputarr);
00680                         $ret = call_user_func_array('mysqli_stmt_bind_param',$fnarr);
00681                         $ret = mysqli_stmt_execute($stmt);
00682                         return $ret;
00683                 }
00684                 
00685                 /*
00686                 if (!$mysql_res =  mysqli_query($this->_connectionID, $sql, ($ADODB_COUNTRECS) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT)) {
00687                     if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
00688                     return false;
00689                 }
00690                 
00691                 return $mysql_res;
00692                 */
00693                 
00694                 if ($this->multiQuery) {
00695                         $rs = mysqli_multi_query($this->_connectionID, $sql.';');
00696                         if ($rs) {
00697                                 $rs = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->_connectionID ) : @mysqli_use_result( $this->_connectionID );
00698                                 return $rs ? $rs : true; // mysqli_more_results( $this->_connectionID )
00699                         }
00700                 } else {
00701                         $rs = mysqli_query($this->_connectionID, $sql, $ADODB_COUNTRECS ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT);
00702                 
00703                         if ($rs) return $rs;
00704                 }
00705 
00706                 if($this->debug)
00707                         ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
00708                 
00709                 return false;
00710                 
00711         }
00712 
00713         /*      Returns: the last error message from previous database operation        */      
00714         function ErrorMsg() 
00715           {
00716             if (empty($this->_connectionID)) 
00717               $this->_errorMsg = @mysqli_connect_error();
00718             else 
00719               $this->_errorMsg = @mysqli_error($this->_connectionID);
00720             return $this->_errorMsg;
00721           }
00722         
00723         /*      Returns: the last error number from previous database operation */      
00724         function ErrorNo() 
00725           {
00726             if (empty($this->_connectionID))  
00727               return @mysqli_connect_errno();
00728             else 
00729               return @mysqli_errno($this->_connectionID);
00730           }
00731         
00732         // returns true or false
00733         function _close()
00734           {
00735             @mysqli_close($this->_connectionID);
00736             $this->_connectionID = false;
00737           }
00738 
00739         /*
00740         * Maximum size of C field
00741         */
00742         function CharMax()
00743         {
00744                 return 255; 
00745         }
00746         
00747         /*
00748         * Maximum size of X field
00749         */
00750         function TextMax()
00751         {
00752           return 4294967295; 
00753         }
00754 
00755 
00756 
00757         // this is a set of functions for managing client encoding - very important if the encodings
00758         // of your database and your output target (i.e. HTML) don't match
00759         // for instance, you may have UTF8 database and server it on-site as latin1 etc.
00760         // GetCharSet - get the name of the character set the client is using now
00761         // Under Windows, the functions should work with MySQL 4.1.11 and above, the set of charsets supported
00762         // depends on compile flags of mysql distribution 
00763 
00764   function GetCharSet()
00765   {
00766     //we will use ADO's builtin property charSet
00767     if (!method_exists($this->_connectionID,'character_set_name'))
00768         return false;
00769         
00770     $this->charSet = @$this->_connectionID->character_set_name();
00771     if (!$this->charSet) {
00772       return false;
00773     } else {
00774       return $this->charSet;
00775     }
00776   }
00777 
00778   // SetCharSet - switch the client encoding
00779   function SetCharSet($charset_name)
00780   {
00781     if (!method_exists($this->_connectionID,'set_charset'))
00782         return false;
00783 
00784     if ($this->charSet !== $charset_name) {
00785       $if = @$this->_connectionID->set_charset($charset_name);
00786       if ($if == "0" & $this->GetCharSet() == $charset_name) {
00787         return true;
00788       } else return false;
00789     } else return true;
00790   }
00791 
00792 
00793 
00794 
00795 }
00796  
00797 /*--------------------------------------------------------------------------------------
00798          Class Name: Recordset
00799 --------------------------------------------------------------------------------------*/
00800 
00801 class ADORecordSet_mysqli extends ADORecordSet{ 
00802         
00803         var $databaseType = "mysqli";
00804         var $canSeek = true;
00805         
00806         function ADORecordSet_mysqli($queryID, $mode = false) 
00807         {
00808           if ($mode === false) 
00809            { 
00810               global $ADODB_FETCH_MODE;
00811               $mode = $ADODB_FETCH_MODE;
00812            }
00813            
00814           switch ($mode)
00815             {
00816             case ADODB_FETCH_NUM: 
00817               $this->fetchMode = MYSQLI_NUM; 
00818               break;
00819             case ADODB_FETCH_ASSOC:
00820               $this->fetchMode = MYSQLI_ASSOC; 
00821               break;
00822             case ADODB_FETCH_DEFAULT:
00823             case ADODB_FETCH_BOTH:
00824             default:
00825               $this->fetchMode = MYSQLI_BOTH; 
00826               break;
00827             }
00828           $this->adodbFetchMode = $mode;
00829           $this->ADORecordSet($queryID);        
00830         }
00831         
00832         function _initrs()
00833         {
00834         global $ADODB_COUNTRECS;
00835         
00836                 $this->_numOfRows = $ADODB_COUNTRECS ? @mysqli_num_rows($this->_queryID) : -1;
00837                 $this->_numOfFields = @mysqli_num_fields($this->_queryID);
00838         }
00839         
00840 /*
00841 1      = MYSQLI_NOT_NULL_FLAG
00842 2      = MYSQLI_PRI_KEY_FLAG
00843 4      = MYSQLI_UNIQUE_KEY_FLAG
00844 8      = MYSQLI_MULTIPLE_KEY_FLAG
00845 16     = MYSQLI_BLOB_FLAG
00846 32     = MYSQLI_UNSIGNED_FLAG
00847 64     = MYSQLI_ZEROFILL_FLAG
00848 128    = MYSQLI_BINARY_FLAG
00849 256    = MYSQLI_ENUM_FLAG
00850 512    = MYSQLI_AUTO_INCREMENT_FLAG
00851 1024   = MYSQLI_TIMESTAMP_FLAG
00852 2048   = MYSQLI_SET_FLAG
00853 32768  = MYSQLI_NUM_FLAG
00854 16384  = MYSQLI_PART_KEY_FLAG
00855 32768  = MYSQLI_GROUP_FLAG
00856 65536  = MYSQLI_UNIQUE_FLAG
00857 131072 = MYSQLI_BINCMP_FLAG
00858 */
00859 
00860         function FetchField($fieldOffset = -1) 
00861         {       
00862                 $fieldnr = $fieldOffset;
00863                 if ($fieldOffset != -1) {
00864                   $fieldOffset = @mysqli_field_seek($this->_queryID, $fieldnr);
00865                 }
00866                 $o = @mysqli_fetch_field($this->_queryID);
00867                 if (!$o) return false;
00868                 /* Properties of an ADOFieldObject as set by MetaColumns */
00869                 $o->primary_key = $o->flags & MYSQLI_PRI_KEY_FLAG;
00870                 $o->not_null = $o->flags & MYSQLI_NOT_NULL_FLAG;
00871                 $o->auto_increment = $o->flags & MYSQLI_AUTO_INCREMENT_FLAG;
00872                 $o->binary = $o->flags & MYSQLI_BINARY_FLAG;
00873                 // $o->blob = $o->flags & MYSQLI_BLOB_FLAG; /* not returned by MetaColumns */
00874                 $o->unsigned = $o->flags & MYSQLI_UNSIGNED_FLAG;
00875 
00876                 return $o;
00877         }
00878 
00879         function GetRowAssoc($upper = true)
00880         {
00881                 if ($this->fetchMode == MYSQLI_ASSOC && !$upper) 
00882                   return $this->fields;
00883                 $row = ADORecordSet::GetRowAssoc($upper);
00884                 return $row;
00885         }
00886         
00887         /* Use associative array to get fields array */
00888         function Fields($colname)
00889         {       
00890           if ($this->fetchMode != MYSQLI_NUM) 
00891             return @$this->fields[$colname];
00892                 
00893           if (!$this->bind) {
00894             $this->bind = array();
00895             for ($i = 0; $i < $this->_numOfFields; $i++) {
00896               $o = $this->FetchField($i);
00897               $this->bind[strtoupper($o->name)] = $i;
00898             }
00899           }
00900           return $this->fields[$this->bind[strtoupper($colname)]];
00901         }
00902         
00903         function _seek($row)
00904         {
00905           if ($this->_numOfRows == 0) 
00906             return false;
00907 
00908           if ($row < 0)
00909             return false;
00910 
00911           mysqli_data_seek($this->_queryID, $row);
00912           $this->EOF = false;
00913           return true;
00914         }
00915                 
00916                 
00917         function NextRecordSet()
00918         {
00919         global $ADODB_COUNTRECS;
00920         
00921                 mysqli_free_result($this->_queryID);
00922                 $this->_queryID = -1;
00923                 // Move to the next recordset, or return false if there is none. In a stored proc
00924                 // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
00925                 // returns false. I think this is because the last "recordset" is actually just the
00926                 // return value of the stored proc (ie the number of rows affected).
00927                 if(!mysqli_next_result($this->connection->_connectionID)) {
00928                 return false;
00929                 }
00930                 // CD: There is no $this->_connectionID variable, at least in the ADO version I'm using
00931                 $this->_queryID = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->connection->_connectionID )
00932                                                 : @mysqli_use_result( $this->connection->_connectionID );
00933                 if(!$this->_queryID) {
00934                         return false;
00935                 }
00936                 $this->_inited = false;
00937                 $this->bind = false;
00938                 $this->_currentRow = -1;
00939                 $this->Init();
00940                 return true;
00941         }
00942 
00943         // 10% speedup to move MoveNext to child class
00944         // This is the only implementation that works now (23-10-2003).
00945         // Other functions return no or the wrong results.
00946         function MoveNext() 
00947         {
00948                 if ($this->EOF) return false;
00949                 $this->_currentRow++;
00950                 $this->fields = @mysqli_fetch_array($this->_queryID,$this->fetchMode);
00951                 
00952                 if (is_array($this->fields)) return true;
00953                 $this->EOF = true;
00954                 return false;
00955         }       
00956         
00957         function _fetch()
00958         {
00959                 $this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode);  
00960                 return is_array($this->fields);
00961         }
00962         
00963         function _close() 
00964         {
00965             //if results are attached to this pointer from Stored Proceedure calls, the next standard query will die 2014
00966         //only a problem with persistant connections
00967 
00968         //mysqli_next_result($this->connection->_connectionID); trashes the DB side attached results.
00969 
00970         while(mysqli_more_results($this->connection->_connectionID)){
00971            @mysqli_next_result($this->connection->_connectionID);
00972         }
00973 
00974         //Because you can have one attached result, without tripping mysqli_more_results
00975         @mysqli_next_result($this->connection->_connectionID);
00976 
00977 
00978                 mysqli_free_result($this->_queryID); 
00979                 $this->_queryID = false;        
00980         }
00981         
00982 /*
00983 
00984 0 = MYSQLI_TYPE_DECIMAL
00985 1 = MYSQLI_TYPE_CHAR
00986 1 = MYSQLI_TYPE_TINY
00987 2 = MYSQLI_TYPE_SHORT
00988 3 = MYSQLI_TYPE_LONG
00989 4 = MYSQLI_TYPE_FLOAT
00990 5 = MYSQLI_TYPE_DOUBLE
00991 6 = MYSQLI_TYPE_NULL
00992 7 = MYSQLI_TYPE_TIMESTAMP
00993 8 = MYSQLI_TYPE_LONGLONG
00994 9 = MYSQLI_TYPE_INT24
00995 10 = MYSQLI_TYPE_DATE
00996 11 = MYSQLI_TYPE_TIME
00997 12 = MYSQLI_TYPE_DATETIME
00998 13 = MYSQLI_TYPE_YEAR
00999 14 = MYSQLI_TYPE_NEWDATE
01000 247 = MYSQLI_TYPE_ENUM
01001 248 = MYSQLI_TYPE_SET
01002 249 = MYSQLI_TYPE_TINY_BLOB
01003 250 = MYSQLI_TYPE_MEDIUM_BLOB
01004 251 = MYSQLI_TYPE_LONG_BLOB
01005 252 = MYSQLI_TYPE_BLOB
01006 253 = MYSQLI_TYPE_VAR_STRING
01007 254 = MYSQLI_TYPE_STRING
01008 255 = MYSQLI_TYPE_GEOMETRY
01009 */
01010 
01011         function MetaType($t, $len = -1, $fieldobj = false)
01012         {
01013                 if (is_object($t)) {
01014                     $fieldobj = $t;
01015                     $t = $fieldobj->type;
01016                     $len = $fieldobj->max_length;
01017                 }
01018                 
01019                 
01020                  $len = -1; // mysql max_length is not accurate
01021                  switch (strtoupper($t)) {
01022                  case 'STRING': 
01023                  case 'CHAR':
01024                  case 'VARCHAR': 
01025                  case 'TINYBLOB': 
01026                  case 'TINYTEXT': 
01027                  case 'ENUM': 
01028                  case 'SET': 
01029                 
01030                 case MYSQLI_TYPE_TINY_BLOB :
01031                 #case MYSQLI_TYPE_CHAR :
01032                 case MYSQLI_TYPE_STRING :
01033                 case MYSQLI_TYPE_ENUM :
01034                 case MYSQLI_TYPE_SET :
01035                 case 253 :
01036                    if ($len <= $this->blobSize) return 'C';
01037                    
01038                 case 'TEXT':
01039                 case 'LONGTEXT': 
01040                 case 'MEDIUMTEXT':
01041                    return 'X';
01042                 
01043                 
01044                    // php_mysql extension always returns 'blob' even if 'text'
01045                    // so we have to check whether binary...
01046                 case 'IMAGE':
01047                 case 'LONGBLOB': 
01048                 case 'BLOB':
01049                 case 'MEDIUMBLOB':
01050                 
01051                 case MYSQLI_TYPE_BLOB :
01052                 case MYSQLI_TYPE_LONG_BLOB :
01053                 case MYSQLI_TYPE_MEDIUM_BLOB :
01054                 
01055                    return !empty($fieldobj->binary) ? 'B' : 'X';
01056                 case 'YEAR':
01057                 case 'DATE': 
01058                 case MYSQLI_TYPE_DATE :
01059                 case MYSQLI_TYPE_YEAR :
01060                 
01061                    return 'D';
01062                 
01063                 case 'TIME':
01064                 case 'DATETIME':
01065                 case 'TIMESTAMP':
01066                 
01067                 case MYSQLI_TYPE_DATETIME :
01068                 case MYSQLI_TYPE_NEWDATE :
01069                 case MYSQLI_TYPE_TIME :
01070                 case MYSQLI_TYPE_TIMESTAMP :
01071                 
01072                         return 'T';
01073                 
01074                 case 'INT': 
01075                 case 'INTEGER':
01076                 case 'BIGINT':
01077                 case 'TINYINT':
01078                 case 'MEDIUMINT':
01079                 case 'SMALLINT': 
01080                 
01081                 case MYSQLI_TYPE_INT24 :
01082                 case MYSQLI_TYPE_LONG :
01083                 case MYSQLI_TYPE_LONGLONG :
01084                 case MYSQLI_TYPE_SHORT :
01085                 case MYSQLI_TYPE_TINY :
01086                 
01087                    if (!empty($fieldobj->primary_key)) return 'R';
01088                    
01089                    return 'I';
01090                 
01091                 
01092                    // Added floating-point types
01093                    // Maybe not necessery.
01094                  case 'FLOAT':
01095                  case 'DOUBLE':
01096                    //           case 'DOUBLE PRECISION':
01097                  case 'DECIMAL':
01098                  case 'DEC':
01099                  case 'FIXED':
01100                  default:
01101                         //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>"; 
01102                         return 'N';
01103                 }
01104         } // function
01105         
01106 
01107 } // rs class
01108  
01109 }
01110 
01111 class ADORecordSet_array_mysqli extends ADORecordSet_array {
01112   
01113   function ADORecordSet_array_mysqli($id=-1,$mode=false) 
01114   {
01115     $this->ADORecordSet_array($id,$mode);
01116   }
01117   
01118         function MetaType($t, $len = -1, $fieldobj = false)
01119         {
01120                 if (is_object($t)) {
01121                     $fieldobj = $t;
01122                     $t = $fieldobj->type;
01123                     $len = $fieldobj->max_length;
01124                 }
01125                 
01126                 
01127                  $len = -1; // mysql max_length is not accurate
01128                  switch (strtoupper($t)) {
01129                  case 'STRING': 
01130                  case 'CHAR':
01131                  case 'VARCHAR': 
01132                  case 'TINYBLOB': 
01133                  case 'TINYTEXT': 
01134                  case 'ENUM': 
01135                  case 'SET': 
01136                 
01137                 case MYSQLI_TYPE_TINY_BLOB :
01138                 #case MYSQLI_TYPE_CHAR :
01139                 case MYSQLI_TYPE_STRING :
01140                 case MYSQLI_TYPE_ENUM :
01141                 case MYSQLI_TYPE_SET :
01142                 case 253 :
01143                    if ($len <= $this->blobSize) return 'C';
01144                    
01145                 case 'TEXT':
01146                 case 'LONGTEXT': 
01147                 case 'MEDIUMTEXT':
01148                    return 'X';
01149                 
01150                 
01151                    // php_mysql extension always returns 'blob' even if 'text'
01152                    // so we have to check whether binary...
01153                 case 'IMAGE':
01154                 case 'LONGBLOB': 
01155                 case 'BLOB':
01156                 case 'MEDIUMBLOB':
01157                 
01158                 case MYSQLI_TYPE_BLOB :
01159                 case MYSQLI_TYPE_LONG_BLOB :
01160                 case MYSQLI_TYPE_MEDIUM_BLOB :
01161                 
01162                    return !empty($fieldobj->binary) ? 'B' : 'X';
01163                 case 'YEAR':
01164                 case 'DATE': 
01165                 case MYSQLI_TYPE_DATE :
01166                 case MYSQLI_TYPE_YEAR :
01167                 
01168                    return 'D';
01169                 
01170                 case 'TIME':
01171                 case 'DATETIME':
01172                 case 'TIMESTAMP':
01173                 
01174                 case MYSQLI_TYPE_DATETIME :
01175                 case MYSQLI_TYPE_NEWDATE :
01176                 case MYSQLI_TYPE_TIME :
01177                 case MYSQLI_TYPE_TIMESTAMP :
01178                 
01179                         return 'T';
01180                 
01181                 case 'INT': 
01182                 case 'INTEGER':
01183                 case 'BIGINT':
01184                 case 'TINYINT':
01185                 case 'MEDIUMINT':
01186                 case 'SMALLINT': 
01187                 
01188                 case MYSQLI_TYPE_INT24 :
01189                 case MYSQLI_TYPE_LONG :
01190                 case MYSQLI_TYPE_LONGLONG :
01191                 case MYSQLI_TYPE_SHORT :
01192                 case MYSQLI_TYPE_TINY :
01193                 
01194                    if (!empty($fieldobj->primary_key)) return 'R';
01195                    
01196                    return 'I';
01197                 
01198                 
01199                    // Added floating-point types
01200                    // Maybe not necessery.
01201                  case 'FLOAT':
01202                  case 'DOUBLE':
01203                    //           case 'DOUBLE PRECISION':
01204                  case 'DECIMAL':
01205                  case 'DEC':
01206                  case 'FIXED':
01207                  default:
01208                         //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>"; 
01209                         return 'N';
01210                 }
01211         } // function
01212   
01213 }
01214 
01215 ?>
 All Data Structures Namespaces Files Functions Variables Enumerations