Exemplo n.º 1
0
 /**
  * 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)
 {
     // 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 = '<span class="syntax">';
             $html_line_break = '<br />';
             break;
         case 'query_only':
             $str = '';
             $html_line_break = "\n";
             break;
         case 'text':
             $str = '';
             $html_line_break = '<br />';
             break;
     }
     // end switch
     $indent = 0;
     $bracketlevel = 0;
     $functionlevel = 0;
     $infunction = FALSE;
     $space_punct_listsep = ' ';
     $space_punct_listsep_function_name = ' ';
     // $space_alpha_reserved_word = '<br />'."\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', '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 "<b>" . $arr[$i]['data'] . "</b> " . $arr[$i]['type'] . "<br />";
         $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' ? '<div class="syntax_indent' . $indent . '">' : ' ';
                 }
                 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_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' ? '</div>' : ' ';
                 }
                 $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
                 // select * from mysql.user where binary user="******"
                 // 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':
                 // other workaround for a problem similar to the one
                 // explained below for quote_single
                 if (!$in_priv_list) {
                     $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] != 'alpha_variable') {
                     $before .= ' ';
                 }
                 if ($infunction && $typearr[3] == 'punct_bracket_close_round') {
                     $after .= ' ';
                 }
                 break;
             case 'quote_backtick':
                 if ($typearr[3] != 'punct_qualifier') {
                     $after .= ' ';
                 }
                 if ($typearr[1] != 'punct_qualifier') {
                     $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 .= '</span>';
     }
     return $str;
 }
Exemplo n.º 2
0
/**
 * Formats SQL queries to html
 *
 * @param array   $arr              The SQL queries
 * @param string  $mode             mode of printing
 * @param integer $start_token      starting token
 * @param integer $number_of_tokens 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)
{
    global $PMA_SQPdata_operators_docs, $PMA_SQPdata_functions_docs;
    //DEBUG echo 'in Format<pre>'; print_r($arr); echo '</pre>';
    // 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 = '<span class="syntax">';
            $html_line_break = '<br />';
            $docu = true;
            break;
        case 'query_only':
            $str = '';
            $html_line_break = "\n";
            $docu = false;
            break;
        case 'text':
            $str = '';
            $html_line_break = '<br />';
            $docu = true;
            break;
    }
    // end switch
    // inner_sql is a span that exists for all cases, except query_only
    // of $cfg['SQP']['fmtType'] to make possible a replacement
    // for inline editing
    if ($mode != 'query_only') {
        $str .= '<span class="inner_sql">';
    }
    $close_docu_link = false;
    $indent = 0;
    $bracketlevel = 0;
    $functionlevel = 0;
    $infunction = false;
    $space_punct_listsep = ' ';
    $space_punct_listsep_function_name = ' ';
    // $space_alpha_reserved_word = '<br />'."\n";
    $space_alpha_reserved_word = ' ';
    $keywords_with_brackets_1before = array('INDEX' => 1, 'KEY' => 1, 'ON' => 1, 'USING' => 1);
    $keywords_with_brackets_2before = array('IGNORE' => 1, 'INDEX' => 1, 'INTO' => 1, 'KEY' => 1, 'PRIMARY' => 1, 'PROCEDURE' => 1, 'REFERENCES' => 1, 'UNIQUE' => 1, 'USE' => 1);
    // These reserved words do NOT get a newline placed near them.
    $keywords_no_newline = array('AS' => 1, 'ASC' => 1, 'DESC' => 1, 'DISTINCT' => 1, 'DUPLICATE' => 1, 'HOUR' => 1, 'INTERVAL' => 1, 'IS' => 1, 'LIKE' => 1, 'NOT' => 1, 'NULL' => 1, 'ON' => 1, 'REGEXP' => 1);
    // These reserved words introduce a privilege list
    $keywords_priv_list = array('GRANT' => 1, 'REVOKE' => 1);
    if ($number_of_tokens == -1) {
        $number_of_tokens = $arr['len'];
    }
    $typearr = array();
    if ($number_of_tokens >= 0) {
        $typearr[0] = '';
        $typearr[1] = '';
        $typearr[2] = '';
        $typearr[3] = $arr[$start_token]['type'];
    }
    $in_priv_list = false;
    for ($i = $start_token; $i < $number_of_tokens; $i++) {
        // DEBUG echo "Loop format <strong>" . $arr[$i]['data']
        // . "</strong> " . $arr[$i]['type'] . "<br />";
        $before = '';
        $after = '';
        // array_shift($typearr);
        /*
        0 prev2
        1 prev
        2 current
        3 next
        */
        if ($i + 1 < $number_of_tokens) {
            $typearr[4] = $arr[$i + 1]['type'];
        } else {
            $typearr[4] = '';
        }
        for ($j = 0; $j < 4; $j++) {
            $typearr[$j] = $typearr[$j + 1];
        }
        switch ($typearr[2]) {
            case 'alpha_bitfield_constant_introducer':
                $before = ' ';
                $after = '';
                break;
            case 'white_newline':
                $before = '';
                break;
            case 'punct_bracket_open_round':
                $bracketlevel++;
                $infunction = false;
                $keyword_brackets_2before = isset($keywords_with_brackets_2before[strtoupper($arr[$i - 2]['data'])]);
                $keyword_brackets_1before = isset($keywords_with_brackets_1before[strtoupper($arr[$i - 1]['data'])]);
                // 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' && $keyword_brackets_2before || $typearr[1] == 'alpha_reservedWord' && $keyword_brackets_1before) {
                    $functionlevel++;
                    $infunction = true;
                    $after .= ' ';
                } else {
                    $indent++;
                    if ($mode != 'query_only') {
                        $after .= '<div class="syntax_indent' . $indent . '">';
                    } else {
                        $after .= ' ';
                    }
                }
                break;
            case 'alpha_identifier':
                if ($typearr[1] == 'punct_qualifier' || $typearr[3] == 'punct_qualifier') {
                    $after = '';
                    $before = '';
                }
                // for example SELECT 1 somealias
                if ($typearr[1] == 'digit_integer') {
                    $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 .= ' ';
                if ($docu && isset($PMA_SQPdata_operators_docs[$arr[$i]['data']]) && ($arr[$i]['data'] != '*' || in_array($arr[$i]['type'], array('digit_integer', 'digit_float', 'digit_hex')))) {
                    $before .= PMA_Util::showMySQLDocu('functions', $PMA_SQPdata_operators_docs[$arr[$i]['data']]['link'], false, $PMA_SQPdata_operators_docs[$arr[$i]['data']]['anchor'], true);
                    $after .= '</a>';
                }
                // 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':
                // only close bracket level when it was opened before
                if ($bracketlevel > 0) {
                    $bracketlevel--;
                    if ($infunction == true) {
                        $functionlevel--;
                        $after .= ' ';
                        $before .= ' ';
                    } else {
                        $indent--;
                        $before .= $mode != 'query_only' ? '</div>' : ' ';
                    }
                    $infunction = $functionlevel > 0 ? true : false;
                }
                break;
            case 'alpha_columnType':
                if ($docu) {
                    switch ($arr[$i]['data']) {
                        case 'tinyint':
                        case 'smallint':
                        case 'mediumint':
                        case 'int':
                        case 'bigint':
                        case 'decimal':
                        case 'float':
                        case 'double':
                        case 'real':
                        case 'bit':
                        case 'boolean':
                        case 'serial':
                            $before .= PMA_Util::showMySQLDocu('data-types', 'numeric-types', false, '', true);
                            $after = '</a>' . $after;
                            break;
                        case 'date':
                        case 'datetime':
                        case 'timestamp':
                        case 'time':
                        case 'year':
                            $before .= PMA_Util::showMySQLDocu('data-types', 'date-and-time-types', false, '', true);
                            $after = '</a>' . $after;
                            break;
                        case 'char':
                        case 'varchar':
                        case 'tinytext':
                        case 'text':
                        case 'mediumtext':
                        case 'longtext':
                        case 'binary':
                        case 'varbinary':
                        case 'tinyblob':
                        case 'mediumblob':
                        case 'blob':
                        case 'longblob':
                        case 'enum':
                        case 'set':
                            $before .= PMA_Util::showMySQLDocu('data-types', 'string-types', false, '', true);
                            $after = '</a>' . $after;
                            break;
                    }
                }
                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="******"
                // 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_functionName':
                $funcname = strtoupper($arr[$i]['data']);
                if ($docu && isset($PMA_SQPdata_functions_docs[$funcname])) {
                    $before .= PMA_Util::showMySQLDocu('functions', $PMA_SQPdata_functions_docs[$funcname]['link'], false, $PMA_SQPdata_functions_docs[$funcname]['anchor'], true);
                    $after .= '</a>';
                }
                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' && isset($keywords_no_newline[strtoupper($arr[$i - 1]['data'])])) && $typearr[1] != 'punct_level_plus' && !isset($keywords_no_newline[$arr[$i]['data']])) {
                    // do not put a space before the first token, because
                    // we use a lot of pattern matching 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 (isset($keywords_priv_list[$arr[$i]['data']])) {
                            $in_priv_list = true;
                        }
                    }
                } else {
                    $before .= ' ';
                }
                switch ($arr[$i]['data']) {
                    case 'CREATE':
                    case 'ALTER':
                    case 'DROP':
                    case 'RENAME':
                    case 'TRUNCATE':
                    case 'ANALYZE':
                    case 'ANALYSE':
                    case 'OPTIMIZE':
                        if ($docu) {
                            switch ($arr[$i + 1]['data']) {
                                case 'EVENT':
                                case 'TABLE':
                                case 'TABLESPACE':
                                case 'FUNCTION':
                                case 'INDEX':
                                case 'PROCEDURE':
                                case 'TRIGGER':
                                case 'SERVER':
                                case 'DATABASE':
                                case 'VIEW':
                                    $before .= PMA_Util::showMySQLDocu('SQL-Syntax', $arr[$i]['data'] . '_' . $arr[$i + 1]['data'], false, '', true);
                                    $close_docu_link = true;
                                    break;
                            }
                            if ($arr[$i + 1]['data'] == 'LOGFILE' && $arr[$i + 2]['data'] == 'GROUP') {
                                $before .= PMA_Util::showMySQLDocu('SQL-Syntax', $arr[$i]['data'] . '_LOGFILE_GROUP', false, '', true);
                                $close_docu_link = true;
                            }
                        }
                        if (!$in_priv_list) {
                            $space_punct_listsep = $html_line_break;
                            $space_alpha_reserved_word = ' ';
                        }
                        break;
                    case 'EVENT':
                    case 'TABLESPACE':
                    case 'TABLE':
                    case 'FUNCTION':
                    case 'INDEX':
                    case 'PROCEDURE':
                    case 'SERVER':
                    case 'TRIGGER':
                    case 'DATABASE':
                    case 'VIEW':
                    case 'GROUP':
                        if ($close_docu_link) {
                            $after = '</a>' . $after;
                            $close_docu_link = false;
                        }
                        break;
                    case 'SET':
                        if ($docu && ($i == 0 || $arr[$i - 1]['data'] != 'CHARACTER')) {
                            $before .= PMA_Util::showMySQLDocu('SQL-Syntax', $arr[$i]['data'], false, '', true);
                            $after = '</a>' . $after;
                        }
                        if (!$in_priv_list) {
                            $space_punct_listsep = $html_line_break;
                            $space_alpha_reserved_word = ' ';
                        }
                        break;
                    case 'EXPLAIN':
                    case 'DESCRIBE':
                    case 'DELETE':
                    case 'SHOW':
                    case 'UPDATE':
                        if ($docu) {
                            $before .= PMA_Util::showMySQLDocu('SQL-Syntax', $arr[$i]['data'], false, '', true);
                            $after = '</a>' . $after;
                        }
                        if (!$in_priv_list) {
                            $space_punct_listsep = $html_line_break;
                            $space_alpha_reserved_word = ' ';
                        }
                        break;
                    case 'INSERT':
                    case 'REPLACE':
                        if ($docu) {
                            $before .= PMA_Util::showMySQLDocu('SQL-Syntax', $arr[$i]['data'], false, '', true);
                            $after = '</a>' . $after;
                        }
                        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':
                        if ($docu) {
                            $before .= PMA_Util::showMySQLDocu('SQL-Syntax', 'SELECT', false, '', true);
                            $after = '</a>' . $after;
                        }
                        $space_punct_listsep = ' ';
                        $space_alpha_reserved_word = $html_line_break;
                        break;
                    case 'CALL':
                    case 'DO':
                    case 'HANDLER':
                        if ($docu) {
                            $before .= PMA_Util::showMySQLDocu('SQL-Syntax', $arr[$i]['data'], false, '', true);
                            $after = '</a>' . $after;
                        }
                        break;
                    default:
                        if ($close_docu_link && in_array($arr[$i]['data'], array('LIKE', 'NOT', 'IN', 'REGEXP', 'NULL'))) {
                            $after .= '</a>';
                            $close_docu_link = false;
                        } else {
                            if ($docu && isset($PMA_SQPdata_functions_docs[$arr[$i]['data']])) {
                                /* Handle multi word statements first */
                                if (isset($typearr[4]) && $typearr[4] == 'alpha_reservedWord' && $typearr[3] == 'alpha_reservedWord' && isset($PMA_SQPdata_functions_docs[strtoupper($arr[$i]['data'] . '_' . $arr[$i + 1]['data'] . '_' . $arr[$i + 2]['data'])])) {
                                    $tempname = strtoupper($arr[$i]['data'] . '_' . $arr[$i + 1]['data'] . '_' . $arr[$i + 2]['data']);
                                    $before .= PMA_Util::showMySQLDocu('functions', $PMA_SQPdata_functions_docs[$tempname]['link'], false, $PMA_SQPdata_functions_docs[$tempname]['anchor'], true);
                                    $close_docu_link = true;
                                } else {
                                    if (isset($typearr[3]) && $typearr[3] == 'alpha_reservedWord' && isset($PMA_SQPdata_functions_docs[strtoupper($arr[$i]['data'] . '_' . $arr[$i + 1]['data'])])) {
                                        $tempname = strtoupper($arr[$i]['data'] . '_' . $arr[$i + 1]['data']);
                                        $before .= PMA_Util::showMySQLDocu('functions', $PMA_SQPdata_functions_docs[$tempname]['link'], false, $PMA_SQPdata_functions_docs[$tempname]['anchor'], true);
                                        $close_docu_link = true;
                                    } else {
                                        $before .= PMA_Util::showMySQLDocu('functions', $PMA_SQPdata_functions_docs[$arr[$i]['data']]['link'], false, $PMA_SQPdata_functions_docs[$arr[$i]['data']]['anchor'], true);
                                        $after .= '</a>';
                                    }
                                }
                            }
                        }
                        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' && $typearr[1] != 'alpha_bitfield_constant_introducer') {
                    $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;
        if ($mode == 'color') {
            $str .= PMA_SQP_formatHTML_colorize($arr[$i]);
        } elseif ($mode == 'text') {
            $str .= htmlspecialchars($arr[$i]['data']);
        } else {
            $str .= $arr[$i]['data'];
        }
        $str .= $after;
    }
    // end for
    // close unclosed indent levels
    while ($indent > 0) {
        $indent--;
        $str .= $mode != 'query_only' ? '</div>' : ' ';
    }
    /* End possibly unclosed documentation link */
    if ($close_docu_link) {
        $str .= '</a>';
        $close_docu_link = false;
    }
    if ($mode != 'query_only') {
        // close inner_sql span
        $str .= '</span>';
    }
    if ($mode == 'color') {
        // close syntax span
        $str .= '</span>';
    }
    return $str;
}