Подсветка синтаксиса MySQL-запросов
При выводе диагностики в своих рабочих проектах я использую вот такую функцию для подсветки синтаксиса MySQL-запросов. Она преобразует текст запроса, делая все служебные слова языка заглавными буквами и подсвечивает их цветом, а также выделяет различными цветами числовые значения и скобки. Такая подсветка позволяет сразу же увидеть синтаксические ошибки, да и вообще повышает наглядность сообщений при отладке скриптов.Code (PHP) : Убрать нумерацию
- //-------------------------------------------------------------------
- // Функция подсветки синтаксиса 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));
- }
Функция может вернуть неправильный результат, если в комментариях запроса содержатся несогласованные кавычки или апострофы, в остальном при тестировании я никаких проблем не нашел. Вот несколько примеров работы скрипта:
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. Достаточно просто добавить или убрать служебные слова в соответствующем массиве.
Просмотров: 4834 | Комментариев: 7
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(10.04.2012 в 12:06):
Заменить пробелы на ' ' или выводить запрос в <pre> ... </pre>
Onix
(10.04.2012 в 12:05):
А как сделать чтобы табуляция в запросе сохранялась ?
Rush
(08.04.2012 в 02:17):
Тут самое интересное в запросах к MySQL.
ManHunter
(07.04.2012 в 20:10):
Не пойму только смысл генерации HTML-кода на ассемблере. Все равно никогда не понадобится.
Rush
(07.04.2012 в 17:23):
Интереснее было бы сделать, тоже самое на FASM. Хотелось было бы увидеть примерчик запросов на асме в MySQL.
ManHunter
(06.04.2012 в 12:41):
Вся проблема в том, что PHP делали много людей, каждый со своим понимаем и логикой. Меня тоже вымораживает разнобой в наименованиях и вольность в параметрах, особенно для строковых функций. Нет-нет и приходится заглядывать в документацию. Хорошо хоть автокомплит в редакторе есть.
DV
(06.04.2012 в 12:36):
Хороший скрипт. Но при виде PHP-шных конструкций "foreach($keywords as $keyword)" во мне каждый раз поднимается раздражение. Какой больной ум придумал нездоровый синтаксис "foreach(array as item)" вместо интуитивно понятного "foreach(item in array)"? При чём тут "as" - мы что, приводим массив к элементу этого массива?
Добавить комментарий
Заполните форму для добавления комментария