Add OK and Cancel button for grid editing
[phpmyadmin/arisferyanto.git] / libraries / dbi / mysqli.dbi.lib.php
blob3d8a2e28c2927849523f8c3d9be218c03ee13b14
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-MySQLi
7 */
8 if (! defined('PHPMYADMIN')) {
9 exit;
12 require_once './libraries/logging.lib.php';
14 /**
15 * MySQL client API
17 if (!defined('PMA_MYSQL_CLIENT_API')) {
18 $client_api = explode('.', mysqli_get_client_info());
19 define('PMA_MYSQL_CLIENT_API', (int)sprintf('%d%02d%02d', $client_api[0], $client_api[1], intval($client_api[2])));
20 unset($client_api);
23 /**
24 * some PHP versions are reporting extra messages like "No index used in query"
27 mysqli_report(MYSQLI_REPORT_OFF);
29 /**
30 * some older mysql client libs are missing these constants ...
32 if (! defined('MYSQLI_BINARY_FLAG')) {
33 define('MYSQLI_BINARY_FLAG', 128);
36 /**
37 * @see http://bugs.php.net/36007
39 if (! defined('MYSQLI_TYPE_NEWDECIMAL')) {
40 define('MYSQLI_TYPE_NEWDECIMAL', 246);
42 if (! defined('MYSQLI_TYPE_BIT')) {
43 define('MYSQLI_TYPE_BIT', 16);
46 // for Drizzle
47 if (! defined('MYSQLI_TYPE_VARCHAR')) {
48 define('MYSQLI_TYPE_VARCHAR', 15);
51 /**
52 * Helper function for connecting to the database server
54 * @param mysqli $link
55 * @param string $host
56 * @param string $user
57 * @param string $password
58 * @param string $dbname
59 * @param int $server_port
60 * @param string $server_socket
61 * @param int $client_flags
62 * @param bool $persistent
63 * @return bool
65 function PMA_DBI_real_connect($link, $host, $user, $password, $dbname, $server_port, $server_socket, $client_flags = null, $persistent = false)
67 global $cfg;
69 if ($cfg['PersistentConnections'] || $persistent) {
70 $host = 'p:' . $host;
72 if ($client_flags === null) {
73 return @mysqli_real_connect(
74 $link,
75 $host,
76 $user,
77 $password,
78 $dbname,
79 $server_port,
80 $server_socket
82 } else {
83 return @mysqli_real_connect(
84 $link,
85 $host,
86 $user,
87 $password,
88 $dbname,
89 $server_port,
90 $server_socket,
91 $client_flags
96 /**
97 * connects to the database server
99 * @param string $user mysql user name
100 * @param string $password mysql user password
101 * @param bool $is_controluser
102 * @param array $server host/port/socket
103 * @param bool $auxiliary_connection (when true, don't go back to login if connection fails)
104 * @return mixed false on error or a mysqli object on success
106 function PMA_DBI_connect($user, $password, $is_controluser = false, $server = null, $auxiliary_connection = false)
108 global $cfg;
110 if ($server) {
111 $server_port = (empty($server['port']))
112 ? false
113 : (int)$server['port'];
114 $server_socket = (empty($server['socket']))
115 ? ''
116 : $server['socket'];
117 $server['host'] = (empty($server['host']))
118 ? 'localhost'
119 : $server['host'];
120 } else {
121 $server_port = (empty($cfg['Server']['port']))
122 ? false
123 : (int) $cfg['Server']['port'];
124 $server_socket = (empty($cfg['Server']['socket']))
125 ? null
126 : $cfg['Server']['socket'];
129 // NULL enables connection to the default socket
131 $link = mysqli_init();
133 mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, true);
135 $client_flags = 0;
137 /* Optionally compress connection */
138 if ($cfg['Server']['compress'] && defined('MYSQLI_CLIENT_COMPRESS')) {
139 $client_flags |= MYSQLI_CLIENT_COMPRESS;
142 /* Optionally enable SSL */
143 if ($cfg['Server']['ssl'] && defined('MYSQLI_CLIENT_SSL')) {
144 $client_flags |= MYSQLI_CLIENT_SSL;
147 if (!$server) {
148 $return_value = @PMA_DBI_real_connect(
149 $link,
150 $cfg['Server']['host'],
151 $user,
152 $password,
153 false,
154 $server_port,
155 $server_socket,
156 $client_flags
158 // Retry with empty password if we're allowed to
159 if ($return_value == false && isset($cfg['Server']['nopassword']) && $cfg['Server']['nopassword'] && !$is_controluser) {
160 $return_value = @PMA_DBI_real_connect(
161 $link,
162 $cfg['Server']['host'],
163 $user,
165 false,
166 $server_port,
167 $server_socket,
168 $client_flags
171 } else {
172 $return_value = @PMA_DBI_real_connect(
173 $link,
174 $server['host'],
175 $user,
176 $password,
177 false,
178 $server_port,
179 $server_socket
183 if ($return_value == false) {
184 if ($is_controluser) {
185 trigger_error(
186 __('Connection for controluser as defined in your configuration failed.'),
187 E_USER_WARNING
189 return false;
191 // we could be calling PMA_DBI_connect() to connect to another
192 // server, for example in the Synchronize feature, so do not
193 // go back to main login if it fails
194 if (! $auxiliary_connection) {
195 PMA_log_user($user, 'mysql-denied');
196 PMA_auth_fails();
197 } else {
198 return false;
200 } else {
201 PMA_DBI_postConnect($link, $is_controluser);
204 return $link;
208 * selects given database
210 * @param string $dbname database name to select
211 * @param mysqli $link the mysqli object
212 * @return boolean
214 function PMA_DBI_select_db($dbname, $link = null)
216 if (empty($link)) {
217 if (isset($GLOBALS['userlink'])) {
218 $link = $GLOBALS['userlink'];
219 } else {
220 return false;
223 return mysqli_select_db($link, $dbname);
227 * runs a query and returns the result
229 * @param string $query query to execute
230 * @param mysqli $link mysqli object
231 * @param int $options
232 * @return mysqli_result|bool
234 function PMA_DBI_real_query($query, $link, $options)
236 if ($options == ($options | PMA_DBI_QUERY_STORE)) {
237 $method = MYSQLI_STORE_RESULT;
238 } elseif ($options == ($options | PMA_DBI_QUERY_UNBUFFERED)) {
239 $method = MYSQLI_USE_RESULT;
240 } else {
241 $method = 0;
244 return mysqli_query($link, $query, $method);
248 * returns array of rows with associative and numeric keys from $result
250 * @param mysqli_result $result
251 * @return array
253 function PMA_DBI_fetch_array($result)
255 return mysqli_fetch_array($result, MYSQLI_BOTH);
259 * returns array of rows with associative keys from $result
261 * @param mysqli_result $result
262 * @return array
264 function PMA_DBI_fetch_assoc($result)
266 return mysqli_fetch_array($result, MYSQLI_ASSOC);
270 * returns array of rows with numeric keys from $result
272 * @param mysqli_result $result
273 * @return array
275 function PMA_DBI_fetch_row($result)
277 return mysqli_fetch_array($result, MYSQLI_NUM);
281 * Adjusts the result pointer to an arbitrary row in the result
283 * @param $result
284 * @param $offset
285 * @return bool true on success, false on failure
287 function PMA_DBI_data_seek($result, $offset)
289 return mysqli_data_seek($result, $offset);
293 * Frees memory associated with the result
295 * @param mysqli_result $result
297 function PMA_DBI_free_result($result)
299 if ($result instanceof mysqli_result) {
300 mysqli_free_result($result);
305 * Check if there are any more query results from a multi query
307 * @param mysqli $link the mysqli object
308 * @return bool true or false
310 function PMA_DBI_more_results($link = null)
312 if (empty($link)) {
313 if (isset($GLOBALS['userlink'])) {
314 $link = $GLOBALS['userlink'];
315 } else {
316 return false;
319 return mysqli_more_results($link);
323 * Prepare next result from multi_query
325 * @param mysqli $link the mysqli object
326 * @return bool true or false
328 function PMA_DBI_next_result($link = null)
330 if (empty($link)) {
331 if (isset($GLOBALS['userlink'])) {
332 $link = $GLOBALS['userlink'];
333 } else {
334 return false;
337 return mysqli_next_result($link);
341 * Returns a string representing the type of connection used
343 * @param resource $link mysql link
344 * @return string type of connection used
346 function PMA_DBI_get_host_info($link = null)
348 if (null === $link) {
349 if (isset($GLOBALS['userlink'])) {
350 $link = $GLOBALS['userlink'];
351 } else {
352 return false;
355 return mysqli_get_host_info($link);
359 * Returns the version of the MySQL protocol used
361 * @param resource $link mysql link
362 * @return integer version of the MySQL protocol used
364 function PMA_DBI_get_proto_info($link = null)
366 if (null === $link) {
367 if (isset($GLOBALS['userlink'])) {
368 $link = $GLOBALS['userlink'];
369 } else {
370 return false;
373 return mysqli_get_proto_info($link);
377 * returns a string that represents the client library version
379 * @return string MySQL client library version
381 function PMA_DBI_get_client_info()
383 return mysqli_get_client_info();
387 * returns last error message or false if no errors occured
389 * @param resource $link mysql link
390 * @return string|bool $error or false
392 function PMA_DBI_getError($link = null)
394 $GLOBALS['errno'] = 0;
396 /* Treat false same as null because of controllink */
397 if ($link === false) {
398 $link = null;
401 if (null === $link && isset($GLOBALS['userlink'])) {
402 $link =& $GLOBALS['userlink'];
403 // Do not stop now. We still can get the error code
404 // with mysqli_connect_errno()
405 // } else {
406 // return false;
409 if (null !== $link) {
410 $error_number = mysqli_errno($link);
411 $error_message = mysqli_error($link);
412 } else {
413 $error_number = mysqli_connect_errno();
414 $error_message = mysqli_connect_error();
416 if (0 == $error_number) {
417 return false;
420 // keep the error number for further check after the call to PMA_DBI_getError()
421 $GLOBALS['errno'] = $error_number;
423 return PMA_DBI_formatError($error_number, $error_message);
427 * returns the number of rows returned by last query
429 * @param mysqli_result $result
430 * @return string|int
432 function PMA_DBI_num_rows($result)
434 // see the note for PMA_DBI_try_query();
435 if (!is_bool($result)) {
436 return @mysqli_num_rows($result);
437 } else {
438 return 0;
443 * returns last inserted auto_increment id for given $link or $GLOBALS['userlink']
445 * @param mysqli $link the mysqli object
446 * @return string|int
448 function PMA_DBI_insert_id($link = null)
450 if (empty($link)) {
451 if (isset($GLOBALS['userlink'])) {
452 $link = $GLOBALS['userlink'];
453 } else {
454 return false;
457 // When no controluser is defined, using mysqli_insert_id($link)
458 // does not always return the last insert id due to a mixup with
459 // the tracking mechanism, but this works:
460 return PMA_DBI_fetch_value('SELECT LAST_INSERT_ID();', 0, 0, $link);
461 // Curiously, this problem does not happen with the mysql extension but
462 // there is another problem with BIGINT primary keys so PMA_DBI_insert_id()
463 // in the mysql extension also uses this logic.
467 * returns the number of rows affected by last query
469 * @param mysqli $link the mysqli object
470 * @param boolean $get_from_cache
471 * @return string|int
473 function PMA_DBI_affected_rows($link = null, $get_from_cache = true)
475 if (empty($link)) {
476 if (isset($GLOBALS['userlink'])) {
477 $link = $GLOBALS['userlink'];
478 } else {
479 return false;
482 if ($get_from_cache) {
483 return $GLOBALS['cached_affected_rows'];
484 } else {
485 return mysqli_affected_rows($link);
490 * returns metainfo for fields in $result
492 * @param mysqli_result $result
493 * @return array meta info for fields in $result
495 function PMA_DBI_get_fields_meta($result)
497 // Build an associative array for a type look up
498 $typeAr = array();
499 $typeAr[MYSQLI_TYPE_DECIMAL] = 'real';
500 $typeAr[MYSQLI_TYPE_NEWDECIMAL] = 'real';
501 $typeAr[MYSQLI_TYPE_BIT] = 'int';
502 $typeAr[MYSQLI_TYPE_TINY] = 'int';
503 $typeAr[MYSQLI_TYPE_SHORT] = 'int';
504 $typeAr[MYSQLI_TYPE_LONG] = 'int';
505 $typeAr[MYSQLI_TYPE_FLOAT] = 'real';
506 $typeAr[MYSQLI_TYPE_DOUBLE] = 'real';
507 $typeAr[MYSQLI_TYPE_NULL] = 'null';
508 $typeAr[MYSQLI_TYPE_TIMESTAMP] = 'timestamp';
509 $typeAr[MYSQLI_TYPE_LONGLONG] = 'int';
510 $typeAr[MYSQLI_TYPE_INT24] = 'int';
511 $typeAr[MYSQLI_TYPE_DATE] = 'date';
512 $typeAr[MYSQLI_TYPE_TIME] = 'time';
513 $typeAr[MYSQLI_TYPE_DATETIME] = 'datetime';
514 $typeAr[MYSQLI_TYPE_YEAR] = 'year';
515 $typeAr[MYSQLI_TYPE_NEWDATE] = 'date';
516 $typeAr[MYSQLI_TYPE_ENUM] = 'unknown';
517 $typeAr[MYSQLI_TYPE_SET] = 'unknown';
518 $typeAr[MYSQLI_TYPE_TINY_BLOB] = 'blob';
519 $typeAr[MYSQLI_TYPE_MEDIUM_BLOB] = 'blob';
520 $typeAr[MYSQLI_TYPE_LONG_BLOB] = 'blob';
521 $typeAr[MYSQLI_TYPE_BLOB] = 'blob';
522 $typeAr[MYSQLI_TYPE_VAR_STRING] = 'string';
523 $typeAr[MYSQLI_TYPE_STRING] = 'string';
524 $typeAr[MYSQLI_TYPE_VARCHAR] = 'string'; // for Drizzle
525 // MySQL returns MYSQLI_TYPE_STRING for CHAR
526 // and MYSQLI_TYPE_CHAR === MYSQLI_TYPE_TINY
527 // so this would override TINYINT and mark all TINYINT as string
528 // https://sf.net/tracker/?func=detail&aid=1532111&group_id=23067&atid=377408
529 //$typeAr[MYSQLI_TYPE_CHAR] = 'string';
530 $typeAr[MYSQLI_TYPE_GEOMETRY] = 'geometry';
531 $typeAr[MYSQLI_TYPE_BIT] = 'bit';
533 $fields = mysqli_fetch_fields($result);
535 // this happens sometimes (seen under MySQL 4.0.25)
536 if (!is_array($fields)) {
537 return false;
540 foreach ($fields as $k => $field) {
541 $fields[$k]->_type = $field->type;
542 $fields[$k]->type = $typeAr[$field->type];
543 $fields[$k]->_flags = $field->flags;
544 $fields[$k]->flags = PMA_DBI_field_flags($result, $k);
546 // Enhance the field objects for mysql-extension compatibilty
547 //$flags = explode(' ', $fields[$k]->flags);
548 //array_unshift($flags, 'dummy');
549 $fields[$k]->multiple_key
550 = (int) (bool) ($fields[$k]->_flags & MYSQLI_MULTIPLE_KEY_FLAG);
551 $fields[$k]->primary_key
552 = (int) (bool) ($fields[$k]->_flags & MYSQLI_PRI_KEY_FLAG);
553 $fields[$k]->unique_key
554 = (int) (bool) ($fields[$k]->_flags & MYSQLI_UNIQUE_KEY_FLAG);
555 $fields[$k]->not_null
556 = (int) (bool) ($fields[$k]->_flags & MYSQLI_NOT_NULL_FLAG);
557 $fields[$k]->unsigned
558 = (int) (bool) ($fields[$k]->_flags & MYSQLI_UNSIGNED_FLAG);
559 $fields[$k]->zerofill
560 = (int) (bool) ($fields[$k]->_flags & MYSQLI_ZEROFILL_FLAG);
561 $fields[$k]->numeric
562 = (int) (bool) ($fields[$k]->_flags & MYSQLI_NUM_FLAG);
563 $fields[$k]->blob
564 = (int) (bool) ($fields[$k]->_flags & MYSQLI_BLOB_FLAG);
566 return $fields;
570 * return number of fields in given $result
572 * @param mysqli_result $result
573 * @return int field count
575 function PMA_DBI_num_fields($result)
577 return mysqli_num_fields($result);
581 * returns the length of the given field $i in $result
583 * @param mysqli_result $result
584 * @param int $i field
585 * @return int length of field
587 function PMA_DBI_field_len($result, $i)
589 return mysqli_fetch_field_direct($result, $i)->length;
593 * returns name of $i. field in $result
595 * @param mysqli_result $result
596 * @param int $i field
597 * @return string name of $i. field in $result
599 function PMA_DBI_field_name($result, $i)
601 return mysqli_fetch_field_direct($result, $i)->name;
605 * returns concatenated string of human readable field flags
607 * @param mysqli_result $result
608 * @param int $i field
609 * @return string field flags
611 function PMA_DBI_field_flags($result, $i)
613 // This is missing from PHP 5.2.5, see http://bugs.php.net/bug.php?id=44846
614 if (! defined('MYSQLI_ENUM_FLAG')) {
615 define('MYSQLI_ENUM_FLAG', 256); // see MySQL source include/mysql_com.h
617 $f = mysqli_fetch_field_direct($result, $i);
618 $type = $f->type;
619 $charsetnr = $f->charsetnr;
620 $f = $f->flags;
621 $flags = '';
622 if ($f & MYSQLI_UNIQUE_KEY_FLAG) {
623 $flags .= 'unique ';
625 if ($f & MYSQLI_NUM_FLAG) {
626 $flags .= 'num ';
628 if ($f & MYSQLI_PART_KEY_FLAG) {
629 $flags .= 'part_key ';
631 if ($f & MYSQLI_SET_FLAG) {
632 $flags .= 'set ';
634 if ($f & MYSQLI_TIMESTAMP_FLAG) {
635 $flags .= 'timestamp ';
637 if ($f & MYSQLI_AUTO_INCREMENT_FLAG) {
638 $flags .= 'auto_increment ';
640 if ($f & MYSQLI_ENUM_FLAG) {
641 $flags .= 'enum ';
643 // See http://dev.mysql.com/doc/refman/6.0/en/c-api-datatypes.html:
644 // to determine if a string is binary, we should not use MYSQLI_BINARY_FLAG
645 // but instead the charsetnr member of the MYSQL_FIELD
646 // structure. Watch out: some types like DATE returns 63 in charsetnr
647 // so we have to check also the type.
648 // Unfortunately there is no equivalent in the mysql extension.
649 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) {
650 $flags .= 'binary ';
652 if ($f & MYSQLI_ZEROFILL_FLAG) {
653 $flags .= 'zerofill ';
655 if ($f & MYSQLI_UNSIGNED_FLAG) {
656 $flags .= 'unsigned ';
658 if ($f & MYSQLI_BLOB_FLAG) {
659 $flags .= 'blob ';
661 if ($f & MYSQLI_MULTIPLE_KEY_FLAG) {
662 $flags .= 'multiple_key ';
664 if ($f & MYSQLI_UNIQUE_KEY_FLAG) {
665 $flags .= 'unique_key ';
667 if ($f & MYSQLI_PRI_KEY_FLAG) {
668 $flags .= 'primary_key ';
670 if ($f & MYSQLI_NOT_NULL_FLAG) {
671 $flags .= 'not_null ';
673 return trim($flags);