Skip to content

Alexeyyy/SQL-Parser

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SQL-Parser

Парсер, который позволяет "разобрать" SQL запрос вида SELECT по "полочкам".

Например, вот такие запросы (несовсем логичные примеры с точки зрения смысла, но синтаксически верные --> значит имеют место быть):

Запрос 1

select     f.*,           (select     sum   (           a.flight_id)from flights              as a group by a.flight_id) as s         from flights as f
    join           aircrafts   as air on ((((air.aircraft_code) = f.aircraft_code)) and air.aircraft_code = f.aircraft_code) or (1=1 and 1=1 or (((2 >   3 and 4< 2 or 3!=3 and 2< 1))))
    full       outer   join   aircrafts_data as ad on ad.aircraft_code = air.aircraft_code
    left  join          airports_data     as    apd on    apd.airport_code = f.aircraft_code and apd.airport_code =      (select ap.airport_code from airports   as   ap   where   (select     1 as   column) = 1   limit  1   )
where   f.flight_no =   'a'    and   ((f.aircraft_code = 'asd' or    f.aircraft_code    = '5454'    ) and      f.aircraft_code = '2332' or (select count(*)   + (select count(*)    from flights) from tickets)     > 10)
order  by f.aircraft_code,    f.flight_no, (select max(airports.airport_code) from airports limit 10) asc
limit  ( select    count(*)     from        airports    )

Запрос 2

SeLeCt "f1".flight_id
fRoM flights as "f1"
    inner join flights as f_2 on "f1".aircraft_code = f_2.aircraft_code
where "f1".flight_id between 10 and 100 and f_2.flight_id not in (1,2,3,4,5,6,7, (select 1), (select (select 2)))
group by "f1".flight_id
order by "f1".flight_id DESC
limit ((select count(*) alias_1 from flights limit all) + (select count(*) + 1 alias_2 from flights limit null))
offset (select 8)

Запрос 3

select (select (select (select (select (select (select (select (select (select 1 a)b)c)d)e)f)g)h)i)k

P.S. схема и данные PG-базы взяты с сайта PostgresPro, за что им отдельное Спасибо!

Как работает парсер?

Если не вдаваться в подробности, то парсер работает по следующему алгоритму:

  • На вход получает набор запросов, которые необходимо "распарсить". Вот пример тестового файла.
  • "Нормирует" строку запроса с точки зрения удаления лишних пробелов
  • Находит все подзапросы и составляет "дерево вложенности". Для i-го запроса все видимые подзапросы маркируются guid-ами
  • Раскладывает запрос и все его подзапросы по ключевым словам - clauses, ими являются select, from, join, where, order by, group by, having, limit, offset
  • Парсит каждый из запросов в отдельности и сохраняет данные в виде списков
  • Печатает информацию в виде таблиц в файл. Пример выходных данных программы-парсера

Дополнительно был реализован функционал восстановления запроса – обратная операция, чтобы была возможность протестировать правильность раскладки частей запроса парсером.

P.S.

В парсер не встроена проверка на синтаксическую правильность SQL (компилятора тут нет =) ), поэтому пожалуйста подавайте запрос, который компилируется утилитой psql или какой-нибудь средой, например, DataGrip.

P.P.S.

Недостатком парсера является то, что он не поддерживает алиасы в виде ключевых слов SQL (могут быть интересные последствия), например:

SELECT 10 AS JOIN

About

Парсер для SELECT-запросов

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages