парсер для SQL

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
В продолжение темы про Query Builder

Нужен парсер для запросов SQL.

В той теме AmdY уже посоветовал https://code.google.com/p/php-sql-parser/ и парсер DQL из Doctrine. Кроме него есть ещё PEAR'овский SQL_Parser, который за 10 лет так до конца и не был дописан. Остальные результаты поиска в интернетах выдают в основном форки SQL_Parser'а разной степени перепиленности.

Из перечисленного наиболее прилично выглядит парсер DQL, переработать под SQL его в принципе можно. Но вдруг кто знает проект ещё лучше?
 

Тугай

Новичок
Последнее редактирование:

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Если писать свой, то тут ссылка
чел советует транслировать в xml, для дальнейшей работы.
ой.

Хотя самому писать и тестить граматику, может и не лучше того что есть уже готовое.
вот да, у меня есть подозрение, что трудозатраты на отладку грамматики будут сравнимы с написанием своего парсера методом рекурсивного спуска (не с нуля, а по мотивам парсера DQL).

К тому же похапэшные парсеры все застыли в разных степенях недоделанности:
http://www.antlr3.org/pipermail/antlr-interest/2011-September/042627.html
http://pear.php.net/package/PHP_ParserGenerator
http://pear.php.net/package/PHP_LexerGenerator


Спасибо, этого раньше не видел. Надо погонять, он вроде позволяет делать, что мне нужно (т.е. разбирать "куски" выражения).
 

Фанат

oncle terrible
Команда форума
А точно ли он нужен?
Все-таки, тема скользкая.
Любой парсер знает о своем диалекте SQL ровно столько, сколько знает его автор.
И обычно эти множества не слишком-то и пересекаются.
 

hell0w0rd

Продвинутый новичок
А что на счет попробовать выдрать из субд парсер и сделать расширение?) или из области фантастики?
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
А точно ли он нужен?
Все-таки, тема скользкая.
Любой парсер знает о своем диалекте SQL ровно столько, сколько знает его автор.
Но всё-таки существенно больше, чем модуль preg, ага.

И обычно эти множества не слишком-то и пересекаются.
Я чё-то потерял нить --- какие "эти множества"?

А что на счет попробовать выдрать из субд парсер и сделать расширение?) или из области фантастики?
У меня есть некие сомнения, что это будет проще, чем написать свой на PHP. Тем более, что нужна поддержка только SELECT / INSERT / UPDATE / DELETE.

http://git.postgresql.org/gitweb/?p=postgresql.git;a=tree;f=src/backend/parser;hb=HEAD
 

Фанат

oncle terrible
Команда форума
Синтаксис диалекта SQL и синтаксис, о котором знает парсер.
Обычно да, все останавливается на запросах SELECT / INSERT / UPDATE / DELETE. причем в самом примитивном формате.
И спотыкается на всем остальном. Скажем, DELETE с джойном.

Зачем-то авторы парсеров и билдеров упираются в синтаксис, при том что он-то всегда константный.
Поддержкой же динамических элементов занимаются в десятую очередь
При том что если сделать нормальную поддержку добавления динамических элементов в запрос, никакой парсер и не понадобится.
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
При том что если сделать нормальную поддержку добавления динамических элементов в запрос, никакой парсер и не понадобится.
Ну так а как в готовый запрос добавить, например, дополнительный элемент во FROM?
С парсером понятно, берём синтаксическое дерево, впихиваем новую ветку. А без него --- регулярными выражениями?
 

hell0w0rd

Продвинутый новичок
А вот такой вопрос, зачем вообще нужен парсер? Почему не написать удобный билдер?
 

Фанат

oncle terrible
Команда форума
Ой, не знаааю...
Ты точно имел в виду FROM? Это совсем другой запрос, вообще-то, получится.

Боюсь, такой парсер до сих пор не сделали не потому, что лень, а потому что слишком много нюансов.
И желающие впихнуть новую ветку идут другим путем - креви билдером. Изначально имея дерево, и только в финале получая из него строку запроса.
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
А вот такой вопрос, зачем вообще нужен парсер? Почему не написать удобный билдер?
С моей точки зрения "удобным билдером" будет такой, который позволит вставлять готовые куски запроса.

