Rev Author Line No. Line
250 kaklik 1 <?php
2 /* $Id: sql.php,v 2.83.2.7 2006/04/27 08:57:09 nijel Exp $ */
3 // vim: expandtab sw=4 ts=4 sts=4:
4  
5 /**
6 * Gets some core libraries
7 */
8 require_once './libraries/common.lib.php';
9 require_once './libraries/tbl_indexes.lib.php';
10 require_once './libraries/check_user_privileges.lib.php';
11 require_once './libraries/bookmark.lib.php';
12  
13 /**
14 * Could be coming from a subform ("T" column expander)
15 */
16 if (isset($_REQUEST['dontlimitchars'])) {
17 $dontlimitchars = $_REQUEST['dontlimitchars'];
18 }
19  
20 /**
21 * Defines the url to return to in case of error in a sql statement
22 */
23 // Security checkings
24 if (!empty($goto)) {
25 $is_gotofile = preg_replace('@^([^?]+).*$@s', '\\1', $goto);
26 if (!@file_exists('./' . $is_gotofile)) {
27 unset($goto);
28 } else {
29 $is_gotofile = ($is_gotofile == $goto);
30 }
31 } // end if (security checkings)
32  
33 if (empty($goto)) {
34 $goto = (! isset($table) || ! strlen($table)) ? $cfg['DefaultTabDatabase'] : $cfg['DefaultTabTable'];
35 $is_gotofile = true;
36 } // end if
37 if (!isset($err_url)) {
38 $err_url = (!empty($back) ? $back : $goto)
39 . '?' . PMA_generate_common_url(isset($db) ? $db : '')
40 . ((strpos(' ' . $goto, 'db_details') != 1 && isset($table)) ? '&amp;table=' . urlencode($table) : '');
41 } // end if
42  
43 // Coming from a bookmark dialog
44 if (isset($fields['query'])) {
45 $sql_query = $fields['query'];
46 }
47  
48 // This one is just to fill $db
49 if (isset($fields['dbase'])) {
50 $db = $fields['dbase'];
51 }
52  
53 // Default to browse if no query set an we have table (needed for browsing from DefaultTabTable)
54 if (!isset($sql_query) && isset($table) && isset($db)) {
55 require_once './libraries/bookmark.lib.php';
56 $book_sql_query = PMA_queryBookmarks($db, $GLOBALS['cfg']['Bookmark'], '\'' . PMA_sqlAddslashes($table) . '\'', 'label');
57 if (!empty($book_sql_query)) {
58 $sql_query = $book_sql_query;
59 } else {
60 $sql_query = 'SELECT * FROM ' . PMA_backquote($table);
61 }
62 unset($book_sql_query);
63  
64 // set $goto to what will be displayed if query returns 0 rows
65 $goto = 'tbl_properties_structure.php';
66 } else {
67 // Now we can check the parameters
68 PMA_checkParameters(array('sql_query'));
69 }
70  
71 // instead of doing the test twice
72 $is_drop_database = preg_match('/DROP[[:space:]]+(DATABASE|SCHEMA)[[:space:]]+/i',
73 $sql_query);
74  
75 /**
76 * Check rights in case of DROP DATABASE
77 *
78 * This test may be bypassed if $is_js_confirmed = 1 (already checked with js)
79 * but since a malicious user may pass this variable by url/form, we don't take
80 * into account this case.
81 */
82 if (!defined('PMA_CHK_DROP')
83 && !$cfg['AllowUserDropDatabase']
84 && $is_drop_database
85 && !$is_superuser) {
86 require_once './libraries/header.inc.php';
87 PMA_mysqlDie($strNoDropDatabases, '', '', $err_url);
88 } // end if
89  
90  
91 /**
92 * Need to find the real end of rows?
93 */
94  
95 if (isset($find_real_end) && $find_real_end) {
96 $unlim_num_rows = PMA_countRecords($db, $table, true, true);
97 $pos = @((ceil($unlim_num_rows / $session_max_rows) - 1) * $session_max_rows);
98 }
99 /**
100 * Avoids undefined variables
101 */
102 elseif (!isset($pos)) {
103 $pos = 0;
104 }
105  
106 /**
107 * Bookmark add
108 */
109 if (isset($store_bkm)) {
110 PMA_addBookmarks($fields, $cfg['Bookmark'], (isset($bkm_all_users) && $bkm_all_users == 'true' ? true : false));
111 PMA_sendHeaderLocation($cfg['PmaAbsoluteUri'] . $goto);
112 } // end if
113  
114  
115 /**
116 * Gets the true sql query
117 */
118 // $sql_query has been urlencoded in the confirmation form for drop/delete
119 // queries or in the navigation bar for browsing among records
120 if (isset($btnDrop) || isset($navig)) {
121 $sql_query = urldecode($sql_query);
122 }
123  
124 /**
125 * Reformat the query
126 */
127  
128 $GLOBALS['unparsed_sql'] = $sql_query;
129 $parsed_sql = PMA_SQP_parse($sql_query);
130 $analyzed_sql = PMA_SQP_analyze($parsed_sql);
131  
132 // Bug #641765 - Robbat2 - 12 January 2003, 10:49PM
133 // Reverted - Robbat2 - 13 January 2003, 2:40PM
134  
135 // lem9: for bug 780516: now that we use case insensitive preg_match
136 // or flags from the analyser, do not put back the reformatted query
137 // into $sql_query, to make this kind of query work without
138 // capitalizing keywords:
139 //
140 // CREATE TABLE SG_Persons (
141 // id int(10) unsigned NOT NULL auto_increment,
142 // first varchar(64) NOT NULL default '',
143 // PRIMARY KEY (`id`)
144 // )
145 //
146 // Note: now we probably do not need to fill and use $GLOBALS['unparsed_sql']
147 // but I let this intact for now.
148 //
149 //$sql_query = PMA_SQP_formatHtml($parsed_sql, 'query_only');
150  
151  
152 // check for a real SELECT ... FROM
153 $is_select = isset($analyzed_sql[0]['queryflags']['select_from']);
154  
155 // If the query is a Select, extract the db and table names and modify
156 // $db and $table, to have correct page headers, links and left frame.
157 // db and table name may be enclosed with backquotes, db is optionnal,
158 // query may contain aliases.
159  
160 // (TODO: if there are more than one table name in the Select:
161 // - do not extract the first table name
162 // - do not show a table name in the page header
163 // - do not display the sub-pages links)
164  
165 if ($is_select) {
166 $prev_db = $db;
167 if (isset($analyzed_sql[0]['table_ref'][0]['table_true_name'])) {
168 $table = $analyzed_sql[0]['table_ref'][0]['table_true_name'];
169 }
170 if (isset($analyzed_sql[0]['table_ref'][0]['db'])
171 && strlen($analyzed_sql[0]['table_ref'][0]['db'])) {
172 $db = $analyzed_sql[0]['table_ref'][0]['db'];
173 } else {
174 $db = $prev_db;
175 }
176 // Nijel: don't change reload, if we already decided to reload in import
177 if (empty($reload)) {
178 $reload = ($db == $prev_db) ? 0 : 1;
179 }
180 }
181  
182 /**
183 * Sets or modifies the $goto variable if required
184 */
185 if ($goto == 'sql.php') {
186 $is_gotofile = false;
187 $goto = 'sql.php?'
188 . PMA_generate_common_url($db, $table)
189 . '&amp;pos=' . $pos
190 . '&amp;sql_query=' . urlencode($sql_query);
191 } // end if
192  
193  
194 /**
195 * Go back to further page if table should not be dropped
196 */
197 if (isset($btnDrop) && $btnDrop == $strNo) {
198 if (!empty($back)) {
199 $goto = $back;
200 }
201 if ($is_gotofile) {
202 if (strpos(' ' . $goto, 'db_details') == 1 && isset($table) && strlen($table)) {
203 unset($table);
204 }
205 $active_page = $goto;
206 require './' . PMA_securePath($goto);
207 } else {
208 PMA_sendHeaderLocation($cfg['PmaAbsoluteUri'] . str_replace('&amp;', '&', $goto));
209 }
210 exit();
211 } // end if
212  
213  
214 /**
215 * Displays the confirm page if required
216 *
217 * This part of the script is bypassed if $is_js_confirmed = 1 (already checked
218 * with js) because possible security issue is not so important here: at most,
219 * the confirm message isn't displayed.
220 *
221 * Also bypassed if only showing php code.or validating a SQL query
222 */
223 if (!$cfg['Confirm']
224 || (isset($is_js_confirmed) && $is_js_confirmed)
225 || isset($btnDrop)
226  
227 // if we are coming from a "Create PHP code" or a "Without PHP Code"
228 // dialog, we won't execute the query anyway, so don't confirm
229 //|| !empty($GLOBALS['show_as_php'])
230 || isset($GLOBALS['show_as_php'])
231  
232 || !empty($GLOBALS['validatequery'])) {
233 $do_confirm = false;
234 } else {
235 $do_confirm = isset($analyzed_sql[0]['queryflags']['need_confirm']);
236 }
237  
238 if ($do_confirm) {
239 $stripped_sql_query = $sql_query;
240 require_once './libraries/header.inc.php';
241 if ($is_drop_database) {
242 echo '<h1 class="warning">' . $strDropDatabaseStrongWarning . '</h1>';
243 }
244 echo '<form action="sql.php" method="post">' . "\n"
245 .PMA_generate_common_hidden_inputs($db, (isset($table)?$table:''));
246 ?>
247 <input type="hidden" name="sql_query" value="<?php echo urlencode($sql_query); ?>" />
248 <input type="hidden" name="zero_rows" value="<?php echo isset($zero_rows) ? PMA_sanitize($zero_rows) : ''; ?>" />
249 <input type="hidden" name="goto" value="<?php echo $goto; ?>" />
250 <input type="hidden" name="back" value="<?php echo isset($back) ? PMA_sanitize($back) : ''; ?>" />
251 <input type="hidden" name="reload" value="<?php echo isset($reload) ? PMA_sanitize($reload) : 0; ?>" />
252 <input type="hidden" name="purge" value="<?php echo isset($purge) ? PMA_sanitize($purge) : ''; ?>" />
253 <input type="hidden" name="cpurge" value="<?php echo isset($cpurge) ? PMA_sanitize($cpurge) : ''; ?>" />
254 <input type="hidden" name="purgekey" value="<?php echo isset($purgekey) ? PMA_sanitize($purgekey) : ''; ?>" />
255 <input type="hidden" name="show_query" value="<?php echo isset($show_query) ? PMA_sanitize($show_query) : ''; ?>" />
256 <?php
257 echo '<fieldset class="confirmation">' . "\n"
258 .' <legend>' . $strDoYouReally . '</legend>'
259 .' <tt>' . htmlspecialchars($stripped_sql_query) . '</tt>' . "\n"
260 .'</fieldset>' . "\n"
261 .'<fieldset class="tblFooters">' . "\n";
262 ?>
263 <input type="submit" name="btnDrop" value="<?php echo $strYes; ?>" id="buttonYes" />
264 <input type="submit" name="btnDrop" value="<?php echo $strNo; ?>" id="buttonNo" />
265 <?php
266 echo '</fieldset>' . "\n"
267 . '</form>' . "\n";
268 } // end if $do_confirm
269  
270  
271 /**
272 * Executes the query and displays results
273 */
274 else {
275 if (!isset($sql_query)) {
276 $sql_query = '';
277 }
278 // Defines some variables
279 // A table has to be created or renamed -> left frame should be reloaded
280 // TODO: use the parser/analyzer
281  
282 if (empty($reload)
283 && preg_match('/^(CREATE|ALTER|DROP)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i', $sql_query)) {
284 $reload = 1;
285 }
286 // Gets the number of rows per page
287 if (empty($session_max_rows)) {
288 $session_max_rows = $cfg['MaxRows'];
289 } elseif ($session_max_rows != 'all') {
290 $cfg['MaxRows'] = $session_max_rows;
291 }
292 // Defines the display mode (horizontal/vertical) and header "frequency"
293 if (empty($disp_direction)) {
294 $disp_direction = $cfg['DefaultDisplay'];
295 }
296 if (empty($repeat_cells)) {
297 $repeat_cells = $cfg['RepeatCells'];
298 }
299  
300 // SK -- Patch: $is_group added for use in calculation of total number of
301 // rows.
302 // $is_count is changed for more correct "LIMIT" clause
303 // appending in queries like
304 // "SELECT COUNT(...) FROM ... GROUP BY ..."
305  
306 // TODO: detect all this with the parser, to avoid problems finding
307 // those strings in comments or backquoted identifiers
308  
309 $is_explain = $is_count = $is_export = $is_delete = $is_insert = $is_affected = $is_show = $is_maint = $is_analyse = $is_group = $is_func = $is_replace = false;
310 if ($is_select) { // see line 141
311 $is_group = preg_match('@(GROUP[[:space:]]+BY|HAVING|SELECT[[:space:]]+DISTINCT)[[:space:]]+@i', $sql_query);
312 $is_func = !$is_group && (preg_match('@[[:space:]]+(SUM|AVG|STD|STDDEV|MIN|MAX|BIT_OR|BIT_AND)\s*\(@i', $sql_query));
313 $is_count = !$is_group && (preg_match('@^SELECT[[:space:]]+COUNT\((.*\.+)?.*\)@i', $sql_query));
314 $is_export = (preg_match('@[[:space:]]+INTO[[:space:]]+OUTFILE[[:space:]]+@i', $sql_query));
315 $is_analyse = (preg_match('@[[:space:]]+PROCEDURE[[:space:]]+ANALYSE@i', $sql_query));
316 } elseif (preg_match('@^EXPLAIN[[:space:]]+@i', $sql_query)) {
317 $is_explain = true;
318 } elseif (preg_match('@^DELETE[[:space:]]+@i', $sql_query)) {
319 $is_delete = true;
320 $is_affected = true;
321 } elseif (preg_match('@^(INSERT|LOAD[[:space:]]+DATA|REPLACE)[[:space:]]+@i', $sql_query)) {
322 $is_insert = true;
323 $is_affected = true;
324 if (preg_match('@^(REPLACE)[[:space:]]+@i', $sql_query)) {
325 $is_replace = true;
326 }
327 } elseif (preg_match('@^UPDATE[[:space:]]+@i', $sql_query)) {
328 $is_affected = true;
329 } elseif (preg_match('@^SHOW[[:space:]]+@i', $sql_query)) {
330 $is_show = true;
331 } elseif (preg_match('@^(CHECK|ANALYZE|REPAIR|OPTIMIZE)[[:space:]]+TABLE[[:space:]]+@i', $sql_query)) {
332 $is_maint = true;
333 }
334  
335 // Do append a "LIMIT" clause?
336 if (isset($pos)
337 && (!$cfg['ShowAll'] || $session_max_rows != 'all')
338 && !($is_count || $is_export || $is_func || $is_analyse)
339 && isset($analyzed_sql[0]['queryflags']['select_from'])
340 && !isset($analyzed_sql[0]['queryflags']['offset'])
341 && !preg_match('@[[:space:]]LIMIT[[:space:]0-9,-]+(;)?$@i', $sql_query)) {
342 $sql_limit_to_append = " LIMIT $pos, ".$cfg['MaxRows'] . " ";
343  
344 $full_sql_query = $analyzed_sql[0]['section_before_limit'] . "\n" . $sql_limit_to_append . $analyzed_sql[0]['section_after_limit'];
345 // FIXME: pretty printing of this modified query
346  
347 if (isset($display_query)) {
348 // if the analysis of the original query revealed that we found
349 // a section_after_limit, we now have to analyze $display_query
350 // to display it correctly
351  
352 if (!empty($analyzed_sql[0]['section_after_limit']) && trim($analyzed_sql[0]['section_after_limit']) != ';') {
353 $analyzed_display_query = PMA_SQP_analyze(PMA_SQP_parse($display_query));
354 $display_query = $analyzed_display_query[0]['section_before_limit'] . "\n" . $sql_limit_to_append . $analyzed_display_query[0]['section_after_limit'];
355 }
356 }
357  
358 } else {
359 $full_sql_query = $sql_query;
360 } // end if...else
361  
362 if (isset($db)) {
363 PMA_DBI_select_db($db);
364 }
365  
366 // If the query is a DELETE query with no WHERE clause, get the number of
367 // rows that will be deleted (mysql_affected_rows will always return 0 in
368 // this case)
369 // Note: testing shows that this no longer applies since MySQL 4.0.x
370  
371 if (PMA_MYSQL_INT_VERSION < 40000) {
372 if ($is_delete
373 && preg_match('@^DELETE([[:space:]].+)?(FROM[[:space:]](.+))$@i', $sql_query, $parts)
374 && !preg_match('@[[:space:]]WHERE[[:space:]]@i', $parts[3])) {
375 $cnt_all_result = @PMA_DBI_try_query('SELECT COUNT(*) as count ' . $parts[2]);
376 if ($cnt_all_result) {
377 list($num_rows) = PMA_DBI_fetch_row($cnt_all_result);
378 PMA_DBI_free_result($cnt_all_result);
379 } else {
380 $num_rows = 0;
381 }
382 }
383 }
384  
385 // E x e c u t e t h e q u e r y
386  
387 // Only if we didn't ask to see the php code (mikebeck)
388 if (isset($GLOBALS['show_as_php']) || !empty($GLOBALS['validatequery'])) {
389 unset($result);
390 $num_rows = 0;
391 } else {
392 // garvin: Measure query time.
393 // TODO-Item http://sourceforge.net/tracker/index.php?func=detail&aid=571934&group_id=23067&atid=377411
394 $querytime_before = array_sum(explode(' ', microtime()));
395  
396 $result = @PMA_DBI_try_query($full_sql_query, null, PMA_DBI_QUERY_STORE);
397  
398 $querytime_after = array_sum(explode(' ', microtime()));
399  
400 $GLOBALS['querytime'] = $querytime_after - $querytime_before;
401  
402 // Displays an error message if required and stop parsing the script
403 if ($error = PMA_DBI_getError()) {
404 require_once './libraries/header.inc.php';
405 $full_err_url = (preg_match('@^(db_details|tbl_properties)@', $err_url))
406 ? $err_url . '&amp;show_query=1&amp;sql_query=' . urlencode($sql_query)
407 : $err_url;
408 PMA_mysqlDie($error, $full_sql_query, '', $full_err_url);
409 }
410 unset($error);
411  
412 // Gets the number of rows affected/returned
413 // (This must be done immediately after the query because
414 // mysql_affected_rows() reports about the last query done)
415  
416 if (!$is_affected) {
417 $num_rows = ($result) ? @PMA_DBI_num_rows($result) : 0;
418 } elseif (!isset($num_rows)) {
419 $num_rows = @PMA_DBI_affected_rows();
420 }
421  
422 // Checks if the current database has changed
423 // This could happen if the user sends a query like "USE `database`;"
424 $res = PMA_DBI_query('SELECT DATABASE() AS \'db\';');
425 $row = PMA_DBI_fetch_row($res);
426 if (is_array($row) && isset($row[0]) && (strcasecmp($db, $row[0]) != 0)) {
427 $db = $row[0];
428 $reload = 1;
429 }
430 @PMA_DBI_free_result($res);
431 unset($res, $row);
432  
433 // tmpfile remove after convert encoding appended by Y.Kawada
434 if (function_exists('PMA_kanji_file_conv')
435 && (isset($textfile) && file_exists($textfile))) {
436 unlink($textfile);
437 }
438  
439 // Counts the total number of rows for the same 'SELECT' query without the
440 // 'LIMIT' clause that may have been programatically added
441  
442 if (empty($sql_limit_to_append)) {
443 $unlim_num_rows = $num_rows;
444 // if we did not append a limit, set this to get a correct
445 // "Showing rows..." message
446 $GLOBALS['session_max_rows'] = 'all';
447 } elseif ($is_select) {
448  
449 // c o u n t q u e r y
450  
451 // If we are "just browsing", there is only one table,
452 // and no where clause (or just 'WHERE 1 '),
453 // so we do a quick count (which uses MaxExactCount)
454 // because SQL_CALC_FOUND_ROWS
455 // is not quick on large InnoDB tables
456  
457 // but do not count again if we did it previously
458 // due to $find_real_end == true
459  
460 if (!$is_group
461 && !isset($analyzed_sql[0]['queryflags']['union'])
462 && !isset($analyzed_sql[0]['table_ref'][1]['table_name'])
463 && (empty($analyzed_sql[0]['where_clause'])
464 || $analyzed_sql[0]['where_clause'] == '1 ')
465 && !isset($find_real_end)
466 ) {
467  
468 // "j u s t b r o w s i n g"
469 $unlim_num_rows = PMA_countRecords($db, $table, true);
470  
471 } else { // n o t " j u s t b r o w s i n g "
472  
473 if (PMA_MYSQL_INT_VERSION < 40000) {
474  
475 // detect this case:
476 // SELECT DISTINCT x AS foo, y AS bar FROM sometable
477  
478 if (isset($analyzed_sql[0]['queryflags']['distinct'])) {
479 $count_what = 'DISTINCT ';
480 $first_expr = true;
481 foreach ($analyzed_sql[0]['select_expr'] as $part) {
482 $count_what .= (!$first_expr ? ', ' : '') . $part['expr'];
483 $first_expr = false;
484 }
485 } else {
486 $count_what = '*';
487 }
488 // this one does not apply to VIEWs
489 $count_query = 'SELECT COUNT(' . $count_what . ') AS count';
490 }
491  
492 // add the remaining of select expression if there is
493 // a GROUP BY or HAVING clause
494 if (PMA_MYSQL_INT_VERSION < 40000
495 && $count_what =='*'
496 && (!empty($analyzed_sql[0]['group_by_clause'])
497 || !empty($analyzed_sql[0]['having_clause']))) {
498 $count_query .= ' ,' . $analyzed_sql[0]['select_expr_clause'];
499 }
500  
501 if (PMA_MYSQL_INT_VERSION >= 40000) {
502 // add select expression after the SQL_CALC_FOUND_ROWS
503  
504 // for UNION, just adding SQL_CALC_FOUND_ROWS
505 // after the first SELECT works.
506  
507 // take the left part, could be:
508 // SELECT
509 // (SELECT
510 $count_query = PMA_SQP_formatHtml($parsed_sql, 'query_only', 0, $analyzed_sql[0]['position_of_first_select'] + 1);
511 $count_query .= ' SQL_CALC_FOUND_ROWS ';
512 // add everything that was after the first SELECT
513 $count_query .= PMA_SQP_formatHtml($parsed_sql, 'query_only', $analyzed_sql[0]['position_of_first_select']+1);
514 } else { // PMA_MYSQL_INT_VERSION < 40000
515  
516 if (!empty($analyzed_sql[0]['from_clause'])) {
517 $count_query .= ' FROM ' . $analyzed_sql[0]['from_clause'];
518 }
519 if (!empty($analyzed_sql[0]['where_clause'])) {
520 $count_query .= ' WHERE ' . $analyzed_sql[0]['where_clause'];
521 }
522 if (!empty($analyzed_sql[0]['group_by_clause'])) {
523 $count_query .= ' GROUP BY ' . $analyzed_sql[0]['group_by_clause'];
524 }
525 if (!empty($analyzed_sql[0]['having_clause'])) {
526 $count_query .= ' HAVING ' . $analyzed_sql[0]['having_clause'];
527 }
528 } // end if
529  
530 // if using SQL_CALC_FOUND_ROWS, add a LIMIT to avoid
531 // long delays. Returned count will be complete anyway.
532 // (but a LIMIT would disrupt results in an UNION)
533  
534 if (PMA_MYSQL_INT_VERSION >= 40000
535 && !isset($analyzed_sql[0]['queryflags']['union'])) {
536 $count_query .= ' LIMIT 1';
537 }
538  
539 // run the count query
540  
541 if (PMA_MYSQL_INT_VERSION < 40000) {
542 if ($cnt_all_result = PMA_DBI_try_query($count_query)) {
543 if ($is_group && $count_what == '*') {
544 $unlim_num_rows = @PMA_DBI_num_rows($cnt_all_result);
545 } else {
546 $unlim_num_rows = PMA_DBI_fetch_assoc($cnt_all_result);
547 $unlim_num_rows = $unlim_num_rows['count'];
548 }
549 PMA_DBI_free_result($cnt_all_result);
550 } else {
551 if (PMA_DBI_getError()) {
552  
553 // there are some cases where the generated
554 // count_query (for MySQL 3) is wrong,
555 // so we get here.
556 //TODO: use a big unlimited query to get
557 // the correct number of rows (depending
558 // on a config variable?)
559 $unlim_num_rows = 0;
560 }
561 }
562 } else {
563 PMA_DBI_try_query($count_query);
564 // if (mysql_error()) {
565 // void.
566 // I tried the case
567 // (SELECT `User`, `Host`, `Db`, `Select_priv` FROM `db`)
568 // UNION (SELECT `User`, `Host`, "%" AS "Db",
569 // `Select_priv`
570 // FROM `user`) ORDER BY `User`, `Host`, `Db`;
571 // and although the generated count_query is wrong
572 // the SELECT FOUND_ROWS() work! (maybe it gets the
573 // count from the latest query that worked)
574 //
575 // another case where the count_query is wrong:
576 // SELECT COUNT(*), f1 from t1 group by f1
577 // and you click to sort on count(*)
578 // }
579 $cnt_all_result = PMA_DBI_query('SELECT FOUND_ROWS() as count;');
580 list($unlim_num_rows) = PMA_DBI_fetch_row($cnt_all_result);
581 @PMA_DBI_free_result($cnt_all_result);
582 }
583 } // end else "just browsing"
584  
585 } else { // not $is_select
586 $unlim_num_rows = 0;
587 } // end rows total count
588  
589 // garvin: if a table or database gets dropped, check column comments.
590 if (isset($purge) && $purge == '1') {
591 require_once './libraries/relation_cleanup.lib.php';
592  
593 if (isset($table) && isset($db) && strlen($table) && strlen($db)) {
594 PMA_relationsCleanupTable($db, $table);
595 } elseif (isset($db) && strlen($db)) {
596 PMA_relationsCleanupDatabase($db);
597 } else {
598 // garvin: VOID. No DB/Table gets deleted.
599 } // end if relation-stuff
600 } // end if ($purge)
601  
602 // garvin: If a column gets dropped, do relation magic.
603 if (isset($cpurge) && $cpurge == '1' && isset($purgekey)
604 && isset($db) && isset($table)
605 && strlen($db) && strlen($table) && !empty($purgekey)) {
606 require_once './libraries/relation_cleanup.lib.php';
607 PMA_relationsCleanupColumn($db, $table, $purgekey);
608  
609 } // end if column PMA_* purge
610 } // end else "didn't ask to see php code"
611  
612 // No rows returned -> move back to the calling page
613 if ($num_rows < 1 || $is_affected) {
614 if ($is_delete) {
615 $message = $strDeletedRows . '&nbsp;' . $num_rows;
616 } elseif ($is_insert) {
617 if ($is_replace) {
618 /* For replace we get DELETED + INSERTED row count, so we have to call it affected */
619 $message = $strAffectedRows . '&nbsp;' . $num_rows;
620 } else {
621 $message = $strInsertedRows . '&nbsp;' . $num_rows;
622 }
623 $insert_id = PMA_DBI_insert_id();
624 if ($insert_id != 0) {
625 // insert_id is id of FIRST record inserted in one insert, so if we inserted multiple rows, we had to increment this
626 $message .= '[br]'.$strInsertedRowId . '&nbsp;' . ($insert_id + $num_rows - 1);
627 }
628 } elseif ($is_affected) {
629 $message = $strAffectedRows . '&nbsp;' . $num_rows;
630  
631 // Ok, here is an explanation for the !$is_select.
632 // The form generated by sql_query_form.lib.php
633 // and db_details.php has many submit buttons
634 // on the same form, and some confusion arises from the
635 // fact that $zero_rows is sent for every case.
636 // The $zero_rows containing $strSuccess and sent with
637 // the form should not have priority over
638 // errors like $strEmptyResultSet
639 } elseif (!empty($zero_rows) && !$is_select) {
640 $message = $zero_rows;
641 } elseif (!empty($GLOBALS['show_as_php'])) {
642 $message = $strPhp;
643 } elseif (!empty($GLOBALS['validatequery'])) {
644 $message = $strValidateSQL;
645 } else {
646 $message = $strEmptyResultSet;
647 }
648  
649 $message .= ' ' . (isset($GLOBALS['querytime']) ? '(' . sprintf($strQueryTime, $GLOBALS['querytime']) . ')' : '');
650  
651 if ($is_gotofile) {
652 $goto = PMA_securePath($goto);
653 // Checks for a valid target script
654 if (isset($table) && $table == '') {
655 unset($table);
656 }
657 if (isset($db) && $db == '') {
658 unset($db);
659 }
660 $is_db = $is_table = false;
661 if (strpos(' ' . $goto, 'tbl_properties') == 1) {
662 if (!isset($table)) {
663 $goto = 'db_details.php';
664 } else {
665 $is_table = @PMA_DBI_query('SHOW TABLES LIKE \'' . PMA_sqlAddslashes($table, true) . '\';', null, PMA_DBI_QUERY_STORE);
666 if (!($is_table && @PMA_DBI_num_rows($is_table))) {
667 $goto = 'db_details.php';
668 unset($table);
669 }
670 @PMA_DBI_free_result($is_table);
671 } // end if... else...
672 }
673 if (strpos(' ' . $goto, 'db_details') == 1) {
674 if (isset($table)) {
675 unset($table);
676 }
677 if (!isset($db)) {
678 $goto = 'main.php';
679 } else {
680 $is_db = @PMA_DBI_select_db($db);
681 if (!$is_db) {
682 $goto = 'main.php';
683 unset($db);
684 }
685 } // end if... else...
686 }
687 // Loads to target script
688 if (strpos(' ' . $goto, 'db_details') == 1
689 || strpos(' ' . $goto, 'tbl_properties') == 1) {
690 $js_to_run = 'functions.js';
691 }
692 if ($goto != 'main.php') {
693 require_once './libraries/header.inc.php';
694 }
695 $active_page = $goto;
696 require './' . $goto;
697 } else {
698 PMA_sendHeaderLocation($cfg['PmaAbsoluteUri'] . str_replace('&amp;', '&', $goto) . '&message=' . urlencode($message));
699 } // end else
700 exit();
701 } // end no rows returned
702  
703 // At least one row is returned -> displays a table with results
704 else {
705 // Displays the headers
706 if (isset($show_query)) {
707 unset($show_query);
708 }
709 if (isset($printview) && $printview == '1') {
710 require_once './libraries/header_printview.inc.php';
711 } else {
712 $js_to_run = 'functions.js';
713 unset($message);
714 if (isset($table) && strlen($table)) {
715 require './libraries/tbl_properties_common.php';
716 $url_query .= '&amp;goto=tbl_properties.php&amp;back=tbl_properties.php';
717 require './libraries/tbl_properties_table_info.inc.php';
718 require './libraries/tbl_properties_links.inc.php';
719 } elseif (isset($db) && strlen($db)) {
720 require './libraries/db_details_common.inc.php';
721 require './libraries/db_details_db_info.inc.php';
722 } else {
723 require './libraries/server_common.inc.php';
724 require './libraries/server_links.inc.php';
725 }
726 }
727  
728 if (isset($db) && strlen($db)) {
729 require_once './libraries/relation.lib.php';
730 $cfgRelation = PMA_getRelationsParam();
731 }
732  
733 // Gets the list of fields properties
734 if (isset($result) && $result) {
735 $fields_meta = PMA_DBI_get_fields_meta($result);
736 $fields_cnt = count($fields_meta);
737 }
738  
739 // Display previous update query (from tbl_replace)
740 if (isset($disp_query) && $cfg['ShowSQL'] == true) {
741 $tmp_sql_query = $GLOBALS['sql_query'];
742 $GLOBALS['sql_query'] = $disp_query;
743 PMA_showMessage($disp_message);
744 $GLOBALS['sql_query'] = $tmp_sql_query;
745 }
746  
747 // Displays the results in a table
748 require_once './libraries/display_tbl.lib.php';
749 if (empty($disp_mode)) {
750 // see the "PMA_setDisplayMode()" function in
751 // libraries/display_tbl.lib.php
752 $disp_mode = 'urdr111101';
753 }
754 if (!isset($dontlimitchars)) {
755 $dontlimitchars = 0;
756 }
757  
758 // hide edit and delete links for information_schema
759 if (PMA_MYSQL_INT_VERSION >= 50002 && isset($db) && $db == 'information_schema') {
760 $disp_mode = 'nnnn110111';
761 }
762  
763 PMA_displayTable($result, $disp_mode, $analyzed_sql);
764 PMA_DBI_free_result($result);
765  
766 // BEGIN INDEX CHECK See if indexes should be checked.
767 if (isset($query_type) && $query_type == 'check_tbl' && isset($selected) && is_array($selected)) {
768 foreach ($selected AS $idx => $tbl_name) {
769 $indexes = $indexes_info = $indexes_data = array();
770 $tbl_ret_keys = PMA_get_indexes(urldecode($tbl_name), $err_url_0);
771  
772 PMA_extract_indexes($tbl_ret_keys, $indexes, $indexes_info, $indexes_data);
773  
774 $idx_collection = PMA_show_indexes(urldecode($tbl_name), $indexes, $indexes_info, $indexes_data, false);
775 $check = PMA_check_indexes($idx_collection);
776 if (!empty($check)) {
777 ?>
778 <table border="0" cellpadding="2" cellspacing="0">
779 <tr>
780 <td class="tblHeaders" colspan="7"><?php printf($strIndexWarningTable, urldecode($tbl_name)); ?></td>
781 </tr>
782 <?php echo $check; ?>
783 </table>
784 <?php
785 }
786 }
787 } // End INDEX CHECK
788  
789 if ($disp_mode[6] == '1' || $disp_mode[9] == '1') {
790 echo "\n";
791 echo '<hr />' . "\n";
792  
793 // Displays "Insert a new row" link if required
794 if ($disp_mode[6] == '1') {
795 $lnk_goto = 'sql.php?'
796 . PMA_generate_common_url($db, $table)
797 . '&amp;pos=' . $pos
798 . '&amp;session_max_rows=' . $session_max_rows
799 . '&amp;disp_direction=' . $disp_direction
800 . '&amp;repeat_cells=' . $repeat_cells
801 . '&amp;dontlimitchars=' . $dontlimitchars
802 . '&amp;sql_query=' . urlencode($sql_query);
803 $url_query = '?'
804 . PMA_generate_common_url($db, $table)
805 . '&amp;pos=' . $pos
806 . '&amp;session_max_rows=' . $session_max_rows
807 . '&amp;disp_direction=' . $disp_direction
808 . '&amp;repeat_cells=' . $repeat_cells
809 . '&amp;dontlimitchars=' . $dontlimitchars
810 . '&amp;sql_query=' . urlencode($sql_query)
811 . '&amp;goto=' . urlencode($lnk_goto);
812  
813 echo ' <!-- Insert a new row -->' . "\n";
814 echo PMA_linkOrButton(
815 'tbl_change.php' . $url_query,
816 ($cfg['PropertiesIconic'] ? '<img class="icon" src="' . $pmaThemeImage . 'b_insrow.png" height="16" width="16" alt="' . $strInsertNewRow . '"/>' : '') . $strInsertNewRow,
817 '', true, true, '') . "\n";
818  
819 if ($disp_mode[9] == '1') {
820 echo '&nbsp;&nbsp;';
821 }
822 echo "\n";
823 } // end insert new row
824  
825 // Displays "printable view" link if required
826 if ($disp_mode[9] == '1') {
827 $url_query = '?'
828 . PMA_generate_common_url($db, $table)
829 . '&amp;pos=' . $pos
830 . '&amp;session_max_rows=' . $session_max_rows
831 . '&amp;disp_direction=' . $disp_direction
832 . '&amp;repeat_cells=' . $repeat_cells
833 . '&amp;printview=1'
834 . '&amp;sql_query=' . urlencode($sql_query);
835 echo ' <!-- Print view -->' . "\n";
836 echo PMA_linkOrButton(
837 'sql.php' . $url_query . ((isset($dontlimitchars) && $dontlimitchars == '1') ? '&amp;dontlimitchars=1' : ''),
838 ($cfg['PropertiesIconic'] ? '<img class="icon" src="' . $pmaThemeImage . 'b_print.png" height="16" width="16" alt="' . $strPrintView . '"/>' : '') . $strPrintView,
839 '', true, true, 'print_view') . "\n";
840  
841 if (!$dontlimitchars) {
842 echo ' &nbsp;&nbsp;' . "\n";
843 echo PMA_linkOrButton(
844 'sql.php' . $url_query . '&amp;dontlimitchars=1',
845 ($cfg['PropertiesIconic'] ? '<img class="icon" src="' . $pmaThemeImage . 'b_print.png" height="16" width="16" alt="' . $strPrintViewFull . '"/>' : '') . $strPrintViewFull,
846 '', true, true, 'print_view') . "\n";
847 }
848 } // end displays "printable view"
849  
850 echo "\n";
851 }
852  
853 // Export link
854 // (the url_query has extra parameters that won't be used to export)
855 // (the single_table parameter is used in display_export.lib.php
856 // to hide the SQL and the structure export dialogs)
857 if (isset($analyzed_sql[0]) && $analyzed_sql[0]['querytype'] == 'SELECT' && !isset($printview)) {
858 if (isset($analyzed_sql[0]['table_ref'][0]['table_true_name']) && !isset($analyzed_sql[0]['table_ref'][1]['table_true_name'])) {
859 $single_table = '&amp;single_table=true';
860 } else {
861 $single_table = '';
862 }
863 echo ' <!-- Export -->' . "\n";
864 echo ' &nbsp;&nbsp;' . "\n";
865 echo PMA_linkOrButton(
866 'tbl_properties_export.php' . $url_query . '&amp;unlim_num_rows=' . $unlim_num_rows . $single_table,
867 ($cfg['PropertiesIconic'] ? '<img class="icon" src="' . $pmaThemeImage . 'b_tblexport.png" height="16" width="16" alt="' . $strExport . '" />' : '') . $strExport,
868 '', true, true, '') . "\n";
869 }
870  
871 // Bookmark Support if required
872 if ($disp_mode[7] == '1'
873 && (isset($cfg['Bookmark']) && $cfg['Bookmark']['db'] && $cfg['Bookmark']['table'] && empty($id_bookmark))
874 && !empty($sql_query)) {
875 echo "\n";
876  
877 $goto = 'sql.php?'
878 . PMA_generate_common_url($db, $table)
879 . '&amp;pos=' . $pos
880 . '&amp;session_max_rows=' . $session_max_rows
881 . '&amp;disp_direction=' . $disp_direction
882 . '&amp;repeat_cells=' . $repeat_cells
883 . '&amp;dontlimitchars=' . $dontlimitchars
884 . '&amp;sql_query=' . urlencode($sql_query)
885 . '&amp;id_bookmark=1';
886  
887 if ($disp_mode[3] == '1') {
888 echo ' <i>' . $strOr . '</i>';
889 } else {
890 echo '<br /><br />';
891 }
892 ?>
893 <form action="sql.php" method="post" onsubmit="return emptyFormElements(this, 'fields[label]');">
894 <?php echo PMA_generate_common_hidden_inputs(); ?>
895 <input type="hidden" name="goto" value="<?php echo $goto; ?>" />
896 <input type="hidden" name="fields[dbase]" value="<?php echo htmlspecialchars($db); ?>" />
897 <input type="hidden" name="fields[user]" value="<?php echo $cfg['Bookmark']['user']; ?>" />
898 <input type="hidden" name="fields[query]" value="<?php echo urlencode(isset($complete_query) ? $complete_query : $sql_query); ?>" />
899 <fieldset>
900 <legend><?php
901 echo ($cfg['PropertiesIconic'] ? '<img class="icon" src="' . $pmaThemeImage . 'b_bookmark.png" width="16" height="16" alt="' . $strBookmarkThis . '" />' : '')
902 . $strBookmarkThis;
903 ?>
904 </legend>
905  
906 <div class="formelement">
907 <label for="fields_label_"><?php echo $strBookmarkLabel; ?>:</label>
908 <input type="text" id="fields_label_" name="fields[label]" value="" />
909 </div>
910  
911 <div class="formelement">
912 <input type="checkbox" name="bkm_all_users" id="bkm_all_users" value="true" />
913 <label for="bkm_all_users"><?php echo $strBookmarkAllUsers; ?></label>
914 </div>
915  
916 <div class="clearfloat"></div>
917 </fieldset>
918 <fieldset class="tblFooters">
919 <input type="submit" name="store_bkm" value="<?php echo $strBookmarkThis; ?>" />
920 </fieldset>
921 </form>
922 <?php
923 } // end bookmark support
924  
925 // Do print the page if required
926 if (isset($printview) && $printview == '1') {
927 ?>
928 <script type="text/javascript" language="javascript">
929 //<![CDATA[
930 // Do print the page
931 window.onload = function()
932 {
933 if (typeof(window.print) != 'undefined') {
934 window.print();
935 }
936 }
937 //]]>
938 </script>
939 <?php
940 } // end print case
941 } // end rows returned
942  
943 } // end executes the query
944  
945 /**
946 * Displays the footer
947 */
948 require_once './libraries/footer.inc.php';
949 ?>