2 /* vim: set expandtab sw=4 ts=4 sts=4: */
4 * Interface to the improved MySQL extension (MySQLi)
6 * @package PhpMyAdmin-DBI
9 if (! defined('PHPMYADMIN')) {
13 require_once './libraries/dbi/DBIExtension.int.php';
18 PMA_defineClientAPI(mysqli_get_client_info());
21 * some PHP versions are reporting extra messages like "No index used in query"
24 mysqli_report(MYSQLI_REPORT_OFF
);
27 * some older mysql client libs are missing these constants ...
29 if (! defined('MYSQLI_BINARY_FLAG')) {
30 define('MYSQLI_BINARY_FLAG', 128);
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);
44 if (! defined('MYSQLI_TYPE_VARCHAR')) {
45 define('MYSQLI_TYPE_VARCHAR', 15);
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: */
69 * Interface to the improved MySQL extension (MySQLi)
71 * @package PhpMyAdmin-DBI
74 class PMA_DBI_Mysqli
implements PMA_DBI_Extension
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
91 private function _realConnect(
92 $link, $host, $user, $password, $dbname, $server_port,
93 $server_socket, $client_flags = null, $persistent = false
97 // mysqli persistent connections
98 if ($cfg['PersistentConnections'] ||
$persistent) {
102 if ($client_flags === null) {
103 return @mysqli_real_connect
(
113 return @mysqli_real_connect
(
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
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
144 $server_port = $GLOBALS['dbi']->getServerPort($server);
145 $server_socket = $GLOBALS['dbi']->getServerSocket($server);
148 $server['host'] = (empty($server['host']))
153 // NULL enables connection to the default socket
155 $link = mysqli_init();
157 mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE
, true);
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')) {
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
;
180 $return_value = @$this->_realConnect(
182 $cfg['Server']['host'],
190 // Retry with empty password if we're allowed to
191 if ($return_value == false
192 && isset($cfg['Server']['nopassword'])
193 && $cfg['Server']['nopassword']
196 $return_value = @$this->_realConnect(
198 $cfg['Server']['host'],
208 $return_value = @$this->_realConnect(
219 if ($return_value === false) {
227 * selects given database
229 * @param string $dbname database name to select
230 * @param mysqli $link the mysqli object
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
;
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
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
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
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
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);
422 $error_number = mysqli_connect_errno();
423 $error_message = mysqli_connect_error();
425 if (0 == $error_number) {
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
443 public function numRows($result)
445 // see the note for tryQuery();
446 if (is_bool($result)) {
450 return @mysqli_num_rows
($result);
454 * returns the number of rows affected by last query
456 * @param mysqli $link the mysqli object
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
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)) {
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
);
539 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_NUM_FLAG
);
541 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_BLOB_FLAG
);
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);
596 $charsetnr = $f->charsetnr
;
599 foreach ($GLOBALS['pma_mysqli_flag_names'] as $flag => $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
)
617 return implode(' ', $flags);