Большие и страшные запросы просто часто приходится писать-отлаживать по частям. И хотелось бы такую часть тупо пихнуть в строку, а не переводить на язык, понятный "удобному билдеру". Этим переводом и будет заниматься парсер --- у компьютера голова железная, пусть он ей и думает.

Ой, не знаааю...
Ты точно имел в виду FROM? Это совсем другой запрос, вообще-то, получится.
Ну это смотря что считать другим, пусть у нас будет
Код:
select foo.* from foo;
а при сборке запроса нужно выбрать записи по критерию bar.baz в связанной таблице, и получим мы либо
Код:
select foo.* 
from foo, bar 
where foo.bar_id = bar.id and 
      bar.baz = ?;
либо
Код:
select foo.*
from foo
where foo.bar_id in (
       select id
       from bar
       where baz = ?
      );
Боюсь, такой парсер до сих пор не сделали не потому, что лень, а потому что слишком много нюансов.
И желающие впихнуть новую ветку идут другим путем - креви билдером. Изначально имея дерево, и только в финале получая из него строку запроса.
Ну я в первом же сообщении упомянул Доктрину, где из запроса на SQL-подобном языке DQL строится AST, а из AST строится уже запрос на SQL. Правда, насколько я понимаю, над деревом надругаться там не дают, но тут уже вопрос доработки.
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Sad Spirit
А зачем тогда вообще билдер?)
Собирать запрос из кусков при помощи только оператора '.' и функции str_replace() не всегда удобно потому что.
Твои вопросы утомлять начинают, кстати.
 

Absinthe

жожо
С моей точки зрения "удобным билдером" будет такой, который позволит вставлять готовые куски запроса.
Не согласен.
В простой запрос куски вставлять не нужно - можно обойтись методами билдера.
Для сложных запросов билдеры непригодны (представьте себе, как будет выглядеть билдер для сложного запроса из десятков/сотен строк с множетсвом подзапросов и множеством связей между этими подзапросами).
 

С.

Продвинутый новичок
Все идет к тому, что составление запроса будет стоить дороже его исполнения.
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Для сложных запросов билдеры непригодны (представьте себе, как будет выглядеть билдер для сложного запроса из десятков/сотен строк с множетсвом подзапросов и множеством связей между этими подзапросами).
У меня оно щас выглядит как большой метод с кучей if'ов, который принимает на вход среди прочего ассоциативный массив с ключами в виде названий кусков, которые надо вставить в запрос. Куски оформлены как строки. Собираются при этом угрёбища на несколько десятков строк и десяток используемых таблиц.

Это всё чрезвычайно неудобно --- нет подсказок в IDE, нет проверок на разумность, кроме написанных руками... Я хочу нечто такое же, но с нормальным API, с возможностью интроспекции типа "а участвует ли у нас уже в запросе таблица foo / алиас foo?" / "а есть ли у нас уже именованный параметр :blah?"

Все идет к тому, что составление запроса будет стоить дороже его исполнения.
Первоначальный разбор шаблона шаблонизатором тоже вполне может быть дольше типичного вывода этого самого шаблона.

Плюс, DQL'ем ведь кто-то пользуется --- не просто же так они написали эти немереные тыщи строк. :]
 

С.

Продвинутый новичок
Первоначальный разбор шаблона шаблонизатором тоже вполне может быть дольше типичного вывода этого самого шаблона.
Но-но, не надо тут широкими жестами риторически сравнивать вывод данных и выборку данных из базы.
 

Absinthe

жожо
Плюс, DQL'ем ведь кто-то пользуется --- не просто же так они написали эти немереные тыщи строк. :]
Для сложных запросов обычно так происходит: $this->entityManager->getConnection()->executeQuery($query);
Без DQL, так как результатом сложных запросов навряд ли будут сущности :)
 

Вурдалак

Продвинутый новичок
Но-но, не надо тут широкими жестами риторически сравнивать вывод данных и выборку данных из базы.
DQL как раз-таки кешируется, как и шаблоны.
http://docs.doctrine-project.org/en/latest/reference/caching.html#query-cache

Все идет к тому, что составление запроса будет стоить дороже его исполнения.
Составление запроса — константа времени, а выполнение уже зависит от многих вещей. Ну да, медленней немного, меньше запросов в секунду один backend держит. И что?
 
Последнее редактирование:

WMix

герр M:)ller
Партнер клуба
поговаривают, что порою два простых запроса работают быстрее чем один сложный.
 
Сверху