[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

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


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1