Blog. Just Blog

Быстрый поиск

Введите фрагмент названия статьи для поиска

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

07.04.2012 | Категория: Web-мастеру и не только | Автор: ManHunter
При выводе диагностики в своих рабочих проектах я использую вот такую функцию для подсветки синтаксиса MySQL-запросов. Она преобразует текст запроса, делая все служебные слова языка заглавными буквами и подсвечивает их цветом, а также выделяет различными цветами числовые значения и скобки. Такая подсветка позволяет сразу же увидеть синтаксические ошибки, да и вообще повышает наглядность сообщений при отладке скриптов.
  1. //-------------------------------------------------------------------
  2. // Функция подсветки синтаксиса MySQL-запроса
  3. // (C) ManHunter / PCL
  4. // http://www.manhunter.ru
  5. //-------------------------------------------------------------------
  6. function mysql_debug($query) {
  7.     $tmp=htmlspecialchars($query);
  8.     $tmp=str_replace("\r",'',$tmp);
  9.     $tmp=trim(str_replace("\n","\r\n",$tmp))."\r\n";
  10.  
  11.     $quote_list_text=array();
  12.     $quote_list_symbols=array();
  13.  
  14.     $k=0;
  15.     $quotes=Array();
  16.     // Обработать экранированные кавычки
  17.     preg_match_all("/\\\'|\\\"/is"$tmp$quotes);
  18.     array_unique($quotes);
  19.     if (count($quotes)) {
  20.         foreach($quotes[0] as $i) {
  21.             $k++;
  22.             $quote_list_symbols[$k]=$i;
  23.             $tmp=str_replace($i'<symbol'.$k.'>'$tmp);
  24.         }
  25.     }
  26.  
  27.     $matches=Array(
  28.         "/(&quot;|'|`)(.*?)(\\1)/is"// текст в кавычках
  29.         "/\/\*.*?\*\//s",             // текст комментария
  30.         "/ \-\-.*\x0D\x0A/",          // текст ' --' комментария
  31.         "/ #.*\x0D\x0A/",             // текст ' #' комментария
  32.     );
  33.  
  34.     // Обработать текст
  35.     foreach($matches as $match) {
  36.         // Обработать текст
  37.         $found=array();
  38.         preg_match_all($match$tmp$found);
  39.         $quotes=(array)$found[0];
  40.         array_unique($quotes);
  41.         if (count($quotes)) {
  42.             foreach($quotes as $i) {
  43.                 $k++;
  44.                 $quote_list_text[$k]=$i;
  45.                 $tmp=str_replace($i'<text'.$k.'>'$tmp);
  46.             }
  47.         }
  48.     }    
  49.  
  50.     // Служебные слова MySQL
  51.     $keywords=Array(
  52.         "avg""as""auto_increment""and""analyze""alter",
  53.         "asc""all""after""add""action""against",
  54.         "aes_encrypt""aes_decrypt""ascii""abs""acos",
  55.         "asin""atan""authors""between""btree""backup",
  56.         "by""binary""before""binlog""benchmark""blob",
  57.         "bigint""bit_count""bit_or""bit_and""bin",
  58.         "bit_length""both""create""count""comment",
  59.         "check""char""concat""cipher""changed""column",
  60.         "columns""change""constraint""cascade""checksum",
  61.         "cross""close""concurrent""commit""curdate",
  62.         "current_date""curtime""current_time",
  63.         "current_timestamp""cast""convert""connection_id",
  64.         "coalesce""case""conv""concat_ws""char_length",
  65.         "character_length""ceiling""cos""cot""crc32",
  66.         "compress""delete""drop""default""distinct",
  67.         "decimal""date""describe""data""desc",
  68.         "dayofmonth""date_add""database""databases",
  69.         "double""duplicate""disable""datetime""dumpfile",
  70.         "distinctrow""delayed""dayofweek""dayofyear",
  71.         "dayname""day_minute""date_format""date_sub"
  72.         "decode""des_encrypt""des_decrypt""degrees",
  73.         "decompress""dec""engine""explain""enum",
  74.         "escaped""execute""extended""errors""exists",
  75.         "enable""enclosed""extract""encrypt""encode",
  76.         "elt""export_set""escape""exp""end""from",
  77.         "float""flush""fields""file""for""fast""full",
  78.         "fulltext""first""foreign""force""from_days"
  79.         "from_unixtime""format""found_rows""floor""field",
  80.         "find_in_set""group""grant""grants""global"
  81.         "get_lock""greatest""having""high_priority"
  82.         "handler""hour""hex""insert""into""inner"
  83.         "int""ifnull""if""isnull""in""infile""is"
  84.         "interval""ignore""identified""index""issuer"
  85.         "integer""is_free_lock""inet_ntoa""inet_aton"
  86.         "instr""join""kill""key""keys""left""load"
  87.         "local""limit""like""lock""lpad""last_insert_id"
  88.         "logs""length""longblob""longtext""last""lines"
  89.         "low_priority""locate""ltrim""leading""lcase"
  90.         "lower""load_file""ln""log""least""month""mod"
  91.         "max""min""mediumint""medium""master""modify"
  92.         "mediumblob""mediumtext""match""mode""monthname"
  93.         "mid""minute""master_pos_wait""make_set""null"
  94.         "not""now""none""new""numeric""no""natural"
  95.         "next""nullif""national""nchar""on""or"
  96.         "optimize""order""optionally""option""outfile"
  97.         "open""offset""outer""old_password""ord""oct"
  98.         "octet_length""primary""password""privileges"
  99.         "process""processlist""purge""partial""procedure",
  100.         "prev""period_add""period_diff""position""pow"
  101.         "power""pi""quick""quarter""quote""right"
  102.         "repair""restore""reset""regexp""references"
  103.         "replace""revoke""reload""require""replication"
  104.         "read""rand""rename""real""restrict"
  105.         "release_lock""rpad""rtrim""repeat""reverse"
  106.         "rlike""round""radians""rollup""select""sum"
  107.         "set""show""substring""smallint""super""subject"
  108.         "status""slave""session""start""share"
  109.         "straight_join""sql_small_result""sql_big_result"
  110.         "sql_buffer_result""sql_cache""sql_no_cache"
  111.         "sql_calc_found_rows""second""sysdate""sec_to_time"
  112.         "system_user""session_user""substring_index""std"
  113.         "stddev""soundex""space""strcmp""sign""sqrt"
  114.         "sin""straight""sleep""text""truncate""table"
  115.         "tinyint""tables""to_days""temporary""terminated"
  116.         "to""types""time""timestamp""tinytext"
  117.         "tinyblob""transaction""time_format""time_to_sec"
  118.         "trim""trailing""tan""then""update""union"
  119.         "using""unsigned""unlock""usage""use_frm"
  120.         "unix_timestamp""unique""use""user""ucase"
  121.         "upper""uuid""values""varchar""variables"
  122.         "version""variance""varying""where""with"
  123.         "warnings""write""weekday""week""when""xor"
  124.         "year""yearweek""year_month""zerofill");
  125.     $replace=Array();
  126.     foreach($keywords as $keyword) {
  127.         $replace[]='/\b'.$keyword.'\b/ie';
  128.     }
  129.  
  130.     // Выделить служебные слова в тексте запроса
  131.     $tmp=preg_replace($replace,
  132.         '"<b style=\"color:#0000FF\">".strtoupper("$0")."</b>"',$tmp);
  133.  
  134.     // Выделить числовые значения в тексте запроса
  135.     $tmp=preg_replace('/\b([\.0-9]+)\b/',
  136.         '<b style="color:#008000">\1</b>',$tmp);
  137.  
  138.     // Выделить скобки в тексте запроса
  139.     $tmp=preg_replace('/([\(\)])/',
  140.         '<b style="color:#FF0000">\1</b>',$tmp);
  141.  
  142.     // Вернуть обратно строки в кавычках
  143.     if (count($quote_list_text)) {
  144.         $quote_list_text=array_reverse($quote_list_texttrue);
  145.         foreach($quote_list_text as $k=>$i) {
  146.             $tmp=str_replace('<text'.$k.'>',
  147.                 '<span style="color:#777;">'.$i.'</span>'$tmp);
  148.         }
  149.     }
  150.     // Вернуть обратно экранированные символы
  151.     if (count($quote_list_symbols)) {
  152.         $quote_list_symbols=array_reverse($quote_list_symbolstrue);
  153.         foreach($quote_list_symbols as $k=>$i) {
  154.             $tmp=str_replace('<symbol'.$k.'>'$i$tmp);
  155.         }
  156.     }
  157.  
  158.     // Вернуть подсвеченный текст запроса
  159.     // Если не надо расставлять переносы, то уберите nl2br
  160.     return nl2br(trim($tmp));
  161. }
