21
21
CaselessKeyword ,
22
22
DelimitedList ,
23
23
Group ,
24
+ MatchFirst ,
24
25
ParserElement ,
25
26
ParseResults ,
26
27
Suppress ,
57
58
StartsWith ,
58
59
)
59
60
from pyiceberg .expressions .literals import (
61
+ BooleanLiteral ,
60
62
DecimalLiteral ,
61
63
Literal ,
62
64
LongLiteral ,
77
79
NAN = CaselessKeyword ("nan" )
78
80
LIKE = CaselessKeyword ("like" )
79
81
80
- identifier = Word (alphas , alphanums + "_$" ).set_results_name ("identifier" )
82
+ unquoted_identifier = Word (alphas , alphanums + "_$" )
83
+ quoted_identifier = Suppress ('"' ) + unquoted_identifier + Suppress ('"' )
84
+ identifier = MatchFirst ([unquoted_identifier , quoted_identifier ]).set_results_name ("identifier" )
81
85
column = DelimitedList (identifier , delim = "." , combine = False ).set_results_name ("column" )
82
86
83
87
like_regex = r"(?P<valid_wildcard>(?<!\\)%$)|(?P<invalid_wildcard>(?<!\\)%)"
@@ -100,16 +104,18 @@ def _(result: ParseResults) -> Reference:
100
104
string = sgl_quoted_string .set_results_name ("raw_quoted_string" )
101
105
decimal = common .real ().set_results_name ("decimal" )
102
106
integer = common .signed_integer ().set_results_name ("integer" )
103
- literal = Group (string | decimal | integer ).set_results_name ("literal" )
104
- literal_set = Group (DelimitedList (string ) | DelimitedList (decimal ) | DelimitedList (integer )).set_results_name ("literal_set" )
107
+ literal = Group (string | decimal | integer | boolean ).set_results_name ("literal" )
108
+ literal_set = Group (
109
+ DelimitedList (string ) | DelimitedList (decimal ) | DelimitedList (integer ) | DelimitedList (boolean )
110
+ ).set_results_name ("literal_set" )
105
111
106
112
107
113
@boolean .set_parse_action
108
- def _ (result : ParseResults ) -> BooleanExpression :
114
+ def _ (result : ParseResults ) -> Literal [ bool ] :
109
115
if strtobool (result .boolean ):
110
- return AlwaysTrue ( )
116
+ return BooleanLiteral ( True )
111
117
else :
112
- return AlwaysFalse ( )
118
+ return BooleanLiteral ( False )
113
119
114
120
115
121
@string .set_parse_action
@@ -265,14 +271,29 @@ def handle_or(result: ParseResults) -> Or:
265
271
return Or (* result [0 ])
266
272
267
273
268
- boolean_expression = infix_notation (
269
- predicate ,
270
- [
271
- (Suppress (NOT ), 1 , opAssoc .RIGHT , handle_not ),
272
- (Suppress (AND ), 2 , opAssoc .LEFT , handle_and ),
273
- (Suppress (OR ), 2 , opAssoc .LEFT , handle_or ),
274
- ],
275
- ).set_name ("expr" )
274
+ def handle_always_expression (result : ParseResults ) -> BooleanExpression :
275
+ # If the entire result is "true" or "false", return AlwaysTrue or AlwaysFalse
276
+ expr = result [0 ]
277
+ if isinstance (expr , BooleanLiteral ):
278
+ if expr .value :
279
+ return AlwaysTrue ()
280
+ else :
281
+ return AlwaysFalse ()
282
+ return result [0 ]
283
+
284
+
285
+ boolean_expression = (
286
+ infix_notation (
287
+ predicate ,
288
+ [
289
+ (Suppress (NOT ), 1 , opAssoc .RIGHT , handle_not ),
290
+ (Suppress (AND ), 2 , opAssoc .LEFT , handle_and ),
291
+ (Suppress (OR ), 2 , opAssoc .LEFT , handle_or ),
292
+ ],
293
+ )
294
+ .set_name ("expr" )
295
+ .add_parse_action (handle_always_expression )
296
+ )
276
297
277
298
278
299
def parse (expr : str ) -> BooleanExpression :
0 commit comments