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 if (! defined('PMA_DBI_CONNECT_FAILED_CONTROLUSER')) {
95 define('PMA_DBI_CONNECT_FAILED_CONTROLUSER', true);
102 PMA_DBI_postConnect($link, $is_controluser);
108 * selects given database
110 * @uses $GLOBALS['userlink']
111 * @uses PMA_MYSQL_INT_VERSION
112 * @uses PMA_convert_charset()
113 * @uses mysqli_select_db()
114 * @param string $dbname database name to select
115 * @param object mysqli $link the mysli object
116 * @return boolean treu or false
118 function PMA_DBI_select_db($dbname, $link = null)
121 if (isset($GLOBALS['userlink'])) {
122 $link = $GLOBALS['userlink'];
127 if (PMA_MYSQL_INT_VERSION
< 40100) {
128 $dbname = PMA_convert_charset($dbname);
130 return mysqli_select_db($link, $dbname);
134 * runs a query and returns the result
136 * @uses PMA_DBI_QUERY_STORE
137 * @uses PMA_DBI_QUERY_UNBUFFERED
138 * @uses PMA_MYSQL_INT_VERSION
139 * @uses $GLOBALS['userlink']
140 * @uses PMA_convert_charset()
141 * @uses MYSQLI_STORE_RESULT
142 * @uses MYSQLI_USE_RESULT
143 * @uses mysqli_query()
145 * @param string $query query to execute
146 * @param object mysqli $link mysqli object
147 * @param integer $options
148 * @return mixed true, false or result object
150 function PMA_DBI_try_query($query, $link = null, $options = 0)
152 if ($options == ($options | PMA_DBI_QUERY_STORE
)) {
153 $method = MYSQLI_STORE_RESULT
;
154 } elseif ($options == ($options | PMA_DBI_QUERY_UNBUFFERED
)) {
155 $method = MYSQLI_USE_RESULT
;
161 if (isset($GLOBALS['userlink'])) {
162 $link = $GLOBALS['userlink'];
167 if (defined('PMA_MYSQL_INT_VERSION') && PMA_MYSQL_INT_VERSION
< 40100) {
168 $query = PMA_convert_charset($query);
170 return mysqli_query($link, $query, $method);
172 // From the PHP manual:
173 // "note: returns true on success or false on failure. For SELECT,
174 // SHOW, DESCRIBE or EXPLAIN, mysqli_query() will return a result object"
175 // so, do not use the return value to feed mysqli_num_rows() if it's
180 * returns $type array of rows from given $result
182 * The following function is meant for internal use only.
183 * Do not call it from outside this library!
185 * @uses $GLOBALS['allow_recoding']
186 * @uses $GLOBALS['cfg']['AllowAnywhereRecoding']
187 * @uses PMA_MYSQL_INT_VERSION
188 * @uses PMA_DBI_get_fields_meta()
189 * @uses PMA_convert_display_charset()
190 * @uses mysqli_fetch_array()
191 * @uses mysqli_num_fields()
193 * @param object mysqli result $result
194 * @param integer $type ASSOC, BOTH, or NUMERIC array
195 * @return array results
198 function PMA_mysqli_fetch_array($result, $type = false)
200 if ($type != false) {
201 $data = @mysqli_fetch_array
($result, $type);
203 $data = @mysqli_fetch_array
($result);
206 /* No data returned => do not touch it */
211 if (!defined('PMA_MYSQL_INT_VERSION') || PMA_MYSQL_INT_VERSION
>= 40100
212 ||
!(isset($GLOBALS['cfg']['AllowAnywhereRecoding'])
213 && $GLOBALS['cfg']['AllowAnywhereRecoding']
214 && $GLOBALS['allow_recoding'])) {
215 /* No recoding -> return data as we got them */
220 $num = mysqli_num_fields($result);
222 $fields = PMA_DBI_get_fields_meta($result);
224 // sometimes, mysqli_fetch_fields() does not return results
225 // (as seen in PHP 5.1.0-dev), so for now, return $data unchanged
230 for ($i = 0; $i < $num; $i++
) {
231 if (!isset($fields[$i]->type
)) {
232 /* No meta information available -> we guess that it should be
234 if (isset($data[$i])) {
235 $ret[$i] = PMA_convert_display_charset($data[$i]);
237 if (isset($fields[$i]->name
) && isset($data[$fields[$i]->name
])) {
238 $ret[PMA_convert_display_charset($fields[$i]->name
)] =
239 PMA_convert_display_charset($data[$fields[$i]->name
]);
242 /* Meta information available -> check type of field and convert
243 * it according to the type */
244 if (stristr($fields[$i]->type
, 'BLOB')
245 ||
stristr($fields[$i]->type
, 'BINARY')) {
246 if (isset($data[$i])) {
247 $ret[$i] = $data[$i];
249 if (isset($data[$fields[$i]->name
])) {
250 $ret[PMA_convert_display_charset($fields[$i]->name
)] =
251 $data[$fields[$i]->name
];
254 if (isset($data[$i])) {
255 $ret[$i] = PMA_convert_display_charset($data[$i]);
257 if (isset($data[$fields[$i]->name
])) {
258 $ret[PMA_convert_display_charset($fields[$i]->name
)] =
259 PMA_convert_display_charset($data[$fields[$i]->name
]);
268 * returns array of rows with associative and numeric keys from $result
270 * @uses PMA_mysqli_fetch_array()
272 * @param object mysqli result $result
273 * @return array result rows
275 function PMA_DBI_fetch_array($result)
277 return PMA_mysqli_fetch_array($result, MYSQLI_BOTH
);
281 * returns array of rows with associative keys from $result
283 * @uses PMA_mysqli_fetch_array()
285 * @param object mysqli result $result
286 * @return array result rows
288 function PMA_DBI_fetch_assoc($result)
290 return PMA_mysqli_fetch_array($result, MYSQLI_ASSOC
);
294 * returns array of rows with numeric keys from $result
296 * @uses PMA_mysqli_fetch_array()
298 * @param object mysqli result $result
299 * @return array result rows
301 function PMA_DBI_fetch_row($result)
303 return PMA_mysqli_fetch_array($result, MYSQLI_NUM
);
307 * Frees the memory associated with the results
309 * @uses mysqli_result
310 * @uses func_get_args()
312 * @uses mysqli_free_result()
313 * @param result $result,... one or more mysql result resources
315 function PMA_DBI_free_result()
317 foreach (func_get_args() as $result) {
318 if ($result instanceof mysqli_result
) {
319 mysqli_free_result($result);
325 * Returns a string representing the type of connection used
326 * @uses mysqli_get_host_info()
327 * @uses $GLOBALS['userlink'] as default for $link
328 * @param resource $link mysql link
329 * @return string type of connection used
331 function PMA_DBI_get_host_info($link = null)
333 if (null === $link) {
334 if (isset($GLOBALS['userlink'])) {
335 $link = $GLOBALS['userlink'];
340 return mysqli_get_host_info($link);
344 * Returns the version of the MySQL protocol used
345 * @uses mysqli_get_proto_info()
346 * @uses $GLOBALS['userlink'] as default for $link
347 * @param resource $link mysql link
348 * @return integer version of the MySQL protocol used
350 function PMA_DBI_get_proto_info($link = null)
352 if (null === $link) {
353 if (isset($GLOBALS['userlink'])) {
354 $link = $GLOBALS['userlink'];
359 return mysqli_get_proto_info($link);
363 * returns a string that represents the client library version
364 * @uses mysqli_get_client_info()
365 * @return string MySQL client library version
367 function PMA_DBI_get_client_info()
369 return mysqli_get_client_info();
373 * returns last error message or false if no errors occured
375 * @uses PMA_MYSQL_INT_VERSION
376 * @uses PMA_convert_display_charset()
377 * @uses PMA_DBI_convert_message()
378 * @uses $GLOBALS['errno']
379 * @uses $GLOBALS['userlink']
380 * @uses $GLOBALS['strServerNotResponding']
381 * @uses $GLOBALS['strSocketProblem']
382 * @uses mysqli_errno()
383 * @uses mysqli_error()
384 * @uses mysqli_connect_errno()
385 * @uses mysqli_connect_error()
387 * @param resource $link mysql link
388 * @return string|boolean $error or false
390 function PMA_DBI_getError($link = null)
392 $GLOBALS['errno'] = 0;
394 if (null === $link && isset($GLOBALS['userlink'])) {
395 $link =& $GLOBALS['userlink'];
396 // Do not stop now. We still can get the error code
397 // with mysqli_connect_errno()
402 if (null !== $link) {
403 $error_number = mysqli_errno($link);
404 $error_message = mysqli_error($link);
406 $error_number = mysqli_connect_errno();
407 $error_message = mysqli_connect_error();
409 if (0 == $error_number) {
413 // keep the error number for further check after the call to PMA_DBI_getError()
414 $GLOBALS['errno'] = $error_number;
416 if (! empty($error_message)) {
417 $error_message = PMA_DBI_convert_message($error_message);
420 if ($error_number == 2002) {
421 $error = '#' . ((string) $error_number) . ' - ' . $GLOBALS['strServerNotResponding'] . ' ' . $GLOBALS['strSocketProblem'];
422 } elseif (defined('PMA_MYSQL_INT_VERSION') && PMA_MYSQL_INT_VERSION
>= 40100) {
423 $error = '#' . ((string) $error_number) . ' - ' . $error_message;
425 $error = '#' . ((string) $error_number) . ' - ' . PMA_convert_display_charset($error_message);
431 * closes given database $link or $GLOBALS['userlink']
433 * @uses $GLOBALS['userlink']
434 * @uses mysqli_close()
435 * @param object mysqli $link the mysqli object
436 * @return boolean treu or false
438 function PMA_DBI_close($link = null)
441 if (isset($GLOBALS['userlink'])) {
442 $link = $GLOBALS['userlink'];
447 return @mysqli_close
($link);
452 * @param object mysqli result $result
454 function PMA_DBI_num_rows($result)
456 // see the note for PMA_DBI_try_query();
457 if (!is_bool($result)) {
458 return @mysqli_num_rows
($result);
465 * returns last inserted auto_increment id for given $link or $GLOBALS['userlink']
467 * @uses $GLOBALS['userlink']
468 * @uses mysqli_insert_id()
469 * @param object mysqli $link the mysqli object
470 * @return string ineteger
472 function PMA_DBI_insert_id($link = '')
475 if (isset($GLOBALS['userlink'])) {
476 $link = $GLOBALS['userlink'];
481 return mysqli_insert_id($link);
485 * returns the number of rows affected by last query
487 * @uses $GLOBALS['userlink']
488 * @uses mysqli_affected_rows()
489 * @param object mysqli $link the mysqli object
490 * @return string integer
492 function PMA_DBI_affected_rows($link = null)
495 if (isset($GLOBALS['userlink'])) {
496 $link = $GLOBALS['userlink'];
501 return mysqli_affected_rows($link);
505 * returns metainfo for fields in $result
507 * @todo preserve orignal flags value
508 * @uses PMA_DBI_field_flags()
509 * @uses MYSQLI_TYPE_*
510 * @uses MYSQLI_MULTIPLE_KEY_FLAG
511 * @uses MYSQLI_PRI_KEY_FLAG
512 * @uses MYSQLI_UNIQUE_KEY_FLAG
513 * @uses MYSQLI_NOT_NULL_FLAG
514 * @uses MYSQLI_UNSIGNED_FLAG
515 * @uses MYSQLI_ZEROFILL_FLAG
516 * @uses MYSQLI_NUM_FLAG
517 * @uses MYSQLI_TYPE_BLOB
518 * @uses MYSQLI_BLOB_FLAG
520 * @uses mysqli_fetch_fields()
522 * @param object mysqli result $result
523 * @return array meta info for fields in $result
525 function PMA_DBI_get_fields_meta($result)
527 // Build an associative array for a type look up
529 $typeAr[MYSQLI_TYPE_DECIMAL
] = 'real';
530 $typeAr[MYSQLI_TYPE_NEWDECIMAL
] = 'real';
531 $typeAr[MYSQLI_TYPE_BIT
] = 'int';
532 $typeAr[MYSQLI_TYPE_TINY
] = 'int';
533 $typeAr[MYSQLI_TYPE_SHORT
] = 'int';
534 $typeAr[MYSQLI_TYPE_LONG
] = 'int';
535 $typeAr[MYSQLI_TYPE_FLOAT
] = 'real';
536 $typeAr[MYSQLI_TYPE_DOUBLE
] = 'real';
537 $typeAr[MYSQLI_TYPE_NULL
] = 'null';
538 $typeAr[MYSQLI_TYPE_TIMESTAMP
] = 'timestamp';
539 $typeAr[MYSQLI_TYPE_LONGLONG
] = 'int';
540 $typeAr[MYSQLI_TYPE_INT24
] = 'int';
541 $typeAr[MYSQLI_TYPE_DATE
] = 'date';
542 $typeAr[MYSQLI_TYPE_TIME
] = 'time';
543 $typeAr[MYSQLI_TYPE_DATETIME
] = 'datetime';
544 $typeAr[MYSQLI_TYPE_YEAR
] = 'year';
545 $typeAr[MYSQLI_TYPE_NEWDATE
] = 'date';
546 $typeAr[MYSQLI_TYPE_ENUM
] = 'unknown';
547 $typeAr[MYSQLI_TYPE_SET
] = 'unknown';
548 $typeAr[MYSQLI_TYPE_TINY_BLOB
] = 'blob';
549 $typeAr[MYSQLI_TYPE_MEDIUM_BLOB
] = 'blob';
550 $typeAr[MYSQLI_TYPE_LONG_BLOB
] = 'blob';
551 $typeAr[MYSQLI_TYPE_BLOB
] = 'blob';
552 $typeAr[MYSQLI_TYPE_VAR_STRING
] = 'string';
553 $typeAr[MYSQLI_TYPE_STRING
] = 'string';
554 // MySQL returns MYSQLI_TYPE_STRING for CHAR
555 // and MYSQLI_TYPE_CHAR === MYSQLI_TYPE_TINY
556 // so this would override TINYINT and mark all TINYINT as string
557 // https://sf.net/tracker/?func=detail&aid=1532111&group_id=23067&atid=377408
558 //$typeAr[MYSQLI_TYPE_CHAR] = 'string';
559 $typeAr[MYSQLI_TYPE_GEOMETRY
] = 'unknown';
560 $typeAr[MYSQLI_TYPE_BIT
] = 'bit';
562 $fields = mysqli_fetch_fields($result);
564 // this happens sometimes (seen under MySQL 4.0.25)
565 if (!is_array($fields)) {
569 foreach ($fields as $k => $field) {
570 $fields[$k]->_type
= $field->type
;
571 $fields[$k]->type
= $typeAr[$field->type
];
572 $fields[$k]->_flags
= $field->flags
;
573 $fields[$k]->flags
= PMA_DBI_field_flags($result, $k);
575 // Enhance the field objects for mysql-extension compatibilty
576 //$flags = explode(' ', $fields[$k]->flags);
577 //array_unshift($flags, 'dummy');
578 $fields[$k]->multiple_key
579 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_MULTIPLE_KEY_FLAG
);
580 $fields[$k]->primary_key
581 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_PRI_KEY_FLAG
);
582 $fields[$k]->unique_key
583 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_UNIQUE_KEY_FLAG
);
584 $fields[$k]->not_null
585 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_NOT_NULL_FLAG
);
586 $fields[$k]->unsigned
587 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_UNSIGNED_FLAG
);
588 $fields[$k]->zerofill
589 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_ZEROFILL_FLAG
);
591 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_NUM_FLAG
);
593 = (int) (bool) ($fields[$k]->_flags
& MYSQLI_BLOB_FLAG
);
599 * return number of fields in given $result
601 * @param object mysqli result $result
602 * @return integer field count
604 function PMA_DBI_num_fields($result)
606 return mysqli_num_fields($result);
610 * returns the length of the given field $i in $result
612 * @uses mysqli_fetch_field_direct()
613 * @param object mysqli result $result
614 * @param integer $i field
615 * @return integer length of field
617 function PMA_DBI_field_len($result, $i)
619 $info = mysqli_fetch_field_direct($result, $i);
620 // stdClass::$length will be integrated in
621 // mysqli-ext when mysql4.1 has been released.
622 return @$info->length
;
626 * returns name of $i. field in $result
628 * @uses mysqli_fetch_field_direct()
629 * @param object mysqli result $result
630 * @param integer $i field
631 * @return string name of $i. field in $result
633 function PMA_DBI_field_name($result, $i)
635 $info = mysqli_fetch_field_direct($result, $i);
640 * returns concatenated string of human readable field flags
642 * @uses MYSQLI_UNIQUE_KEY_FLAG
643 * @uses MYSQLI_NUM_FLAG
644 * @uses MYSQLI_PART_KEY_FLAG
645 * @uses MYSQLI_TYPE_SET
646 * @uses MYSQLI_TIMESTAMP_FLAG
647 * @uses MYSQLI_AUTO_INCREMENT_FLAG
648 * @uses MYSQLI_TYPE_ENUM
649 * @uses MYSQLI_ZEROFILL_FLAG
650 * @uses MYSQLI_UNSIGNED_FLAG
651 * @uses MYSQLI_BLOB_FLAG
652 * @uses MYSQLI_MULTIPLE_KEY_FLAG
653 * @uses MYSQLI_UNIQUE_KEY_FLAG
654 * @uses MYSQLI_PRI_KEY_FLAG
655 * @uses MYSQLI_NOT_NULL_FLAG
656 * @uses MYSQLI_TYPE_TINY_BLOB
657 * @uses MYSQLI_TYPE_BLOB
658 * @uses MYSQLI_TYPE_MEDIUM_BLOB
659 * @uses MYSQLI_TYPE_LONG_BLOB
660 * @uses MYSQLI_TYPE_VAR_STRING
661 * @uses MYSQLI_TYPE_STRING
662 * @uses mysqli_fetch_field_direct()
663 * @uses PMA_convert_display_charset()
664 * @param object mysqli result $result
665 * @param integer $i field
666 * @return string field flags
668 function PMA_DBI_field_flags($result, $i)
670 // This is missing from PHP 5.2.5, see http://bugs.php.net/bug.php?id=44846
671 if (! defined('MYSQLI_ENUM_FLAG')) {
672 define('MYSQLI_ENUM_FLAG', 256); // see MySQL source include/mysql_com.h
674 $f = mysqli_fetch_field_direct($result, $i);
676 $charsetnr = $f->charsetnr
;
679 if ($f & MYSQLI_UNIQUE_KEY_FLAG
) { $flags .= 'unique ';}
680 if ($f & MYSQLI_NUM_FLAG
) { $flags .= 'num ';}
681 if ($f & MYSQLI_PART_KEY_FLAG
) { $flags .= 'part_key ';}
682 if ($f & MYSQLI_SET_FLAG
) { $flags .= 'set ';}
683 if ($f & MYSQLI_TIMESTAMP_FLAG
) { $flags .= 'timestamp ';}
684 if ($f & MYSQLI_AUTO_INCREMENT_FLAG
) { $flags .= 'auto_increment ';}
685 if ($f & MYSQLI_ENUM_FLAG
) { $flags .= 'enum ';}
686 // See http://dev.mysql.com/doc/refman/6.0/en/c-api-datatypes.html:
687 // to determine if a string is binary, we should not use MYSQLI_BINARY_FLAG
688 // but instead the charsetnr member of the MYSQL_FIELD
689 // structure. Watch out: some types like DATE returns 63 in charsetnr
690 // so we have to check also the type.
691 // Unfortunately there is no equivalent in the mysql extension.
692 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 ';}
693 if ($f & MYSQLI_ZEROFILL_FLAG
) { $flags .= 'zerofill ';}
694 if ($f & MYSQLI_UNSIGNED_FLAG
) { $flags .= 'unsigned ';}
695 if ($f & MYSQLI_BLOB_FLAG
) { $flags .= 'blob ';}
696 if ($f & MYSQLI_MULTIPLE_KEY_FLAG
) { $flags .= 'multiple_key ';}
697 if ($f & MYSQLI_UNIQUE_KEY_FLAG
) { $flags .= 'unique_key ';}
698 if ($f & MYSQLI_PRI_KEY_FLAG
) { $flags .= 'primary_key ';}
699 if ($f & MYSQLI_NOT_NULL_FLAG
) { $flags .= 'not_null ';}
700 return PMA_convert_display_charset(trim($flags));