diff --git a/htdocs/sql/libraries/sqlparser.lib.php b/htdocs/sql/libraries/sqlparser.lib.php deleted file mode 100755 --- a/htdocs/sql/libraries/sqlparser.lib.php +++ /dev/null @@ -1,2525 +0,0 @@ - - * http://www.orbis-terrarum.net/?l=people.robbat2 - * - * These functions define an SQL parser system, capable of understanding and - * extracting data from a MySQL type SQL query. - * - * The basic procedure for using the new SQL parser: - * On any page that needs to extract data from a query or to pretty-print a - * query, you need code like this up at the top: - * - * ($sql contains the query) - * $parsed_sql = PMA_SQP_parse($sql); - * - * If you want to extract data from it then, you just need to run - * $sql_info = PMA_SQP_analyze($parsed_sql); - * - * 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); - * (note that that you need to have syntax.css.php included somehow in your - * page for it to work, I recommend '' at the moment.) - * - * @version $Id: sqlparser.lib.php 11513 2008-08-28 16:17:53Z lem9 $ - */ -if (! defined('PHPMYADMIN')) { - exit; -} - -/** - * Minimum inclusion? (i.e. for the stylesheet builder) - */ -if (! defined('PMA_MINIMUM_COMMON')) { - /** - * Include the string library as we use it heavily - */ - require_once './libraries/string.lib.php'; - - /** - * Include data for the SQL Parser - */ - require_once './libraries/sqlparser.data.php'; - require_once './libraries/mysql_charsets.lib.php'; - if (!isset($mysql_charsets)) { - $mysql_charsets = array(); - $mysql_charsets_count = 0; - $mysql_collations_flat = array(); - $mysql_collations_count = 0; - } - - if (!defined('DEBUG_TIMING')) { - // currently we don't need the $pos (token position in query) - // for other purposes than LIMIT clause verification, - // so many calls to this function do not include the 4th parameter - function PMA_SQP_arrayAdd(&$arr, $type, $data, &$arrsize, $pos = 0) - { - $arr[] = array('type' => $type, 'data' => $data, 'pos' => $pos); - $arrsize++; - } // end of the "PMA_SQP_arrayAdd()" function - } else { - function PMA_SQP_arrayAdd(&$arr, $type, $data, &$arrsize, $pos = 0) - { - global $timer; - - $t = $timer; - $arr[] = array('type' => $type, 'data' => $data, 'pos' => $pos, 'time' => $t); - $timer = microtime(); - $arrsize++; - } // end of the "PMA_SQP_arrayAdd()" function - } // end if... else... - - - /** - * Reset the error variable for the SQL parser - * - * @access public - */ - // Added, Robbat2 - 13 Janurary 2003, 2:59PM - function PMA_SQP_resetError() - { - global $SQP_errorString; - $SQP_errorString = ''; - unset($SQP_errorString); - } - - /** - * Get the contents of the error variable for the SQL parser - * - * @return string Error string from SQL parser - * - * @access public - */ - // Added, Robbat2 - 13 Janurary 2003, 2:59PM - function PMA_SQP_getErrorString() - { - global $SQP_errorString; - return isset($SQP_errorString) ? $SQP_errorString : ''; - } - - /** - * Check if the SQL parser hit an error - * - * @return boolean error state - * - * @access public - */ - // Added, Robbat2 - 13 Janurary 2003, 2:59PM - function PMA_SQP_isError() - { - global $SQP_errorString; - return isset($SQP_errorString) && !empty($SQP_errorString); - } - - /** - * Set an error message for the system - * - * @param string The error message - * @param string The failing SQL query - * - * @access private - * @scope SQL Parser internal - */ - // Revised, Robbat2 - 13 Janurary 2003, 2:59PM - function PMA_SQP_throwError($message, $sql) - { - - global $SQP_errorString; - $SQP_errorString = '

'.$GLOBALS['strSQLParserUserError'] . '

