UPDATE 4.4.0.0
[phpmyadmin.git] / libraries / dbi / DBIMysqli.class.php
blobe1adb4a8e0c4d3d5af558f303936ddce8a5593ef
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Interface to the improved MySQL extension (MySQLi)
6 * @package PhpMyAdmin-DBI
7 * @subpackage MySQLi
8 */
9 if (! defined('PHPMYADMIN')) {
10 exit;
13 require_once './libraries/dbi/DBIExtension.int.php';
15 /**
16 * MySQL client API
18 PMA_defineClientAPI(mysqli_get_client_info());
20 /**
21 * some PHP versions are reporting extra messages like "No index used in query"
24 mysqli_report(MYSQLI_REPORT_OFF);
26 /**
27 * some older mysql client libs are missing these constants ...
29 if (! defined('MYSQLI_BINARY_FLAG')) {
30 define('MYSQLI_BINARY_FLAG', 128);
33 /**
34 * @see http://bugs.php.net/36007
36 if (! defined('MYSQLI_TYPE_NEWDECIMAL')) {
37 define('MYSQLI_TYPE_NEWDECIMAL', 246);
39 if (! defined('MYSQLI_TYPE_BIT')) {
40 define('MYSQLI_TYPE_BIT', 16);
43 // for Drizzle
44 if (! defined('MYSQLI_TYPE_VARCHAR')) {
45 define('MYSQLI_TYPE_VARCHAR', 15);
48 /**
49 * Names of field flags.
51 $pma_mysqli_flag_names = array(
52 MYSQLI_NUM_FLAG => 'num',
53 MYSQLI_PART_KEY_FLAG => 'part_key',
54 MYSQLI_SET_FLAG => 'set',
55 MYSQLI_TIMESTAMP_FLAG => 'timestamp',
56 MYSQLI_AUTO_INCREMENT_FLAG => 'auto_increment',
57 MYSQLI_ENUM_FLAG => 'enum',
58 MYSQLI_ZEROFILL_FLAG => 'zerofill',
59 MYSQLI_UNSIGNED_FLAG => 'unsigned',
60 MYSQLI_BLOB_FLAG => 'blob',
61 MYSQLI_MULTIPLE_KEY_FLAG => 'multiple_key',
62 MYSQLI_UNIQUE_KEY_FLAG => 'unique_key',
63 MYSQLI_PRI_KEY_FLAG => 'primary_key',
64 MYSQLI_NOT_NULL_FLAG => 'not_null',
67 /* vim: set expandtab sw=4 ts=4 sts=4: */
68 /**
69 * Interface to the improved MySQL extension (MySQLi)
71 * @package PhpMyAdmin-DBI
72 * @subpackage MySQLi
74 class PMA_DBI_Mysqli implements PMA_DBI_Extension
76 /**
77 * Helper function for connecting to the database server
79 * @param mysqli $link connection link
80 * @param string $host mysql hostname
81 * @param string $user mysql user name
82 * @param string $password mysql user password
83 * @param string $dbname database name
84 * @param int $server_port server port
85 * @param string $server_socket server socket
86 * @param int $client_flags client flags of connection
87 * @param bool $persistent whether to use persistent connection
89 * @return bool
91 private function _realConnect(
92 $link, $host, $user, $password, $dbname, $server_port,
93 $server_socket, $client_flags = null, $persistent = false
94 ) {
95 global $cfg;
97 // mysqli persistent connections
98 if ($cfg['PersistentConnections'] || $persistent) {
99 $host = 'p:' . $host;
102 if ($client_flags === null) {
103 return @mysqli_real_connect(
104 $link,
105 $host,
106 $user,
107 $password,
108 $dbname,
109 $server_port,
110 $server_socket
112 } else {
113 return @mysqli_real_connect(
114 $link,
115 $host,
116 $user,
117 $password,
118 $dbname,
119 $server_port,
120 $server_socket,
121 $client_flags
127 * connects to the database server
129 * @param string $user mysql user name
130 * @param string $password mysql user password
131 * @param bool $is_controluser whether this is a control user connection
132 * @param array $server host/port/socket/persistent
133 * @param bool $auxiliary_connection (when true, don't go back to login if
134 * connection fails)
136 * @return mixed false on error or a mysqli object on success
138 public function connect(
139 $user, $password, $is_controluser = false, $server = null,
140 $auxiliary_connection = false
142 global $cfg;
144 $server_port = $GLOBALS['dbi']->getServerPort($server);
145 $server_socket = $GLOBALS['dbi']->getServerSocket($server);
147 if ($server) {
148 $server['host'] = (empty($server['host']))
149 ? 'localhost'
150 : $server['host'];
153 // NULL enables connection to the default socket
155 $link = mysqli_init();
157 mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, true);
159 $client_flags = 0;
161 /* Optionally compress connection */
162 if ($cfg['Server']['compress'] && defined('MYSQLI_CLIENT_COMPRESS')) {
163 $client_flags |= MYSQLI_CLIENT_COMPRESS;
166 /* Optionally enable SSL */
167 if ($cfg['Server']['ssl'] && defined('MYSQLI_CLIENT_SSL')) {
168 mysqli_ssl_set(
169 $link,
170 $cfg['Server']['ssl_key'],
171 $cfg['Server']['ssl_cert'],
172 $cfg['Server']['ssl_ca'],
173 $cfg['Server']['ssl_ca_path'],
174 $cfg['Server']['ssl_ciphers']
176 $client_flags |= MYSQLI_CLIENT_SSL;
179 if (! $server) {
180 $return_value = @$this->_realConnect(
181 $link,
182 $cfg['Server']['host'],
183 $user,
184 $password,
185 false,
186 $server_port,
187 $server_socket,
188 $client_flags
190 // Retry with empty password if we're allowed to
191 if ($return_value == false
192 && isset($cfg['Server']['nopassword'])
193 && $cfg['Server']['nopassword']
194 && ! $is_controluser
196 $return_value = @$this->_realConnect(
197 $link,
198 $cfg['Server']['host'],
199 $user,
201 false,
202 $server_port,
203 $server_socket,
204 $client_flags
207 } else {
208 $return_value = @$this->_realConnect(
209 $link,
210 $server['host'],
211 $user,
212 $password,
213 false,
214 $server_port,
215 $server_socket
219 if ($return_value === false) {
220 return false;
223 return $link;
227 * selects given database
229 * @param string $dbname database name to select
230 * @param mysqli $link the mysqli object
232 * @return boolean
234 public function selectDb($dbname, $link)
236 return mysqli_select_db($link, $dbname);
240 * runs a query and returns the result
242 * @param string $query query to execute
243 * @param mysqli $link mysqli object
244 * @param int $options query options
246 * @return mysqli_result|bool
248 public function realQuery($query, $link, $options)
250 if ($options == ($options | PMA_DatabaseInterface::QUERY_STORE)) {
251 $method = MYSQLI_STORE_RESULT;
252 } elseif ($options == ($options | PMA_DatabaseInterface::QUERY_UNBUFFERED)) {
253 $method = MYSQLI_USE_RESULT;
254 } else {
255 $method = 0;
258 return mysqli_query($link, $query, $method);
262 * Run the multi query and output the results
264 * @param mysqli $link mysqli object
265 * @param string $query multi query statement to execute
267 * @return mysqli_result collection | boolean(false)
269 public function realMultiQuery($link, $query)
271 return mysqli_multi_query($link, $query);
275 * returns array of rows with associative and numeric keys from $result
277 * @param mysqli_result $result result set identifier
279 * @return array
281 public function fetchArray($result)
283 return mysqli_fetch_array($result, MYSQLI_BOTH);
287 * returns array of rows with associative keys from $result
289 * @param mysqli_result $result result set identifier
291 * @return array
293 public function fetchAssoc($result)
295 return mysqli_fetch_array($result, MYSQLI_ASSOC);
299 * returns array of rows with numeric keys from $result
301 * @param mysqli_result $result result set identifier
303 * @return array
305 public function fetchRow($result)
307 return mysqli_fetch_array($result, MYSQLI_NUM);
311 * Adjusts the result pointer to an arbitrary row in the result
313 * @param mysqli_result $result database result
314 * @param integer $offset offset to seek
316 * @return bool true on success, false on failure
318 public function dataSeek($result, $offset)
320 return mysqli_data_seek($result, $offset);
324 * Frees memory associated with the result
326 * @param mysqli_result $result database result
328 * @return void
330 public function freeResult($result)
332 if ($result instanceof mysqli_result) {
333 mysqli_free_result($result);
338 * Check if there are any more query results from a multi query
340 * @param mysqli $link the mysqli object
342 * @return bool true or false
344 public function moreResults($link)
346 return mysqli_more_results($link);
350 * Prepare next result from multi_query
352 * @param mysqli $link the mysqli object
354 * @return bool true or false
356 public function nextResult($link)
358 return mysqli_next_result($link);
362 * Store the result returned from multi query
364 * @param mysqli $link the mysqli object
366 * @return mixed false when empty results / result set when not empty
368 public function storeResult($link)
370 return mysqli_store_result($link);
374 * Returns a string representing the type of connection used
376 * @param resource $link mysql link
378 * @return string type of connection used
380 public function getHostInfo($link)
382 return mysqli_get_host_info($link);
386 * Returns the version of the MySQL protocol used
388 * @param resource $link mysql link
390 * @return integer version of the MySQL protocol used
392 public function getProtoInfo($link)
394 return mysqli_get_proto_info($link);
398 * returns a string that represents the client library version
400 * @return string MySQL client library version
402 public function getClientInfo()
404 return mysqli_get_client_info();
408 * returns last error message or false if no errors occurred
410 * @param resource $link mysql link
412 * @return string|bool $error or false
414 public function getError($link)
416 $GLOBALS['errno'] = 0;
418 if (null !== $link && false !== $link) {
419 $error_number = mysqli_errno($link);
420 $error_message = mysqli_error($link);
421 } else {
422 $error_number = mysqli_connect_errno();
423 $error_message = mysqli_connect_error();
425 if (0 == $error_number) {
426 return false;
429 // keep the error number for further check after
430 // the call to getError()
431 $GLOBALS['errno'] = $error_number;
433 return $GLOBALS['dbi']->formatError($error_number, $error_message);
437 * returns the number of rows returned by last query
439 * @param mysqli_result $result result set identifier
441 * @return string|int
443 public function numRows($result)
445 // see the note for tryQuery();
446 if (is_bool($result)) {
447 return 0;
450 return @mysqli_num_rows($result);
454 * returns the number of rows affected by last query
456 * @param mysqli $link the mysqli object
458 * @return int
460 public function affectedRows($link)
462 return mysqli_affected_rows($link);
466 * returns metainfo for fields in $result
468 * @param mysqli_result $result result set identifier
470 * @return array meta info for fields in $result
472 public function getFieldsMeta($result)
474 // Build an associative array for a type look up
475 $typeAr = array();
476 $typeAr[MYSQLI_TYPE_DECIMAL] = 'real';
477 $typeAr[MYSQLI_TYPE_NEWDECIMAL] = 'real';
478 $typeAr[MYSQLI_TYPE_BIT] = 'int';
479 $typeAr[MYSQLI_TYPE_TINY] = 'int';
480 $typeAr[MYSQLI_TYPE_SHORT] = 'int';
481 $typeAr[MYSQLI_TYPE_LONG] = 'int';
482 $typeAr[MYSQLI_TYPE_FLOAT] = 'real';
483 $typeAr[MYSQLI_TYPE_DOUBLE] = 'real';
484 $typeAr[MYSQLI_TYPE_NULL] = 'null';
485 $typeAr[MYSQLI_TYPE_TIMESTAMP] = 'timestamp';
486 $typeAr[MYSQLI_TYPE_LONGLONG] = 'int';
487 $typeAr[MYSQLI_TYPE_INT24] = 'int';
488 $typeAr[MYSQLI_TYPE_DATE] = 'date';
489 $typeAr[MYSQLI_TYPE_TIME] = 'time';
490 $typeAr[MYSQLI_TYPE_DATETIME] = 'datetime';
491 $typeAr[MYSQLI_TYPE_YEAR] = 'year';
492 $typeAr[MYSQLI_TYPE_NEWDATE] = 'date';
493 $typeAr[MYSQLI_TYPE_ENUM] = 'unknown';
494 $typeAr[MYSQLI_TYPE_SET] = 'unknown';
495 $typeAr[MYSQLI_TYPE_TINY_BLOB] = 'blob';
496 $typeAr[MYSQLI_TYPE_MEDIUM_BLOB] = 'blob';
497 $typeAr[MYSQLI_TYPE_LONG_BLOB] = 'blob';
498 $typeAr[MYSQLI_TYPE_BLOB] = 'blob';
499 $typeAr[MYSQLI_TYPE_VAR_STRING] = 'string';
500 $typeAr[MYSQLI_TYPE_STRING] = 'string';
501 $typeAr[MYSQLI_TYPE_VARCHAR] = 'string'; // for Drizzle
502 // MySQL returns MYSQLI_TYPE_STRING for CHAR
503 // and MYSQLI_TYPE_CHAR === MYSQLI_TYPE_TINY
504 // so this would override TINYINT and mark all TINYINT as string
505 // https://sourceforge.net/p/phpmyadmin/bugs/2205/
506 //$typeAr[MYSQLI_TYPE_CHAR] = 'string';
507 $typeAr[MYSQLI_TYPE_GEOMETRY] = 'geometry';
508 $typeAr[MYSQLI_TYPE_BIT] = 'bit';
510 $fields = mysqli_fetch_fields($result);
512 // this happens sometimes (seen under MySQL 4.0.25)
513 if (!is_array($fields)) {
514 return false;
517 foreach ($fields as $k => $field) {
518 $fields[$k]->_type = $field->type;
519 $fields[$k]->type = $typeAr[$field->type];
520 $fields[$k]->_flags = $field->flags;
521 $fields[$k]->flags = $this->fieldFlags($result, $k);
523 // Enhance the field objects for mysql-extension compatibility
524 //$flags = explode(' ', $fields[$k]->flags);
525 //array_unshift($flags, 'dummy');
526 $fields[$k]->multiple_key
527 = (int) (bool) ($fields[$k]->_flags & MYSQLI_MULTIPLE_KEY_FLAG);
528 $fields[$k]->primary_key
529 = (int) (bool) ($fields[$k]->_flags & MYSQLI_PRI_KEY_FLAG);
530 $fields[$k]->unique_key
531 = (int) (bool) ($fields[$k]->_flags & MYSQLI_UNIQUE_KEY_FLAG);
532 $fields[$k]->not_null
533 = (int) (bool) ($fields[$k]->_flags & MYSQLI_NOT_NULL_FLAG);
534 $fields[$k]->unsigned
535 = (int) (bool) ($fields[$k]->_flags & MYSQLI_UNSIGNED_FLAG);
536 $fields[$k]->zerofill
537 = (int) (bool) ($fields[$k]->_flags & MYSQLI_ZEROFILL_FLAG);
538 $fields[$k]->numeric
539 = (int) (bool) ($fields[$k]->_flags & MYSQLI_NUM_FLAG);
540 $fields[$k]->blob
541 = (int) (bool) ($fields[$k]->_flags & MYSQLI_BLOB_FLAG);
543 return $fields;
547 * return number of fields in given $result
549 * @param mysqli_result $result result set identifier
551 * @return int field count
553 public function numFields($result)
555 return mysqli_num_fields($result);
559 * returns the length of the given field $i in $result
561 * @param mysqli_result $result result set identifier
562 * @param int $i field
564 * @return int length of field
566 public function fieldLen($result, $i)
568 return mysqli_fetch_field_direct($result, $i)->length;
572 * returns name of $i. field in $result
574 * @param mysqli_result $result result set identifier
575 * @param int $i field
577 * @return string name of $i. field in $result
579 public function fieldName($result, $i)
581 return mysqli_fetch_field_direct($result, $i)->name;
585 * returns concatenated string of human readable field flags
587 * @param mysqli_result $result result set identifier
588 * @param int $i field
590 * @return string field flags
592 public function fieldFlags($result, $i)
594 $f = mysqli_fetch_field_direct($result, $i);
595 $type = $f->type;
596 $charsetnr = $f->charsetnr;
597 $f = $f->flags;
598 $flags = array();
599 foreach ($GLOBALS['pma_mysqli_flag_names'] as $flag => $name) {
600 if ($f & $flag) {
601 $flags[] = $name;
604 // See http://dev.mysql.com/doc/refman/6.0/en/c-api-datatypes.html:
605 // to determine if a string is binary, we should not use MYSQLI_BINARY_FLAG
606 // but instead the charsetnr member of the MYSQL_FIELD
607 // structure. Watch out: some types like DATE returns 63 in charsetnr
608 // so we have to check also the type.
609 // Unfortunately there is no equivalent in the mysql extension.
610 if (($type == MYSQLI_TYPE_TINY_BLOB || $type == MYSQLI_TYPE_BLOB
611 || $type == MYSQLI_TYPE_MEDIUM_BLOB || $type == MYSQLI_TYPE_LONG_BLOB
612 || $type == MYSQLI_TYPE_VAR_STRING || $type == MYSQLI_TYPE_STRING)
613 && 63 == $charsetnr
615 $flags[] = 'binary';
617 return implode(' ', $flags);