Merge pull request #431 from xmujay/0609_monitor
[phpmyadmin/aamir.git] / sql.php
blob1f0fda58b87f86cdb739b68cd9a917eae1aba2fc
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * SQL executor
6 * @todo we must handle the case if sql.php is called directly with a query
7 * that returns 0 rows - to prevent cyclic redirects or includes
8 * @package PhpMyAdmin
9 */
11 /**
12 * Gets some core libraries
14 require_once 'libraries/common.inc.php';
15 require_once 'libraries/Table.class.php';
16 require_once 'libraries/Header.class.php';
17 require_once 'libraries/check_user_privileges.lib.php';
18 require_once 'libraries/bookmark.lib.php';
19 require_once 'libraries/sql.lib.php';
20 require_once 'libraries/sqlparser.lib.php';
22 $response = PMA_Response::getInstance();
23 $header = $response->getHeader();
24 $scripts = $header->getScripts();
25 $scripts->addFile('jquery/jquery-ui-timepicker-addon.js');
26 $scripts->addFile('tbl_change.js');
27 // the next one needed because sql.php may do a "goto" to tbl_structure.php
28 $scripts->addFile('tbl_structure.js');
29 $scripts->addFile('indexes.js');
30 $scripts->addFile('gis_data_editor.js');
32 /**
33 * Set ajax_reload in the response if it was already set
35 if (isset($ajax_reload) && $ajax_reload['reload'] === true) {
36 $response->addJSON('ajax_reload', $ajax_reload);
40 /**
41 * Defines the url to return to in case of error in a sql statement
43 // Security checkings
44 if (! empty($goto)) {
45 $is_gotofile = preg_replace('@^([^?]+).*$@s', '\\1', $goto);
46 if (! @file_exists('' . $is_gotofile)) {
47 unset($goto);
48 } else {
49 $is_gotofile = ($is_gotofile == $goto);
51 } else {
52 if (empty($table)) {
53 $goto = $cfg['DefaultTabDatabase'];
54 } else {
55 $goto = $cfg['DefaultTabTable'];
57 $is_gotofile = true;
58 } // end if
60 if (! isset($err_url)) {
61 $err_url = (! empty($back) ? $back : $goto)
62 . '?' . PMA_generate_common_url($db)
63 . ((strpos(' ' . $goto, 'db_') != 1 && strlen($table))
64 ? '&amp;table=' . urlencode($table)
65 : ''
67 } // end if
69 // Coming from a bookmark dialog
70 if (isset($_POST['bkm_fields']['bkm_sql_query'])) {
71 $sql_query = $_POST['bkm_fields']['bkm_sql_query'];
72 } elseif (isset($_GET['sql_query'])) {
73 $sql_query = $_GET['sql_query'];
76 // This one is just to fill $db
77 if (isset($_POST['bkm_fields']['bkm_database'])) {
78 $db = $_POST['bkm_fields']['bkm_database'];
82 // During grid edit, if we have a relational field, show the dropdown for it.
83 if (isset($_REQUEST['get_relational_values'])
84 && $_REQUEST['get_relational_values'] == true
85 ) {
86 $column = $_REQUEST['column'];
87 if ($_SESSION['tmp_user_values']['relational_display'] == 'D'
88 && isset($display_field)
89 && strlen($display_field)
90 && isset($_REQUEST['relation_key_or_display_column'])
91 && $_REQUEST['relation_key_or_display_column']
92 ) {
93 $curr_value = $_REQUEST['relation_key_or_display_column'];
94 } else {
95 $curr_value = $_REQUEST['curr_value'];
97 $dropdown = PMA_getHtmlForRelationalColumnDropdown(
98 $db, $table, $column, $curr_value
100 $response = PMA_Response::getInstance();
101 $response->addJSON('dropdown', $dropdown);
102 exit;
105 // Just like above, find possible values for enum fields during grid edit.
106 if (isset($_REQUEST['get_enum_values']) && $_REQUEST['get_enum_values'] == true) {
107 $column = $_REQUEST['column'];
108 $curr_value = $_REQUEST['curr_value'];
109 $dropdown = PMA_getHtmlForEnumColumnDropdown($db, $table, $column, $curr_value);
110 $response = PMA_Response::getInstance();
111 $response->addJSON('dropdown', $dropdown);
112 exit;
116 // Find possible values for set fields during grid edit.
117 if (isset($_REQUEST['get_set_values']) && $_REQUEST['get_set_values'] == true) {
118 $column = $_REQUEST['column'];
119 $curr_value = $_REQUEST['curr_value'];
120 $select = PMA_getHtmlForSetColumn($db, $table, $column, $curr_value);
121 $response = PMA_Response::getInstance();
122 $response->addJSON('select', $select);
123 exit;
127 * Check ajax request to set the column order
129 if (isset($_REQUEST['set_col_prefs']) && $_REQUEST['set_col_prefs'] == true) {
130 $pmatable = new PMA_Table($table, $db);
131 $retval = false;
133 // set column order
134 if (isset($_REQUEST['col_order'])) {
135 $col_order = explode(',', $_REQUEST['col_order']);
136 $retval = $pmatable->setUiProp(
137 PMA_Table::PROP_COLUMN_ORDER,
138 $col_order,
139 $_REQUEST['table_create_time']
141 if (gettype($retval) != 'boolean') {
142 $response = PMA_Response::getInstance();
143 $response->isSuccess(false);
144 $response->addJSON('message', $retval->getString());
145 exit;
149 // set column visibility
150 if ($retval === true && isset($_REQUEST['col_visib'])) {
151 $col_visib = explode(',', $_REQUEST['col_visib']);
152 $retval = $pmatable->setUiProp(
153 PMA_Table::PROP_COLUMN_VISIB, $col_visib,
154 $_REQUEST['table_create_time']
156 if (gettype($retval) != 'boolean') {
157 $response = PMA_Response::getInstance();
158 $response->isSuccess(false);
159 $response->addJSON('message', $retval->getString());
160 exit;
164 $response = PMA_Response::getInstance();
165 $response->isSuccess($retval == true);
166 exit;
169 // Default to browse if no query set and we have table
170 // (needed for browsing from DefaultTabTable)
171 if (empty($sql_query) && strlen($table) && strlen($db)) {
172 include_once 'libraries/bookmark.lib.php';
173 $book_sql_query = PMA_Bookmark_get(
174 $db,
175 '\'' . PMA_Util::sqlAddSlashes($table) . '\'',
176 'label',
177 false,
178 true
181 if (! empty($book_sql_query)) {
182 $GLOBALS['using_bookmark_message'] = PMA_message::notice(
183 __('Using bookmark "%s" as default browse query.')
185 $GLOBALS['using_bookmark_message']->addParam($table);
186 $GLOBALS['using_bookmark_message']->addMessage(
187 PMA_Util::showDocu('faq', 'faq6-22')
189 $sql_query = $book_sql_query;
190 } else {
191 $sql_query = 'SELECT * FROM ' . PMA_Util::backquote($table);
193 unset($book_sql_query);
195 // set $goto to what will be displayed if query returns 0 rows
196 $goto = '';
197 } else {
198 // Now we can check the parameters
199 PMA_Util::checkParameters(array('sql_query'));
203 * Parse and analyze the query
205 require_once 'libraries/parse_analyze.inc.php';
209 * Check rights in case of DROP DATABASE
211 * This test may be bypassed if $is_js_confirmed = 1 (already checked with js)
212 * but since a malicious user may pass this variable by url/form, we don't take
213 * into account this case.
215 if (! defined('PMA_CHK_DROP')
216 && ! $cfg['AllowUserDropDatabase']
217 && isset ($drop_database)
218 && $drop_database == 1
219 && ! $is_superuser
221 PMA_Util::mysqlDie(
222 __('"DROP DATABASE" statements are disabled.'),
225 $err_url
227 } // end if
229 // Include PMA_Index class for use in PMA_DisplayResults class
230 require_once './libraries/Index.class.php';
232 require_once 'libraries/DisplayResults.class.php';
234 $displayResultsObject = new PMA_DisplayResults(
235 $GLOBALS['db'], $GLOBALS['table'], $GLOBALS['goto'], $GLOBALS['sql_query']
238 $displayResultsObject->setConfigParamsForDisplayTable();
241 * Need to find the real end of rows?
243 if (isset($find_real_end) && $find_real_end) {
244 $unlim_num_rows = PMA_Table::countRecords($db, $table, true);
245 $_SESSION['tmp_user_values']['pos'] = @((ceil(
246 $unlim_num_rows / $_SESSION['tmp_user_values']['max_rows']
247 ) - 1) * $_SESSION['tmp_user_values']['max_rows']);
252 * Bookmark add
254 if (isset($_POST['store_bkm'])) {
255 $result = PMA_Bookmark_save(
256 $_POST['bkm_fields'],
257 (isset($_POST['bkm_all_users']) && $_POST['bkm_all_users'] == 'true' ? true : false)
259 $response = PMA_Response::getInstance();
260 if ($response->isAjax()) {
261 if ($result) {
262 $msg = PMA_message::success(__('Bookmark %s created'));
263 $msg->addParam($_POST['bkm_fields']['bkm_label']);
264 $response->addJSON('message', $msg);
265 } else {
266 $msg = PMA_message::error(__('Bookmark not created'));
267 $response->isSuccess(false);
268 $response->addJSON('message', $msg);
270 exit;
271 } else {
272 // go back to sql.php to redisplay query; do not use &amp; in this case:
273 PMA_sendHeaderLocation(
274 $cfg['PmaAbsoluteUri'] . $goto . '&label=' . $_POST['bkm_fields']['bkm_label']
277 } // end if
281 * Sets or modifies the $goto variable if required
283 if ($goto == 'sql.php') {
284 $is_gotofile = false;
285 $goto = 'sql.php?'
286 . PMA_generate_common_url($db, $table)
287 . '&amp;sql_query=' . urlencode($sql_query);
288 } // end if
291 * Go back to further page if table should not be dropped
293 if (isset($_REQUEST['btnDrop']) && $_REQUEST['btnDrop'] == __('No')) {
294 if (! empty($back)) {
295 $goto = $back;
297 if ($is_gotofile) {
298 if (strpos($goto, 'db_') === 0 && strlen($table)) {
299 $table = '';
301 $active_page = $goto;
302 include '' . PMA_securePath($goto);
303 } else {
304 PMA_sendHeaderLocation(
305 $cfg['PmaAbsoluteUri'] . str_replace('&amp;', '&', $goto)
308 exit();
309 } // end if
312 // assign default full_sql_query
313 $full_sql_query = $sql_query;
315 // Handle remembered sorting order, only for single table query
316 if ($GLOBALS['cfg']['RememberSorting']
317 && ! ($is_count || $is_export || $is_func || $is_analyse)
318 && isset($analyzed_sql[0]['select_expr'])
319 && (count($analyzed_sql[0]['select_expr']) == 0)
320 && isset($analyzed_sql[0]['queryflags']['select_from'])
321 && count($analyzed_sql[0]['table_ref']) == 1
323 PMA_handleSortOrder($db, $table, $analyzed_sql, $full_sql_query);
326 $sql_limit_to_append = '';
327 // Do append a "LIMIT" clause?
328 if (($_SESSION['tmp_user_values']['max_rows'] != 'all')
329 && ! ($is_count || $is_export || $is_func || $is_analyse)
330 && isset($analyzed_sql[0]['queryflags']['select_from'])
331 && ! isset($analyzed_sql[0]['queryflags']['offset'])
332 && empty($analyzed_sql[0]['limit_clause'])
334 $sql_limit_to_append = ' LIMIT ' . $_SESSION['tmp_user_values']['pos']
335 . ', ' . $_SESSION['tmp_user_values']['max_rows'] . " ";
336 $full_sql_query = PMA_getSqlWithLimitClause(
337 $full_sql_query,
338 $analyzed_sql,
339 $sql_limit_to_append
343 * @todo pretty printing of this modified query
345 if (isset($display_query)) {
346 // if the analysis of the original query revealed that we found
347 // a section_after_limit, we now have to analyze $display_query
348 // to display it correctly
350 if (! empty($analyzed_sql[0]['section_after_limit'])
351 && trim($analyzed_sql[0]['section_after_limit']) != ';'
353 $analyzed_display_query = PMA_SQP_analyze(
354 PMA_SQP_parse($display_query)
356 $display_query = $analyzed_display_query[0]['section_before_limit']
357 . "\n" . $sql_limit_to_append
358 . $analyzed_display_query[0]['section_after_limit'];
363 if (strlen($db)) {
364 $GLOBALS['dbi']->selectDb($db);
367 // E x e c u t e t h e q u e r y
369 // Only if we didn't ask to see the php code
370 if (isset($GLOBALS['show_as_php']) || ! empty($GLOBALS['validatequery'])) {
371 unset($result);
372 $num_rows = 0;
373 $unlim_num_rows = 0;
374 } else {
375 if (isset($_SESSION['profiling']) && PMA_Util::profilingSupported()) {
376 $GLOBALS['dbi']->query('SET PROFILING=1;');
379 // Measure query time.
380 $querytime_before = array_sum(explode(' ', microtime()));
382 $result = @$GLOBALS['dbi']->tryQuery(
383 $full_sql_query, null, PMA_DatabaseInterface::QUERY_STORE
386 // If a stored procedure was called, there may be more results that are
387 // queued up and waiting to be flushed from the buffer. So let's do that.
388 do {
389 $GLOBALS['dbi']->storeResult();
390 if (! $GLOBALS['dbi']->moreResults()) {
391 break;
393 } while ($GLOBALS['dbi']->nextResult());
395 $is_procedure = false;
397 // Since multiple query execution is anyway handled,
398 // ignore the WHERE clause of the first sql statement
399 // which might contain a phrase like 'call '
400 if (preg_match("/\bcall\b/i", $full_sql_query)
401 && empty($analyzed_sql[0]['where_clause'])
403 $is_procedure = true;
406 $querytime_after = array_sum(explode(' ', microtime()));
408 $GLOBALS['querytime'] = $querytime_after - $querytime_before;
410 // Displays an error message if required and stop parsing the script
411 $error = $GLOBALS['dbi']->getError();
412 if ($error) {
413 if ($is_gotofile) {
414 if (strpos($goto, 'db_') === 0 && strlen($table)) {
415 $table = '';
417 $active_page = $goto;
418 $message = PMA_Message::rawError($error);
420 if ($GLOBALS['is_ajax_request'] == true) {
421 $response = PMA_Response::getInstance();
422 $response->isSuccess(false);
423 $response->addJSON('message', $message);
424 exit;
428 * Go to target path.
430 include '' . PMA_securePath($goto);
431 } else {
432 $full_err_url = $err_url;
433 if (preg_match('@^(db|tbl)_@', $err_url)) {
434 $full_err_url .= '&amp;show_query=1&amp;sql_query='
435 . urlencode($sql_query);
437 PMA_Util::mysqlDie($error, $full_sql_query, '', $full_err_url);
439 exit;
441 unset($error);
443 // If there are no errors and bookmarklabel was given,
444 // store the query as a bookmark
445 if (! empty($bkm_label) && ! empty($import_text)) {
446 include_once 'libraries/bookmark.lib.php';
447 $bfields = array(
448 'dbase' => $db,
449 'user' => $cfg['Bookmark']['user'],
450 'query' => urlencode($import_text),
451 'label' => $bkm_label
454 // Should we replace bookmark?
455 if (isset($bkm_replace)) {
456 $bookmarks = PMA_Bookmark_getList($db);
457 foreach ($bookmarks as $key => $val) {
458 if ($val == $bkm_label) {
459 PMA_Bookmark_delete($db, $key);
464 PMA_Bookmark_save($bfields, isset($_POST['bkm_all_users']));
466 $bookmark_created = true;
467 } // end store bookmarks
469 // Gets the number of rows affected/returned
470 // (This must be done immediately after the query because
471 // mysql_affected_rows() reports about the last query done)
473 if (! $is_affected) {
474 $num_rows = ($result) ? @$GLOBALS['dbi']->numRows($result) : 0;
475 } elseif (! isset($num_rows)) {
476 $num_rows = @$GLOBALS['dbi']->affectedRows();
479 // Grabs the profiling results
480 if (isset($_SESSION['profiling']) && PMA_Util::profilingSupported()) {
481 $profiling_results = $GLOBALS['dbi']->fetchResult('SHOW PROFILE;');
484 // Checks if the current database has changed
485 // This could happen if the user sends a query like "USE `database`;"
487 * commented out auto-switching to active database - really required?
488 * bug #2558 win: table list disappears (mixed case db names)
489 * https://sourceforge.net/p/phpmyadmin/bugs/2558/
490 * @todo RELEASE test and comit or rollback before release
491 $current_db = $GLOBALS['dbi']->fetchValue('SELECT DATABASE()');
492 if ($db !== $current_db) {
493 $db = $current_db;
494 $reload = 1;
496 unset($current_db);
499 // tmpfile remove after convert encoding appended by Y.Kawada
500 if (function_exists('PMA_Kanji_fileConv')
501 && (isset($textfile) && file_exists($textfile))
503 unlink($textfile);
506 // Counts the total number of rows for the same 'SELECT' query without the
507 // 'LIMIT' clause that may have been programatically added
509 $justBrowsing = false;
510 if (empty($sql_limit_to_append)) {
511 $unlim_num_rows = $num_rows;
512 // if we did not append a limit, set this to get a correct
513 // "Showing rows..." message
514 //$_SESSION['tmp_user_values']['max_rows'] = 'all';
515 } elseif ($is_select) {
517 // c o u n t q u e r y
519 // If we are "just browsing", there is only one table,
520 // and no WHERE clause (or just 'WHERE 1 '),
521 // we do a quick count (which uses MaxExactCount) because
522 // SQL_CALC_FOUND_ROWS is not quick on large InnoDB tables
524 // However, do not count again if we did it previously
525 // due to $find_real_end == true
526 if (! $is_group
527 && ! isset($analyzed_sql[0]['queryflags']['union'])
528 && ! isset($analyzed_sql[0]['queryflags']['distinct'])
529 && ! isset($analyzed_sql[0]['table_ref'][1]['table_name'])
530 && (empty($analyzed_sql[0]['where_clause'])
531 || $analyzed_sql[0]['where_clause'] == '1 ')
532 && ! isset($find_real_end)
534 // "j u s t b r o w s i n g"
535 $justBrowsing = true;
536 $unlim_num_rows = PMA_Table::countRecords(
537 $db,
538 $table,
539 $force_exact = true
542 } else { // n o t " j u s t b r o w s i n g "
544 // add select expression after the SQL_CALC_FOUND_ROWS
546 // for UNION, just adding SQL_CALC_FOUND_ROWS
547 // after the first SELECT works.
549 // take the left part, could be:
550 // SELECT
551 // (SELECT
552 $count_query = PMA_SQP_format(
553 $parsed_sql,
554 'query_only',
556 $analyzed_sql[0]['position_of_first_select'] + 1
558 $count_query .= ' SQL_CALC_FOUND_ROWS ';
559 // add everything that was after the first SELECT
560 $count_query .= PMA_SQP_format(
561 $parsed_sql,
562 'query_only',
563 $analyzed_sql[0]['position_of_first_select'] + 1
565 // ensure there is no semicolon at the end of the
566 // count query because we'll probably add
567 // a LIMIT 1 clause after it
568 $count_query = rtrim($count_query);
569 $count_query = rtrim($count_query, ';');
571 // if using SQL_CALC_FOUND_ROWS, add a LIMIT to avoid
572 // long delays. Returned count will be complete anyway.
573 // (but a LIMIT would disrupt results in an UNION)
575 if (! isset($analyzed_sql[0]['queryflags']['union'])) {
576 $count_query .= ' LIMIT 1';
579 // run the count query
581 $GLOBALS['dbi']->tryQuery($count_query);
582 // if (mysql_error()) {
583 // void.
584 // I tried the case
585 // (SELECT `User`, `Host`, `Db`, `Select_priv` FROM `db`)
586 // UNION (SELECT `User`, `Host`, "%" AS "Db",
587 // `Select_priv`
588 // FROM `user`) ORDER BY `User`, `Host`, `Db`;
589 // and although the generated count_query is wrong
590 // the SELECT FOUND_ROWS() work! (maybe it gets the
591 // count from the latest query that worked)
593 // another case where the count_query is wrong:
594 // SELECT COUNT(*), f1 from t1 group by f1
595 // and you click to sort on count(*)
596 // }
597 $unlim_num_rows = $GLOBALS['dbi']->fetchValue('SELECT FOUND_ROWS()');
598 } // end else "just browsing"
600 } else { // not $is_select
601 $unlim_num_rows = 0;
602 } // end rows total count
604 // if a table or database gets dropped, check column comments.
605 if (isset($purge) && $purge == '1') {
607 * Cleanup relations.
609 include_once 'libraries/relation_cleanup.lib.php';
611 if (strlen($table) && strlen($db)) {
612 PMA_relationsCleanupTable($db, $table);
613 } elseif (strlen($db)) {
614 PMA_relationsCleanupDatabase($db);
615 } else {
616 // VOID. No DB/Table gets deleted.
617 } // end if relation-stuff
618 } // end if ($purge)
620 // If a column gets dropped, do relation magic.
621 if (isset($dropped_column)
622 && strlen($db)
623 && strlen($table)
624 && ! empty($dropped_column)
626 include_once 'libraries/relation_cleanup.lib.php';
627 PMA_relationsCleanupColumn($db, $table, $dropped_column);
628 // to refresh the list of indexes (Ajax mode)
629 $extra_data['indexes_list'] = PMA_Index::getView($table, $db);
630 } // end if column was dropped
631 } // end else "didn't ask to see php code"
633 // No rows returned -> move back to the calling page
634 if ((0 == $num_rows && 0 == $unlim_num_rows) || $is_affected) {
635 // Delete related tranformation information
636 if (!empty($analyzed_sql[0]['querytype'])
637 && (($analyzed_sql[0]['querytype'] == 'ALTER')
638 || ($analyzed_sql[0]['querytype'] == 'DROP'))
640 include_once 'libraries/transformations.lib.php';
641 if ($analyzed_sql[0]['querytype'] == 'ALTER') {
642 if (stripos($analyzed_sql[0]['unsorted_query'], 'DROP') !== false) {
643 $drop_column = PMA_getColumnNameInColumnDropSql(
644 $analyzed_sql[0]['unsorted_query']
647 if ($drop_column != '') {
648 PMA_clearTransformations($db, $table, $drop_column);
652 } else if (($analyzed_sql[0]['querytype'] == 'DROP') && ($table != '')) {
653 PMA_clearTransformations($db, $table);
657 if ($is_delete) {
658 $message = PMA_Message::getMessageForDeletedRows($num_rows);
659 } elseif ($is_insert) {
660 if ($is_replace) {
661 // For replace we get DELETED + INSERTED row count,
662 // so we have to call it affected
663 $message = PMA_Message::getMessageForAffectedRows($num_rows);
664 } else {
665 $message = PMA_Message::getMessageForInsertedRows($num_rows);
667 $insert_id = $GLOBALS['dbi']->insertId();
668 if ($insert_id != 0) {
669 // insert_id is id of FIRST record inserted in one insert,
670 // so if we inserted multiple rows, we had to increment this
671 $message->addMessage('[br]');
672 // need to use a temporary because the Message class
673 // currently supports adding parameters only to the first
674 // message
675 $_inserted = PMA_Message::notice(__('Inserted row id: %1$d'));
676 $_inserted->addParam($insert_id + $num_rows - 1);
677 $message->addMessage($_inserted);
679 } elseif ($is_affected) {
680 $message = PMA_Message::getMessageForAffectedRows($num_rows);
682 // Ok, here is an explanation for the !$is_select.
683 // The form generated by sql_query_form.lib.php
684 // and db_sql.php has many submit buttons
685 // on the same form, and some confusion arises from the
686 // fact that $message_to_show is sent for every case.
687 // The $message_to_show containing a success message and sent with
688 // the form should not have priority over errors
689 } elseif (! empty($message_to_show) && ! $is_select) {
690 $message = PMA_Message::rawSuccess(htmlspecialchars($message_to_show));
691 } elseif (! empty($GLOBALS['show_as_php'])) {
692 $message = PMA_Message::success(__('Showing as PHP code'));
693 } elseif (isset($GLOBALS['show_as_php'])) {
694 /* User disable showing as PHP, query is only displayed */
695 $message = PMA_Message::notice(__('Showing SQL query'));
696 } elseif (! empty($GLOBALS['validatequery'])) {
697 $message = PMA_Message::notice(__('Validated SQL'));
698 } else {
699 $message = PMA_Message::success(
700 __('MySQL returned an empty result set (i.e. zero rows).')
704 if (isset($GLOBALS['querytime'])) {
705 $_querytime = PMA_Message::notice('(' . __('Query took %01.4f sec') . ')');
706 $_querytime->addParam($GLOBALS['querytime']);
707 $message->addMessage($_querytime);
710 if ($GLOBALS['is_ajax_request'] == true) {
711 if ($cfg['ShowSQL']) {
712 $extra_data['sql_query'] = PMA_Util::getMessage(
713 $message, $GLOBALS['sql_query'], 'success'
716 if (isset($GLOBALS['reload']) && $GLOBALS['reload'] == 1) {
717 $extra_data['reload'] = 1;
718 $extra_data['db'] = $GLOBALS['db'];
720 $response = PMA_Response::getInstance();
721 $response->isSuccess($message->isSuccess());
722 // No need to manually send the message
723 // The Response class will handle that automatically
724 $query__type = PMA_DisplayResults::QUERY_TYPE_SELECT;
725 if ($analyzed_sql[0]['querytype'] == $query__type) {
726 $createViewHTML = $displayResultsObject->getCreateViewQueryResultOp(
727 $analyzed_sql
729 $response->addHTML($createViewHTML.'<br />');
732 $response->addJSON(isset($extra_data) ? $extra_data : array());
733 if (empty($_REQUEST['ajax_page_request'])) {
734 $response->addJSON('message', $message);
735 exit;
739 if ($is_gotofile) {
740 $goto = PMA_securePath($goto);
741 // Checks for a valid target script
742 $is_db = $is_table = false;
743 if (isset($_REQUEST['purge']) && $_REQUEST['purge'] == '1') {
744 $table = '';
745 unset($url_params['table']);
747 include 'libraries/db_table_exists.lib.php';
749 if (strpos($goto, 'tbl_') === 0 && ! $is_table) {
750 if (strlen($table)) {
751 $table = '';
753 $goto = 'db_sql.php';
755 if (strpos($goto, 'db_') === 0 && ! $is_db) {
756 if (strlen($db)) {
757 $db = '';
759 $goto = 'index.php';
761 // Loads to target script
762 if (strlen($goto) > 0) {
763 $active_page = $goto;
764 include '' . $goto;
765 } else {
766 // Echo at least one character to prevent showing last page from history
767 echo " ";
770 } else {
771 // avoid a redirect loop when last record was deleted
772 if (0 == $num_rows && 'sql.php' == $cfg['DefaultTabTable']) {
773 $goto = str_replace('sql.php', 'tbl_structure.php', $goto);
775 PMA_sendHeaderLocation(
776 $cfg['PmaAbsoluteUri'] . str_replace('&amp;', '&', $goto)
777 . '&message=' . urlencode($message)
779 } // end else
780 exit();
781 // end no rows returned
782 } else {
783 $html_output='';
784 // At least one row is returned -> displays a table with results
785 //If we are retrieving the full value of a truncated field or the original
786 // value of a transformed field, show it here and exit
787 if ($GLOBALS['grid_edit'] == true) {
788 $row = $GLOBALS['dbi']->fetchRow($result);
789 $response = PMA_Response::getInstance();
790 $response->addJSON('value', $row[0]);
791 exit;
794 if (isset($_REQUEST['ajax_request']) && isset($_REQUEST['table_maintenance'])) {
795 $response = PMA_Response::getInstance();
796 $header = $response->getHeader();
797 $scripts = $header->getScripts();
798 $scripts->addFile('makegrid.js');
799 $scripts->addFile('sql.js');
801 // Gets the list of fields properties
802 if (isset($result) && $result) {
803 $fields_meta = $GLOBALS['dbi']->getFieldsMeta($result);
804 $fields_cnt = count($fields_meta);
807 if (empty($disp_mode)) {
808 // see the "PMA_setDisplayMode()" function in
809 // libraries/DisplayResults.class.php
810 $disp_mode = 'urdr111101';
813 // hide edit and delete links for information_schema
814 if ($GLOBALS['dbi']->isSystemSchema($db)) {
815 $disp_mode = 'nnnn110111';
818 if (isset($message)) {
819 $message = PMA_Message::success($message);
820 $html_output .= PMA_Util::getMessage(
821 $message, $GLOBALS['sql_query'], 'success'
825 // Should be initialized these parameters before parsing
826 $showtable = isset($showtable) ? $showtable : null;
827 $printview = isset($_REQUEST['printview']) ? $_REQUEST['printview'] : null;
828 $url_query = isset($url_query) ? $url_query : null;
830 if (!empty($sql_data) && ($sql_data['valid_queries'] > 1)) {
832 $_SESSION['is_multi_query'] = true;
833 $html_output .= getTableHtmlForMultipleQueries(
834 $displayResultsObject, $db, $sql_data, $goto,
835 $pmaThemeImage, $text_dir, $printview, $url_query,
836 $disp_mode, $sql_limit_to_append, false
838 } else {
839 $_SESSION['is_multi_query'] = false;
840 $displayResultsObject->setProperties(
841 $unlim_num_rows, $fields_meta, $is_count, $is_export, $is_func,
842 $is_analyse, $num_rows, $fields_cnt, $querytime, $pmaThemeImage,
843 $text_dir, $is_maint, $is_explain, $is_show, $showtable,
844 $printview, $url_query, false
847 $html_output .= $displayResultsObject->getTable(
848 $result, $disp_mode, $analyzed_sql
850 $response = PMA_Response::getInstance();
851 $response->addHTML($html_output);
852 exit();
856 // Displays the headers
857 if (isset($show_query)) {
858 unset($show_query);
860 if (isset($_REQUEST['printview']) && $_REQUEST['printview'] == '1') {
861 PMA_Util::checkParameters(array('db', 'full_sql_query'));
863 $response = PMA_Response::getInstance();
864 $header = $response->getHeader();
865 $header->enablePrintView();
867 $html_output .= PMA_getHtmlForPrintViewHeader(
868 $db, $full_sql_query, $num_rows
870 } else {
871 $response = PMA_Response::getInstance();
872 $header = $response->getHeader();
873 $scripts = $header->getScripts();
874 $scripts->addFile('makegrid.js');
875 $scripts->addFile('sql.js');
877 unset($message);
879 if (! $GLOBALS['is_ajax_request']) {
880 if (strlen($table)) {
881 include 'libraries/tbl_common.inc.php';
882 $url_query .= '&amp;goto=tbl_sql.php&amp;back=tbl_sql.php';
883 include 'libraries/tbl_info.inc.php';
884 } elseif (strlen($db)) {
885 include 'libraries/db_common.inc.php';
886 include 'libraries/db_info.inc.php';
887 } else {
888 include 'libraries/server_common.inc.php';
890 } else {
891 //we don't need to buffer the output in getMessage here.
892 //set a global variable and check against it in the function
893 $GLOBALS['buffer_message'] = false;
897 if (strlen($db)) {
898 $cfgRelation = PMA_getRelationsParam();
901 // Gets the list of fields properties
902 if (isset($result) && $result) {
903 $fields_meta = $GLOBALS['dbi']->getFieldsMeta($result);
904 $fields_cnt = count($fields_meta);
907 //begin the sqlqueryresults div here. container div
908 $html_output .= '<div id="sqlqueryresults"';
909 $html_output .= ' class="ajax"';
910 $html_output .= '>';
912 // Display previous update query (from tbl_replace)
913 if (isset($disp_query) && ($cfg['ShowSQL'] == true) && empty($sql_data)) {
914 $html_output .= PMA_Util::getMessage($disp_message, $disp_query, 'success');
917 if (isset($profiling_results)) {
918 // pma_token/url_query needed for chart export
919 $token = $_SESSION[' PMA_token '];
920 $url = (isset($url_query) ? $url_query : PMA_generate_common_url($db));
922 $html_output .= PMA_getHtmlForProfilingChart(
923 $url, $token, $profiling_results
927 // Displays the results in a table
928 if (empty($disp_mode)) {
929 // see the "PMA_setDisplayMode()" function in
930 // libraries/DisplayResults.class.php
931 $disp_mode = 'urdr111101';
934 $has_unique = PMA_resultSetContainsUniqueKey(
935 $db, $table, $fields_meta
938 // hide edit and delete links:
939 // - for information_schema
940 // - if the result set does not contain all the columns of a unique key
941 // and we are not just browing all the columns of an updatable view
942 $updatableView
943 = $justBrowsing
944 && trim($analyzed_sql[0]['select_expr_clause']) == '*'
945 && PMA_Table::isUpdatableView($db, $table);
946 $editable = $has_unique || $updatableView;
947 if (!empty($table) && ($GLOBALS['dbi']->isSystemSchema($db) || !$editable)) {
948 $disp_mode = 'nnnn110111';
949 $msg = PMA_message::notice(
951 'Table %s does not contain a unique column.'
952 . ' Grid edit, checkbox, Edit, Copy and Delete features'
953 . ' are not available.'
956 $msg->addParam($table);
957 $html_output .= $msg->getDisplay();
960 if (isset($_GET['label'])) {
961 $msg = PMA_message::success(__('Bookmark %s created'));
962 $msg->addParam($_GET['label']);
963 $html_output .= $msg->getDisplay();
966 // Should be initialized these parameters before parsing
967 $showtable = isset($showtable) ? $showtable : null;
968 $printview = isset($_REQUEST['printview']) ? $_REQUEST['printview'] : null;
969 $url_query = isset($url_query) ? $url_query : null;
971 if (! empty($sql_data) && ($sql_data['valid_queries'] > 1) || $is_procedure) {
973 $_SESSION['is_multi_query'] = true;
974 $html_output .= getTableHtmlForMultipleQueries(
975 $displayResultsObject, $db, $sql_data, $goto,
976 $pmaThemeImage, $text_dir, $printview, $url_query,
977 $disp_mode, $sql_limit_to_append, $editable
979 } else {
980 $_SESSION['is_multi_query'] = false;
981 $displayResultsObject->setProperties(
982 $unlim_num_rows, $fields_meta, $is_count, $is_export, $is_func,
983 $is_analyse, $num_rows, $fields_cnt, $querytime, $pmaThemeImage,
984 $text_dir, $is_maint, $is_explain, $is_show, $showtable,
985 $printview, $url_query, $editable
988 $html_output .= $displayResultsObject->getTable(
989 $result, $disp_mode, $analyzed_sql
991 $GLOBALS['dbi']->freeResult($result);
994 // BEGIN INDEX CHECK See if indexes should be checked.
995 if (isset($query_type)
996 && $query_type == 'check_tbl'
997 && isset($selected)
998 && is_array($selected)
1000 foreach ($selected as $idx => $tbl_name) {
1001 $check = PMA_Index::findDuplicates($tbl_name, $db);
1002 if (! empty($check)) {
1003 $html_output .= sprintf(
1004 __('Problems with indexes of table `%s`'), $tbl_name
1006 $html_output .= $check;
1009 } // End INDEX CHECK
1011 // Bookmark support if required
1012 if ($disp_mode[7] == '1'
1013 && (! empty($cfg['Bookmark']) && empty($_GET['id_bookmark']))
1014 && ! empty($sql_query)
1016 $html_output .= "\n";
1017 $goto = 'sql.php?'
1018 . PMA_generate_common_url($db, $table)
1019 . '&amp;sql_query=' . urlencode($sql_query)
1020 . '&amp;id_bookmark=1';
1022 $html_output .= '<form action="sql.php" method="post"'
1023 . ' onsubmit="return ! emptyFormElements(this, \'bkm_fields[bkm_label]\');"'
1024 . ' id="bookmarkQueryForm">';
1025 $html_output .= PMA_generate_common_hidden_inputs();
1026 $html_output .= '<input type="hidden" name="goto" value="' . $goto . '" />';
1027 $html_output .= '<input type="hidden" name="bkm_fields[bkm_database]"'
1028 . ' value="' . htmlspecialchars($db) . '" />';
1029 $html_output .= '<input type="hidden" name="bkm_fields[bkm_user]"'
1030 . ' value="' . $cfg['Bookmark']['user'] . '" />';
1031 $html_output .= '<input type="hidden" name="bkm_fields[bkm_sql_query]"' . ' value="'
1032 . urlencode(isset($complete_query) ? $complete_query : $sql_query)
1033 . '" />';
1034 $html_output .= '<fieldset>';
1035 $html_output .= '<legend>';
1036 $html_output .= PMA_Util::getIcon(
1037 'b_bookmark.png', __('Bookmark this SQL query'), true
1039 $html_output .= '</legend>';
1040 $html_output .= '<div class="formelement">';
1041 $html_output .= '<label for="fields_label_">' . __('Label:') . '</label>';
1042 $html_output .= '<input type="text" id="fields_label_"'
1043 . ' name="bkm_fields[bkm_label]" value="" />';
1044 $html_output .= '</div>';
1045 $html_output .= '<div class="formelement">';
1046 $html_output .= '<input type="checkbox" name="bkm_all_users"'
1047 . ' id="bkm_all_users" value="true" />';
1048 $html_output .= '<label for="bkm_all_users">'
1049 . __('Let every user access this bookmark')
1050 . '</label>';
1051 $html_output .= '</div>';
1052 $html_output .= '<div class="clearfloat"></div>';
1053 $html_output .= '</fieldset>';
1054 $html_output .= '<fieldset class="tblFooters">';
1055 $html_output .= '<input type="hidden" name="store_bkm" value="1" />';
1056 $html_output .= '<input type="submit"'
1057 . ' value="' . __('Bookmark this SQL query') . '" />';
1058 $html_output .= '</fieldset>';
1059 $html_output .= '</form>';
1060 } // end bookmark support
1062 // Do print the page if required
1063 if (isset($_REQUEST['printview']) && $_REQUEST['printview'] == '1') {
1064 $html_output .= PMA_Util::getButton();
1065 } // end print case
1066 $html_output .= '</div>'; // end sqlqueryresults div
1067 $response = PMA_Response::getInstance();
1068 $response->addHTML($html_output);
1069 } // end rows returned
1071 $_SESSION['is_multi_query'] = false;
1074 * Displays the footer
1076 if (! isset($_REQUEST['table_maintenance'])) {
1077 exit;