Comments 35
Может я чего подзабыл, но разве зависимости для хранимок не лежат где-то в системных таблицах?
конкретные связи между таблицами по полям
Для того, чтобы убедиться, что процедура все еще валидна после переименования или удаления колонки, нужно знать не только таблицы, но и колонки (а также и их типы). Ну т.е. я реально не помню, но кажется мне отчего-то, что должно это где-то быть.
Это впрочем не делает примененный способ менее полезным. Я сам так делал совсем недавно, правда, на примере VBA — т.е. парсил код, и искал зависимости между процедурами и функциями.
Listener тоже так используется(а может использовался). Я ж говорю, подзабыл, сам видел в исходниках NetBeans. Обязательно рассмотрю реализацию в NetBeans. Надеюсь статья не последняя.
Писал аналогичный скрипт для PL/SQL на Python. Подскажите, как решались проблемы с:
1) Сложными конструкциями в блоках select и for
2) Устаревшим синтаксисом в стандартном наборе ANTRL
достаточно просто повнимательнее взглянуть на грамматику — там иерархия выражений. Если не хватает чего-то в грамматике, то надо дописать в ней. Обрабатываем только нужные нам узлы. Методы именуются так же как выражения в грамматике + префикс «Enter» в начале.
Проще самому потестировать этот код и поудалять мешающие return.
Чтобы обход дерева был более наглядным можно вставлять в методы код обхода дочерних узлов
for (ii = 0; ii < ctx.ChildCount; ++ii)
{
Console.WriteLine("ii=" + ii.ToString());
Console.WriteLine(ctx.GetChild(ii).GetType().ToString());
Console.WriteLine(ctx.GetChild(ii).GetText());
}
Эх, бедный антлер, как только над ним не изгаляются: antl, ANTRL, ATNLR =)
Ну а так вообще конечно лучше новую книгу читать The Definitive ANTLR 4 Reference. В четвертой версии ANTLR появилось несколько фундамельных изменений (полноценный LL парсинг, поддержка левой рекурсии). Хотя даже с 2013 года в ANTLR 4 много нововведений и рантаймов, доступно в списке релизов.
1) Сложными конструкциями в блоках select и for
Что вы имеете в виду, можно пример? Можно использовать дополнителный стек для контроля вложенности конструкций.
2) Устаревшим синтаксисом в стандартном наборе ANTRL
Опять-таки, что за устаревший синтаксис в стандартном наборе? Грамматика PL/SQL в репозитории сейчас актуальная.
2) Синтаксис Oracle SQL, PL/SQL в стандартном наборе действительно стал значительно лучше в последнее время. Только я не вижу некоторых новых конструкции из Oracle 12c (навскидку WITH_PLSQL, MATCH_RECOGNIZE). А между прочим расширенная поддержка 11g заканчивается уже в этом месяце.
Я вообще к чему это всё, инструмент — рабочий, общую картину увидеть позволяет. Но к сожалению от 10% до 30% связей мы не увидим. Частично из-за старой граматики (это как раз исправимо, пиши граматику сам), а вот проблема с динамическим кодом неразрешима.
В итоге получается, что инструменту на 100% доверять нельзя и всё-равно приходится посмотривать весь код глазами. Поиграться — да, надёжный инструмент — нет.
У Информатики даже продукт готовый есть за много тысяч долларов — Metadata Manager, увы, с той же степенью надёжности.
В случае с Oracle, если код в хранимых процедурах, то гораздо проще пользоваться таблицей ALL_DEPENDENCIES (пролема с динамикой остаётся). Если код в SVN, то только ANTRL.
«жалко, что молоток сам не выпрямляет гнутые гвозди», но молоток не был для этого предназначен. Инструмент на 100% рабочий. То что нужно детерминировать процедуры с динамическим кодом(которого думаю небольшой процент) и поставить заглушки и получить статический код и обработать его отдельно, я не вижу проблемы. Грамматику дописать? Конечно, и тут надо поработать, изучить как пишутся правила и т.д. Но, елки, ты ж программист.
Удачи.
Только я не вижу некоторых новых конструкции из Oracle 12c (навскидку WITH_PLSQL, MATCH_RECOGNIZE). А между прочим расширенная поддержка 11g заканчивается уже в этом месяце.
Можете создать issue на GitHub — рассмотрим. А в идеале вообще Pull Request.
Частично из-за старой граматики (это как раз исправимо, пиши граматику сам), а вот проблема с динамическим кодом неразрешима.
Ну да, это не проблема грамматики — нужно проводить дальнейшие действия над деревом разбора, возможно абстрактно интерпретировать.
Точнее сказать ограничить грамматику Java рантаймом.
Не поддерживаются в ANTLR вставки кода на универсальном языке, смотри мою issue Unified Actions Language. С другой стороны, уменьшать возможности грамматики из-за вырезания всех вставок кода я не хочу. Просто измените фрагменты кода Java на Python — это несложно.
Однако есть другой подход, который подходит к существующей версией ANTLR, смотри грамматику JavaScript. Однако в нем есть свои недостати: он громоздкий в реализации, да и не уверен, что применим к Python без доработки (поддерживаются C# и Java).
mathhelpplanet.com
CaseChangingCharStream.cs на github
Program.cs:
...
//string text = System.IO.File.ReadAllText(@"c:\dev\antlr4\grammars-v4-master\tsql\examples\dml_select.sql");
//StringReader reader = new StringReader(text);
//// В качестве входного потока символов устанавливаем ...
//AntlrInputStream input = new AntlrInputStream(reader);
// Настраиваем лексер на этот поток
TSqlLexer lexer = new TSqlLexer(new CaseChangingCharStream(new AntlrFileStream(@"c:\dev\antlr4\grammars-v4-master\tsql\examples\dml_select1.sql"), true));//(input);
...
Спасибо тов. KvanTTT
Проблема: в гитхабе antlr4 лежат два файла: TSQLLexer.g4, TSQLParser.g4.
Я попробовал скомпилировать оба, но лексер прошел, а парсер дал массу ошибок типа
error(126): TSqlParser.g4:4030:48: cannot create implicit token for string literal in non-combined grammar: '^='
error(126): TSqlParser.g4:4030:55: cannot create implicit token for string literal in non-combined grammar: '|='
error(126): TSqlParser.g4:4034:35: cannot create implicit token for string literal in non-combined grammar: '%'
...
В статье, кстати, рассматривается грамматика TSQL.g4, видимо, в этом дело.
Но такого файла на гитхабе не нашел.
Нашел по ссылке в статье, прмер настроил. Кстати, в гугле группе пример отличается, здесь рабочий, там, похоже, требует коррекции.
Все правильно в репозитории. Похоже на то, что лексер вы все же не сгенерировали — ругается на неопределенные токены. Не могли бы показать команды, с помощью которых сгенерировали все?
groups.google.com/forum/#!msg/antlr-discussion/avO91b8J2JE/iWuwBQ96AAAJ
Вот так генерировал, причем для лексера все прошло без ошибок.
java org.antlr.v4.Tool -visitor -Dlanguage=CSharp "%1\TSqlLexer.g4" -o "%1\TSQLLexer"
java org.antlr.v4.Tool -visitor -Dlanguage=CSharp "%1\TSqlParser.g4" -o "%1\TSQLParser"
Я могу тестовое приложение завернуть и выложить.
Кажется понял — генерация должна быть в одной папке, в которой создается файл .tokens
при генерации лексера и который используется при генерации парсера. Т.е. значение параметра -o
должно быть одинаковым в обоих случаях.
public override void EnterTable_source_item_joined([NotNull] tsqlParser.Table_source_item_joinedContext ctx)
{
if ((mode == JoinMode.Undefined & ctx.ChildCount == 1) || (mode == JoinMode.Where))
Да, скорее всего логическое и &&
— так и скобки лишние не нужны.
Есть неплохой цикл статей на эту тему: https://ruslanspivak.com/lsbasi-part1/
В примере — только запросы. В чем же суть и как парсить хранимые процедуры? Что должно быть входом (sp?) и выходом?
Не совсем понятно, какая задача изначально решается. Скорей всего, поиск процедур, использующих таблицу или поиск таблиц, используемых в процедуре.
Через t-sql это можно получить одним запросом, см. sys.objects, object_definition, sys.sql_expression_dependencies.
Парсим с помощью ANTLR 4 хранимки T-SQL для получения связей между таблицами