我打算为我的视图/业务层提供将字符串中的HQL查询发送到我的数据层的可能性。
但是,数据层需要分析和操作这些查询(特别是在where子句中添加一个标准)。
支持的HQL查询形式是以下任意组合:
from ...
where ...
order by ...
我认为这种简化的HQL查询应该是regex-able,这是我定义的正则表达式:
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);
更新:我甚至尝试过使用非贪婪的修饰符:
public const string HqlRegex = @"^(\bfrom\b\s*(?<FromPart>.+?)\s*)?"
+ @"(\bwhere\b\s*(?<WherePart>.+?)\s*)?"
+ @"(\border\b\s+\bby\b\s*(?<OrderByPart>.+?))?$";
但是,当我尝试匹配包含where 和 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。名称不像'%X')和e.StatusID不在(7,8,9)的顺序中由e.DateCreated desc
赞赏以下任何帮助:
答案 0 :(得分:2)
HQL没有正则表达式,因为HQL不是常规语言。
要快速解决问题,您可以为每个?
使用non-greedy modifier .+
:
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执行此操作,那么您可以查看文章Working with ANTLR: HQL Grammar。
答案 1 :(得分:1)
我不确定正则表达式是最好的工具。我宁愿尝试ANTLR并定义一个小语法来解析你的HQL-lite查询。
答案 2 :(得分:1)
我不会尝试将Regex用于像HQL这样复杂的任何东西,因为HQL不是常规语言。
请参阅When not to use Regex in C# (or Java, C++, etc.)
正如您可以控制两端,我会考虑将您的查询表示为对象树,然后将其转换为xml或json。这样你就不必自己编写任何字符串解析代码了。
否则,有人必须为HQL查询编写解析器,查看使用HQL的任何开源项目的源代码。