Единственный параметр функции $query - текст исходного запроса. На выходе подсвеченная строка запроса в формате HTML. Цвета подсветки захардкодены в исходнике, если надо, то поменяйте их на свои или вообще замените на определения стилей CSS.

Читать статью целиком »
Просмотров: 4442 | Комментариев: 7

Релевантный поиск по базе MySQL

04.11.2011 | Категория: Web-мастеру и не только | Автор: ManHunter

Релевантный поиск по базе MySQL

Я уже писал о возможностях поиска с учетом морфологии, а теперь обещанная статья о релевантном поиске по базе MySQL. Как разъясняют словари, релевантность - в поисковых системах - мера соответствия результатов поиска задаче поставленной в запросе. То есть чем ближе найденный результат соответствует искомому, тем выше в результатах поиска он должен находиться. Применительно к выборке из базы, в строках результата релевантность должна быть представлена неким числовым значением, по которому эта выборка должна быть отсортирована.

Начнем с теории. Если мы ищем строку из нескольких слов среди нескольких текстов, то наибольшей релевантностью обладает текст, в котором встречается вся эта строка целиком и точно в том виде, как ее задали к поиску. Затем идут тексты, где есть все слова из искомой фразы, но расположенные не по порядку. После них идут тексты, где встречаются только отдельные слова, и, чем меньше слов из фразы, тем ниже релевантность. К тому же слова из заголовка текста должны иметь поисковый вес больше, чем такие же слова из текста.

