我坚持这一点:我采用了bauble (a program on github)并且部分是用来指定sql数据库上的查询。查询语言实际上是三种不同的语言,其中一种(像SQL查询中的过滤)我正在重写。
最初的作者选择了pyparsing,我没有理由回顾这个选择,除了我不知道pyparsing,我一直在与lex和yacc一起玩得很开心。。。但我决定继续解析,所以我在学习它。
我已经(重新)编写了一个解析器,它识别给定的查询,并且大多数语法类别都转换为类。我认为解析部分很好,我卡住的地方是,我用pyparsing创建的对象需要使用SQLAlchemy查询数据库,特别是当我基于连接表的属性进行筛选时。
语法的相关部分,以pyparsing格式:
query_expression = Forward()
identifier = Group(delimitedList(Word(alphas, alphanums+'_'),
'.')).setParseAction(IdentifierToken)
ident_expression = (
Group(identifier + binop + value).setParseAction(IdentExpressionToken)
| (
Literal('(') + query_expression + Literal(')')
).setParseAction(ParenthesisedQuery))
query_expression << infixNotation(
ident_expression,
[ (NOT_, 1, opAssoc.RIGHT, SearchNotAction),
(AND_, 2, opAssoc.LEFT, SearchAndAction),
(OR_, 2, opAssoc.LEFT, SearchOrAction) ] )
而最后两个类的对应类(前两个类的^{{cd1>}方法是我还不知道如何编写的):
^{pr2}$以上代码段的完整和最新代码是here。
几个可能的查询:
^{pr3}$
我想我找到了一个暂时可以接受的答案,但是它使用了SQLAlchemy的内部信息(一个带下划线前缀的字段)。在
问题的核心是,由于我处理的是来自用户的解析信息,所以我从一个类的名称和要导航的关系的名称开始。例如在
plant where accession.species.id=44
中,类名是Plant
,我正在对连接的Species
对象的id
进行过滤。在上面的例子可能会让人觉得事情很简单,只是一个资本化问题。但是我们仍然需要知道}在哪个模块中被找到。在
Plant
,Accession
,和{另一个例子:
family where genera.id!=0
。一般来说,关系的名称不必等于所引用的类的名称。在语法没问题,我不需要再改了。问题是(而且部分仍然是)在与SQLAlchemy的交互中,所以我不得不更正}类中的
IdentifierToken
和{evaluate
方法。在我的解决方案包括以下代码:
一些要点:
_joinpoint
,它看起来像是未公开的信息。在query._joinpoint['_joinpoint_entity']
是对类的引用,我需要从中检索解析查询中命名的字段。_joinpoint
字典在非别名查询上看起来不同。这个问题仍然悬而未决的部分是,是否有一种“官方的”SQLAlchemy方法来检索这些信息。
以前的开发人员似乎在创建这些类时费了很大的劲——这实际上是使用pyparsing时的“最佳实践”。其目的是,这些类作为解析过程的输出,通常使用已解析的元素来支持它们自己的一些行为。在本例中,还可以通过名称访问元素(另一个pyparsing“最佳实践”)。一旦这些类在解析过程中被构造出来,pyparsing就不可能了——任何进一步的处理都纯粹是这些类的函数。在
我想我们的目标很可能和你假设的一样,在这些类上有一个方法,比如
results.statement.invoke()
。看看这些类上的方法,看看它们为您提供了什么,特别是顶级StatementAction类。如果没有这样的方法,那么这可能是下一步,您将以对SQLAlchemy数据库包装有意义的方式应用解析的值。在相关问题 更多 >
编程相关推荐