' . "\n" - . '
' . "\n"
-            . 'ERROR: ' . $message . "\n"
-            . 'SQL: ' . htmlspecialchars($sql) .  "\n"
-            . '
' . "\n"; - - } // end of the "PMA_SQP_throwError()" function - - - /** - * Do display the bug report - * - * @param string The error message - * @param string The failing SQL query - * - * @access public - */ - function PMA_SQP_bug($message, $sql) - { - global $SQP_errorString; - $debugstr = 'ERROR: ' . $message . "\n"; - $debugstr .= 'SVN: $Id: sqlparser.lib.php 11513 2008-08-28 16:17:53Z lem9 $' . "\n"; - $debugstr .= 'MySQL: '.PMA_MYSQL_STR_VERSION . "\n"; - $debugstr .= 'USR OS, AGENT, VER: ' . PMA_USR_OS . ' ' . PMA_USR_BROWSER_AGENT . ' ' . PMA_USR_BROWSER_VER . "\n"; - $debugstr .= 'PMA: ' . PMA_VERSION . "\n"; - $debugstr .= 'PHP VER,OS: ' . PMA_PHP_STR_VERSION . ' ' . PHP_OS . "\n"; - $debugstr .= 'LANG: ' . $GLOBALS['lang'] . "\n"; - $debugstr .= 'SQL: ' . htmlspecialchars($sql); - - $encodedstr = $debugstr; - if (@function_exists('gzcompress')) { - $encodedstr = gzcompress($debugstr, 9); - } - $encodedstr = preg_replace("/(\015\012)|(\015)|(\012)/", '
' . "\n", chunk_split(base64_encode($encodedstr))); - - $SQP_errorString .= $GLOBALS['strSQLParserBugMessage'] . '
' . "\n" - . '----' . $GLOBALS['strBeginCut'] . '----' . '
' . "\n" - . $encodedstr . "\n" - . '----' . $GLOBALS['strEndCut'] . '----' . '
' . "\n"; - - $SQP_errorString .= '----' . $GLOBALS['strBeginRaw'] . '----
' . "\n" - . '
' . "\n"
-             . $debugstr
-             . '
' . "\n" - . '----' . $GLOBALS['strEndRaw'] . '----
' . "\n"; - - } // end of the "PMA_SQP_bug()" function - - - /** - * Parses the SQL queries - * - * @param string The SQL query list - * - * @return mixed Most of times, nothing... - * - * @global array The current PMA configuration - * @global array MySQL column attributes - * @global array MySQL reserved words - * @global array MySQL column types - * @global array MySQL function names - * @global integer MySQL column attributes count - * @global integer MySQL reserved words count - * @global integer MySQL column types count - * @global integer MySQL function names count - * @global array List of available character sets - * @global array List of available collations - * @global integer Character sets count - * @global integer Collations count - * - * @access public - */ - function PMA_SQP_parse($sql) - { - global $cfg; - global $PMA_SQPdata_column_attrib, $PMA_SQPdata_reserved_word, $PMA_SQPdata_column_type, $PMA_SQPdata_function_name, - $PMA_SQPdata_column_attrib_cnt, $PMA_SQPdata_reserved_word_cnt, $PMA_SQPdata_column_type_cnt, $PMA_SQPdata_function_name_cnt; - global $mysql_charsets, $mysql_collations_flat, $mysql_charsets_count, $mysql_collations_count; - global $PMA_SQPdata_forbidden_word, $PMA_SQPdata_forbidden_word_cnt; - - // rabus: Convert all line feeds to Unix style - $sql = str_replace("\r\n", "\n", $sql); - $sql = str_replace("\r", "\n", $sql); - - $len = PMA_strlen($sql); - if ($len == 0) { - return array(); - } - - $sql_array = array(); - $sql_array['raw'] = $sql; - $count1 = 0; - $count2 = 0; - $punct_queryend = ';'; - $punct_qualifier = '.'; - $punct_listsep = ','; - $punct_level_plus = '('; - $punct_level_minus = ')'; - $punct_user = '@'; - $digit_floatdecimal = '.'; - $digit_hexset = 'x'; - $bracket_list = '()[]{}'; - $allpunct_list = '-,;:!?/.^~\*&%+<=>|'; - $allpunct_list_pair = array ( - 0 => '!=', - 1 => '&&', - 2 => ':=', - 3 => '<<', - 4 => '<=', - 5 => '<=>', - 6 => '<>', - 7 => '>=', - 8 => '>>', - 9 => '||' - ); - $allpunct_list_pair_size = 10; //count($allpunct_list_pair); - $quote_list = '\'"`'; - $arraysize = 0; - - $previous_was_space = false; - $this_was_space = false; - $previous_was_bracket = false; - $this_was_bracket = false; - $previous_was_punct = false; - $this_was_punct = false; - $previous_was_listsep = false; - $this_was_listsep = false; - $previous_was_quote = false; - $this_was_quote = false; - - while ($count2 < $len) { - $c = PMA_substr($sql, $count2, 1); - $count1 = $count2; - - $previous_was_space = $this_was_space; - $this_was_space = false; - $previous_was_bracket = $this_was_bracket; - $this_was_bracket = false; - $previous_was_punct = $this_was_punct; - $this_was_punct = false; - $previous_was_listsep = $this_was_listsep; - $this_was_listsep = false; - $previous_was_quote = $this_was_quote; - $this_was_quote = false; - - if (($c == "\n")) { - $this_was_space = true; - $count2++; - PMA_SQP_arrayAdd($sql_array, 'white_newline', '', $arraysize); - continue; - } - - // Checks for white space - if (PMA_STR_isSpace($c)) { - $this_was_space = true; - $count2++; - continue; - } - - // Checks for comment lines. - // MySQL style # - // C style /* */ - // ANSI style -- - if (($c == '#') - || (($count2 + 1 < $len) && ($c == '/') && (PMA_substr($sql, $count2 + 1, 1) == '*')) - || (($count2 + 2 == $len) && ($c == '-') && (PMA_substr($sql, $count2 + 1, 1) == '-')) - || (($count2 + 2 < $len) && ($c == '-') && (PMA_substr($sql, $count2 + 1, 1) == '-') && ((PMA_substr($sql, $count2 + 2, 1) <= ' ')))) { - $count2++; - $pos = 0; - $type = 'bad'; - switch ($c) { - case '#': - $type = 'mysql'; - case '-': - $type = 'ansi'; - $pos = $GLOBALS['PMA_strpos']($sql, "\n", $count2); - break; - case '/': - $type = 'c'; - $pos = $GLOBALS['PMA_strpos']($sql, '*/', $count2); - $pos += 2; - break; - default: - break; - } // end switch - $count2 = ($pos < $count2) ? $len : $pos; - $str = PMA_substr($sql, $count1, $count2 - $count1); - PMA_SQP_arrayAdd($sql_array, 'comment_' . $type, $str, $arraysize); - continue; - } // end if - - // Checks for something inside quotation marks - if (PMA_STR_strInStr($c, $quote_list)) { - $startquotepos = $count2; - $quotetype = $c; - $count2++; - $escaped = FALSE; - $escaped_escaped = FALSE; - $pos = $count2; - $oldpos = 0; - do { - $oldpos = $pos; - $pos = $GLOBALS['PMA_strpos'](' ' . $sql, $quotetype, $oldpos + 1) - 1; - // ($pos === FALSE) - if ($pos < 0) { - $debugstr = $GLOBALS['strSQPBugUnclosedQuote'] . ' @ ' . $startquotepos. "\n" - . 'STR: ' . htmlspecialchars($quotetype); - PMA_SQP_throwError($debugstr, $sql); - return $sql; - } - - // If the quote is the first character, it can't be - // escaped, so don't do the rest of the code - if ($pos == 0) { - break; - } - - // Checks for MySQL escaping using a \ - // And checks for ANSI escaping using the $quotetype character - if (($pos < $len) && PMA_STR_charIsEscaped($sql, $pos)) { - $pos ++; - continue; - } elseif (($pos + 1 < $len) && (PMA_substr($sql, $pos, 1) == $quotetype) && (PMA_substr($sql, $pos + 1, 1) == $quotetype)) { - $pos = $pos + 2; - continue; - } else { - break; - } - } while ($len > $pos); // end do - - $count2 = $pos; - $count2++; - $type = 'quote_'; - switch ($quotetype) { - case '\'': - $type .= 'single'; - $this_was_quote = true; - break; - case '"': - $type .= 'double'; - $this_was_quote = true; - break; - case '`': - $type .= 'backtick'; - $this_was_quote = true; - break; - default: - break; - } // end switch - $data = PMA_substr($sql, $count1, $count2 - $count1); - PMA_SQP_arrayAdd($sql_array, $type, $data, $arraysize); - continue; - } - - // Checks for brackets - if (PMA_STR_strInStr($c, $bracket_list)) { - // All bracket tokens are only one item long - $this_was_bracket = true; - $count2++; - $type_type = ''; - if (PMA_STR_strInStr($c, '([{')) { - $type_type = 'open'; - } else { - $type_type = 'close'; - } - - $type_style = ''; - if (PMA_STR_strInStr($c, '()')) { - $type_style = 'round'; - } elseif (PMA_STR_strInStr($c, '[]')) { - $type_style = 'square'; - } else { - $type_style = 'curly'; - } - - $type = 'punct_bracket_' . $type_type . '_' . $type_style; - PMA_SQP_arrayAdd($sql_array, $type, $c, $arraysize); - continue; - } - - /* DEBUG - echo '
1';
-            var_dump(PMA_STR_isSqlIdentifier($c, false));
-            var_dump($c == '@');
-            var_dump($c == '.');
-            var_dump(PMA_STR_isDigit(PMA_substr($sql, $count2 + 1, 1)));
-            var_dump($previous_was_space);
-            var_dump($previous_was_bracket);
-            var_dump($previous_was_listsep);
-            echo '
'; - */ - - // Checks for identifier (alpha or numeric) - if (PMA_STR_isSqlIdentifier($c, false) - || $c == '@' - || ($c == '.' - && PMA_STR_isDigit(PMA_substr($sql, $count2 + 1, 1)) - && ($previous_was_space || $previous_was_bracket || $previous_was_listsep))) { - - /* DEBUG - echo PMA_substr($sql, $count2); - echo '
'; - */ - - $count2++; - - /** - * @todo a @ can also be present in expressions like - * FROM 'user'@'%' or TO 'user'@'%' - * in this case, the @ is wrongly marked as alpha_variable - */ - $is_identifier = $previous_was_punct; - $is_sql_variable = $c == '@' && ! $previous_was_quote; - $is_user = $c == '@' && $previous_was_quote; - $is_digit = !$is_identifier && !$is_sql_variable && PMA_STR_isDigit($c); - $is_hex_digit = $is_digit && $c == '0' && $count2 < $len && PMA_substr($sql, $count2, 1) == 'x'; - $is_float_digit = $c == '.'; - $is_float_digit_exponent = FALSE; - - /* DEBUG - echo '
2';
-                var_dump($is_identifier);
-                var_dump($is_sql_variable);
-                var_dump($is_digit);
-                var_dump($is_float_digit);
-                echo '
'; - */ - - // Nijel: Fast skip is especially needed for huge BLOB data, requires PHP at least 4.3.0: - if (PMA_PHP_INT_VERSION >= 40300) { - if ($is_hex_digit) { - $count2++; - $pos = strspn($sql, '0123456789abcdefABCDEF', $count2); - if ($pos > $count2) { - $count2 = $pos; - } - unset($pos); - } elseif ($is_digit) { - $pos = strspn($sql, '0123456789', $count2); - if ($pos > $count2) { - $count2 = $pos; - } - unset($pos); - } - } - - while (($count2 < $len) && PMA_STR_isSqlIdentifier(PMA_substr($sql, $count2, 1), ($is_sql_variable || $is_digit))) { - $c2 = PMA_substr($sql, $count2, 1); - if ($is_sql_variable && ($c2 == '.')) { - $count2++; - continue; - } - if ($is_digit && (!$is_hex_digit) && ($c2 == '.')) { - $count2++; - if (!$is_float_digit) { - $is_float_digit = TRUE; - continue; - } else { - $debugstr = $GLOBALS['strSQPBugInvalidIdentifer'] . ' @ ' . ($count1+1) . "\n" - . 'STR: ' . htmlspecialchars(PMA_substr($sql, $count1, $count2 - $count1)); - PMA_SQP_throwError($debugstr, $sql); - return $sql; - } - } - if ($is_digit && (!$is_hex_digit) && (($c2 == 'e') || ($c2 == 'E'))) { - if (!$is_float_digit_exponent) { - $is_float_digit_exponent = TRUE; - $is_float_digit = TRUE; - $count2++; - continue; - } else { - $is_digit = FALSE; - $is_float_digit = FALSE; - } - } - if (($is_hex_digit && PMA_STR_isHexDigit($c2)) || ($is_digit && PMA_STR_isDigit($c2))) { - $count2++; - continue; - } else { - $is_digit = FALSE; - $is_hex_digit = FALSE; - } - - $count2++; - } // end while - - $l = $count2 - $count1; - $str = PMA_substr($sql, $count1, $l); - - $type = ''; - if ($is_digit || $is_float_digit || $is_hex_digit) { - $type = 'digit'; - if ($is_float_digit) { - $type .= '_float'; - } elseif ($is_hex_digit) { - $type .= '_hex'; - } else { - $type .= '_integer'; - } - } elseif ($is_user) { - $type = 'punct_user'; - } elseif ($is_sql_variable != FALSE) { - $type = 'alpha_variable'; - } else { - $type = 'alpha'; - } // end if... else.... - PMA_SQP_arrayAdd($sql_array, $type, $str, $arraysize, $count2); - - continue; - } - - // Checks for punct - if (PMA_STR_strInStr($c, $allpunct_list)) { - while (($count2 < $len) && PMA_STR_strInStr(PMA_substr($sql, $count2, 1), $allpunct_list)) { - $count2++; - } - $l = $count2 - $count1; - if ($l == 1) { - $punct_data = $c; - } else { - $punct_data = PMA_substr($sql, $count1, $l); - } - - // Special case, sometimes, althought two characters are - // adjectent directly, they ACTUALLY need to be seperate - /* DEBUG - echo '
';
-                var_dump($l);
-                var_dump($punct_data);
-                echo '
'; - */ - - if ($l == 1) { - $t_suffix = ''; - switch ($punct_data) { - case $punct_queryend: - $t_suffix = '_queryend'; - break; - case $punct_qualifier: - $t_suffix = '_qualifier'; - $this_was_punct = true; - break; - case $punct_listsep: - $this_was_listsep = true; - $t_suffix = '_listsep'; - break; - default: - break; - } - PMA_SQP_arrayAdd($sql_array, 'punct' . $t_suffix, $punct_data, $arraysize); - } elseif (PMA_STR_binarySearchInArr($punct_data, $allpunct_list_pair, $allpunct_list_pair_size)) { - // Ok, we have one of the valid combined punct expressions - PMA_SQP_arrayAdd($sql_array, 'punct', $punct_data, $arraysize); - } else { - // Bad luck, lets split it up more - $first = $punct_data[0]; - $first2 = $punct_data[0] . $punct_data[1]; - $last2 = $punct_data[$l - 2] . $punct_data[$l - 1]; - $last = $punct_data[$l - 1]; - if (($first == ',') || ($first == ';') || ($first == '.') || ($first == '*')) { - $count2 = $count1 + 1; - $punct_data = $first; - } elseif (($last2 == '/*') || (($last2 == '--') && ($count2 == $len || PMA_substr($sql, $count2, 1) <= ' '))) { - $count2 -= 2; - $punct_data = PMA_substr($sql, $count1, $count2 - $count1); - } elseif (($last == '-') || ($last == '+') || ($last == '!')) { - $count2--; - $punct_data = PMA_substr($sql, $count1, $count2 - $count1); - /** - * @todo for negation operator, split in 2 tokens ? - * "select x&~1 from t" - * becomes "select x & ~ 1 from t" ? - */ - - } elseif ($last != '~') { - $debugstr = $GLOBALS['strSQPBugUnknownPunctuation'] . ' @ ' . ($count1+1) . "\n" - . 'STR: ' . htmlspecialchars($punct_data); - PMA_SQP_throwError($debugstr, $sql); - return $sql; - } - PMA_SQP_arrayAdd($sql_array, 'punct', $punct_data, $arraysize); - continue; - } // end if... elseif... else - continue; - } - - // DEBUG - $count2++; - - $debugstr = 'C1 C2 LEN: ' . $count1 . ' ' . $count2 . ' ' . $len . "\n" - . 'STR: ' . PMA_substr($sql, $count1, $count2 - $count1) . "\n"; - PMA_SQP_bug($debugstr, $sql); - return $sql; - - } // end while ($count2 < $len) - - /* - echo '
';
-        print_r($sql_array);
-        echo '
'; - */ - - if ($arraysize > 0) { - $t_next = $sql_array[0]['type']; - $t_prev = ''; - $t_bef_prev = ''; - $t_cur = ''; - $d_next = $sql_array[0]['data']; - $d_prev = ''; - $d_bef_prev = ''; - $d_cur = ''; - $d_next_upper = $t_next == 'alpha' ? strtoupper($d_next) : $d_next; - $d_prev_upper = ''; - $d_bef_prev_upper = ''; - $d_cur_upper = ''; - } - - for ($i = 0; $i < $arraysize; $i++) { - $t_bef_prev = $t_prev; - $t_prev = $t_cur; - $t_cur = $t_next; - $d_bef_prev = $d_prev; - $d_prev = $d_cur; - $d_cur = $d_next; - $d_bef_prev_upper = $d_prev_upper; - $d_prev_upper = $d_cur_upper; - $d_cur_upper = $d_next_upper; - if (($i + 1) < $arraysize) { - $t_next = $sql_array[$i + 1]['type']; - $d_next = $sql_array[$i + 1]['data']; - $d_next_upper = $t_next == 'alpha' ? strtoupper($d_next) : $d_next; - } else { - $t_next = ''; - $d_next = ''; - $d_next_upper = ''; - } - - //DEBUG echo "[prev: ".$d_prev." ".$t_prev."][cur: ".$d_cur." ".$t_cur."][next: ".$d_next." ".$t_next."]
"; - - if ($t_cur == 'alpha') { - $t_suffix = '_identifier'; - if (($t_next == 'punct_qualifier') || ($t_prev == 'punct_qualifier')) { - $t_suffix = '_identifier'; - } elseif (($t_next == 'punct_bracket_open_round') - && PMA_STR_binarySearchInArr($d_cur_upper, $PMA_SQPdata_function_name, $PMA_SQPdata_function_name_cnt)) { - /** - * @todo 2005-10-16: in the case of a CREATE TABLE containing - * a TIMESTAMP, since TIMESTAMP() is also a function, it's - * found here and the token is wrongly marked as alpha_functionName. - * But we compensate for this when analysing for timestamp_not_null - * later in this script. - * - * Same applies to CHAR vs. CHAR() function. - */ - $t_suffix = '_functionName'; - /* There are functions which might be as well column types */ - if (PMA_STR_binarySearchInArr($d_cur_upper, $PMA_SQPdata_column_type, $PMA_SQPdata_column_type_cnt)) { - } - } elseif (PMA_STR_binarySearchInArr($d_cur_upper, $PMA_SQPdata_column_type, $PMA_SQPdata_column_type_cnt)) { - $t_suffix = '_columnType'; - - /** - * Temporary fix for BUG #621357 - * - * @todo FIX PROPERLY NEEDS OVERHAUL OF SQL TOKENIZER - */ - if ($d_cur_upper == 'SET' && $t_next != 'punct_bracket_open_round') { - $t_suffix = '_reservedWord'; - } - //END OF TEMPORARY FIX - - // CHARACTER is a synonym for CHAR, but can also be meant as - // CHARACTER SET. In this case, we have a reserved word. - if ($d_cur_upper == 'CHARACTER' && $d_next_upper == 'SET') { - $t_suffix = '_reservedWord'; - } - - // experimental - // current is a column type, so previous must not be - // a reserved word but an identifier - // CREATE TABLE SG_Persons (first varchar(64)) - - //if ($sql_array[$i-1]['type'] =='alpha_reservedWord') { - // $sql_array[$i-1]['type'] = 'alpha_identifier'; - //} - - } elseif (PMA_STR_binarySearchInArr($d_cur_upper, $PMA_SQPdata_reserved_word, $PMA_SQPdata_reserved_word_cnt)) { - $t_suffix = '_reservedWord'; - } elseif (PMA_STR_binarySearchInArr($d_cur_upper, $PMA_SQPdata_column_attrib, $PMA_SQPdata_column_attrib_cnt)) { - $t_suffix = '_columnAttrib'; - // INNODB is a MySQL table type, but in "SHOW INNODB STATUS", - // it should be regarded as a reserved word. - if ($d_cur_upper == 'INNODB' && $d_prev_upper == 'SHOW' && $d_next_upper == 'STATUS') { - $t_suffix = '_reservedWord'; - } - - if ($d_cur_upper == 'DEFAULT' && $d_next_upper == 'CHARACTER') { - $t_suffix = '_reservedWord'; - } - // Binary as character set - if ($d_cur_upper == 'BINARY' && ( - ($d_bef_prev_upper == 'CHARACTER' && $d_prev_upper == 'SET') - || ($d_bef_prev_upper == 'SET' && $d_prev_upper == '=') - || ($d_bef_prev_upper == 'CHARSET' && $d_prev_upper == '=') - || $d_prev_upper == 'CHARSET' - ) && PMA_STR_binarySearchInArr($d_cur, $mysql_charsets, count($mysql_charsets))) { - $t_suffix = '_charset'; - } - } elseif (PMA_STR_binarySearchInArr($d_cur, $mysql_charsets, $mysql_charsets_count) - || PMA_STR_binarySearchInArr($d_cur, $mysql_collations_flat, $mysql_collations_count) - || ($d_cur{0} == '_' && PMA_STR_binarySearchInArr(substr($d_cur, 1), $mysql_charsets, $mysql_charsets_count))) { - $t_suffix = '_charset'; - } else { - // Do nothing - } - // check if present in the list of forbidden words - if ($t_suffix == '_reservedWord' && PMA_STR_binarySearchInArr($d_cur_upper, $PMA_SQPdata_forbidden_word, $PMA_SQPdata_forbidden_word_cnt)) { - $sql_array[$i]['forbidden'] = TRUE; - } else { - $sql_array[$i]['forbidden'] = FALSE; - } - $sql_array[$i]['type'] .= $t_suffix; - } - } // end for - - // Stores the size of the array inside the array, as count() is a slow - // operation. - $sql_array['len'] = $arraysize; - - // DEBUG echo 'After parsing
'; print_r($sql_array); echo '
'; - // Sends the data back - return $sql_array; - } // end of the "PMA_SQP_parse()" function - - /** - * Checks for token types being what we want... - * - * @param string String of type that we have - * @param string String of type that we want - * - * @return boolean result of check - * - * @access private - */ - function PMA_SQP_typeCheck($toCheck, $whatWeWant) - { - $typeSeperator = '_'; - if (strcmp($whatWeWant, $toCheck) == 0) { - return TRUE; - } else { - if (strpos($whatWeWant, $typeSeperator) === FALSE) { - return strncmp($whatWeWant, $toCheck, strpos($toCheck, $typeSeperator)) == 0; - } else { - return FALSE; - } - } - } - - - /** - * Analyzes SQL queries - * - * @param array The SQL queries - * - * @return array The analyzed SQL queries - * - * @access public - */ - function PMA_SQP_analyze($arr) - { - if ($arr == array()) { - return array(); - } - $result = array(); - $size = $arr['len']; - $subresult = array( - 'querytype' => '', - 'select_expr_clause'=> '', // the whole stuff between SELECT and FROM , except DISTINCT - 'position_of_first_select' => '', // the array index - 'from_clause'=> '', - 'group_by_clause'=> '', - 'order_by_clause'=> '', - 'having_clause' => '', - 'limit_clause' => '', - 'where_clause' => '', - 'where_clause_identifiers' => array(), - 'unsorted_query' => '', - 'queryflags' => array(), - 'select_expr' => array(), - 'table_ref' => array(), - 'foreign_keys' => array(), - 'create_table_fields' => array() - ); - $subresult_empty = $subresult; - $seek_queryend = FALSE; - $seen_end_of_table_ref = FALSE; - $number_of_brackets_in_extract = 0; - $number_of_brackets_in_group_concat = 0; - - $number_of_brackets = 0; - $in_subquery = false; - $seen_subquery = false; - $seen_from = false; - - // for SELECT EXTRACT(YEAR_MONTH FROM CURDATE()) - // we must not use CURDATE as a table_ref - // so we track wether we are in the EXTRACT() - $in_extract = FALSE; - - // for GROUP_CONCAT(...) - $in_group_concat = FALSE; - -/* Description of analyzer results by lem9 - * - * db, table, column, alias - * ------------------------ - * - * Inside the $subresult array, we create ['select_expr'] and ['table_ref'] arrays. - * - * The SELECT syntax (simplified) is - * - * SELECT - * select_expression,... - * [FROM [table_references] - * - * - * ['select_expr'] is filled with each expression, the key represents the - * expression position in the list (0-based) (so we don't lose track of - * multiple occurences of the same column). - * - * ['table_ref'] is filled with each table ref, same thing for the key. - * - * I create all sub-values empty, even if they are - * not present (for example no select_expression alias). - * - * There is a debug section at the end of loop #1, if you want to - * see the exact contents of select_expr and table_ref - * - * queryflags - * ---------- - * - * In $subresult, array 'queryflags' is filled, according to what we - * find in the query. - * - * Currently, those are generated: - * - * ['queryflags']['need_confirm'] = 1; if the query needs confirmation - * ['queryflags']['select_from'] = 1; if this is a real SELECT...FROM - * ['queryflags']['distinct'] = 1; for a DISTINCT - * ['queryflags']['union'] = 1; for a UNION - * ['queryflags']['join'] = 1; for a JOIN - * ['queryflags']['offset'] = 1; for the presence of OFFSET - * ['queryflags']['procedure'] = 1; for the presence of PROCEDURE - * - * query clauses - * ------------- - * - * The select is splitted in those clauses: - * ['select_expr_clause'] - * ['from_clause'] - * ['group_by_clause'] - * ['order_by_clause'] - * ['having_clause'] - * ['where_clause'] - * ['limit_clause'] - * - * The identifiers of the WHERE clause are put into the array - * ['where_clause_identifier'] - * - * For a SELECT, the whole query without the ORDER BY clause is put into - * ['unsorted_query'] - * - * foreign keys - * ------------ - * The CREATE TABLE may contain FOREIGN KEY clauses, so they get - * analyzed and ['foreign_keys'] is an array filled with - * the constraint name, the index list, - * the REFERENCES table name and REFERENCES index list, - * and ON UPDATE | ON DELETE clauses - * - * position_of_first_select - * ------------------------ - * - * The array index of the first SELECT we find. Will be used to - * insert a SQL_CALC_FOUND_ROWS. - * - * create_table_fields - * ------------------- - * - * For now, mostly used to detect the DEFAULT CURRENT_TIMESTAMP and - * ON UPDATE CURRENT_TIMESTAMP clauses of the CREATE TABLE query. - * An array, each element is the identifier name. - * Note that for now, the timestamp_not_null element is created - * even for non-TIMESTAMP fields. - * - * Sub-elements: ['type'] which contains the column type - * optional (currently they are never false but can be absent): - * ['default_current_timestamp'] boolean - * ['on_update_current_timestamp'] boolean - * ['timestamp_not_null'] boolean - * - * section_before_limit, section_after_limit - * ----------------------------------------- - * - * Marks the point of the query where we can insert a LIMIT clause; - * so the section_before_limit will contain the left part before - * a possible LIMIT clause - * - * - * End of description of analyzer results - */ - - // must be sorted - // TODO: current logic checks for only one word, so I put only the - // first word of the reserved expressions that end a table ref; - // maybe this is not ok (the first word might mean something else) -// $words_ending_table_ref = array( -// 'FOR UPDATE', -// 'GROUP BY', -// 'HAVING', -// 'LIMIT', -// 'LOCK IN SHARE MODE', -// 'ORDER BY', -// 'PROCEDURE', -// 'UNION', -// 'WHERE' -// ); - $words_ending_table_ref = array( - 'FOR', - 'GROUP', - 'HAVING', - 'LIMIT', - 'LOCK', - 'ORDER', - 'PROCEDURE', - 'UNION', - 'WHERE' - ); - $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' - /* - // Support for these additional query types will come later on. - 'DELETE', - 'INSERT', - 'REPLACE', - 'TRUNCATE', - 'UPDATE' - 'EXPLAIN', - 'DESCRIBE', - 'SHOW', - 'CREATE', - 'SET', - 'ALTER' - */ - ); - $supported_query_types_cnt = count($supported_query_types); - - // loop #1 for each token: select_expr, table_ref for SELECT - - for ($i = 0; $i < $size; $i++) { -//DEBUG echo "Loop1 " . $arr[$i]['data'] . " (" . $arr[$i]['type'] . ")
"; - - // High speed seek for locating the end of the current query - if ($seek_queryend == TRUE) { - if ($arr[$i]['type'] == 'punct_queryend') { - $seek_queryend = FALSE; - } else { - continue; - } // end if (type == punct_queryend) - } // end if ($seek_queryend) - - /** - * Note: do not split if this is a punct_queryend for the first and only query - * @todo when we find a UNION, should we split in another subresult? - */ - if ($arr[$i]['type'] == 'punct_queryend' && ($i + 1 != $size)) { - $result[] = $subresult; - $subresult = $subresult_empty; - continue; - } // end if (type == punct_queryend) - -// ============================================================== - if ($arr[$i]['type'] == 'punct_bracket_open_round') { - $number_of_brackets++; - 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') { - $number_of_brackets--; - if ($number_of_brackets == 0) { - $in_subquery = false; - } - if ($in_extract) { - $number_of_brackets_in_extract--; - if ($number_of_brackets_in_extract == 0) { - $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 ($in_subquery) { - /** - * skip the subquery to avoid setting - * select_expr or table_ref with the contents - * of this subquery; this is to avoid a bug when - * trying to edit the results of - * select * from child where not exists (select id from - * parent where child.parent_id = parent.id); - */ - continue; - } -// ============================================================== - if ($arr[$i]['type'] == 'alpha_functionName') { - $upper_data = strtoupper($arr[$i]['data']); - if ($upper_data =='EXTRACT') { - $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; - } - } - -// ============================================================== - if ($arr[$i]['type'] == 'alpha_reservedWord' -// && $arr[$i]['forbidden'] == FALSE) { - ) { - // We don't know what type of query yet, so run this - if ($subresult['querytype'] == '') { - $subresult['querytype'] = strtoupper($arr[$i]['data']); - } // end if (querytype was empty) - - // Check if we support this type of query - if (!PMA_STR_binarySearchInArr($subresult['querytype'], $supported_query_types, $supported_query_types_cnt)) { - // Skip ahead to the next one if we don't - $seek_queryend = TRUE; - continue; - } // end if (query not supported) - - // upper once - $upper_data = strtoupper($arr[$i]['data']); - /** - * @todo reset for each query? - */ - - if ($upper_data == 'SELECT') { - if ($number_of_brackets > 0) { - $in_subquery = true; - $seen_subquery = true; - // this is a subquery so do not analyze inside it - continue; - } - $seen_from = FALSE; - $previous_was_identifier = FALSE; - $current_select_expr = -1; - $seen_end_of_table_ref = FALSE; - } // end if (data == SELECT) - - if ($upper_data =='FROM' && !$in_extract) { - $current_table_ref = -1; - $seen_from = TRUE; - $previous_was_identifier = FALSE; - $save_table_ref = TRUE; - } // end if (data == FROM) - - // here, do not 'continue' the loop, as we have more work for - // reserved words below - } // end if (type == alpha_reservedWord) - -// ============================== - if ($arr[$i]['type'] == 'quote_backtick' - || $arr[$i]['type'] == 'quote_double' - || $arr[$i]['type'] == 'quote_single' - || $arr[$i]['type'] == 'alpha_identifier' - || ($arr[$i]['type'] == 'alpha_reservedWord' - && $arr[$i]['forbidden'] == FALSE)) { - - switch ($arr[$i]['type']) { - case 'alpha_identifier': - case 'alpha_reservedWord': - /** - * this is not a real reservedWord, because it's not - * present in the list of forbidden words, for example - * "storage" which can be used as an identifier - * - * @todo avoid the pretty printing in color in this case - */ - $identifier = $arr[$i]['data']; - break; - - case 'quote_backtick': - case 'quote_double': - case 'quote_single': - $identifier = PMA_unQuote($arr[$i]['data']); - break; - } // end switch - - if ($subresult['querytype'] == 'SELECT' - && ! $in_group_concat - && ! ($seen_subquery && $arr[$i - 1]['type'] == 'punct_bracket_close_round')) { - if (!$seen_from) { - if ($previous_was_identifier && isset($chain)) { - // found alias for this select_expr, save it - // but only if we got something in $chain - // (for example, SELECT COUNT(*) AS cnt - // puts nothing in $chain, so we avoid - // setting the alias) - $alias_for_select_expr = $identifier; - } else { - $chain[] = $identifier; - $previous_was_identifier = TRUE; - - } // end if !$previous_was_identifier - } else { - // ($seen_from) - if ($save_table_ref && !$seen_end_of_table_ref) { - if ($previous_was_identifier) { - // found alias for table ref - // save it for later - $alias_for_table_ref = $identifier; - } else { - $chain[] = $identifier; - $previous_was_identifier = TRUE; - - } // end if ($previous_was_identifier) - } // end if ($save_table_ref &&!$seen_end_of_table_ref) - } // end if (!$seen_from) - } // end if (querytype SELECT) - } // end if (quote_backtick or double quote or alpha_identifier) - -// =================================== - if ($arr[$i]['type'] == 'punct_qualifier') { - // to be able to detect an identifier following another - $previous_was_identifier = FALSE; - continue; - } // end if (punct_qualifier) - - /** - * @todo check if 3 identifiers following one another -> error - */ - - // s a v e a s e l e c t e x p r - // finding a list separator or FROM - // means that we must save the current chain of identifiers - // into a select expression - - // for now, we only save a select expression if it contains - // at least one identifier, as we are interested in checking - // the columns and table names, so in "select * from persons", - // the "*" is not saved - - if (isset($chain) && !$seen_end_of_table_ref - && ((!$seen_from && $arr[$i]['type'] == 'punct_listsep') - || ($arr[$i]['type'] == 'alpha_reservedWord' && $upper_data == 'FROM'))) { - $size_chain = count($chain); - $current_select_expr++; - $subresult['select_expr'][$current_select_expr] = array( - 'expr' => '', - 'alias' => '', - 'db' => '', - 'table_name' => '', - 'table_true_name' => '', - 'column' => '' - ); - - if (isset($alias_for_select_expr) && strlen($alias_for_select_expr)) { - // we had found an alias for this select expression - $subresult['select_expr'][$current_select_expr]['alias'] = $alias_for_select_expr; - unset($alias_for_select_expr); - } - // there is at least a column - $subresult['select_expr'][$current_select_expr]['column'] = $chain[$size_chain - 1]; - $subresult['select_expr'][$current_select_expr]['expr'] = $chain[$size_chain - 1]; - - // maybe a table - if ($size_chain > 1) { - $subresult['select_expr'][$current_select_expr]['table_name'] = $chain[$size_chain - 2]; - // we assume for now that this is also the true name - $subresult['select_expr'][$current_select_expr]['table_true_name'] = $chain[$size_chain - 2]; - $subresult['select_expr'][$current_select_expr]['expr'] - = $subresult['select_expr'][$current_select_expr]['table_name'] - . '.' . $subresult['select_expr'][$current_select_expr]['expr']; - } // end if ($size_chain > 1) - - // maybe a db - if ($size_chain > 2) { - $subresult['select_expr'][$current_select_expr]['db'] = $chain[$size_chain - 3]; - $subresult['select_expr'][$current_select_expr]['expr'] - = $subresult['select_expr'][$current_select_expr]['db'] - . '.' . $subresult['select_expr'][$current_select_expr]['expr']; - } // end if ($size_chain > 2) - unset($chain); - - /** - * @todo explain this: - */ - if (($arr[$i]['type'] == 'alpha_reservedWord') - && ($upper_data != 'FROM')) { - $previous_was_identifier = TRUE; - } - - } // end if (save a select expr) - - - //====================================== - // s a v e a t a b l e r e f - //====================================== - - // maybe we just saw the end of table refs - // but the last table ref has to be saved - // or we are at the last token - // or we just got a reserved word - /** - * @todo there could be another query after this one - */ - - if (isset($chain) && $seen_from && $save_table_ref - && ($arr[$i]['type'] == 'punct_listsep' - || ($arr[$i]['type'] == 'alpha_reservedWord' && $upper_data!="AS") - || $seen_end_of_table_ref - || $i==$size-1)) { - - $size_chain = count($chain); - $current_table_ref++; - $subresult['table_ref'][$current_table_ref] = array( - 'expr' => '', - 'db' => '', - 'table_name' => '', - 'table_alias' => '', - 'table_true_name' => '' - ); - if (isset($alias_for_table_ref) && strlen($alias_for_table_ref)) { - $subresult['table_ref'][$current_table_ref]['table_alias'] = $alias_for_table_ref; - unset($alias_for_table_ref); - } - $subresult['table_ref'][$current_table_ref]['table_name'] = $chain[$size_chain - 1]; - // we assume for now that this is also the true name - $subresult['table_ref'][$current_table_ref]['table_true_name'] = $chain[$size_chain - 1]; - $subresult['table_ref'][$current_table_ref]['expr'] - = $subresult['table_ref'][$current_table_ref]['table_name']; - // maybe a db - if ($size_chain > 1) { - $subresult['table_ref'][$current_table_ref]['db'] = $chain[$size_chain - 2]; - $subresult['table_ref'][$current_table_ref]['expr'] - = $subresult['table_ref'][$current_table_ref]['db'] - . '.' . $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; - - } // end if (save a table ref) - - - // when we have found all table refs, - // for each table_ref alias, put the true name of the table - // in the corresponding select expressions - - if (isset($current_table_ref) && ($seen_end_of_table_ref || $i == $size-1) && $subresult != $subresult_empty) { - for ($tr=0; $tr <= $current_table_ref; $tr++) { - $alias = $subresult['table_ref'][$tr]['table_alias']; - $truename = $subresult['table_ref'][$tr]['table_true_name']; - for ($se=0; $se <= $current_select_expr; $se++) { - if (isset($alias) && strlen($alias) && $subresult['select_expr'][$se]['table_true_name'] - == $alias) { - $subresult['select_expr'][$se]['table_true_name'] - = $truename; - } // end if (found the alias) - } // end for (select expressions) - - } // end for (table refs) - } // end if (set the true names) - - - // e n d i n g l o o p #1 - // set the $previous_was_identifier to FALSE if the current - // token is not an identifier - if (($arr[$i]['type'] != 'alpha_identifier') - && ($arr[$i]['type'] != 'quote_double') - && ($arr[$i]['type'] != 'quote_single') - && ($arr[$i]['type'] != 'quote_backtick')) { - $previous_was_identifier = FALSE; - } // end if - - // however, if we are on AS, we must keep the $previous_was_identifier - if (($arr[$i]['type'] == 'alpha_reservedWord') - && ($upper_data == 'AS')) { - $previous_was_identifier = TRUE; - } - - if (($arr[$i]['type'] == 'alpha_reservedWord') - && ($upper_data =='ON' || $upper_data =='USING')) { - $save_table_ref = FALSE; - } // end if (data == ON) - - if (($arr[$i]['type'] == 'alpha_reservedWord') - && ($upper_data =='JOIN' || $upper_data =='FROM')) { - $save_table_ref = TRUE; - } // end if (data == JOIN) - - /** - * no need to check the end of table ref if we already did - * - * @todo maybe add "&& $seen_from" - */ - if (!$seen_end_of_table_ref) { - // 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 - if (isset($save_table_ref) && $save_table_ref != FALSE) { - $save_table_ref = TRUE; - } //end if - - } // end if (check for end of table ref) - } //end if (!$seen_end_of_table_ref) - - if ($seen_end_of_table_ref) { - $save_table_ref = FALSE; - } // end if - - } // end for $i (loop #1) - - //DEBUG - /* - 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"; - } - } - - 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"; - } - } - */ - // ------------------------------------------------------- - - - // loop #2: - queryflags - // - querytype (for queries != 'SELECT') - // - section_before_limit, section_after_limit - // - // 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; - } - - $section_before_limit = ''; - $section_after_limit = ''; // truly the section after the limit clause - $seen_reserved_word = FALSE; - $seen_group = FALSE; - $seen_order = FALSE; - $seen_order_by = FALSE; - $in_group_by = FALSE; // true when we are inside the GROUP BY clause - $in_order_by = FALSE; // true when we are inside the ORDER BY clause - $in_having = FALSE; // true when we are inside the HAVING clause - $in_select_expr = FALSE; // true when we are inside the select expr clause - $in_where = FALSE; // true when we are inside the WHERE clause - $seen_limit = FALSE; // true if we have seen a LIMIT clause - $in_limit = FALSE; // true when we are inside the LIMIT clause - $after_limit = FALSE; // true when we are after the LIMIT clause - $in_from = FALSE; // true when we are in the FROM clause - $in_group_concat = FALSE; - $first_reserved_word = ''; - $current_identifier = ''; - $unsorted_query = $arr['raw']; // in case there is no ORDER BY - - for ($i = 0; $i < $size; $i++) { -//DEBUG echo "Loop2 " . $arr[$i]['data'] . " (" . $arr[$i]['type'] . ")
"; - - // need_confirm - // - // check for reserved words that will have to generate - // a confirmation request later in sql.php - // the cases are: - // DROP TABLE - // DROP DATABASE - // ALTER TABLE... DROP - // DELETE FROM... - // - // this code is not used for confirmations coming from functions.js - - if ($arr[$i]['type'] == 'alpha_reservedWord') { - $upper_data = strtoupper($arr[$i]['data']); - if (!$seen_reserved_word) { - $first_reserved_word = $upper_data; - $subresult['querytype'] = $upper_data; - $seen_reserved_word = TRUE; - - // if the first reserved word is DROP or DELETE, - // we know this is a query that needs to be confirmed - if ($first_reserved_word=='DROP' - || $first_reserved_word == 'DELETE' - || $first_reserved_word == 'TRUNCATE') { - $subresult['queryflags']['need_confirm'] = 1; - } - - if ($first_reserved_word=='SELECT'){ - $position_of_first_select = $i; - } - - } else { - if ($upper_data == 'DROP' && $first_reserved_word == 'ALTER') { - $subresult['queryflags']['need_confirm'] = 1; - } - } - - if ($upper_data == 'LIMIT') { - $section_before_limit = substr($arr['raw'], 0, $arr[$i]['pos'] - 5); - $in_limit = TRUE; - $seen_limit = TRUE; - $limit_clause = ''; - $in_order_by = FALSE; // @todo maybe others to set FALSE - } - - if ($upper_data == 'PROCEDURE') { - $subresult['queryflags']['procedure'] = 1; - $in_limit = FALSE; - $after_limit = TRUE; - } - /** - * @todo set also to FALSE if we find FOR UPDATE or LOCK IN SHARE MODE - */ - if ($upper_data == 'SELECT') { - $in_select_expr = TRUE; - $select_expr_clause = ''; - } - if ($upper_data == 'DISTINCT' && !$in_group_concat) { - $subresult['queryflags']['distinct'] = 1; - } - - if ($upper_data == 'UNION') { - $subresult['queryflags']['union'] = 1; - } - - if ($upper_data == 'JOIN') { - $subresult['queryflags']['join'] = 1; - } - - if ($upper_data == 'OFFSET') { - $subresult['queryflags']['offset'] = 1; - } - - // 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' && !$in_group_concat) { - $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 = ''; - $where_clause_identifiers = array(); - $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) { - $seen_order_by = TRUE; - // here we assume that the ORDER BY keywords took - // exactly 8 characters - $unsorted_query = substr($arr['raw'], 0, $arr[$i]['pos'] - 8); - $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 space 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; - } - } - } - - // do not add a space after an identifier if followed by a dot - if ($arr[$i]['type'] == 'alpha_identifier' && $i < $size - 1 && $arr[$i + 1]['data'] == '.') { - $sep = ''; - } - - // do not add a space after a dot if followed by an identifier - if ($arr[$i]['data'] == '.' && $i < $size - 1 && $arr[$i + 1]['type'] == 'alpha_identifier') { - $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') { - // add a space only before ASC or DESC - // not around the dot between dbname and tablename - if ($arr[$i]['type'] == 'alpha_reservedWord') { - $order_by_clause .= $sep; - } - $order_by_clause .= $arr[$i]['data']; - } - if ($in_having && $upper_data != 'HAVING') { - $having_clause .= $arr[$i]['data'] . $sep; - } - if ($in_where && $upper_data != 'WHERE') { - $where_clause .= $arr[$i]['data'] . $sep; - - if (($arr[$i]['type'] == 'quote_backtick') - || ($arr[$i]['type'] == 'alpha_identifier')) { - $where_clause_identifiers[] = $arr[$i]['data']; - } - } - - // to grab the rest of the query after the ORDER BY clause - if (isset($subresult['queryflags']['select_from']) - && $subresult['queryflags']['select_from'] == 1 - && ! $in_order_by - && $seen_order_by - && $upper_data != 'BY') { - $unsorted_query .= $arr[$i]['data']; - if ($arr[$i]['type'] != 'punct_bracket_open_round' - && $arr[$i]['type'] != 'punct_bracket_close_round' - && $arr[$i]['type'] != 'punct') { - $unsorted_query .= $sep; - } - } - - if ($in_limit) { - if ($upper_data == 'OFFSET') { - $limit_clause .= $sep; - } - $limit_clause .= $arr[$i]['data']; - if ($upper_data == 'LIMIT' || $upper_data == 'OFFSET') { - $limit_clause .= $sep; - } - } - if ($after_limit && $seen_limit) { - $section_after_limit .= $arr[$i]['data'] . $sep; - } - - // clear $upper_data for next iteration - $upper_data=''; - - } // end for $i (loop #2) - if (empty($section_before_limit)) { - $section_before_limit = $arr['raw']; - } - - // ----------------------------------------------------- - // loop #3: foreign keys and MySQL 4.1.2+ TIMESTAMP options - // (for now, check only the first query) - // (for now, identifiers are assumed to be backquoted) - - // If we find that we are dealing with a CREATE TABLE query, - // we look for the next punct_bracket_open_round, which - // introduces the fields list. Then, when we find a - // quote_backtick, it must be a field, so we put it into - // the create_table_fields array. Even if this field is - // not a timestamp, it will be useful when logic has been - // added for complete field attributes analysis. - - $seen_foreign = FALSE; - $seen_references = FALSE; - $seen_constraint = FALSE; - $foreign_key_number = -1; - $seen_create_table = FALSE; - $seen_create = FALSE; - $in_create_table_fields = FALSE; - $brackets_level = 0; - $in_timestamp_options = FALSE; - $seen_default = FALSE; - - for ($i = 0; $i < $size; $i++) { - // DEBUG echo "Loop 3 " . $arr[$i]['data'] . " " . $arr[$i]['type'] . "
"; - - if ($arr[$i]['type'] == 'alpha_reservedWord') { - $upper_data = strtoupper($arr[$i]['data']); - - if ($upper_data == 'NOT' && $in_timestamp_options) { - $create_table_fields[$current_identifier]['timestamp_not_null'] = TRUE; - - } - - if ($upper_data == 'CREATE') { - $seen_create = TRUE; - } - - if ($upper_data == 'TABLE' && $seen_create) { - $seen_create_table = TRUE; - $create_table_fields = array(); - } - - if ($upper_data == 'CURRENT_TIMESTAMP') { - if ($in_timestamp_options) { - if ($seen_default) { - $create_table_fields[$current_identifier]['default_current_timestamp'] = TRUE; - } - } - } - - if ($upper_data == 'CONSTRAINT') { - $foreign_key_number++; - $seen_foreign = FALSE; - $seen_references = FALSE; - $seen_constraint = TRUE; - } - if ($upper_data == 'FOREIGN') { - $seen_foreign = TRUE; - $seen_references = FALSE; - $seen_constraint = FALSE; - } - if ($upper_data == 'REFERENCES') { - $seen_foreign = FALSE; - $seen_references = TRUE; - $seen_constraint = FALSE; - } - - - // Cases covered: - - // [ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}] - // [ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}] - - // but we set ['on_delete'] or ['on_cascade'] to - // CASCADE | SET_NULL | NO_ACTION | RESTRICT - - // ON UPDATE CURRENT_TIMESTAMP - - if ($upper_data == 'ON') { - if (isset($arr[$i+1]) && $arr[$i+1]['type'] == 'alpha_reservedWord') { - $second_upper_data = strtoupper($arr[$i+1]['data']); - if ($second_upper_data == 'DELETE') { - $clause = 'on_delete'; - } - if ($second_upper_data == 'UPDATE') { - $clause = 'on_update'; - } - if (isset($clause) - && ($arr[$i+2]['type'] == 'alpha_reservedWord' - - // ugly workaround because currently, NO is not - // in the list of reserved words in sqlparser.data - // (we got a bug report about not being able to use - // 'no' as an identifier) - || ($arr[$i+2]['type'] == 'alpha_identifier' - && strtoupper($arr[$i+2]['data'])=='NO')) - ) { - $third_upper_data = strtoupper($arr[$i+2]['data']); - if ($third_upper_data == 'CASCADE' - || $third_upper_data == 'RESTRICT') { - $value = $third_upper_data; - } elseif ($third_upper_data == 'SET' - || $third_upper_data == 'NO') { - if ($arr[$i+3]['type'] == 'alpha_reservedWord') { - $value = $third_upper_data . '_' . strtoupper($arr[$i+3]['data']); - } - } elseif ($third_upper_data == 'CURRENT_TIMESTAMP') { - if ($clause == 'on_update' - && $in_timestamp_options) { - $create_table_fields[$current_identifier]['on_update_current_timestamp'] = TRUE; - $seen_default = FALSE; - } - - } else { - $value = ''; - } - if (!empty($value)) { - $foreign[$foreign_key_number][$clause] = $value; - } - unset($clause); - } // endif (isset($clause)) - } - } - - } // end of reserved words analysis - - - if ($arr[$i]['type'] == 'punct_bracket_open_round') { - $brackets_level++; - if ($seen_create_table && $brackets_level == 1) { - $in_create_table_fields = TRUE; - } - } - - - if ($arr[$i]['type'] == 'punct_bracket_close_round') { - $brackets_level--; - if ($seen_references) { - $seen_references = FALSE; - } - if ($seen_create_table && $brackets_level == 0) { - $in_create_table_fields = FALSE; - } - } - - if (($arr[$i]['type'] == 'alpha_columnAttrib')) { - $upper_data = strtoupper($arr[$i]['data']); - if ($seen_create_table && $in_create_table_fields) { - if ($upper_data == 'DEFAULT') { - $seen_default = TRUE; - } - } - } - - /** - * @see @todo 2005-10-16 note: the "or" part here is a workaround for a bug - */ - if (($arr[$i]['type'] == 'alpha_columnType') || ($arr[$i]['type'] == 'alpha_functionName' && $seen_create_table)) { - $upper_data = strtoupper($arr[$i]['data']); - if ($seen_create_table && $in_create_table_fields && isset($current_identifier)) { - $create_table_fields[$current_identifier]['type'] = $upper_data; - if ($upper_data == 'TIMESTAMP') { - $arr[$i]['type'] = 'alpha_columnType'; - $in_timestamp_options = TRUE; - } else { - $in_timestamp_options = FALSE; - if ($upper_data == 'CHAR') { - $arr[$i]['type'] = 'alpha_columnType'; - } - } - } - } - - - if ($arr[$i]['type'] == 'quote_backtick' || $arr[$i]['type'] == 'alpha_identifier') { - - if ($arr[$i]['type'] == 'quote_backtick') { - // remove backquotes - $identifier = PMA_unQuote($arr[$i]['data']); - } else { - $identifier = $arr[$i]['data']; - } - - if ($seen_create_table && $in_create_table_fields) { - $current_identifier = $identifier; - // warning: we set this one even for non TIMESTAMP type - $create_table_fields[$current_identifier]['timestamp_not_null'] = FALSE; - } - - if ($seen_constraint) { - $foreign[$foreign_key_number]['constraint'] = $identifier; - } - - if ($seen_foreign && $brackets_level > 0) { - $foreign[$foreign_key_number]['index_list'][] = $identifier; - } - - if ($seen_references) { - // here, the first bracket level corresponds to the - // bracket of CREATE TABLE - // so if we are on level 2, it must be the index list - // of the foreign key REFERENCES - if ($brackets_level > 1) { - $foreign[$foreign_key_number]['ref_index_list'][] = $identifier; - } else { - // for MySQL 4.0.18, identifier is - // `table` or `db`.`table` - // the first pass will pick the db name - // the next pass will execute the else and pick the - // db name in $db_table[0] - if ($arr[$i+1]['type'] == 'punct_qualifier') { - $foreign[$foreign_key_number]['ref_db_name'] = $identifier; - } else { - // for MySQL 4.0.16, identifier is - // `table` or `db.table` - $db_table = explode('.', $identifier); - if (isset($db_table[1])) { - $foreign[$foreign_key_number]['ref_db_name'] = $db_table[0]; - $foreign[$foreign_key_number]['ref_table_name'] = $db_table[1]; - } else { - $foreign[$foreign_key_number]['ref_table_name'] = $db_table[0]; - } - } - } - } - } - } // end for $i (loop #3) - - - // Fill the $subresult array - - if (isset($create_table_fields)) { - $subresult['create_table_fields'] = $create_table_fields; - } - - if (isset($foreign)) { - $subresult['foreign_keys'] = $foreign; - } - - 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($limit_clause)) { - $subresult['limit_clause'] = $limit_clause; - } - if (isset($where_clause)) { - $subresult['where_clause'] = $where_clause; - } - if (isset($unsorted_query) && !empty($unsorted_query)) { - $subresult['unsorted_query'] = $unsorted_query; - } - if (isset($where_clause_identifiers)) { - $subresult['where_clause_identifiers'] = $where_clause_identifiers; - } - - if (isset($position_of_first_select)) { - $subresult['position_of_first_select'] = $position_of_first_select; - $subresult['section_before_limit'] = $section_before_limit; - $subresult['section_after_limit'] = $section_after_limit; - } - - // They are naughty and didn't have a trailing semi-colon, - // then still handle it properly - if ($subresult['querytype'] != '') { - $result[] = $subresult; - } - return $result; - } // end of the "PMA_SQP_analyze()" function - - - /** - * Colorizes SQL queries html formatted - * - * @todo check why adding a "\n" after the would cause extra blanks - * to be displayed: SELECT p . person_name - * @param array The SQL queries html formatted - * - * @return array The colorized SQL queries - * - * @access public - */ - function PMA_SQP_formatHtml_colorize($arr) - { - $i = $GLOBALS['PMA_strpos']($arr['type'], '_'); - $class = ''; - if ($i > 0) { - $class = 'syntax_' . PMA_substr($arr['type'], 0, $i) . ' '; - } - - $class .= 'syntax_' . $arr['type']; - - return '' . htmlspecialchars($arr['data']) . ''; - } // end of the "PMA_SQP_formatHtml_colorize()" function - - - /** - * Formats SQL queries to html - * - * @param array The SQL queries - * @param string mode - * @param integer starting token - * @param integer number of tokens to format, -1 = all - * - * @return string The formatted SQL queries - * - * @access public - */ - function PMA_SQP_formatHtml($arr, $mode='color', $start_token=0, - $number_of_tokens=-1) - { - //DEBUG echo 'in Format
'; print_r($arr); echo '
'; - // then check for an array - if (!is_array($arr)) { - return htmlspecialchars($arr); - } - // first check for the SQL parser having hit an error - if (PMA_SQP_isError()) { - return htmlspecialchars($arr['raw']); - } - // else do it properly - switch ($mode) { - case 'color': - $str = ''; - $html_line_break = '
'; - break; - case 'query_only': - $str = ''; - $html_line_break = "\n"; - break; - case 'text': - $str = ''; - $html_line_break = '
'; - break; - } // end switch - $indent = 0; - $bracketlevel = 0; - $functionlevel = 0; - $infunction = FALSE; - $space_punct_listsep = ' '; - $space_punct_listsep_function_name = ' '; - // $space_alpha_reserved_word = '
'."\n"; - $space_alpha_reserved_word = ' '; - - $keywords_with_brackets_1before = array( - 'INDEX', - 'KEY', - 'ON', - 'USING' - ); - $keywords_with_brackets_1before_cnt = 4; - - $keywords_with_brackets_2before = array( - 'IGNORE', - 'INDEX', - 'INTO', - 'KEY', - 'PRIMARY', - 'PROCEDURE', - 'REFERENCES', - 'UNIQUE', - 'USE' - ); - // $keywords_with_brackets_2before_cnt = count($keywords_with_brackets_2before); - $keywords_with_brackets_2before_cnt = 9; - - // These reserved words do NOT get a newline placed near them. - $keywords_no_newline = array( - 'AS', - 'ASC', - 'DESC', - 'DISTINCT', - 'DUPLICATE', - 'HOUR', - 'INTERVAL', - 'IS', - 'LIKE', - 'NOT', - 'NULL', - 'ON', - 'REGEXP' - ); - $keywords_no_newline_cnt = 12; - - // These reserved words introduce a privilege list - $keywords_priv_list = array( - 'GRANT', - 'REVOKE' - ); - $keywords_priv_list_cnt = 2; - - if ($number_of_tokens == -1) { - $arraysize = $arr['len']; - } else { - $arraysize = $number_of_tokens; - } - $typearr = array(); - if ($arraysize >= 0) { - $typearr[0] = ''; - $typearr[1] = ''; - $typearr[2] = ''; - //$typearr[3] = $arr[0]['type']; - $typearr[3] = $arr[$start_token]['type']; - } - - $in_priv_list = FALSE; - for ($i = $start_token; $i < $arraysize; $i++) { -// DEBUG echo "Loop format " . $arr[$i]['data'] . " " . $arr[$i]['type'] . "
"; - $before = ''; - $after = ''; - $indent = 0; - // array_shift($typearr); - /* - 0 prev2 - 1 prev - 2 current - 3 next - */ - if (($i + 1) < $arraysize) { - // array_push($typearr, $arr[$i + 1]['type']); - $typearr[4] = $arr[$i + 1]['type']; - } else { - //array_push($typearr, null); - $typearr[4] = ''; - } - - for ($j=0; $j<4; $j++) { - $typearr[$j] = $typearr[$j + 1]; - } - - switch ($typearr[2]) { - case 'white_newline': - $before = ''; - break; - case 'punct_bracket_open_round': - $bracketlevel++; - $infunction = FALSE; - // Make sure this array is sorted! - if (($typearr[1] == 'alpha_functionName') || ($typearr[1] == 'alpha_columnType') || ($typearr[1] == 'punct') - || ($typearr[3] == 'digit_integer') || ($typearr[3] == 'digit_hex') || ($typearr[3] == 'digit_float') - || (($typearr[0] == 'alpha_reservedWord') - && PMA_STR_binarySearchInArr(strtoupper($arr[$i - 2]['data']), $keywords_with_brackets_2before, $keywords_with_brackets_2before_cnt)) - || (($typearr[1] == 'alpha_reservedWord') - && PMA_STR_binarySearchInArr(strtoupper($arr[$i - 1]['data']), $keywords_with_brackets_1before, $keywords_with_brackets_1before_cnt)) - ) { - $functionlevel++; - $infunction = TRUE; - $after .= ' '; - } else { - $indent++; - $after .= ($mode != 'query_only' ? '
' : ' '); - } - break; - case 'alpha_identifier': - if (($typearr[1] == 'punct_qualifier') || ($typearr[3] == 'punct_qualifier')) { - $after = ''; - $before = ''; - } - if (($typearr[3] == 'alpha_columnType') || ($typearr[3] == 'alpha_identifier')) { - $after .= ' '; - } - break; - case 'punct_user': - case 'punct_qualifier': - $before = ''; - $after = ''; - break; - case 'punct_listsep': - if ($infunction == TRUE) { - $after .= $space_punct_listsep_function_name; - } else { - $after .= $space_punct_listsep; - } - break; - case 'punct_queryend': - if (($typearr[3] != 'comment_mysql') && ($typearr[3] != 'comment_ansi') && $typearr[3] != 'comment_c') { - $after .= $html_line_break; - $after .= $html_line_break; - } - $space_punct_listsep = ' '; - $space_punct_listsep_function_name = ' '; - $space_alpha_reserved_word = ' '; - $in_priv_list = FALSE; - break; - case 'comment_mysql': - case 'comment_ansi': - $after .= $html_line_break; - break; - case 'punct': - $before .= ' '; - // workaround for - // select * from mytable limit 0,-1 - // (a side effect of this workaround is that - // select 20 - 9 - // becomes - // select 20 -9 - // ) - if ($typearr[3] != 'digit_integer') { - $after .= ' '; - } - break; - case 'punct_bracket_close_round': - $bracketlevel--; - if ($infunction == TRUE) { - $functionlevel--; - $after .= ' '; - $before .= ' '; - } else { - $indent--; - $before .= ($mode != 'query_only' ? '
' : ' '); - } - $infunction = ($functionlevel > 0) ? TRUE : FALSE; - break; - case 'alpha_columnType': - if ($typearr[3] == 'alpha_columnAttrib') { - $after .= ' '; - } - if ($typearr[1] == 'alpha_columnType') { - $before .= ' '; - } - break; - case 'alpha_columnAttrib': - - // ALTER TABLE tbl_name AUTO_INCREMENT = 1 - // COLLATE LATIN1_GENERAL_CI DEFAULT - if ($typearr[1] == 'alpha_identifier' || $typearr[1] == 'alpha_charset') { - $before .= ' '; - } - if (($typearr[3] == 'alpha_columnAttrib') || ($typearr[3] == 'quote_single') || ($typearr[3] == 'digit_integer')) { - $after .= ' '; - } - // workaround for - // AUTO_INCREMENT = 31DEFAULT_CHARSET = utf-8 - - if ($typearr[2] == 'alpha_columnAttrib' && $typearr[3] == 'alpha_reservedWord') { - $before .= ' '; - } - // workaround for - // select * from mysql.user where binary user="root" - // binary is marked as alpha_columnAttrib - // but should be marked as a reserved word - if (strtoupper($arr[$i]['data']) == 'BINARY' - && $typearr[3] == 'alpha_identifier') { - $after .= ' '; - } - break; - case 'alpha_reservedWord': - // do not uppercase the reserved word if we are calling - // this function in query_only mode, because we need - // the original query (otherwise we get problems with - // semi-reserved words like "storage" which is legal - // as an identifier name) - - if ($mode != 'query_only') { - $arr[$i]['data'] = strtoupper($arr[$i]['data']); - } - - if ((($typearr[1] != 'alpha_reservedWord') - || (($typearr[1] == 'alpha_reservedWord') - && PMA_STR_binarySearchInArr(strtoupper($arr[$i - 1]['data']), $keywords_no_newline, $keywords_no_newline_cnt))) - && ($typearr[1] != 'punct_level_plus') - && (!PMA_STR_binarySearchInArr($arr[$i]['data'], $keywords_no_newline, $keywords_no_newline_cnt))) { - // do not put a space before the first token, because - // we use a lot of eregi() checking for the first - // reserved word at beginning of query - // so do not put a newline before - // - // also we must not be inside a privilege list - if ($i > 0) { - // the alpha_identifier exception is there to - // catch cases like - // GRANT SELECT ON mydb.mytable TO myuser@localhost - // (else, we get mydb.mytableTO) - // - // the quote_single exception is there to - // catch cases like - // GRANT ... TO 'marc'@'domain.com' IDENTIFIED... - /** - * @todo fix all cases and find why this happens - */ - - if (!$in_priv_list || $typearr[1] == 'alpha_identifier' || $typearr[1] == 'quote_single' || $typearr[1] == 'white_newline') { - $before .= $space_alpha_reserved_word; - } - } else { - // on first keyword, check if it introduces a - // privilege list - if (PMA_STR_binarySearchInArr($arr[$i]['data'], $keywords_priv_list, $keywords_priv_list_cnt)) { - $in_priv_list = TRUE; - } - } - } else { - $before .= ' '; - } - - switch ($arr[$i]['data']) { - case 'CREATE': - if (!$in_priv_list) { - $space_punct_listsep = $html_line_break; - $space_alpha_reserved_word = ' '; - } - break; - case 'EXPLAIN': - case 'DESCRIBE': - case 'SET': - case 'ALTER': - case 'DELETE': - case 'SHOW': - case 'DROP': - case 'UPDATE': - case 'TRUNCATE': - case 'ANALYZE': - case 'ANALYSE': - if (!$in_priv_list) { - $space_punct_listsep = $html_line_break; - $space_alpha_reserved_word = ' '; - } - break; - case 'INSERT': - case 'REPLACE': - if (!$in_priv_list) { - $space_punct_listsep = $html_line_break; - $space_alpha_reserved_word = $html_line_break; - } - break; - case 'VALUES': - $space_punct_listsep = ' '; - $space_alpha_reserved_word = $html_line_break; - break; - case 'SELECT': - $space_punct_listsep = ' '; - $space_alpha_reserved_word = $html_line_break; - break; - default: - break; - } // end switch ($arr[$i]['data']) - - $after .= ' '; - break; - case 'digit_integer': - case 'digit_float': - case 'digit_hex': - /** - * @todo could there be other types preceding a digit? - */ - if ($typearr[1] == 'alpha_reservedWord') { - $after .= ' '; - } - if ($infunction && $typearr[3] == 'punct_bracket_close_round') { - $after .= ' '; - } - if ($typearr[1] == 'alpha_columnAttrib') { - $before .= ' '; - } - break; - case 'alpha_variable': - $after = ' '; - break; - case 'quote_double': - case 'quote_single': - // workaround: for the query - // REVOKE SELECT ON `base2\_db`.* FROM 'user'@'%' - // the @ is incorrectly marked as alpha_variable - // in the parser, and here, the '%' gets a blank before, - // which is a syntax error - if ($typearr[1] != 'punct_user') { - $before .= ' '; - } - if ($infunction && $typearr[3] == 'punct_bracket_close_round') { - $after .= ' '; - } - break; - case 'quote_backtick': - // here we check for punct_user to handle correctly - // DEFINER = `username`@`%` - // where @ is the punct_user and `%` is the quote_backtick - if ($typearr[3] != 'punct_qualifier' && $typearr[3] != 'alpha_variable' && $typearr[3] != 'punct_user') { - $after .= ' '; - } - if ($typearr[1] != 'punct_qualifier' && $typearr[1] != 'alpha_variable' && $typearr[1] != 'punct_user') { - $before .= ' '; - } - break; - default: - break; - } // end switch ($typearr[2]) - -/* - if ($typearr[3] != 'punct_qualifier') { - $after .= ' '; - } - $after .= "\n"; -*/ - $str .= $before . ($mode=='color' ? PMA_SQP_formatHTML_colorize($arr[$i]) : $arr[$i]['data']). $after; - } // end for - if ($mode=='color') { - $str .= '
'; - } - - return $str; - } // end of the "PMA_SQP_formatHtml()" function -} - -/** - * Builds a CSS rule used for html formatted SQL queries - * - * @param string The class name - * @param string The property name - * @param string The property value - * - * @return string The CSS rule - * - * @access public - * - * @see PMA_SQP_buildCssData() - */ -function PMA_SQP_buildCssRule($classname, $property, $value) -{ - $str = '.' . $classname . ' {'; - if ($value != '') { - $str .= $property . ': ' . $value . ';'; - } - $str .= '}' . "\n"; - - return $str; -} // end of the "PMA_SQP_buildCssRule()" function - - -/** - * Builds CSS rules used for html formatted SQL queries - * - * @return string The CSS rules set - * - * @access public - * - * @global array The current PMA configuration - * - * @see PMA_SQP_buildCssRule() - */ -function PMA_SQP_buildCssData() -{ - global $cfg; - - $css_string = ''; - foreach ($cfg['SQP']['fmtColor'] AS $key => $col) { - $css_string .= PMA_SQP_buildCssRule('syntax_' . $key, 'color', $col); - } - - for ($i = 0; $i < 8; $i++) { - $css_string .= PMA_SQP_buildCssRule('syntax_indent' . $i, 'margin-left', ($i * $cfg['SQP']['fmtInd']) . $cfg['SQP']['fmtIndUnit']); - } - - return $css_string; -} // end of the "PMA_SQP_buildCssData()" function - -if (! defined('PMA_MINIMUM_COMMON')) { - /** - * Gets SQL queries with no format - * - * @param array The SQL queries list - * - * @return string The SQL queries with no format - * - * @access public - */ - function PMA_SQP_formatNone($arr) - { - $formatted_sql = htmlspecialchars($arr['raw']); - $formatted_sql = preg_replace("@((\015\012)|(\015)|(\012)){3,}@", "\n\n", $formatted_sql); - - return $formatted_sql; - } // end of the "PMA_SQP_formatNone()" function - - - /** - * Gets SQL queries in text format - * - * @todo WRITE THIS! - * @param array The SQL queries list - * - * @return string The SQL queries in text format - * - * @access public - */ - function PMA_SQP_formatText($arr) - { - return PMA_SQP_formatNone($arr); - } // end of the "PMA_SQP_formatText()" function -} // end if: minimal common.lib needed? - -?>