Regex для упрощенного синтаксиса HQL - PullRequest
1 голос
/ 09 сентября 2010

Я намеревался предоставить своему представлению / бизнес-уровню возможность отправлять HQL-запросы в виде строк на мой уровень данных.

Однако уровень данных должен анализировать эти запросы и манипулировать ими (в частности, добавитькритерий в предложении where).

Поддерживаемые формы запросов HQL представляют собой любую комбинацию из следующего:

from ...
where ...
order by ...

Я думаю, что этот вид упрощенного запроса HQL должен поддерживать регулярные выражения, иэто Regex, который я определил:

public const string HqlRegex = @"^(\bfrom\b\s*(?<FromPart>.+)\s*)?"
    + @"(\bwhere\b\s*(?<WherePart>.+)\s*)?"
    + @"(\border\b\s+\bby\b\s*(?<OrderByPart>.+))?$";

Regex re = new Regex(Novartis.MapAdmeBs.NHibernateDAO.DAOFactory.HqlRegex,
    RegexOptions.Singleline);

Обновление: Я даже пытался с модификатором non-жадный:

public const string HqlRegex = @"^(\bfrom\b\s*(?<FromPart>.+?)\s*)?"
    + @"(\bwhere\b\s*(?<WherePart>.+?)\s*)?"
    + @"(\border\b\s+\bby\b\s*(?<OrderByPart>.+?))?$";

Однако, когда я пытаюсьдля сопоставления строки, содержащей где и предложение order by, ключевое слово order by рассматривается как часть предложения where:

Match m = re.Match("where (e.Name not like '%X') and e.StatusID not in (7, 8, 9)"
                 + " order by e.DateCreated desc");
Console.WriteLine(m.Groups["WherePart"].Value);

дает

(e.Name не похож на '% X') и e.StatusID не в (7, 8, 9) порядке по e.DateCreated desc

Любая из следующих справок приветствуется:

  • Как исправить регулярное выражение?
  • Существует ли регулярное выражение для HQL?(Поиск в Google приводит к regexp-функциям языка HQL)
  • Лучшая идея, которую все еще достаточно просто реализовать за день или меньше?

Ответы [ 3 ]

2 голосов
/ 09 сентября 2010

Регулярного выражения для HQL нет, потому что HQL не является регулярным языком.

Чтобы быстро исправить, вы можете использовать не жадный модификатор ? для каждого .+:

string hqlRegex = @"^(\bfrom\b\s*(?<FromPart>.+?)\s*)?"
    + @"(\bwhere\b\s*(?<WherePart>.+?)\s*)?"
    + @"(\border\b\s+\bby\b\s*(?<OrderByPart>.+?))?$";

Regex re = new Regex(hqlRegex);
Match m = re.Match("where (e.Name not like '%X') and e.StatusID not in (7, 8, 9)"
         + " order by e.DateCreated desc");
string wherePart = m.Groups["WherePart"].Value;
Console.WriteLine(wherePart);

Результат:

(e.Name not like '%X') and e.StatusID not in (7, 8, 9)

Я также хотел бы отметить, что бессмысленно включать границу слова в, например, order\b\s+\bby. Всегда должна быть граница слова между r и символом пробела, поэтому нет необходимости указывать его.

Если вы хотите сделать это с ANTLR, вы можете посмотреть статью Работа с ANTLR: HQL Grammar .

1 голос
/ 09 сентября 2010

Я бы не стал использовать Regex для чего-либо столь сложного, как HQL, потому что HQL не является обычным языком.

См. Когда не использовать Regex в C # (или Java, C ++ и т. Д.)

Поскольку вы можете контролировать оба конца, я бы рассмотрел представление вашего запроса в виде дерева объектов, которое вы затем конвертируете в / из XML или JSON.Таким образом, вам не придется самостоятельно писать код для разбора строк.

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

1 голос
/ 09 сентября 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...