Разбор SQL с помощью Python
Вопрос
Я хочу создать интерфейс SQL поверх нереляционного хранилища данных.Нереляционное хранилище данных, но имеет смысл обращаться к данным реляционным способом.
Я рассматриваю возможность использования АНТЛР для создания AST, который представляет SQL как выражение реляционной алгебры.Затем верните данные, оценивая/обходя дерево.
Я никогда раньше не реализовал парсер, и поэтому мне хотелось бы получить совет о том, как лучше всего реализовать синтаксический анализатор и оценщик SQL.
- Подходит ли описанный выше подход?
- Есть ли другие инструменты/библиотеки, на которые мне следует обратить внимание?Нравиться ПЛИ или Пипарсинг.
- Указатели на статьи, книги или исходный код, которые могут мне помочь, приветствуются.
Обновлять:
Я реализовал простой парсер SQL, используя pyparsing.В сочетании с кодом Python, реализующим реляционные операции с моим хранилищем данных, это было довольно просто.
Как я сказал в одном из комментариев, цель упражнения заключалась в том, чтобы сделать данные доступными для систем отчетности.Для этого мне, вероятно, понадобится реализовать драйвер ODBC.Наверное, это большой труд.
Решение
Я довольно подробно изучил этот вопрос.Python-sqlparse — это парсер без проверки, который на самом деле не то, что вам нужно.Примеры в antlr требуют большой работы, чтобы преобразовать их в хороший ast в python.Стандартные программисты sql: здесь, но преобразование их самостоятельно потребовало бы полной занятости, и вполне вероятно, что вам понадобится только их подмножество, т. е. никаких объединений.Вы можете попробовать посмотреть овод (база данных Python sql), но я избегал этого, поскольку они использовали свой собственный инструмент синтаксического анализа.
В моем случае мне понадобилось только предложениеwhere.Я пытался буленео (анализатор логических выражений), написанный с использованием pyparsing, но в конечном итоге использующий pyparsing с нуля.Первая ссылка в сообщении Марка Рушакова на Reddit дает пример использования sql. Свист полнотекстовая поисковая система также использует его, но я не смотрел источник, чтобы узнать, как это сделать.
Pyparsing очень прост в использовании, и вы можете легко настроить его так, чтобы он не был точно таким же, как sql (большая часть синтаксиса вам не понадобится).Мне не понравился ply, поскольку в нем используется некоторая магия, связанная с соглашениями об именах.
Короче говоря, попробуйте pyparsing, он, скорее всего, будет достаточно мощным, чтобы делать то, что вам нужно, а простая интеграция с Python (с простыми обратными вызовами и обработкой ошибок) сделает работу довольно безболезненной.
Другие советы
Этот пост на Reddit предполагает Python-sqlparse как существующая реализация, среди пары других ссылок.
Python SQL Parser от TwoLaid очень хорошо подходит для моих целей.Он написан на C и требует компиляции.Он прочный.Он анализирует отдельные элементы каждого предложения.
https://github.com/TwoLaid/python-sqlparser
Я использую его для анализа имен столбцов запросов для использования в заголовках отчета.Вот пример.
import sqlparser
def get_query_columns(sql):
'''Return a list of column headers from given sqls select clause'''
columns = []
parser = sqlparser.Parser()
# Parser does not like new lines
sql2 = sql.replace('\n', ' ')
# Check for syntax errors
if parser.check_syntax(sql2) != 0:
raise Exception('get_query_columns: SQL invalid.')
stmt = parser.get_statement(0)
root = stmt.get_root()
qcolumns = root.__dict__['resultColumnList']
for qcolumn in qcolumns.list:
if qcolumn.aliasClause:
alias = qcolumn.aliasClause.get_text()
columns.append(alias)
else:
name = qcolumn.get_text()
name = name.split('.')[-1] # remove table alias
columns.append(name)
return columns
sql = '''
SELECT
a.a,
replace(coalesce(a.b, 'x'), 'x', 'y') as jim,
a.bla as sally -- some comment
FROM
table_a as a
WHERE
c > 20
'''
print get_query_columns(sql)
# output: ['a', 'jim', 'sally']
Конечно, лучше всего использовать python-sqlparse в Google Code
ОБНОВЛЯТЬ:Теперь я вижу, что это было предложено - я согласен, что это того стоит: