TYPO3 CMS  TYPO3_6-2
adodb-mysqli.inc.php
Go to the documentation of this file.
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 (a.de.rijke@xs4all.nl)
13 Based on adodb 3.40
14 */
15 
16 // security - hide paths
17 if (!defined('ADODB_DIR')) die();
18 
19 if (! defined("_ADODB_MYSQLI_LAYER")) {
20  define("_ADODB_MYSQLI_LAYER", 1 );
21 
22  // PHP5 compat...
23  if (! defined("MYSQLI_BINARY_FLAG")) define("MYSQLI_BINARY_FLAG", 128);
24  if (!defined('MYSQLI_READ_DEFAULT_GROUP')) define('MYSQLI_READ_DEFAULT_GROUP',1);
25 
26  // disable adodb extension - currently incompatible.
27  global $ADODB_EXTENSION; $ADODB_EXTENSION = false;
28 
29 class ADODB_mysqli extends ADOConnection {
30  var $databaseType = 'mysqli';
31  var $dataProvider = '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 = '`';
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 andrew005@mnogo.ru
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 
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 }
ADORecordSet_array_mysqli($id=-1, $mode=false)
MetaType($t, $len=-1, $fieldobj=false)
$sql
Definition: server.php:82
if(isset($_REQUEST['nrows'])) else $rs
Definition: server.php:92
die
Definition: index.php:6
if($list_of_literals) if(!empty($literals)) if(!empty($literals)) $result
Analyse literals to prepend the N char to them if their contents aren&#39;t numeric.
debug($variable='', $name=' *variable *', $line=' *line *', $file=' *file *', $recursiveDepth=3, $debugLevel=E_DEBUG)