PHP

Подсветка синтаксиса MySQL-запросов

При выводе диагностики в своих рабочих проектах я использую вот такую функцию для подсветки синтаксиса MySQL-запросов. Она преобразует текст запроса, делая все служебные слова языка заглавными буквами и подсвечивает их цветом, а также выделяет различными цветами числовые значения и скобки. Такая подсветка позволяет сразу же увидеть синтаксические ошибки, да и вообще повышает наглядность сообщений при отладке скриптов.
//-------------------------------------------------------------------
// Функция подсветки синтаксиса MySQL-запроса
// (C) ManHunter / PCL
// http://www.manhunter.ru
//-------------------------------------------------------------------
function mysql_debug($query) {
    $tmp=htmlspecialchars($query);
    $tmp=str_replace("\r",'',$tmp);
    $tmp=trim(str_replace("\n","\r\n",$tmp))."\r\n";
 
    $quote_list_text=array();
    $quote_list_symbols=array();
 
    $k=0;
    $quotes=Array();
    // Обработать экранированные кавычки
    preg_match_all("/\\\'|\\\"/is", $tmp, $quotes);
    array_unique($quotes);
    if (count($quotes)) {
        foreach($quotes[0] as $i) {
            $k++;
            $quote_list_symbols[$k]=$i;
            $tmp=str_replace($i, '<symbol'.$k.'>', $tmp);
        }
    }
 
    $matches=Array(
        "/("|'|`)(.*?)(\\1)/is", // текст в кавычках
        "/\/\*.*?\*\//s",             // текст комментария
        "/ \-\-.*\x0D\x0A/",          // текст ' --' комментария
        "/ #.*\x0D\x0A/",             // текст ' #' комментария
    );
 
    // Обработать текст
    foreach($matches as $match) {
        // Обработать текст
        $found=array();
        preg_match_all($match, $tmp, $found);
        $quotes=(array)$found[0];
        array_unique($quotes);
        if (count($quotes)) {
            foreach($quotes as $i) {
                $k++;
                $quote_list_text[$k]=$i;
                $tmp=str_replace($i, '<text'.$k.'>', $tmp);
            }
        }
    }    
 
    // Служебные слова MySQL
    $keywords=Array(
        "avg", "as", "auto_increment", "and", "analyze", "alter",
        "asc", "all", "after", "add", "action", "against",
        "aes_encrypt", "aes_decrypt", "ascii", "abs", "acos",
        "asin", "atan", "authors", "between", "btree", "backup",
        "by", "binary", "before", "binlog", "benchmark", "blob",
        "bigint", "bit_count", "bit_or", "bit_and", "bin",
        "bit_length", "both", "create", "count", "comment",
        "check", "char", "concat", "cipher", "changed", "column",
        "columns", "change", "constraint", "cascade", "checksum",
        "cross", "close", "concurrent", "commit", "curdate",
        "current_date", "curtime", "current_time",
        "current_timestamp", "cast", "convert", "connection_id",
        "coalesce", "case", "conv", "concat_ws", "char_length",
        "character_length", "ceiling", "cos", "cot", "crc32",
        "compress", "delete", "drop", "default", "distinct",
        "decimal", "date", "describe", "data", "desc",
        "dayofmonth", "date_add", "database", "databases",
        "double", "duplicate", "disable", "datetime", "dumpfile",
        "distinctrow", "delayed", "dayofweek", "dayofyear",
        "dayname", "day_minute", "date_format", "date_sub", 
        "decode", "des_encrypt", "des_decrypt", "degrees",
        "decompress", "dec", "engine", "explain", "enum",
        "escaped", "execute", "extended", "errors", "exists",
        "enable", "enclosed", "extract", "encrypt", "encode",
        "elt", "export_set", "escape", "exp", "end", "from",
        "float", "flush", "fields", "file", "for", "fast", "full",
        "fulltext", "first", "foreign", "force", "from_days", 
        "from_unixtime", "format", "found_rows", "floor", "field",
        "find_in_set", "group", "grant", "grants", "global", 
        "get_lock", "greatest", "having", "high_priority", 
        "handler", "hour", "hex", "insert", "into", "inner", 
        "int", "ifnull", "if", "isnull", "in", "infile", "is", 
        "interval", "ignore", "identified", "index", "issuer", 
        "integer", "is_free_lock", "inet_ntoa", "inet_aton", 
        "instr", "join", "kill", "key", "keys", "left", "load", 
        "local", "limit", "like", "lock", "lpad", "last_insert_id", 
        "logs", "length", "longblob", "longtext", "last", "lines", 
        "low_priority", "locate", "ltrim", "leading", "lcase", 
        "lower", "load_file", "ln", "log", "least", "month", "mod", 
        "max", "min", "mediumint", "medium", "master", "modify", 
        "mediumblob", "mediumtext", "match", "mode", "monthname", 
        "mid", "minute", "master_pos_wait", "make_set", "null", 
        "not", "now", "none", "new", "numeric", "no", "natural", 
        "next", "nullif", "national", "nchar", "on", "or", 
        "optimize", "order", "optionally", "option", "outfile", 
        "open", "offset", "outer", "old_password", "ord", "oct", 
        "octet_length", "primary", "password", "privileges", 
        "process", "processlist", "purge", "partial", "procedure",
        "prev", "period_add", "period_diff", "position", "pow", 
        "power", "pi", "quick", "quarter", "quote", "right", 
        "repair", "restore", "reset", "regexp", "references", 
        "replace", "revoke", "reload", "require", "replication", 
        "read", "rand", "rename", "real", "restrict", 
        "release_lock", "rpad", "rtrim", "repeat", "reverse", 
        "rlike", "round", "radians", "rollup", "select", "sum", 
        "set", "show", "substring", "smallint", "super", "subject", 
        "status", "slave", "session", "start", "share", 
        "straight_join", "sql_small_result", "sql_big_result", 
        "sql_buffer_result", "sql_cache", "sql_no_cache", 
        "sql_calc_found_rows", "second", "sysdate", "sec_to_time", 
        "system_user", "session_user", "substring_index", "std", 
        "stddev", "soundex", "space", "strcmp", "sign", "sqrt", 
        "sin", "straight", "sleep", "text", "truncate", "table", 
        "tinyint", "tables", "to_days", "temporary", "terminated", 
        "to", "types", "time", "timestamp", "tinytext", 
        "tinyblob", "transaction", "time_format", "time_to_sec", 
        "trim", "trailing", "tan", "then", "update", "union", 
        "using", "unsigned", "unlock", "usage", "use_frm", 
        "unix_timestamp", "unique", "use", "user", "ucase", 
        "upper", "uuid", "values", "varchar", "variables", 
        "version", "variance", "varying", "where", "with", 
        "warnings", "write", "weekday", "week", "when", "xor", 
        "year", "yearweek", "year_month", "zerofill");
    $replace=Array();
    foreach($keywords as $keyword) {
        $replace[]='/\b'.$keyword.'\b/ie';
    }
 
    // Выделить служебные слова в тексте запроса
    $tmp=preg_replace($replace,
        '"<b style=\"color:#0000FF\">".strtoupper("$0")."</b>"',$tmp);
 
    // Выделить числовые значения в тексте запроса
    $tmp=preg_replace('/\b([\.0-9]+)\b/',
        '<b style="color:#008000">\1</b>',$tmp);
 
    // Выделить скобки в тексте запроса
    $tmp=preg_replace('/([\(\)])/',
        '<b style="color:#FF0000">\1</b>',$tmp);
 
    // Вернуть обратно строки в кавычках
    if (count($quote_list_text)) {
        $quote_list_text=array_reverse($quote_list_text, true);
        foreach($quote_list_text as $k=>$i) {
            $tmp=str_replace('<text'.$k.'>',
                '<span style="color:#777;">'.$i.'</span>', $tmp);
        }
    }
    // Вернуть обратно экранированные символы
    if (count($quote_list_symbols)) {
        $quote_list_symbols=array_reverse($quote_list_symbols, true);
        foreach($quote_list_symbols as $k=>$i) {
            $tmp=str_replace('<symbol'.$k.'>', $i, $tmp);
        }
    }
 
    // Вернуть подсвеченный текст запроса
    // Если не надо расставлять переносы, то уберите nl2br
    return nl2br(trim($tmp));
}

