pyparsing 可选子字段

1 投票
1 回答
504 浏览
提问于 2025-04-16 23:25

这是关于pyparsing,每个结果的名称的继续讨论。我在使用pyparsing时取得了很好的进展,但在解析SQL的排序子句时遇到了麻烦。问题是,任何字段都可以设置为升序或降序。

所以,一个SQL查询可能看起来像这样:

SELECT a FROM x WHERE a = b ...
ORDER BY c, d
ORDER BY c asc, d
ORDER BY c asc, d desc
ORDER BY c, d asc

我一直在摸索,最终想到的最好办法是:

order_dir = oneOf('asc desc', caseless=True)
...
Optional( CaselessKeyword('order by') + columnNameList('order') + Optional(order_dir)('order_dir'))
...

对于像ORDER BY c asc, d desc这样的情况,这个匹配表示c是我首先排序的字段,而asc是我的排序方向,但没有处理到d

我希望输出能像['c asc', 'd desc']这样,只要我还能把columnNameList放进去就行。

有没有办法用pyparsing来处理这个?我的问题是不是不够清楚?

1 个回答

1

每个排序的列都有一个列名,和一个可选的排序方向。你可以有多个列,用逗号分开。要把每个列名和排序方向配对在一起,这样它们就不会分开。用逗号分开的东西很适合用pyparsing的delimitedList来处理。

试着把你的条件改成:

Optional( CaselessKeyword('order by') + 
        delimitedList(Group(columnNameList('order') + 
                            Optional(order_dir, default="asc")('order_dir')))('orderByColumns')
        )

这样你会得到一个名为'orderByColumns'的字段,里面包含了一系列的配对。即使你没有写asc(升序)或desc(降序),Optional类的默认设置会自动插入'asc'。你可以这样理解这些列:

if result.orderByColumns:
    for ocol in result.orderByColumns:
        print "Order by %(order)s (%(order_dir)s)" % ocol

(所有内容未经测试)

撰写回答