bug #967610, double column sort with JOIN

This commit is contained in:
Marc Delisle
2004-10-11 13:24:59 +00:00
parent 620f9b764b
commit 0a06f5c57c
3 changed files with 55 additions and 40 deletions

View File

@@ -9,6 +9,8 @@ $Source$
* Documentation.html: typos and XHTML validity, thanks to Cedric Corazza * Documentation.html: typos and XHTML validity, thanks to Cedric Corazza
* libraries/export/sql.php: bug #1039639: under mysqli, some field types * libraries/export/sql.php: bug #1039639: under mysqli, some field types
were wrongly exported as binary were wrongly exported as binary
* libraries/sqlparser.lib.php, /display_tbl.lib.php: bug #967610, double
column sort with JOIN
2004-10-11 Michal Čihař <michal@cihar.com> 2004-10-11 Michal Čihař <michal@cihar.com>
* tbl_query_box.php: Don't try to replace %t and %f when table name is empty. * tbl_query_box.php: Don't try to replace %t and %f when table name is empty.

View File

@@ -452,42 +452,29 @@ function PMA_displayTableHeaders(&$is_display, &$fields_meta, $fields_cnt = 0, $
$analyzed_sql = array(); $analyzed_sql = array();
} }
// can be result sorted? // can the result be sorted?
if ($is_display['sort_lnk'] == '1') { if ($is_display['sort_lnk'] == '1') {
// Just as fallback // Just as fallback
$unsorted_sql_query = $sql_query; $unsorted_sql_query = $sql_query;
if (isset($analyzed_sql[0]['unsorted_query'])) {
// sorting by indexes, only if it makes sense $unsorted_sql_query = $analyzed_sql[0]['unsorted_query'];
if (isset($analyzed_sql) && isset($analyzed_sql[0]) &&
isset($analyzed_sql[0]['querytype']) && $analyzed_sql[0]['querytype'] == 'SELECT' &&
isset($analyzed_sql[0]['table_ref']) && count($analyzed_sql[0]['table_ref']) == 1) {
$unsorted_sql_query = 'SELECT ';
if (isset($analyzed_sql[0]['queryflags']['distinct'])) {
$unsorted_sql_query .= ' DISTINCT ';
}
$unsorted_sql_query .= $analyzed_sql[0]['select_expr_clause'];
if (!empty($analyzed_sql[0]['from_clause'])) {
$unsorted_sql_query .= ' FROM ' . $analyzed_sql[0]['from_clause'];
} }
if (!empty($analyzed_sql[0]['where_clause'])) { // we need $sort_expression and $sort_expression_nodir
$unsorted_sql_query .= ' WHERE ' . $analyzed_sql[0]['where_clause']; // even if there are many table references
}
if (!empty($analyzed_sql[0]['group_by_clause'])) {
$unsorted_sql_query .= ' GROUP BY ' . $analyzed_sql[0]['group_by_clause'];
}
if (!empty($analyzed_sql[0]['having_clause'])) {
$unsorted_sql_query .= ' HAVING ' . $analyzed_sql[0]['having_clause'];
}
$sort_expression = trim(str_replace(' ', ' ',$analyzed_sql[0]['order_by_clause'])); $sort_expression = trim(str_replace(' ', ' ',$analyzed_sql[0]['order_by_clause']));
// Get rid of ASC|DESC // Get rid of ASC|DESC (TODO: analyzer)
preg_match('@(.*)([[:space:]]*(ASC|DESC))@si',$sort_expression,$matches); preg_match('@(.*)([[:space:]]*(ASC|DESC))@si',$sort_expression,$matches);
$sort_expression_nodir = isset($matches[1]) ? trim($matches[1]) : $sort_expression; $sort_expression_nodir = isset($matches[1]) ? trim($matches[1]) : $sort_expression;
// sorting by indexes, only if it makes sense (only one table ref)
if (isset($analyzed_sql) && isset($analyzed_sql[0]) &&
isset($analyzed_sql[0]['querytype']) && $analyzed_sql[0]['querytype'] == 'SELECT' &&
isset($analyzed_sql[0]['table_ref']) && count($analyzed_sql[0]['table_ref']) == 1) {
// grab indexes data: // grab indexes data:
PMA_DBI_select_db($db); PMA_DBI_select_db($db);
@@ -513,7 +500,7 @@ function PMA_displayTableHeaders(&$is_display, &$fields_meta, $fields_cnt = 0, $
if (isset($row['Cardinality'])) { if (isset($row['Cardinality'])) {
$indexes_info[$row['Key_name']]['Cardinality'] = $row['Cardinality']; $indexes_info[$row['Key_name']]['Cardinality'] = $row['Cardinality'];
} }
// I don't know what does following column mean.... // I don't know what does the following column mean....
// $indexes_info[$row['Key_name']]['Packed'] = $row['Packed']; // $indexes_info[$row['Key_name']]['Packed'] = $row['Packed'];
$indexes_info[$row['Key_name']]['Comment'] = (isset($row['Comment'])) $indexes_info[$row['Key_name']]['Comment'] = (isset($row['Comment']))
? $row['Comment'] ? $row['Comment']
@@ -714,7 +701,9 @@ function PMA_displayTableHeaders(&$is_display, &$fields_meta, $fields_cnt = 0, $
} }
if ($is_display['sort_lnk'] == '1') { if ($is_display['sort_lnk'] == '1') {
$is_join = preg_match('@(.*)[[:space:]]+FROM[[:space:]]+.*[[:space:]]+JOIN@i', $sql_query, $select_stt); //$is_join = preg_match('@(.*)[[:space:]]+FROM[[:space:]]+.*[[:space:]]+JOIN@im', $sql_query, $select_stt);
$is_join = (isset($analyzed_sql[0]['queryflags']['join']) ?TRUE:FALSE);
$select_expr = $analyzed_sql[0]['select_expr_clause'];
} else { } else {
$is_join = FALSE; $is_join = FALSE;
} }
@@ -763,12 +752,14 @@ function PMA_displayTableHeaders(&$is_display, &$fields_meta, $fields_cnt = 0, $
// FROM `PMA_relation` AS `1` , `PMA_relation` AS `2` // FROM `PMA_relation` AS `1` , `PMA_relation` AS `2`
if (($is_join if (($is_join
&& !preg_match('~([^[:space:],]|`[^`]`)[[:space:]]+(as[[:space:]]+)?' . $fields_meta[$i]->name . '~i', $select_stt[1], $parts)) //&& !preg_match('~([^[:space:],]|`[^`]`)[[:space:]]+(as[[:space:]]+)?' . $fields_meta[$i]->name . '~i', $select_stt[1], $parts))
&& !preg_match('~([^[:space:],]|`[^`]`)[[:space:]]+(as[[:space:]]+)?' . $fields_meta[$i]->name . '~i', $select_expr, $parts))
|| ( isset($analyzed_sql[0]['select_expr'][$i]['expr']) || ( isset($analyzed_sql[0]['select_expr'][$i]['expr'])
&& isset($analyzed_sql[0]['select_expr'][$i]['column']) && isset($analyzed_sql[0]['select_expr'][$i]['column'])
&& $analyzed_sql[0]['select_expr'][$i]['expr'] != && $analyzed_sql[0]['select_expr'][$i]['expr'] !=
$analyzed_sql[0]['select_expr'][$i]['column'] $analyzed_sql[0]['select_expr'][$i]['column']
&& !empty($fields_meta[$i]->table)) ) { && !empty($fields_meta[$i]->table)) ) {
//$sort_tbl = PMA_backquote($fields_meta[$i]->table) . '.';
$sort_tbl = PMA_backquote($fields_meta[$i]->table) . ' . '; $sort_tbl = PMA_backquote($fields_meta[$i]->table) . ' . ';
} else { } else {
$sort_tbl = ''; $sort_tbl = '';

View File

@@ -698,6 +698,7 @@ if ($is_minimum_common == FALSE) {
'having_clause' => '', 'having_clause' => '',
'where_clause' => '', 'where_clause' => '',
'where_clause_identifiers' => array(), 'where_clause_identifiers' => array(),
'unsorted_query' => '',
'queryflags' => array(), 'queryflags' => array(),
'select_expr' => array(), 'select_expr' => array(),
'table_ref' => array(), 'table_ref' => array(),
@@ -753,6 +754,7 @@ if ($is_minimum_common == FALSE) {
* ['queryflags']['select_from'] = 1; if this is a real SELECT...FROM * ['queryflags']['select_from'] = 1; if this is a real SELECT...FROM
* ['queryflags']['distinct'] = 1; for a DISTINCT * ['queryflags']['distinct'] = 1; for a DISTINCT
* ['queryflags']['union'] = 1; for a UNION * ['queryflags']['union'] = 1; for a UNION
* ['queryflags']['join'] = 1; for a JOIN
* *
* lem9: query clauses * lem9: query clauses
* ------------- * -------------
@@ -765,9 +767,12 @@ if ($is_minimum_common == FALSE) {
* ['having_clause'] * ['having_clause']
* ['where_clause'] * ['where_clause']
* *
* and the identifiers of the where clause are put into the array * The identifiers of the WHERE clause are put into the array
* ['where_clause_identifier'] * ['where_clause_identifier']
* *
* For a SELECT, the whole query without the ORDER BY clause is put into
* ['unsorted_query']
*
* lem9: foreign keys * lem9: foreign keys
* ------------ * ------------
* The CREATE TABLE may contain FOREIGN KEY clauses, so they get * The CREATE TABLE may contain FOREIGN KEY clauses, so they get
@@ -781,6 +786,8 @@ if ($is_minimum_common == FALSE) {
* *
* The array index of the first SELECT we find. Will be used to * The array index of the first SELECT we find. Will be used to
* insert a SQL_CALC_FOUND_ROWS. * insert a SQL_CALC_FOUND_ROWS.
*
* End of description of analyzer results
*/ */
// must be sorted // must be sorted
@@ -1235,13 +1242,14 @@ if ($is_minimum_common == FALSE) {
$seen_reserved_word = FALSE; $seen_reserved_word = FALSE;
$seen_group = FALSE; $seen_group = FALSE;
$seen_order = FALSE; $seen_order = FALSE;
$in_group_by = FALSE; // true when we are into the GROUP BY clause $in_group_by = FALSE; // true when we are inside the GROUP BY clause
$in_order_by = FALSE; // true when we are into the ORDER BY clause $in_order_by = FALSE; // true when we are inside the ORDER BY clause
$in_having = FALSE; // true when we are into the HAVING clause $in_having = FALSE; // true when we are inside the HAVING clause
$in_select_expr = FALSE; // true when we are into the select expr clause $in_select_expr = FALSE; // true when we are inside the select expr clause
$in_where = FALSE; // true when we are into the WHERE clause $in_where = FALSE; // true when we are inside the WHERE clause
$in_from = FALSE; $in_from = FALSE;
$in_group_concat = FALSE; $in_group_concat = FALSE;
$unsorted_query = '';
for ($i = 0; $i < $size; $i++) { for ($i = 0; $i < $size; $i++) {
//DEBUG echo "trace loop2 <b>" . $arr[$i]['data'] . "</b> (" . $arr[$i]['type'] . ")<br />"; //DEBUG echo "trace loop2 <b>" . $arr[$i]['data'] . "</b> (" . $arr[$i]['type'] . ")<br />";
@@ -1297,6 +1305,10 @@ if ($is_minimum_common == FALSE) {
$subresult['queryflags']['union'] = 1; $subresult['queryflags']['union'] = 1;
} }
if ($upper_data == 'JOIN') {
$subresult['queryflags']['join'] = 1;
}
// if this is a real SELECT...FROM // if this is a real SELECT...FROM
if ($upper_data == 'FROM' && isset($subresult['queryflags']['select_from']) && $subresult['queryflags']['select_from'] == 1) { if ($upper_data == 'FROM' && isset($subresult['queryflags']['select_from']) && $subresult['queryflags']['select_from'] == 1) {
$in_from = TRUE; $in_from = TRUE;
@@ -1431,6 +1443,13 @@ if ($is_minimum_common == FALSE) {
} }
} }
// FIXME: is it correct to always add $sep ?
if (isset($subresult['queryflags']['select_from'])
&& $subresult['queryflags']['select_from'] == 1
&& !$seen_order) {
$unsorted_query .= $arr[$i]['data'] . $sep;
}
// clear $upper_data for next iteration // clear $upper_data for next iteration
$upper_data=''; $upper_data='';
@@ -1594,6 +1613,9 @@ if ($is_minimum_common == FALSE) {
if (isset($where_clause)) { if (isset($where_clause)) {
$subresult['where_clause'] = $where_clause; $subresult['where_clause'] = $where_clause;
} }
if (isset($unsorted_query) && !empty($unsorted_query)) {
$subresult['unsorted_query'] = $unsorted_query;
}
if (isset($where_clause_identifiers)) { if (isset($where_clause_identifiers)) {
$subresult['where_clause_identifiers'] = $where_clause_identifiers; $subresult['where_clause_identifiers'] = $where_clause_identifiers;
} }