From 189dd358d2ea0ce9603a79398c2a335d61ccfba3 Mon Sep 17 00:00:00 2001 From: Marc Delisle Date: Thu, 29 Jul 2004 16:48:08 +0000 Subject: [PATCH] bug 965026 GROUP_CONCAT, previous commit was wrong --- libraries/sqlparser.data.php | 3 +- libraries/sqlparser.lib.php | 77 ++++++++++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 18 deletions(-) diff --git a/libraries/sqlparser.data.php b/libraries/sqlparser.data.php index 27d315852..56d799645 100644 --- a/libraries/sqlparser.data.php +++ b/libraries/sqlparser.data.php @@ -78,6 +78,7 @@ $PMA_SQPdata_function_name = array ( 'FROM_UNIXTIME', 'GET_LOCK', 'GREATEST', + 'GROUP_CONCAT', 'GROUP_UNIQUE_USERS', 'HEX', 'IFNULL', @@ -168,7 +169,7 @@ $PMA_SQPdata_function_name = array ( 'YEARWEEK' ); //$PMA_SQPdata_function_name_cnt = count($PMA_SQPdata_function_name); -$PMA_SQPdata_function_name_cnt = 151; +$PMA_SQPdata_function_name_cnt = 152; $PMA_SQPdata_column_attrib = array ( 'AUTO_INCREMENT', diff --git a/libraries/sqlparser.lib.php b/libraries/sqlparser.lib.php index fb2553060..f22749607 100644 --- a/libraries/sqlparser.lib.php +++ b/libraries/sqlparser.lib.php @@ -712,6 +712,9 @@ if ($is_minimum_common == FALSE) { // so we track wether we are in the EXTRACT() $in_extract = FALSE; + // for GROUP_CONCAT( ... ) + $in_group_concat = FALSE; + /* Description of analyzer results * * lem9: db, table, column, alias @@ -843,7 +846,7 @@ if ($is_minimum_common == FALSE) { // loop #1 for each token: select_expr, table_ref for SELECT for ($i = 0; $i < $size; $i++) { -//echo "trace " . $arr[$i]['data'] . " (" . $arr[$i]['type'] . ")
"; +//DEBUG echo "trace loop1 " . $arr[$i]['data'] . " (" . $arr[$i]['type'] . ")
"; // High speed seek for locating the end of the current query if ($seek_queryend == TRUE) { @@ -867,6 +870,9 @@ if ($is_minimum_common == FALSE) { if ($in_extract) { $number_of_brackets_in_extract++; } + if ($in_group_concat) { + $number_of_brackets_in_group_concat++; + } } // ============================================================== if ($arr[$i]['type'] == 'punct_bracket_close_round') { @@ -876,6 +882,12 @@ if ($is_minimum_common == FALSE) { $in_extract = FALSE; } } + if ($in_group_concat) { + $number_of_brackets_in_group_concat--; + if ($number_of_brackets_in_group_concat == 0) { + $in_group_concat = FALSE; + } + } } // ============================================================== if ($arr[$i]['type'] == 'alpha_functionName') { @@ -884,6 +896,10 @@ if ($is_minimum_common == FALSE) { $in_extract = TRUE; $number_of_brackets_in_extract = 0; } + if ($upper_data =='GROUP_CONCAT') { + $in_group_concat = TRUE; + $number_of_brackets_in_group_concat = 0; + } } // ============================================================== @@ -946,7 +962,7 @@ if ($is_minimum_common == FALSE) { break; } // end switch - if ($subresult['querytype'] == 'SELECT') { + if ($subresult['querytype'] == 'SELECT' && !$in_group_concat) { if (!$seen_from) { if ($previous_was_identifier && isset($chain)) { // found alias for this select_expr, save it @@ -1153,11 +1169,17 @@ if ($is_minimum_common == FALSE) { // if this is the last token, it implies that we have // seen the end of table references // Check for the end of table references + // + // Note: if we are analyzing a GROUP_CONCAT clause, + // we might find a word that seems to indicate that + // we have found the end of table refs (like ORDER) + // but it's a modifier of the GROUP_CONCAT so + // it's not the real end of table refs if (($i == $size-1) || ($arr[$i]['type'] == 'alpha_reservedWord' + && !$in_group_concat && PMA_STR_binarySearchInArr($upper_data, $words_ending_table_ref, $words_ending_table_ref_cnt))) { $seen_end_of_table_ref = TRUE; - // to be able to save the last table ref, but do not // set it true if we found a word like "ON" that has // already set it to false @@ -1180,22 +1202,22 @@ if ($is_minimum_common == FALSE) { /* if (isset($current_select_expr)) { for ($trace=0; $trace<=$current_select_expr; $trace++) { - - echo "
"; - reset ($subresult['select_expr'][$trace]); - while (list ($key, $val) = each ($subresult['select_expr'][$trace])) - echo "sel expr $trace $key => $val
\n"; - } + echo "
"; + reset ($subresult['select_expr'][$trace]); + while (list ($key, $val) = each ($subresult['select_expr'][$trace])) + echo "sel expr $trace $key => $val
\n"; + } } if (isset($current_table_ref)) { + echo "current_table_ref = " . $current_table_ref . "
"; for ($trace=0; $trace<=$current_table_ref; $trace++) { - echo "
"; - reset ($subresult['table_ref'][$trace]); - while (list ($key, $val) = each ($subresult['table_ref'][$trace])) - echo "table ref $trace $key => $val
\n"; - } + echo "
"; + reset ($subresult['table_ref'][$trace]); + while (list ($key, $val) = each ($subresult['table_ref'][$trace])) + echo "table ref $trace $key => $val
\n"; + } } */ // ------------------------------------------------------- @@ -1219,6 +1241,7 @@ if ($is_minimum_common == FALSE) { $in_select_expr = FALSE; // true when we are into the select expr clause $in_where = FALSE; // true when we are into the WHERE clause $in_from = FALSE; + $in_group_concat = FALSE; for ($i = 0; $i < $size; $i++) { //DEBUG echo "trace loop2 " . $arr[$i]['data'] . " (" . $arr[$i]['type'] . ")
"; @@ -1266,7 +1289,7 @@ if ($is_minimum_common == FALSE) { $in_select_expr = TRUE; $select_expr_clause = ''; } - if ($upper_data == 'DISTINCT') { + if ($upper_data == 'DISTINCT' && !$in_group_concat) { $subresult['queryflags']['distinct'] = 1; } @@ -1297,7 +1320,7 @@ if ($is_minimum_common == FALSE) { $in_select_expr = FALSE; $in_from = FALSE; } - if ($upper_data == 'ORDER') { + if ($upper_data == 'ORDER' && !$in_group_concat) { $seen_order = TRUE; $seen_group = FALSE; $in_having = FALSE; @@ -1357,10 +1380,31 @@ if ($is_minimum_common == FALSE) { // do not add a blank after a function name + // TODO: can we combine loop 2 and loop 1? + // some code is repeated here... $sep=' '; if ($arr[$i]['type'] == 'alpha_functionName') { $sep=''; + $upper_data = strtoupper($arr[$i]['data']); + if ($upper_data =='GROUP_CONCAT') { + $in_group_concat = TRUE; + $number_of_brackets_in_group_concat = 0; + } + } + + if ($arr[$i]['type'] == 'punct_bracket_open_round') { + if ($in_group_concat) { + $number_of_brackets_in_group_concat++; + } + } + if ($arr[$i]['type'] == 'punct_bracket_close_round') { + if ($in_group_concat) { + $number_of_brackets_in_group_concat--; + if ($number_of_brackets_in_group_concat == 0) { + $in_group_concat = FALSE; + } + } } if ($in_select_expr && $upper_data != 'SELECT' && $upper_data != 'DISTINCT') { @@ -1558,7 +1602,6 @@ if ($is_minimum_common == FALSE) { $subresult['position_of_first_select'] = $position_of_first_select; } - // They are naughty and didn't have a trailing semi-colon, // then still handle it properly if ($subresult['querytype'] != '') {