[ Index ]

PHP Cross Reference of MantisBT

title

Body

[close]

/library/adodb/drivers/ -> adodb-mysqli.inc.php (source)

   1  <?php
   2  /*
   3  V5.11 5 May 2010   (c) 2000-2010 John Lim (jlim#natsoft.com). All rights reserved.
   4    Released under both BSD license and Lesser GPL library license. 
   5    Whenever there is any discrepancy between the two licenses, 
   6    the BSD license will take precedence.
   7    Set tabs to 8.
   8    
   9    MySQL code that does not support transactions. Use mysqlt if you need transactions.
  10    Requires mysql client. Works on Windows and Unix.
  11   
  12  21 October 2003: MySQLi extension implementation by Arjen de Rijke (a.de.rijke@xs4all.nl)
  13  Based on adodb 3.40
  14  */ 
  15  
  16  // security - hide paths
  17  if (!defined('ADODB_DIR')) die();
  18  
  19  if (! defined("_ADODB_MYSQLI_LAYER")) {
  20   define("_ADODB_MYSQLI_LAYER", 1 );
  21   
  22   // PHP5 compat...
  23   if (! defined("MYSQLI_BINARY_FLAG"))  define("MYSQLI_BINARY_FLAG", 128); 
  24   if (!defined('MYSQLI_READ_DEFAULT_GROUP')) define('MYSQLI_READ_DEFAULT_GROUP',1);
  25  
  26   // disable adodb extension - currently incompatible.
  27   global $ADODB_EXTENSION; $ADODB_EXTENSION = false;
  28  
  29  class ADODB_mysqli extends ADOConnection {
  30      var $databaseType = 'mysqli';
  31      var $dataProvider = 'native';
  32      var $hasInsertID = true;
  33      var $hasAffectedRows = true;    
  34      var $metaTablesSQL = "SHOW TABLES";    
  35      var $metaColumnsSQL = "SHOW COLUMNS FROM `%s`";
  36      var $fmtTimeStamp = "'Y-m-d H:i:s'";
  37      var $hasLimit = true;
  38      var $hasMoveFirst = true;
  39      var $hasGenID = true;
  40      var $isoDates = true; // accepts dates in ISO format
  41      var $sysDate = 'CURDATE()';
  42      var $sysTimeStamp = 'NOW()';
  43      var $hasTransactions = true;
  44      var $forceNewConnect = false;
  45      var $poorAffectedRows = true;
  46      var $clientFlags = 0;
  47      var $substr = "substring";
  48      var $port = false;
  49      var $socket = false;
  50      var $_bindInputArray = false;
  51      var $nameQuote = '`';        /// string to use to quote identifiers and names
  52      var $optionFlags = array(array(MYSQLI_READ_DEFAULT_GROUP,0));
  53        var $arrayClass = 'ADORecordSet_array_mysqli';
  54        var $multiQuery = false;
  55      
  56  	function ADODB_mysqli() 
  57      {            
  58       // if(!extension_loaded("mysqli"))
  59            ;//trigger_error("You must have the mysqli extension installed.", E_USER_ERROR);
  60          
  61      }
  62      
  63  	function SetTransactionMode( $transaction_mode ) 
  64      {
  65          $this->_transmode  = $transaction_mode;
  66          if (empty($transaction_mode)) {
  67              $this->Execute('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ');
  68              return;
  69          }
  70          if (!stristr($transaction_mode,'isolation')) $transaction_mode = 'ISOLATION LEVEL '.$transaction_mode;
  71          $this->Execute("SET SESSION TRANSACTION ".$transaction_mode);
  72      }
  73  
  74      // returns true or false
  75      // To add: parameter int $port,
  76      //         parameter string $socket
  77  	function _connect($argHostname = NULL, 
  78                $argUsername = NULL, 
  79                $argPassword = NULL, 
  80                $argDatabasename = NULL, $persist=false)
  81        {
  82             if(!extension_loaded("mysqli")) {
  83              return null;
  84           }
  85          $this->_connectionID = @mysqli_init();
  86          
  87          if (is_null($this->_connectionID)) {
  88            // mysqli_init only fails if insufficient memory
  89            if ($this->debug) 
  90                  ADOConnection::outp("mysqli_init() failed : "  . $this->ErrorMsg());
  91            return false;
  92          }
  93          /*
  94          I suggest a simple fix which would enable adodb and mysqli driver to
  95          read connection options from the standard mysql configuration file
  96          /etc/my.cnf - "Bastien Duclaux" <bduclaux#yahoo.com>
  97          */
  98          foreach($this->optionFlags as $arr) {    
  99              mysqli_options($this->_connectionID,$arr[0],$arr[1]);
 100          }
 101  
 102          #if (!empty($this->port)) $argHostname .= ":".$this->port;
 103          $ok = mysqli_real_connect($this->_connectionID,
 104                       $argHostname,
 105                       $argUsername,
 106                       $argPassword,
 107                       $argDatabasename,
 108                      $this->port,
 109                      $this->socket,
 110                      $this->clientFlags);
 111            
 112          if ($ok) {
 113               if ($argDatabasename)  return $this->SelectDB($argDatabasename);
 114               return true;
 115          } else {
 116              if ($this->debug) 
 117                    ADOConnection::outp("Could't connect : "  . $this->ErrorMsg());
 118              $this->_connectionID = null;
 119              return false;
 120         }
 121      }
 122      
 123      // returns true or false
 124      // How to force a persistent connection
 125  	function _pconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
 126      {
 127          return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename, true);
 128  
 129      }
 130      
 131      // When is this used? Close old connection first?
 132      // In _connect(), check $this->forceNewConnect? 
 133  	function _nconnect($argHostname, $argUsername, $argPassword, $argDatabasename)
 134        {
 135          $this->forceNewConnect = true;
 136          return $this->_connect($argHostname, $argUsername, $argPassword, $argDatabasename);
 137        }
 138      
 139  	function IfNull( $field, $ifNull ) 
 140      {
 141          return " IFNULL($field, $ifNull) "; // if MySQL
 142      }
 143      
 144      // do not use $ADODB_COUNTRECS
 145  	function GetOne($sql,$inputarr=false)
 146      {
 147          $ret = false;
 148          $rs = $this->Execute($sql,$inputarr);
 149          if ($rs) {    
 150              if (!$rs->EOF) $ret = reset($rs->fields);
 151              $rs->Close();
 152          }
 153          return $ret;
 154      }
 155      
 156  	function ServerInfo()
 157      {
 158          $arr['description'] = $this->GetOne("select version()");
 159          $arr['version'] = ADOConnection::_findvers($arr['description']);
 160          return $arr;
 161      }
 162      
 163      
 164  	function BeginTrans()
 165      {      
 166          if ($this->transOff) return true;
 167          $this->transCnt += 1;
 168          
 169          //$this->Execute('SET AUTOCOMMIT=0');
 170          mysqli_autocommit($this->_connectionID, false);
 171          $this->Execute('BEGIN');
 172          return true;
 173      }
 174      
 175  	function CommitTrans($ok=true) 
 176      {
 177          if ($this->transOff) return true; 
 178          if (!$ok) return $this->RollbackTrans();
 179          
 180          if ($this->transCnt) $this->transCnt -= 1;
 181          $this->Execute('COMMIT');
 182          
 183          //$this->Execute('SET AUTOCOMMIT=1');
 184          mysqli_autocommit($this->_connectionID, true);
 185          return true;
 186      }
 187      
 188  	function RollbackTrans()
 189      {
 190          if ($this->transOff) return true;
 191          if ($this->transCnt) $this->transCnt -= 1;
 192          $this->Execute('ROLLBACK');
 193          //$this->Execute('SET AUTOCOMMIT=1');
 194          mysqli_autocommit($this->_connectionID, true);
 195          return true;
 196      }
 197      
 198  	function RowLock($tables,$where='',$col='1 as adodbignore') 
 199      {
 200          if ($this->transCnt==0) $this->BeginTrans();
 201          if ($where) $where = ' where '.$where;
 202          $rs = $this->Execute("select $col from $tables $where for update");
 203          return !empty($rs); 
 204      }
 205      
 206      // if magic quotes disabled, use mysql_real_escape_string()
 207      // From readme.htm:
 208      // Quotes a string to be sent to the database. The $magic_quotes_enabled
 209      // parameter may look funny, but the idea is if you are quoting a 
 210      // string extracted from a POST/GET variable, then 
 211      // pass get_magic_quotes_gpc() as the second parameter. This will 
 212      // ensure that the variable is not quoted twice, once by qstr and once 
 213      // by the magic_quotes_gpc.
 214      //
 215      //Eg. $s = $db->qstr(_GET['name'],get_magic_quotes_gpc());
 216  	function qstr($s, $magic_quotes = false)
 217      {
 218          if (is_null($s)) return 'NULL';
 219          if (!$magic_quotes) {
 220              if (PHP_VERSION >= 5)
 221                    return "'" . mysqli_real_escape_string($this->_connectionID, $s) . "'";   
 222          
 223          if ($this->replaceQuote[0] == '\\')
 224              $s = adodb_str_replace(array('\\',"\0"),array('\\\\',"\\\0"),$s);
 225          return  "'".str_replace("'",$this->replaceQuote,$s)."'"; 
 226        }
 227        // undo magic quotes for "
 228        $s = str_replace('\\"','"',$s);
 229        return "'$s'";
 230      }
 231      
 232  	function _insertid()
 233      {
 234        $result = @mysqli_insert_id($this->_connectionID);
 235        if ($result == -1){
 236            if ($this->debug) ADOConnection::outp("mysqli_insert_id() failed : "  . $this->ErrorMsg());
 237        }
 238        return $result;
 239      }
 240      
 241      // Only works for INSERT, UPDATE and DELETE query's
 242  	function _affectedrows()
 243      {
 244        $result =  @mysqli_affected_rows($this->_connectionID);
 245        if ($result == -1) {
 246            if ($this->debug) ADOConnection::outp("mysqli_affected_rows() failed : "  . $this->ErrorMsg());
 247        }
 248        return $result;
 249      }
 250    
 251       // See http://www.mysql.com/doc/M/i/Miscellaneous_functions.html
 252      // Reference on Last_Insert_ID on the recommended way to simulate sequences
 253       var $_genIDSQL = "update %s set id=LAST_INSERT_ID(id+1);";
 254      var $_genSeqSQL = "create table %s (id int not null)";
 255      var $_genSeqCountSQL = "select count(*) from %s";
 256      var $_genSeq2SQL = "insert into %s values (%s)";
 257      var $_dropSeqSQL = "drop table %s";
 258      
 259  	function CreateSequence($seqname='adodbseq',$startID=1)
 260      {
 261          if (empty($this->_genSeqSQL)) return false;
 262          $u = strtoupper($seqname);
 263          
 264          $ok = $this->Execute(sprintf($this->_genSeqSQL,$seqname));
 265          if (!$ok) return false;
 266          return $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
 267      }
 268      
 269  	function GenID($seqname='adodbseq',$startID=1)
 270      {
 271          // post-nuke sets hasGenID to false
 272          if (!$this->hasGenID) return false;
 273          
 274          $getnext = sprintf($this->_genIDSQL,$seqname);
 275          $holdtransOK = $this->_transOK; // save the current status
 276          $rs = @$this->Execute($getnext);
 277          if (!$rs) {
 278              if ($holdtransOK) $this->_transOK = true; //if the status was ok before reset
 279              $u = strtoupper($seqname);
 280              $this->Execute(sprintf($this->_genSeqSQL,$seqname));
 281              $cnt = $this->GetOne(sprintf($this->_genSeqCountSQL,$seqname));
 282              if (!$cnt) $this->Execute(sprintf($this->_genSeq2SQL,$seqname,$startID-1));
 283              $rs = $this->Execute($getnext);
 284          }
 285          
 286          if ($rs) {
 287              $this->genID = mysqli_insert_id($this->_connectionID);
 288              $rs->Close();
 289          } else
 290              $this->genID = 0;
 291              
 292          return $this->genID;
 293      }
 294      
 295    	function MetaDatabases()
 296      {
 297          $query = "SHOW DATABASES";
 298          $ret = $this->Execute($query);
 299          if ($ret && is_object($ret)){
 300             $arr = array();
 301              while (!$ret->EOF){
 302                  $db = $ret->Fields('Database');
 303                  if ($db != 'mysql') $arr[] = $db;
 304                  $ret->MoveNext();
 305              }
 306                return $arr;
 307          }
 308          return $ret;
 309      }
 310  
 311        
 312  	function MetaIndexes ($table, $primary = FALSE, $owner = false)
 313      {
 314          // save old fetch mode
 315          global $ADODB_FETCH_MODE;
 316          
 317          $false = false;
 318          $save = $ADODB_FETCH_MODE;
 319          $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 320          if ($this->fetchMode !== FALSE) {
 321                 $savem = $this->SetFetchMode(FALSE);
 322          }
 323          
 324          // get index details
 325          $rs = $this->Execute(sprintf('SHOW INDEXES FROM %s',$table));
 326          
 327          // restore fetchmode
 328          if (isset($savem)) {
 329                  $this->SetFetchMode($savem);
 330          }
 331          $ADODB_FETCH_MODE = $save;
 332          
 333          if (!is_object($rs)) {
 334                  return $false;
 335          }
 336          
 337          $indexes = array ();
 338          
 339          // parse index data into array
 340          while ($row = $rs->FetchRow()) {
 341                  if ($primary == FALSE AND $row[2] == 'PRIMARY') {
 342                          continue;
 343                  }
 344                  
 345                  if (!isset($indexes[$row[2]])) {
 346                          $indexes[$row[2]] = array(
 347                                  'unique' => ($row[1] == 0),
 348                                  'columns' => array()
 349                          );
 350                  }
 351                  
 352                  $indexes[$row[2]]['columns'][$row[3] - 1] = $row[4];
 353          }
 354          
 355          // sort columns by order in the index
 356          foreach ( array_keys ($indexes) as $index )
 357          {
 358                  ksort ($indexes[$index]['columns']);
 359          }
 360          
 361          return $indexes;
 362      }
 363  
 364      
 365      // Format date column in sql string given an input format that understands Y M D
 366  	function SQLDate($fmt, $col=false)
 367      {    
 368          if (!$col) $col = $this->sysTimeStamp;
 369          $s = 'DATE_FORMAT('.$col.",'";
 370          $concat = false;
 371          $len = strlen($fmt);
 372          for ($i=0; $i < $len; $i++) {
 373              $ch = $fmt[$i];
 374              switch($ch) {
 375              case 'Y':
 376              case 'y':
 377                  $s .= '%Y';
 378                  break;
 379              case 'Q':
 380              case 'q':
 381                  $s .= "'),Quarter($col)";
 382                  
 383                  if ($len > $i+1) $s .= ",DATE_FORMAT($col,'";
 384                  else $s .= ",('";
 385                  $concat = true;
 386                  break;
 387              case 'M':
 388                  $s .= '%b';
 389                  break;
 390                  
 391              case 'm':
 392                  $s .= '%m';
 393                  break;
 394              case 'D':
 395              case 'd':
 396                  $s .= '%d';
 397                  break;
 398              
 399              case 'H': 
 400                  $s .= '%H';
 401                  break;
 402                  
 403              case 'h':
 404                  $s .= '%I';
 405                  break;
 406                  
 407              case 'i':
 408                  $s .= '%i';
 409                  break;
 410                  
 411              case 's':
 412                  $s .= '%s';
 413                  break;
 414                  
 415              case 'a':
 416              case 'A':
 417                  $s .= '%p';
 418                  break;
 419              
 420              case 'w':
 421                  $s .= '%w';
 422                  break;
 423                  
 424              case 'l':
 425                  $s .= '%W';
 426                  break;
 427                  
 428              default:
 429                  
 430                  if ($ch == '\\') {
 431                      $i++;
 432                      $ch = substr($fmt,$i,1);
 433                  }
 434                  $s .= $ch;
 435                  break;
 436              }
 437          }
 438          $s.="')";
 439          if ($concat) $s = "CONCAT($s)";
 440          return $s;
 441      }
 442      
 443      // returns concatenated string
 444      // much easier to run "mysqld --ansi" or "mysqld --sql-mode=PIPES_AS_CONCAT" and use || operator
 445  	function Concat()
 446      {
 447          $s = "";
 448          $arr = func_get_args();
 449          
 450          // suggestion by andrew005@mnogo.ru
 451          $s = implode(',',$arr); 
 452          if (strlen($s) > 0) return "CONCAT($s)";
 453          else return '';
 454      }
 455      
 456      // dayFraction is a day in floating point
 457  	function OffsetDate($dayFraction,$date=false)
 458      {        
 459          if (!$date) $date = $this->sysDate;
 460          
 461          $fraction = $dayFraction * 24 * 3600;
 462          return $date . ' + INTERVAL ' .     $fraction.' SECOND';
 463          
 464  //        return "from_unixtime(unix_timestamp($date)+$fraction)";
 465      }
 466      
 467  	function MetaTables($ttype=false,$showSchema=false,$mask=false) 
 468      {    
 469          $save = $this->metaTablesSQL;
 470          if ($showSchema && is_string($showSchema)) {
 471              $this->metaTablesSQL .= " from $showSchema";
 472          }
 473          
 474          if ($mask) {
 475              $mask = $this->qstr($mask);
 476              $this->metaTablesSQL .= " like $mask";
 477          }
 478          $ret = ADOConnection::MetaTables($ttype,$showSchema);
 479          
 480          $this->metaTablesSQL = $save;
 481          return $ret;
 482      }
 483      
 484      // "Innox - Juan Carlos Gonzalez" <jgonzalez#innox.com.mx>
 485  	function MetaForeignKeys( $table, $owner = FALSE, $upper = FALSE, $associative = FALSE )
 486      {
 487       global $ADODB_FETCH_MODE;
 488          
 489          if ($ADODB_FETCH_MODE == ADODB_FETCH_ASSOC || $this->fetchMode == ADODB_FETCH_ASSOC) $associative = true;
 490          
 491          if ( !empty($owner) ) {
 492             $table = "$owner.$table";
 493          }
 494          $a_create_table = $this->getRow(sprintf('SHOW CREATE TABLE %s', $table));
 495          if ($associative) {
 496              $create_sql = isset($a_create_table["Create Table"]) ? $a_create_table["Create Table"] : $a_create_table["Create View"];
 497          } else $create_sql  = $a_create_table[1];
 498      
 499          $matches = array();
 500      
 501          if (!preg_match_all("/FOREIGN KEY \(`(.*?)`\) REFERENCES `(.*?)` \(`(.*?)`\)/", $create_sql, $matches)) return false;
 502           $foreign_keys = array();          
 503          $num_keys = count($matches[0]);
 504          for ( $i = 0;  $i < $num_keys;  $i ++ ) {
 505              $my_field  = explode('`, `', $matches[1][$i]);
 506              $ref_table = $matches[2][$i];
 507              $ref_field = explode('`, `', $matches[3][$i]);
 508      
 509              if ( $upper ) {
 510                  $ref_table = strtoupper($ref_table);
 511              }
 512      
 513              // see https://sourceforge.net/tracker/index.php?func=detail&aid=2287278&group_id=42718&atid=433976
 514              if (!isset($foreign_keys[$ref_table])) {
 515                  $foreign_keys[$ref_table] = array();
 516              }
 517              $num_fields = count($my_field);
 518              for ( $j = 0;  $j < $num_fields;  $j ++ ) {
 519                  if ( $associative ) {
 520                      $foreign_keys[$ref_table][$ref_field[$j]] = $my_field[$j];
 521                  } else {
 522                      $foreign_keys[$ref_table][] = "{$my_field[$j]}={$ref_field[$j]}";
 523                  }
 524              }
 525          }
 526          
 527          return  $foreign_keys;
 528      }
 529      
 530   	function MetaColumns($table, $normalize=true) 
 531      {
 532          $false = false;
 533          if (!$this->metaColumnsSQL)
 534              return $false;
 535          
 536          global $ADODB_FETCH_MODE;
 537          $save = $ADODB_FETCH_MODE;
 538          $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
 539          if ($this->fetchMode !== false)
 540              $savem = $this->SetFetchMode(false);
 541          $rs = $this->Execute(sprintf($this->metaColumnsSQL,$table));
 542          if (isset($savem)) $this->SetFetchMode($savem);
 543          $ADODB_FETCH_MODE = $save;
 544          if (!is_object($rs))
 545              return $false;
 546          
 547          $retarr = array();
 548          while (!$rs->EOF) {
 549              $fld = new ADOFieldObject();
 550              $fld->name = $rs->fields[0];
 551              $type = $rs->fields[1];
 552              
 553              // split type into type(length):
 554              $fld->scale = null;
 555              if (preg_match("/^(.+)\((\d+),(\d+)/", $type, $query_array)) {
 556                  $fld->type = $query_array[1];
 557                  $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
 558                  $fld->scale = is_numeric($query_array[3]) ? $query_array[3] : -1;
 559              } elseif (preg_match("/^(.+)\((\d+)/", $type, $query_array)) {
 560                  $fld->type = $query_array[1];
 561                  $fld->max_length = is_numeric($query_array[2]) ? $query_array[2] : -1;
 562              } elseif (preg_match("/^(enum)\((.*)\)$/i", $type, $query_array)) {
 563                  $fld->type = $query_array[1];
 564                  $arr = explode(",",$query_array[2]);
 565                  $fld->enums = $arr;
 566                  $zlen = max(array_map("strlen",$arr)) - 2; // PHP >= 4.0.6
 567                  $fld->max_length = ($zlen > 0) ? $zlen : 1;
 568              } else {
 569                  $fld->type = $type;
 570                  $fld->max_length = -1;
 571              }
 572              $fld->not_null = ($rs->fields[2] != 'YES');
 573              $fld->primary_key = ($rs->fields[3] == 'PRI');
 574              $fld->auto_increment = (strpos($rs->fields[5], 'auto_increment') !== false);
 575              $fld->binary = (strpos($type,'blob') !== false);
 576              $fld->unsigned = (strpos($type,'unsigned') !== false);
 577              $fld->zerofill = (strpos($type,'zerofill') !== false);
 578  
 579              if (!$fld->binary) {
 580                  $d = $rs->fields[4];
 581                  if ($d != '' && $d != 'NULL') {
 582                      $fld->has_default = true;
 583                      $fld->default_value = $d;
 584                  } else {
 585                      $fld->has_default = false;
 586                  }
 587              }
 588              
 589              if ($save == ADODB_FETCH_NUM) {
 590                  $retarr[] = $fld;
 591              } else {
 592                  $retarr[strtoupper($fld->name)] = $fld;
 593              }
 594              $rs->MoveNext();
 595          }
 596          
 597          $rs->Close();
 598          return $retarr;
 599      }
 600          
 601      // returns true or false
 602  	function SelectDB($dbName) 
 603      {
 604  //        $this->_connectionID = $this->mysqli_resolve_link($this->_connectionID);
 605          $this->database = $dbName;
 606          $this->databaseName = $dbName; # obsolete, retained for compat with older adodb versions
 607          
 608          if ($this->_connectionID) {
 609              $result = @mysqli_select_db($this->_connectionID, $dbName);
 610              if (!$result) {
 611                  ADOConnection::outp("Select of database " . $dbName . " failed. " . $this->ErrorMsg());
 612              }
 613              return $result;        
 614          }
 615          return false;    
 616      }
 617      
 618      // parameters use PostgreSQL convention, not MySQL
 619  	function SelectLimit($sql,
 620                    $nrows = -1,
 621                    $offset = -1,
 622                    $inputarr = false, 
 623                    $secs = 0)
 624      {
 625          $offsetStr = ($offset >= 0) ? "$offset," : '';
 626          if ($nrows < 0) $nrows = '18446744073709551615';
 627          
 628          if ($secs)
 629              $rs = $this->CacheExecute($secs, $sql . " LIMIT $offsetStr$nrows" , $inputarr );
 630          else
 631              $rs = $this->Execute($sql . " LIMIT $offsetStr$nrows" , $inputarr );
 632              
 633          return $rs;
 634      }
 635      
 636      
 637  	function Prepare($sql)
 638      {
 639          return $sql;
 640          $stmt = $this->_connectionID->prepare($sql);
 641          if (!$stmt) {
 642              echo $this->ErrorMsg();
 643              return $sql;
 644          }
 645          return array($sql,$stmt);
 646      }
 647      
 648      
 649      // returns queryID or false
 650  	function _query($sql, $inputarr)
 651      {
 652      global $ADODB_COUNTRECS;
 653          // Move to the next recordset, or return false if there is none. In a stored proc
 654          // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
 655          // returns false. I think this is because the last "recordset" is actually just the
 656          // return value of the stored proc (ie the number of rows affected).
 657          // Commented out for reasons of performance. You should retrieve every recordset yourself.
 658          //    if (!mysqli_next_result($this->connection->_connectionID))    return false;
 659      
 660          if (is_array($sql)) {
 661          
 662              // Prepare() not supported because mysqli_stmt_execute does not return a recordset, but
 663              // returns as bound variables.
 664          
 665              $stmt = $sql[1];
 666              $a = '';
 667              foreach($inputarr as $k => $v) {
 668                  if (is_string($v)) $a .= 's';
 669                  else if (is_integer($v)) $a .= 'i'; 
 670                  else $a .= 'd';
 671              }
 672              
 673              $fnarr = array_merge( array($stmt,$a) , $inputarr);
 674              $ret = call_user_func_array('mysqli_stmt_bind_param',$fnarr);
 675              $ret = mysqli_stmt_execute($stmt);
 676              return $ret;
 677          }
 678          
 679          /*
 680          if (!$mysql_res =  mysqli_query($this->_connectionID, $sql, ($ADODB_COUNTRECS) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT)) {
 681              if ($this->debug) ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
 682              return false;
 683          }
 684          
 685          return $mysql_res;
 686          */
 687          
 688          if ($this->multiQuery) {
 689              $rs = mysqli_multi_query($this->_connectionID, $sql.';');
 690              if ($rs) {
 691                  $rs = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->_connectionID ) : @mysqli_use_result( $this->_connectionID );
 692                  return $rs ? $rs : true; // mysqli_more_results( $this->_connectionID )
 693              }
 694          } else {
 695              $rs = mysqli_query($this->_connectionID, $sql, $ADODB_COUNTRECS ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT);
 696          
 697              if ($rs) return $rs;
 698          }
 699  
 700          if($this->debug)
 701              ADOConnection::outp("Query: " . $sql . " failed. " . $this->ErrorMsg());
 702          
 703          return false;
 704          
 705      }
 706  
 707      /*    Returns: the last error message from previous database operation    */    
 708  	function ErrorMsg() 
 709        {
 710          if (empty($this->_connectionID)) 
 711            $this->_errorMsg = @mysqli_connect_error();
 712          else 
 713            $this->_errorMsg = @mysqli_error($this->_connectionID);
 714          return $this->_errorMsg;
 715        }
 716      
 717      /*    Returns: the last error number from previous database operation    */    
 718  	function ErrorNo() 
 719        {
 720          if (empty($this->_connectionID))  
 721            return @mysqli_connect_errno();
 722          else 
 723            return @mysqli_errno($this->_connectionID);
 724        }
 725      
 726      // returns true or false
 727  	function _close()
 728        {
 729          @mysqli_close($this->_connectionID);
 730          $this->_connectionID = false;
 731        }
 732  
 733      /*
 734      * Maximum size of C field
 735      */
 736  	function CharMax()
 737      {
 738          return 255; 
 739      }
 740      
 741      /*
 742      * Maximum size of X field
 743      */
 744  	function TextMax()
 745      {
 746        return 4294967295; 
 747      }
 748  
 749  
 750  
 751      // this is a set of functions for managing client encoding - very important if the encodings
 752      // of your database and your output target (i.e. HTML) don't match
 753      // for instance, you may have UTF8 database and server it on-site as latin1 etc.
 754      // GetCharSet - get the name of the character set the client is using now
 755      // Under Windows, the functions should work with MySQL 4.1.11 and above, the set of charsets supported
 756      // depends on compile flags of mysql distribution 
 757  
 758    function GetCharSet()
 759    {
 760      //we will use ADO's builtin property charSet
 761      if (!method_exists($this->_connectionID,'character_set_name'))
 762          return false;
 763          
 764      $this->charSet = @$this->_connectionID->character_set_name();
 765      if (!$this->charSet) {
 766        return false;
 767      } else {
 768        return $this->charSet;
 769      }
 770    }
 771  
 772    // SetCharSet - switch the client encoding
 773    function SetCharSet($charset_name)
 774    {
 775      if (!method_exists($this->_connectionID,'set_charset'))
 776          return false;
 777  
 778      if ($this->charSet !== $charset_name) {
 779        $if = @$this->_connectionID->set_charset($charset_name);
 780        if ($if == "0" & $this->GetCharSet() == $charset_name) {
 781          return true;
 782        } else return false;
 783      } else return true;
 784    }
 785  
 786  
 787  
 788  
 789  }
 790   
 791  /*--------------------------------------------------------------------------------------
 792       Class Name: Recordset
 793  --------------------------------------------------------------------------------------*/
 794  
 795  class ADORecordSet_mysqli extends ADORecordSet{    
 796      
 797      var $databaseType = "mysqli";
 798      var $canSeek = true;
 799      
 800  	function ADORecordSet_mysqli($queryID, $mode = false) 
 801      {
 802        if ($mode === false) 
 803         { 
 804            global $ADODB_FETCH_MODE;
 805            $mode = $ADODB_FETCH_MODE;
 806         }
 807         
 808        switch ($mode)
 809          {
 810          case ADODB_FETCH_NUM: 
 811            $this->fetchMode = MYSQLI_NUM; 
 812            break;
 813          case ADODB_FETCH_ASSOC:
 814            $this->fetchMode = MYSQLI_ASSOC; 
 815            break;
 816          case ADODB_FETCH_DEFAULT:
 817          case ADODB_FETCH_BOTH:
 818          default:
 819            $this->fetchMode = MYSQLI_BOTH; 
 820            break;
 821          }
 822        $this->adodbFetchMode = $mode;
 823        $this->ADORecordSet($queryID);    
 824      }
 825      
 826  	function _initrs()
 827      {
 828      global $ADODB_COUNTRECS;
 829      
 830          $this->_numOfRows = $ADODB_COUNTRECS ? @mysqli_num_rows($this->_queryID) : -1;
 831          $this->_numOfFields = @mysqli_num_fields($this->_queryID);
 832      }
 833      
 834  /*
 835  1      = MYSQLI_NOT_NULL_FLAG
 836  2      = MYSQLI_PRI_KEY_FLAG
 837  4      = MYSQLI_UNIQUE_KEY_FLAG
 838  8      = MYSQLI_MULTIPLE_KEY_FLAG
 839  16     = MYSQLI_BLOB_FLAG
 840  32     = MYSQLI_UNSIGNED_FLAG
 841  64     = MYSQLI_ZEROFILL_FLAG
 842  128    = MYSQLI_BINARY_FLAG
 843  256    = MYSQLI_ENUM_FLAG
 844  512    = MYSQLI_AUTO_INCREMENT_FLAG
 845  1024   = MYSQLI_TIMESTAMP_FLAG
 846  2048   = MYSQLI_SET_FLAG
 847  32768  = MYSQLI_NUM_FLAG
 848  16384  = MYSQLI_PART_KEY_FLAG
 849  32768  = MYSQLI_GROUP_FLAG
 850  65536  = MYSQLI_UNIQUE_FLAG
 851  131072 = MYSQLI_BINCMP_FLAG
 852  */
 853  
 854  	function FetchField($fieldOffset = -1) 
 855      {    
 856          $fieldnr = $fieldOffset;
 857          if ($fieldOffset != -1) {
 858            $fieldOffset = @mysqli_field_seek($this->_queryID, $fieldnr);
 859          }
 860          $o = @mysqli_fetch_field($this->_queryID);
 861          if (!$o) return false;
 862          /* Properties of an ADOFieldObject as set by MetaColumns */
 863          $o->primary_key = $o->flags & MYSQLI_PRI_KEY_FLAG;
 864          $o->not_null = $o->flags & MYSQLI_NOT_NULL_FLAG;
 865          $o->auto_increment = $o->flags & MYSQLI_AUTO_INCREMENT_FLAG;
 866          $o->binary = $o->flags & MYSQLI_BINARY_FLAG;
 867          // $o->blob = $o->flags & MYSQLI_BLOB_FLAG; /* not returned by MetaColumns */
 868          $o->unsigned = $o->flags & MYSQLI_UNSIGNED_FLAG;
 869  
 870          return $o;
 871      }
 872  
 873  	function GetRowAssoc($upper = true)
 874      {
 875          if ($this->fetchMode == MYSQLI_ASSOC && !$upper) 
 876            return $this->fields;
 877          $row = ADORecordSet::GetRowAssoc($upper);
 878          return $row;
 879      }
 880      
 881      /* Use associative array to get fields array */
 882  	function Fields($colname)
 883      {    
 884        if ($this->fetchMode != MYSQLI_NUM) 
 885          return @$this->fields[$colname];
 886          
 887        if (!$this->bind) {
 888          $this->bind = array();
 889          for ($i = 0; $i < $this->_numOfFields; $i++) {
 890            $o = $this->FetchField($i);
 891            $this->bind[strtoupper($o->name)] = $i;
 892          }
 893        }
 894        return $this->fields[$this->bind[strtoupper($colname)]];
 895      }
 896      
 897  	function _seek($row)
 898      {
 899        if ($this->_numOfRows == 0) 
 900          return false;
 901  
 902        if ($row < 0)
 903          return false;
 904  
 905        mysqli_data_seek($this->_queryID, $row);
 906        $this->EOF = false;
 907        return true;
 908      }
 909          
 910          
 911  	function NextRecordSet()
 912      {
 913      global $ADODB_COUNTRECS;
 914      
 915          mysqli_free_result($this->_queryID);
 916          $this->_queryID = -1;
 917          // Move to the next recordset, or return false if there is none. In a stored proc
 918          // call, mysqli_next_result returns true for the last "recordset", but mysqli_store_result
 919          // returns false. I think this is because the last "recordset" is actually just the
 920          // return value of the stored proc (ie the number of rows affected).
 921          if(!mysqli_next_result($this->connection->_connectionID)) {
 922          return false;
 923          }
 924          // CD: There is no $this->_connectionID variable, at least in the ADO version I'm using
 925          $this->_queryID = ($ADODB_COUNTRECS) ? @mysqli_store_result( $this->connection->_connectionID )
 926                          : @mysqli_use_result( $this->connection->_connectionID );
 927          if(!$this->_queryID) {
 928              return false;
 929          }
 930          $this->_inited = false;
 931          $this->bind = false;
 932          $this->_currentRow = -1;
 933          $this->Init();
 934          return true;
 935      }
 936  
 937      // 10% speedup to move MoveNext to child class
 938      // This is the only implementation that works now (23-10-2003).
 939      // Other functions return no or the wrong results.
 940  	function MoveNext() 
 941      {
 942          if ($this->EOF) return false;
 943          $this->_currentRow++;
 944          $this->fields = @mysqli_fetch_array($this->_queryID,$this->fetchMode);
 945          
 946          if (is_array($this->fields)) return true;
 947          $this->EOF = true;
 948          return false;
 949      }    
 950      
 951  	function _fetch()
 952      {
 953          $this->fields = mysqli_fetch_array($this->_queryID,$this->fetchMode);  
 954            return is_array($this->fields);
 955      }
 956      
 957  	function _close() 
 958      {
 959          //if results are attached to this pointer from Stored Proceedure calls, the next standard query will die 2014
 960          //only a problem with persistant connections
 961  
 962          //mysqli_next_result($this->connection->_connectionID); trashes the DB side attached results.
 963  
 964          while(mysqli_more_results($this->connection->_connectionID)){
 965             @mysqli_next_result($this->connection->_connectionID);
 966          }
 967  
 968          //Because you can have one attached result, without tripping mysqli_more_results
 969          @mysqli_next_result($this->connection->_connectionID);
 970  
 971  
 972          mysqli_free_result($this->_queryID); 
 973            $this->_queryID = false;    
 974      }
 975      
 976  /*
 977  
 978  0 = MYSQLI_TYPE_DECIMAL
 979  1 = MYSQLI_TYPE_CHAR
 980  1 = MYSQLI_TYPE_TINY
 981  2 = MYSQLI_TYPE_SHORT
 982  3 = MYSQLI_TYPE_LONG
 983  4 = MYSQLI_TYPE_FLOAT
 984  5 = MYSQLI_TYPE_DOUBLE
 985  6 = MYSQLI_TYPE_NULL
 986  7 = MYSQLI_TYPE_TIMESTAMP
 987  8 = MYSQLI_TYPE_LONGLONG
 988  9 = MYSQLI_TYPE_INT24
 989  10 = MYSQLI_TYPE_DATE
 990  11 = MYSQLI_TYPE_TIME
 991  12 = MYSQLI_TYPE_DATETIME
 992  13 = MYSQLI_TYPE_YEAR
 993  14 = MYSQLI_TYPE_NEWDATE
 994  247 = MYSQLI_TYPE_ENUM
 995  248 = MYSQLI_TYPE_SET
 996  249 = MYSQLI_TYPE_TINY_BLOB
 997  250 = MYSQLI_TYPE_MEDIUM_BLOB
 998  251 = MYSQLI_TYPE_LONG_BLOB
 999  252 = MYSQLI_TYPE_BLOB
1000  253 = MYSQLI_TYPE_VAR_STRING
1001  254 = MYSQLI_TYPE_STRING
1002  255 = MYSQLI_TYPE_GEOMETRY
1003  */
1004  
1005  	function MetaType($t, $len = -1, $fieldobj = false)
1006      {
1007          if (is_object($t)) {
1008              $fieldobj = $t;
1009              $t = $fieldobj->type;
1010              $len = $fieldobj->max_length;
1011          }
1012          
1013          
1014           $len = -1; // mysql max_length is not accurate
1015           switch (strtoupper($t)) {
1016           case 'STRING': 
1017           case 'CHAR':
1018           case 'VARCHAR': 
1019           case 'TINYBLOB': 
1020           case 'TINYTEXT': 
1021           case 'ENUM': 
1022           case 'SET': 
1023          
1024          case MYSQLI_TYPE_TINY_BLOB :
1025          #case MYSQLI_TYPE_CHAR :
1026          case MYSQLI_TYPE_STRING :
1027          case MYSQLI_TYPE_ENUM :
1028          case MYSQLI_TYPE_SET :
1029          case 253 :
1030             if ($len <= $this->blobSize) return 'C';
1031             
1032          case 'TEXT':
1033          case 'LONGTEXT': 
1034          case 'MEDIUMTEXT':
1035             return 'X';
1036          
1037          
1038             // php_mysql extension always returns 'blob' even if 'text'
1039             // so we have to check whether binary...
1040          case 'IMAGE':
1041          case 'LONGBLOB': 
1042          case 'BLOB':
1043          case 'MEDIUMBLOB':
1044          
1045          case MYSQLI_TYPE_BLOB :
1046          case MYSQLI_TYPE_LONG_BLOB :
1047          case MYSQLI_TYPE_MEDIUM_BLOB :
1048          
1049             return !empty($fieldobj->binary) ? 'B' : 'X';
1050          case 'YEAR':
1051          case 'DATE': 
1052          case MYSQLI_TYPE_DATE :
1053          case MYSQLI_TYPE_YEAR :
1054          
1055             return 'D';
1056          
1057          case 'TIME':
1058          case 'DATETIME':
1059          case 'TIMESTAMP':
1060          
1061          case MYSQLI_TYPE_DATETIME :
1062          case MYSQLI_TYPE_NEWDATE :
1063          case MYSQLI_TYPE_TIME :
1064          case MYSQLI_TYPE_TIMESTAMP :
1065          
1066              return 'T';
1067          
1068          case 'INT': 
1069          case 'INTEGER':
1070          case 'BIGINT':
1071          case 'TINYINT':
1072          case 'MEDIUMINT':
1073          case 'SMALLINT': 
1074          
1075          case MYSQLI_TYPE_INT24 :
1076          case MYSQLI_TYPE_LONG :
1077          case MYSQLI_TYPE_LONGLONG :
1078          case MYSQLI_TYPE_SHORT :
1079          case MYSQLI_TYPE_TINY :
1080          
1081             if (!empty($fieldobj->primary_key)) return 'R';
1082             
1083             return 'I';
1084          
1085          
1086             // Added floating-point types
1087             // Maybe not necessery.
1088           case 'FLOAT':
1089           case 'DOUBLE':
1090             //        case 'DOUBLE PRECISION':
1091           case 'DECIMAL':
1092           case 'DEC':
1093           case 'FIXED':
1094           default:
1095               //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>"; 
1096               return 'N';
1097          }
1098      } // function
1099      
1100  
1101  } // rs class
1102   
1103  }
1104  
1105  class ADORecordSet_array_mysqli extends ADORecordSet_array {
1106    
1107    function ADORecordSet_array_mysqli($id=-1,$mode=false) 
1108    {
1109      $this->ADORecordSet_array($id,$mode);
1110    }
1111    
1112  	function MetaType($t, $len = -1, $fieldobj = false)
1113      {
1114          if (is_object($t)) {
1115              $fieldobj = $t;
1116              $t = $fieldobj->type;
1117              $len = $fieldobj->max_length;
1118          }
1119          
1120          
1121           $len = -1; // mysql max_length is not accurate
1122           switch (strtoupper($t)) {
1123           case 'STRING': 
1124           case 'CHAR':
1125           case 'VARCHAR': 
1126           case 'TINYBLOB': 
1127           case 'TINYTEXT': 
1128           case 'ENUM': 
1129           case 'SET': 
1130          
1131          case MYSQLI_TYPE_TINY_BLOB :
1132          #case MYSQLI_TYPE_CHAR :
1133          case MYSQLI_TYPE_STRING :
1134          case MYSQLI_TYPE_ENUM :
1135          case MYSQLI_TYPE_SET :
1136          case 253 :
1137             if ($len <= $this->blobSize) return 'C';
1138             
1139          case 'TEXT':
1140          case 'LONGTEXT': 
1141          case 'MEDIUMTEXT':
1142             return 'X';
1143          
1144          
1145             // php_mysql extension always returns 'blob' even if 'text'
1146             // so we have to check whether binary...
1147          case 'IMAGE':
1148          case 'LONGBLOB': 
1149          case 'BLOB':
1150          case 'MEDIUMBLOB':
1151          
1152          case MYSQLI_TYPE_BLOB :
1153          case MYSQLI_TYPE_LONG_BLOB :
1154          case MYSQLI_TYPE_MEDIUM_BLOB :
1155          
1156             return !empty($fieldobj->binary) ? 'B' : 'X';
1157          case 'YEAR':
1158          case 'DATE': 
1159          case MYSQLI_TYPE_DATE :
1160          case MYSQLI_TYPE_YEAR :
1161          
1162             return 'D';
1163          
1164          case 'TIME':
1165          case 'DATETIME':
1166          case 'TIMESTAMP':
1167          
1168          case MYSQLI_TYPE_DATETIME :
1169          case MYSQLI_TYPE_NEWDATE :
1170          case MYSQLI_TYPE_TIME :
1171          case MYSQLI_TYPE_TIMESTAMP :
1172          
1173              return 'T';
1174          
1175          case 'INT': 
1176          case 'INTEGER':
1177          case 'BIGINT':
1178          case 'TINYINT':
1179          case 'MEDIUMINT':
1180          case 'SMALLINT': 
1181          
1182          case MYSQLI_TYPE_INT24 :
1183          case MYSQLI_TYPE_LONG :
1184          case MYSQLI_TYPE_LONGLONG :
1185          case MYSQLI_TYPE_SHORT :
1186          case MYSQLI_TYPE_TINY :
1187          
1188             if (!empty($fieldobj->primary_key)) return 'R';
1189             
1190             return 'I';
1191          
1192          
1193             // Added floating-point types
1194             // Maybe not necessery.
1195           case 'FLOAT':
1196           case 'DOUBLE':
1197             //        case 'DOUBLE PRECISION':
1198           case 'DECIMAL':
1199           case 'DEC':
1200           case 'FIXED':
1201           default:
1202               //if (!is_numeric($t)) echo "<p>--- Error in type matching $t -----</p>"; 
1203               return 'N';
1204          }
1205      } // function
1206    
1207  }
1208  
1209  ?>


Generated: Thu Jul 28 15:48:31 2011 Cross-referenced by PHPXref 0.7