2 /* vim: set expandtab sw=4 ts=4 sts=4: */
4 * Interface to the improved MySQL extension (MySQLi)
8 if (! defined('PHPMYADMIN')) {
13 if (!defined('PMA_MYSQL_CLIENT_API')) {
14 $client_api = explode('.', mysqli_get_client_info());
15 define('PMA_MYSQL_CLIENT_API', (int)sprintf('%d%02d%02d', $client_api[0], $client_api[1], intval($client_api[2])));
20 * some older mysql client libs are missing this constants ...
22 if (! defined('MYSQLI_BINARY_FLAG')) {
23 define('MYSQLI_BINARY_FLAG', 128);
27 * @see http://bugs.php.net/36007
29 if (! defined('MYSQLI_TYPE_NEWDECIMAL')) {
30 define('MYSQLI_TYPE_NEWDECIMAL', 246);
32 if (! defined('MYSQLI_TYPE_BIT')) {
33 define('MYSQLI_TYPE_BIT', 16);
37 * connects to the database server
39 * @uses $GLOBALS['cfg']['Server']
40 * @uses PMA_auth_fails()
41 * @uses PMA_DBI_postConnect()
42 * @uses MYSQLI_CLIENT_COMPRESS
43 * @uses MYSQLI_OPT_LOCAL_INFILE
46 * @uses mysqli_options()
47 * @uses mysqli_real_connect()
49 * @param string $user mysql user name
50 * @param string $password mysql user password
51 * @param boolean $is_controluser
52 * @return mixed false on error or a mysqli object on success
54 function PMA_DBI_connect($user, $password, $is_controluser = false)
56 $server_port = (empty($GLOBALS['cfg']['Server']['port']))
58 : (int) $GLOBALS['cfg']['Server']['port'];
60 if (strtolower($GLOBALS['cfg']['Server']['connect_type']) == 'tcp') {
61 $GLOBALS['cfg']['Server']['socket'] = '';
64 // NULL enables connection to the default socket
65 $server_socket = (empty($GLOBALS['cfg']['Server']['socket']))
67 : $GLOBALS['cfg']['Server']['socket'];
69 $link = mysqli_init();
71 mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE
, true);
75 /* Optionally compress connection */
76 if ($GLOBALS['cfg']['Server']['compress'] && defined('MYSQLI_CLIENT_COMPRESS')) {
77 $client_flags |
= MYSQLI_CLIENT_COMPRESS
;
80 /* Optionally enable SSL */
81 if ($GLOBALS['cfg']['Server']['ssl'] && defined('MYSQLI_CLIENT_SSL')) {
82 $client_flags |
= MYSQLI_CLIENT_SSL
;
85 $return_value = @mysqli_real_connect
($link, $GLOBALS['cfg']['Server']['host'], $user, $password, false, $server_port, $server_socket, $client_flags);
87 // Retry with empty password if we're allowed to
88 if ($return_value == false && isset($cfg['Server']['nopassword']) && $cfg['Server']['nopassword'] && !$is_controluser) {
89 $return_value = @mysqli_real_connect
($link, $GLOBALS['cfg']['Server']['host'], $user, '', false, $server_port, $server_socket, $client_flags);
92 if ($return_value == false) {
93 if ($is_controluser) {
94 trigger_error($GLOBALS['strControluserFailed'], E_USER_WARNING
);
100 PMA_DBI_postConnect($link, $is_controluser);
106 * selects given database
108 * @uses $GLOBALS['userlink']
109 * @uses PMA_convert_charset()
110 * @uses mysqli_select_db()
111 * @param string $dbname database name to select
112 * @param object mysqli $link the mysqli object
113 * @return boolean true or false
115 function PMA_DBI_select_db($dbname, $link = null)
118 if (isset($GLOBALS['userlink'])) {
119 $link = $GLOBALS['userlink'];
124 return mysqli_select_db($link, $dbname);
128 * runs a query and returns the result
130 * @uses PMA_DBI_QUERY_STORE
131 * @uses PMA_DBI_QUERY_UNBUFFERED
132 * @uses $GLOBALS['userlink']
133 * @uses PMA_convert_charset()
134 * @uses MYSQLI_STORE_RESULT
135 * @uses MYSQLI_USE_RESULT
136 * @uses mysqli_query()
138 * @param string $query query to execute
139 * @param object mysqli $link mysqli object
140 * @param integer $options
141 * @return mixed true, false or result object
143 function PMA_DBI_try_query($query, $link = null, $options = 0)
145 if ($options == ($options | PMA_DBI_QUERY_STORE
)) {
146 $method = MYSQLI_STORE_RESULT
;
147 } elseif ($options == ($options | PMA_DBI_QUERY_UNBUFFERED
)) {
148 $method = MYSQLI_USE_RESULT
;
154 if (isset($GLOBALS['userlink'])) {
155 $link = $GLOBALS['userlink'];
161 if ($GLOBALS['cfg']['DBG']['sql']) {
162 $time = microtime(true);
164 $r = mysqli_query($link, $query, $method);
165 if ($GLOBALS['cfg']['DBG']['sql']) {
166 $time = microtime(true) - $time;
170 if (isset($_SESSION['debug']['queries'][$hash])) {
171 $_SESSION['debug']['queries'][$hash]['count']++
;
173 $_SESSION['debug']['queries'][$hash] = array();
174 $_SESSION['debug']['queries'][$hash]['count'] = 1;
175 $_SESSION['debug']['queries'][$hash]['query'] = $query;
176 $_SESSION['debug']['queries'][$hash]['time'] = $time;
180 foreach (debug_backtrace() as $trace_step) {
181 $trace[] = PMA_Error
::relPath($trace_step['file']) . '#'
182 . $trace_step['line'] . ': '
183 . (isset($trace_step['class']) ?
$trace_step['class'] : '')
184 //. (isset($trace_step['object']) ? get_class($trace_step['object']) : '')
185 . (isset($trace_step['type']) ?
$trace_step['type'] : '')
186 . (isset($trace_step['function']) ?
$trace_step['function'] : '')
188 . (isset($trace_step['params']) ?
implode(', ', $trace_step['params']) : '')
192 $_SESSION['debug']['queries'][$hash]['trace'][] = $trace;
197 // From the PHP manual:
198 // "note: returns true on success or false on failure. For SELECT,
199 // SHOW, DESCRIBE or EXPLAIN, mysqli_query() will return a result object"
200 // so, do not use the return value to feed mysqli_num_rows() if it's
205 * returns array of rows with associative and numeric keys from $result
207 * @uses mysqli_fetch_array()
209 * @param object mysqli result $result
210 * @return array result rows
212 function PMA_DBI_fetch_array($result)
214 return mysqli_fetch_array($result, MYSQLI_BOTH
);
218 * returns array of rows with associative keys from $result
220 * @uses mysqli_fetch_array()
222 * @param object mysqli result $result
223 * @return array result rows
225 function PMA_DBI_fetch_assoc($result)
227 return mysqli_fetch_array($result, MYSQLI_ASSOC
);
231 * returns array of rows with numeric keys from $result
233 * @uses mysqli_fetch_array()
235 * @param object mysqli result $result
236 * @return array result rows
238 function PMA_DBI_fetch_row($result)
240 return mysqli_fetch_array($result, MYSQLI_NUM
);
244 * Adjusts the result pointer to an arbitrary row in the result
246 * @uses mysqli_data_seek()
249 * @return boolean true on success, false on failure
251 function PMA_DBI_data_seek($result, $offset)
253 return mysqli_data_seek($result, $offset);
257 * Frees the memory associated with the results
259 * @uses mysqli_result
260 * @uses func_get_args()
261 * @uses mysqli_free_result()
262 * @param result $result,... one or more mysql result resources
264 function PMA_DBI_free_result()
266 foreach (func_get_args() as $result) {
267 if ($result instanceof mysqli_result
) {
268 mysqli_free_result($result);
274 * Returns a string representing the type of connection used
275 * @uses mysqli_get_host_info()
276 * @uses $GLOBALS['userlink'] as default for $link
277 * @param resource $link mysql link
278 * @return string type of connection used
280 function PMA_DBI_get_host_info($link = null)
282 if (null === $link) {
283 if (isset($GLOBALS['userlink'])) {
284 $link = $GLOBALS['userlink'];
289 return mysqli_get_host_info($link);
293 * Returns the version of the MySQL protocol used
294 * @uses mysqli_get_proto_info()
295 * @uses $GLOBALS['userlink'] as default for $link
296 * @param resource $link mysql link
297 * @return integer version of the MySQL protocol used
299 function PMA_DBI_get_proto_info($link = null)
301 if (null === $link) {
302 if (isset($GLOBALS['userlink'])) {
303 $link = $GLOBALS['userlink'];
308 return mysqli_get_proto_info($link);
312 * returns a string that represents the client library version
313 * @uses mysqli_get_client_info()
314 * @return string MySQL client library version
316 function PMA_DBI_get_client_info()
318 return mysqli_get_client_info();
322 * returns last error message or false if no errors occured
324 * @uses PMA_DBI_convert_message()
325 * @uses $GLOBALS['errno']
326 * @uses $GLOBALS['userlink']
327 * @uses $GLOBALS['strServerNotResponding']
328 * @uses $GLOBALS['strSocketProblem']
329 * @uses mysqli_errno()
330 * @uses mysqli_error()
331 * @uses mysqli_connect_errno()
332 * @uses mysqli_connect_error()
334 * @param resource $link mysql link
335 * @return string|boolean $error or false
337 function PMA_DBI_getError($link = null)
339 $GLOBALS['errno'] = 0;
341 if (null === $link && isset($GLOBALS['userlink'])) {
342 $link =& $GLOBALS['userlink'];
343 // Do not stop now. We still can get the error code
344 // with mysqli_connect_errno()
349 if (null !== $link) {
350 $error_number = mysqli_errno($link);
351 $error_message = mysqli_error($link);
353 $error_number = mysqli_connect_errno();
354 $error_message = mysqli_connect_error();
356 if (0 == $error_number) {
360 // keep the error number for further check after the call to PMA_DBI_getError()
361 $GLOBALS['errno'] = $error_number;
363 if (! empty($error_message)) {
364 $error_message = PMA_DBI_convert_message($error_message);
367 if ($error_number == 2002) {
368 $error = '#' . ((string) $error_number) . ' - ' . $GLOBALS['strServerNotResponding'] . ' ' . $GLOBALS['strSocketProblem'];
370 $error = '#' . ((string) $error_number) . ' - ' . $error_message;
377 * @param object mysqli result $result
379 function PMA_DBI_num_rows($result)
381 // see the note for PMA_DBI_try_query();
382 if (!is_bool($result)) {
383 return @mysqli_num_rows
($result);
390 * returns last inserted auto_increment id for given $link or $GLOBALS['userlink']
392 * @uses $GLOBALS['userlink']
393 * @uses mysqli_insert_id()
394 * @param object mysqli $link the mysqli object
395 * @return string ineteger
397 function PMA_DBI_insert_id($link = '')
400 if (isset($GLOBALS['userlink'])) {
401 $link = $GLOBALS['userlink'];
406 return mysqli_insert_id($link);
410 * returns the number of rows affected by last query
412 * @uses $GLOBALS['userlink']
413 * @uses mysqli_affected_rows()
414 * @param object mysqli $link the mysqli object
415 * @return string integer
417 function PMA_DBI_affected_rows($link = null)
420 if (isset($GLOBALS['userlink'])) {
421 $link = $GLOBALS['userlink'];
426 return mysqli_affected_rows($link);
430 * returns metainfo for fields in $result
432 * @todo preserve orignal flags value
433 * @uses PMA_DBI_field_flags()
434 * @uses MYSQLI_TYPE_*
435 * @uses MYSQLI_MULTIPLE_KEY_FLAG
436 * @uses MYSQLI_PRI_KEY_FLAG
437 * @uses MYSQLI_UNIQUE_KEY_FLAG
438 * @uses MYSQLI_NOT_NULL_FLAG
439 * @uses MYSQLI_UNSIGNED_FLAG
440 * @uses MYSQLI_ZEROFILL_FLAG
441 * @uses MYSQLI_NUM_FLAG
442 * @uses MYSQLI_TYPE_BLOB
443 * @uses MYSQLI_BLOB_FLAG
445 * @uses mysqli_fetch_fields()
447 * @param object mysqli result $result
448 * @return array meta info for fields in $result
450 function PMA_DBI_get_fields_meta($result)
452 // Build an associative array for a type look up
454 $typeAr[MYSQLI_TYPE_DECIMAL
] = 'real';
455 $typeAr[MYSQLI_TYPE_NEWDECIMAL
] = 'real';
456 $typeAr[MYSQLI_TYPE_BIT
] = 'int';
457 $typeAr[MYSQLI_TYPE_TINY
] = 'int';
458 $typeAr[MYSQLI_TYPE_SHORT
] = 'int';
459 $typeAr[MYSQLI_TYPE_LONG
] = 'int';
460 $typeAr[MYSQLI_TYPE_FLOAT
] = 'real';
461 $typeAr[MYSQLI_TYPE_DOUBLE
] = 'real';
462 $typeAr[MYSQLI_TYPE_NULL
] = 'null';
463 $typeAr[MYSQLI_TYPE_TIMESTAMP
] = 'timestamp';
464 $typeAr[MYSQLI_TYPE_LONGLONG
] = 'int';
465 $typeAr[MYSQLI_TYPE_INT24
] = 'int';
466 $typeAr[MYSQLI_TYPE_DATE
] = 'date';
467 $typeAr[MYSQLI_TYPE_TIME
] = 'time';
468 $typeAr[MYSQLI_TYPE_DATETIME
] = 'datetime';
469 $typeAr[MYSQLI_TYPE_YEAR
] = 'year';
470 $typeAr[MYSQLI_TYPE_NEWDATE
] = 'date';
471 $typeAr[MYSQLI_TYPE_ENUM
] = 'unknown';
472 $typeAr[MYSQLI_TYPE_SET
] = 'unknown';
473 $typeAr[MYSQLI_TYPE_TINY_BLOB
] = 'blob';
474 $typeAr[MYSQLI_TYPE_MEDIUM_BLOB
] = 'blob';
475 $typeAr[MYSQLI_TYPE_LONG_BLOB
] = 'blob';
476 $typeAr[MYSQLI_TYPE_BLOB
] = 'blob';
477 $typeAr[MYSQLI_TYPE_VAR_STRING
] = 'string';
478 $typeAr[MYSQLI_TYPE_STRING
] = 'string';
479 // MySQL returns MYSQLI_TYPE_STRING for CHAR
480 // and MYSQLI_TYPE_CHAR === MYSQLI_TYPE_TINY
481 // so this would override TINYINT and mark all TINYINT as string
482 // https://sf.net/tracker/?func=detail&aid=1532111&group_id=23067&atid=377408
483 //$typeAr[MYSQLI_TYPE_CHAR] = 'string';
484 $typeAr[MYSQLI_TYPE_GEOMETRY
] = 'unknown';
485 $typeAr[MYSQLI_TYPE_BIT
] = 'bit';
487 $fields = mysqli_fetch_fields($result);
489 // this happens sometimes (seen under MySQL 4.0.25)
490 if (!is_array($fields)) {
494 foreach ($fields as $k => $field) {
495 $fields[$k]->_type
= $field->type
;
496 $fields[$k]->type
= $typeAr[$field->type
];
497 $fields[$k]->_flags
= $field->flags
;
498 $fields[$k]->flags
= PMA_DBI_field_flags($result, $k);
500 // Enhance the field objects for mysql-extension compatibilty
501 //$flags = explode(' ', $fields[$k]->flags);
502 //array_unshift($flags, 'dummy');
503 $fields[$k]->multiple_key
504 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_MULTIPLE_KEY_FLAG
);
505 $fields[$k]->primary_key
506 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_PRI_KEY_FLAG
);
507 $fields[$k]->unique_key
508 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_UNIQUE_KEY_FLAG
);
509 $fields[$k]->not_null
510 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_NOT_NULL_FLAG
);
511 $fields[$k]->unsigned
512 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_UNSIGNED_FLAG
);
513 $fields[$k]->zerofill
514 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_ZEROFILL_FLAG
);
516 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_NUM_FLAG
);
518 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_BLOB_FLAG
);
524 * return number of fields in given $result
526 * @param object mysqli result $result
527 * @return integer field count
529 function PMA_DBI_num_fields($result)
531 return mysqli_num_fields($result);
535 * returns the length of the given field $i in $result
537 * @uses mysqli_fetch_field_direct()
538 * @param object mysqli result $result
539 * @param integer $i field
540 * @return integer length of field
542 function PMA_DBI_field_len($result, $i)
544 return mysqli_fetch_field_direct($result, $i)->length
;
548 * returns name of $i. field in $result
550 * @uses mysqli_fetch_field_direct()
551 * @param object mysqli result $result
552 * @param integer $i field
553 * @return string name of $i. field in $result
555 function PMA_DBI_field_name($result, $i)
557 return mysqli_fetch_field_direct($result, $i)->name
;
561 * returns concatenated string of human readable field flags
563 * @uses MYSQLI_UNIQUE_KEY_FLAG
564 * @uses MYSQLI_NUM_FLAG
565 * @uses MYSQLI_PART_KEY_FLAG
566 * @uses MYSQLI_TYPE_SET
567 * @uses MYSQLI_TIMESTAMP_FLAG
568 * @uses MYSQLI_AUTO_INCREMENT_FLAG
569 * @uses MYSQLI_TYPE_ENUM
570 * @uses MYSQLI_ZEROFILL_FLAG
571 * @uses MYSQLI_UNSIGNED_FLAG
572 * @uses MYSQLI_BLOB_FLAG
573 * @uses MYSQLI_MULTIPLE_KEY_FLAG
574 * @uses MYSQLI_UNIQUE_KEY_FLAG
575 * @uses MYSQLI_PRI_KEY_FLAG
576 * @uses MYSQLI_NOT_NULL_FLAG
577 * @uses MYSQLI_TYPE_BLOB
578 * @uses MYSQLI_TYPE_MEDIUM_BLOB
579 * @uses MYSQLI_TYPE_LONG_BLOB
580 * @uses MYSQLI_TYPE_VAR_STRING
581 * @uses MYSQLI_TYPE_STRING
582 * @uses mysqli_fetch_field_direct()
583 * @param object mysqli result $result
584 * @param integer $i field
585 * @return string field flags
587 function PMA_DBI_field_flags($result, $i)
589 // This is missing from PHP 5.2.5, see http://bugs.php.net/bug.php?id=44846
590 if (! defined('MYSQLI_ENUM_FLAG')) {
591 define('MYSQLI_ENUM_FLAG', 256); // see MySQL source include/mysql_com.h
593 $f = mysqli_fetch_field_direct($result, $i);
595 $charsetnr = $f->charsetnr
;
598 if ($f & MYSQLI_UNIQUE_KEY_FLAG
) { $flags .= 'unique ';}
599 if ($f & MYSQLI_NUM_FLAG
) { $flags .= 'num ';}
600 if ($f & MYSQLI_PART_KEY_FLAG
) { $flags .= 'part_key ';}
601 if ($f & MYSQLI_SET_FLAG
) { $flags .= 'set ';}
602 if ($f & MYSQLI_TIMESTAMP_FLAG
) { $flags .= 'timestamp ';}
603 if ($f & MYSQLI_AUTO_INCREMENT_FLAG
) { $flags .= 'auto_increment ';}
604 if ($f & MYSQLI_ENUM_FLAG
) { $flags .= 'enum ';}
605 // See http://dev.mysql.com/doc/refman/6.0/en/c-api-datatypes.html:
606 // to determine if a string is binary, we should not use MYSQLI_BINARY_FLAG
607 // but instead the charsetnr member of the MYSQL_FIELD
608 // structure. Watch out: some types like DATE returns 63 in charsetnr
609 // so we have to check also the type.
610 // Unfortunately there is no equivalent in the mysql extension.
611 if (($type == MYSQLI_TYPE_TINY_BLOB ||
$type == MYSQLI_TYPE_BLOB ||
$type == MYSQLI_TYPE_MEDIUM_BLOB ||
$type == MYSQLI_TYPE_LONG_BLOB ||
$type == MYSQLI_TYPE_VAR_STRING ||
$type == MYSQLI_TYPE_STRING
) && 63 == $charsetnr) { $flags .= 'binary ';}
612 if ($f & MYSQLI_ZEROFILL_FLAG
) { $flags .= 'zerofill ';}
613 if ($f & MYSQLI_UNSIGNED_FLAG
) { $flags .= 'unsigned ';}
614 if ($f & MYSQLI_BLOB_FLAG
) { $flags .= 'blob ';}
615 if ($f & MYSQLI_MULTIPLE_KEY_FLAG
) { $flags .= 'multiple_key ';}
616 if ($f & MYSQLI_UNIQUE_KEY_FLAG
) { $flags .= 'unique_key ';}
617 if ($f & MYSQLI_PRI_KEY_FLAG
) { $flags .= 'primary_key ';}
618 if ($f & MYSQLI_NOT_NULL_FLAG
) { $flags .= 'not_null ';}