diff --git a/libraries/sqlparser.lib.php3 b/libraries/sqlparser.lib.php3
index 52a6a21d6..ad02b7fe2 100644
--- a/libraries/sqlparser.lib.php3
+++ b/libraries/sqlparser.lib.php3
@@ -19,12 +19,9 @@
*
* If you want to extract data from it then, you just need to run
* $sql_info = PMA_SQP_analyze($parsed_sql);
- * (returned structure of this function is being rewritten presently);
*
- * lem9: Currently the analyzer can interpret db, table, column, alias
- * for SELECTs;
- * see comments in PMA_SQP_analyze for the new returned info
- * (select_expr and table_ref)
+ * lem9: See comments in PMA_SQP_analyze for the returned info
+ * from the analyzer.
*
* If you want a pretty-printed version of the query, do:
* $string = PMA_SQP_formatHtml($parsed_sql);
@@ -636,6 +633,12 @@ if (!defined('PMA_SQP_LIB_INCLUDED')) {
$size = $arr['len'];
$subresult = array(
'querytype' => '',
+ 'select_expr_clause'=> '', // the whole stuff between SELECT and FROM , except DISTINCT
+ 'from_clause'=> '',
+ 'group_by_clause'=> '',
+ 'order_by_clause'=> '',
+ 'having_clause' => '',
+ 'where_clause' => '',
'queryflags' => array(),
'select_expr' => array(),
'table_ref' => array()
@@ -685,6 +688,17 @@ if (!defined('PMA_SQP_LIB_INCLUDED')) {
*
* ['queryflags']['need_confirm'] = 1; if the query needs confirmation
* ['queryflags']['select_from'] = 1; if this is a real SELECT...FROM
+ *
+ * lem9: query clauses
+ * -------------
+ *
+ * The select is splitted in those clauses:
+ * ['select_expr_clause']
+ * ['from_clause']
+ * ['group_by_clause']
+ * ['order_by_clause']
+ * ['having_clause']
+ * ['where_clause']
*/
// must be sorted
// TODO: current logic checks for only one word, so I put only the
@@ -714,6 +728,18 @@ if (!defined('PMA_SQP_LIB_INCLUDED')) {
);
$words_ending_table_ref_cnt = 9; //count($words_ending_table_ref);
+ $words_ending_clauses = array(
+ 'FOR',
+ 'LIMIT',
+ 'LOCK',
+ 'PROCEDURE',
+ 'UNION'
+ );
+ $words_ending_clauses_cnt = 5; //count($words_ending_clauses);
+
+
+
+
// must be sorted
$supported_query_types = array(
'SELECT'
@@ -980,6 +1006,10 @@ if (!defined('PMA_SQP_LIB_INCLUDED')) {
. '.' . $subresult['table_ref'][$current_table_ref]['expr'];
} // end if ($size_chain > 1)
+ // add the table alias into the whole expression
+ $subresult['table_ref'][$current_table_ref]['expr']
+ .= ' ' . $subresult['table_ref'][$current_table_ref]['table_alias'];
+
unset($chain);
$previous_was_identifier = TRUE;
//continue;
@@ -1088,16 +1118,30 @@ if (!defined('PMA_SQP_LIB_INCLUDED')) {
// loop #2: for queryflags
- // and querytype (for queries != 'SELECT')
+ // ,querytype (for queries != 'SELECT')
//
// This is not in the loop 1 to keep logic simple
+ // we will also need this queryflag in loop 2
+ // so set it here
+ if (isset($current_table_ref) && $current_table_ref > -1) {
+ $subresult['queryflags']['select_from'] = 1;
+ }
+
$seen_reserved_word = FALSE;
+ $seen_group = FALSE;
+ $seen_order = FALSE;
+ $in_group_by = FALSE; // true when we are into the GROUP BY clause
+ $in_order_by = FALSE; // true when we are into the ORDER BY clause
+ $in_having = FALSE; // true when we are into the HAVING clause
+ $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;
for ($i = 0; $i < $size; $i++) {
-//echo "trace 2" . $arr[$i]['data'] . " (" . $arr[$i]['type'] . ")
";
+//echo "trace loop2 " . $arr[$i]['data'] . " (" . $arr[$i]['type'] . ")
";
- // c o n f i r m a t i o n r e q u e s t s (need_confirm)
+ // need_confirm
//
// check for reserved words that will have to generate
// a confirmation request later in sql.php3
@@ -1129,13 +1173,143 @@ if (!defined('PMA_SQP_LIB_INCLUDED')) {
$subresult['queryflags']['need_confirm'] = 1;
}
}
+
+ if ($upper_data == 'SELECT') {
+ $in_select_expr = TRUE;
+ $select_expr_clause = '';
+ }
+
+ // if this is a real SELECT...FROM
+ if ($upper_data == 'FROM' && isset($subresult['queryflags']['select_from']) && $subresult['queryflags']['select_from'] == 1) {
+ $in_from = TRUE;
+ $from_clause = '';
+ $in_select_expr = FALSE;
+ }
+
+
+ // (we could have less resetting of variables to FALSE
+ // if we trust that the query respects the standard
+ // MySQL order for clauses)
+
+ // we use $seen_group and $seen_order because we are looking
+ // for the BY
+ if ($upper_data == 'GROUP') {
+ $seen_group = TRUE;
+ $seen_order = FALSE;
+ $in_having = FALSE;
+ $in_order_by = FALSE;
+ $in_where = FALSE;
+ $in_select_expr = FALSE;
+ $in_from = FALSE;
+ }
+ if ($upper_data == 'ORDER') {
+ $seen_order = TRUE;
+ $seen_group = FALSE;
+ $in_having = FALSE;
+ $in_group_by = FALSE;
+ $in_where = FALSE;
+ $in_select_expr = FALSE;
+ $in_from = FALSE;
+ }
+ if ($upper_data == 'HAVING') {
+ $in_having = TRUE;
+ $having_clause = '';
+ $seen_group = FALSE;
+ $seen_order = FALSE;
+ $in_group_by = FALSE;
+ $in_order_by = FALSE;
+ $in_where = FALSE;
+ $in_select_expr = FALSE;
+ $in_from = FALSE;
+ }
+
+ if ($upper_data == 'WHERE') {
+ $in_where = TRUE;
+ $where_clause = '';
+ $seen_group = FALSE;
+ $seen_order = FALSE;
+ $in_group_by = FALSE;
+ $in_order_by = FALSE;
+ $in_having = FALSE;
+ $in_select_expr = FALSE;
+ $in_from = FALSE;
+ }
+
+ if ($upper_data == 'BY') {
+ if ($seen_group) {
+ $in_group_by = TRUE;
+ $group_by_clause = '';
+ }
+ if ($seen_order) {
+ $in_order_by = TRUE;
+ $order_by_clause = '';
+ }
+ }
+
+ // if we find one of the words that could end the clause
+ if (PMA_STR_binarySearchInArr($upper_data, $words_ending_clauses, $words_ending_clauses_cnt)) {
+
+ $in_group_by = FALSE;
+ $in_order_by = FALSE;
+ $in_having = FALSE;
+ $in_where = FALSE;
+ $in_select_expr = FALSE;
+ $in_from = FALSE;
+ }
+
+ } // endif (reservedWord)
+
+
+ // do not add a blank after a function name
+
+ $sep=' ';
+ if ($arr[$i]['type'] == 'alpha_functionName') {
+ $sep='';
}
+ if ($in_select_expr && $upper_data != 'SELECT' && $upper_data != 'DISTINCT') {
+ $select_expr_clause .= $arr[$i]['data'] . $sep;
+ }
+ if ($in_from && $upper_data != 'FROM') {
+ $from_clause .= $arr[$i]['data'] . $sep;
+ }
+ if ($in_group_by && $upper_data != 'GROUP' && $upper_data != 'BY') {
+ $group_by_clause .= $arr[$i]['data'] . $sep;
+ }
+ if ($in_order_by && $upper_data != 'ORDER' && $upper_data != 'BY') {
+ $order_by_clause .= $arr[$i]['data'] . $sep;
+ }
+ if ($in_having && $upper_data != 'HAVING') {
+ $having_clause .= $arr[$i]['data'] . $sep;
+ }
+ if ($in_where && $upper_data != 'WHERE') {
+ $where_clause .= $arr[$i]['data'] . $sep;
+ }
+
+ // clear $upper_data for next iteration
+ $upper_data='';
+
} // end for $i (loop #2)
- if (isset($current_table_ref) && $current_table_ref > -1) {
- $subresult['queryflags']['select_from'] = 1;
+ if (isset($select_expr_clause)) {
+ $subresult['select_expr_clause'] = $select_expr_clause;
}
+ if (isset($from_clause)) {
+ $subresult['from_clause'] = $from_clause;
+ }
+ if (isset($group_by_clause)) {
+ $subresult['group_by_clause'] = $group_by_clause;
+ }
+ if (isset($order_by_clause)) {
+ $subresult['order_by_clause'] = $order_by_clause;
+ }
+ if (isset($having_clause)) {
+ $subresult['having_clause'] = $having_clause;
+ }
+ if (isset($where_clause)) {
+ $subresult['where_clause'] = $where_clause;
+ }
+
// They are naughty and didn't have a trailing semi-colon,
// then still handle it properly