[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

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

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


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1