Единственный параметр функции $query - текст исходного запроса. На выходе подсвеченная строка запроса в формате HTML. Цвета подсветки захардкодены в исходнике, если надо, то поменяйте их на свои или вообще замените на определения стилей CSS.

Функция может вернуть неправильный результат, если в комментариях запроса содержатся несогласованные кавычки или апострофы, в остальном при тестировании я никаких проблем не нашел. Вот несколько примеров работы скрипта:
CREATE TABLE `orders` (
`o_id` INT(11) NOT NULL AUTO_INCREMENT,
`o_date` INT(11) NOT NULL,
`o_client` INT(11) NOT NULL COMMENT 'пользователь создавший заказ',
`o_status` INT(11) NOT NULL COMMENT 'статус заказа',
`o_sum` INT(11) NOT NULL COMMENT 'стоимость размещения',
`o_nds` DECIMAL(15,2) NOT NULL DEFAULT '0.00',
`o_comment` VARCHAR(1024) NOT NULL COMMENT 'Комментарии к заказу',
PRIMARY KEY (`o_id`)
) ENGINE=MyISAM /*!40101 DEFAULT CHARSET=utf8 */;

SELECT SQL_CACHE `regions`.*,
COUNT(`o_id`) AS `o_num`,
SUM(IF(`o_map` != 0, 1, 0)) AS `sum_map`,
SUM(IF(`o_list` != 0, 1, 0)) AS `sum_list`,
SUM(IF(`p_price`>0),1,0) AS `sum_free`,
FROM `regions`, `orders`
LEFT JOIN `prices` ON `p_o_id`=`o_id` AND `p_year`=2012
WHERE `o_region`=`r_id` AND `o_deleted`=0 AND `o_type`=0
GROUP BY `r_id`
HAVING (`sum_free`>50)
ORDER BY `r_order` DESC, `r_name`

Функция предназначена только для подсветки синтаксиса MySQL, но ее можно легко адаптировать под любой другой диалект SQL. Достаточно просто добавить или убрать служебные слова в соответствующем массиве.
Теги:
Подсветка, синтаксис, MySQL, запрос
Добавлено: 21 Сентября 2013 02:16:59 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...