Читать статью целиком »
Просмотров: 17924 | Комментариев: 13

Как сделать свой сервис коротких ссылок

02.06.2011 | Категория: Web-мастеру и не только | Автор: ManHunter
С ростом популярности социальных сетей типа Twitter, где длина сообщения ограничена, возникла необходимость в специальных сервисах для сокращения длинных ссылок. В результате появилось много сайтов, где вы можете ввести длинную ссылку и вместо нее получить короткую. При переходе по такой ссылке вы сперва попадаете на сайт-редиректор, а уже с него выполняется автоматический переход на нужную ссылку. Я даже встречал такие сокращенные ссылки в печатных изданиях, а не только в интернете. Ничего сложного в реализации такого сервиса нет, и сейчас мы сделаем что-нибудь подобное.

Начинается все с покупки короткого доменного имени. Все красивые имена уже разобраны или захвачены киберсквоттерами, но кое-что еще можно найти. В конце концов, рядовому пользователю нет особой разницы, по красивой ссылке идти или по некрасивой, главное чтобы она помещалась в его сообщение. Хорошо, домен у нас есть, едем дальше.

А дальше нам надо продумать структуру базы данных, в которой будут храниться короткие ссылки и их соответствия. Поскольку мы делаем сейчас самый простейший сервис, то пусть структура базы будет такой:

CREATE TABLE IF NOT EXISTS `redirector_links` (
`link_id` INT(11) NOT NULL AUTO_INCREMENT COMMENT 'ID ссылки в базе',
`link_hash` VARCHAR(32) COMMENT 'Хэш ссылки',
`link_url` TEXT COMMENT 'Адрес ссылки',
PRIMARY KEY (`link_id`),
KEY `link_hash` (`link_hash`)
) ENGINE=MyISAM

Хэш ссылки нужен для того, чтобы не создавать в базе дубли для повторяющихся ссылок. В принципе, сюда же можно добавить счетчик для сбора статистики переходов, добавить принадлежность к какому-нибудь владельцу и т.п. Все зависит от поставленных задач.

Читать статью целиком »
Просмотров: 22376 | Комментариев: 24

Выбор случайной строки из таблицы MySQL

20.04.2011 | Категория: Web-мастеру и не только | Автор: ManHunter
Одна из часто встречающихся задач при создании сайтов - выборка случайной строки из таблицы MySQL. Это может быть случайный баннер в ротации, какая-нибудь "фраза дня" или афоризм, промо-блок на главной странице и т.п. Применений масса. Я решил на практике протестировать несколько вариантов решения этой задачи. Исходные данные: база MySQL, таблица типа MyISAM проиндексирована по полю id, количество записей около 500000, поле id обозначено как PRIMARY KEY, в нумерации есть "дырки" из-за удаленных строк.

Переходим к тестированию. Традиционное решение сводится к такому запросу:

SELECT * FROM `table` ORDER BY RAND() LIMIT 1

Код на PHP для тестирования:
  1. // Тест №1
  2. $query="SELECT * FROM `table` ORDER BY RAND() LIMIT 1";
  3. $sql_result=mysql_query($query);
  4. $row=mysql_fetch_array($sql_result);
  5. mysql_free_result($sql_result);
Результаты не радуют. Среднее время выполнения одного такого запроса на моем компьютере занимает 2.5 секунды. На реальном проекте, особенно если он работает под нагрузкой, такие затраты времени недопустимы.

Читать статью целиком »
Просмотров: 13706 | Комментариев: 9

Ошибка MySQL "Got error 28 from storage engine"

20.05.2010 | Категория: Web-мастеру и не только | Автор: ManHunter
Прихожу на работу, а у меня уже телефон разрывается от звонков. Рабочий сайт компании лежит с загадочной ошибкой MySQL "Got error 28 from storage engine", причем не весь, а выборочно местами и только на некоторых запросах. В официальной документации по MySQL ничего внятного не нашел, но после небольшого расследования и поиска в разных интернетах выяснилось, что такая ошибка возникает из-за нехватки свободного места на диске. На небольших запросах оставшегося места хватало для работы MySQL и возвращался какой-то результат, а на более ресурсоемких появлялась указанная ошибка. Позвонил админам, добавили места, почистили мусор, проблема сразу же решилась. Вот такая загогулина. Может кому-нибудь пригодится.

Просмотров: 14196 | Комментариев: 11

Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2023
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.13 сек. / MySQL: 4 (0.0562 сек.) / Память: 4.75 Mb
Наверх