@@ -274,13 +274,14 @@ class ClauseProperties:
274274
275275@dataclass
276276class Statement :
277- clauses : list [Clause ] = field (default_factory = list )
277+ clauses : list [Clause | ClauseGroup ] = field (default_factory = list )
278278 parent : ExpressionGroup | Function | Group | None = None
279+ separator : str = ""
279280
280281
281282@dataclass
282283class Clause :
283- parent : Statement
284+ parent : ClauseGroup | Statement
284285 properties : ClauseProperties
285286 text : str
286287 expressions : list [Expression ] = field (init = False )
@@ -290,6 +291,12 @@ def __post_init__(self) -> None:
290291 self .expressions = [Expression (self )]
291292
292293
294+ @dataclass
295+ class ClauseGroup :
296+ parent : Statement
297+ clauses : list [Clause ] = field (default_factory = list )
298+
299+
293300@dataclass
294301class Expression :
295302 parent : Clause | ExpressionGroup
@@ -351,7 +358,7 @@ class Operator:
351358
352359
353360type ParentNode = Clause | Expression | ExpressionGroup | Function | Group
354- type Node = ParentNode | Literal | Statement
361+ type Node = ParentNode | ClauseGroup | Literal | Statement
355362type Element = Node | Operator | Part | Placeholder
356363
357364
@@ -387,7 +394,7 @@ def _parse_placeholder(
387394) -> None :
388395 if isinstance (current_node , (Expression , Function , Group , Literal )):
389396 parent = current_node
390- elif isinstance (current_node , Statement ):
397+ elif isinstance (current_node , ( Statement , ClauseGroup ) ):
391398 raise ValueError ("Invalid syntax" )
392399 else : # Clause | ExpressionGroup
393400 parent = current_node .expressions [- 1 ]
@@ -461,7 +468,7 @@ def _parse_string(
461468 current_node , consumed = _parse_token (
462469 current_node , raw_current_token , current_token , tokens [index :], statements
463470 )
464- else : # Statement
471+ else : # ClauseGroup | Statement
465472 current_node , consumed = _parse_token (
466473 current_node , raw_current_token , current_token , tokens [index :], statements
467474 )
@@ -472,7 +479,7 @@ def _parse_string(
472479
473480
474481def _parse_token (
475- current_node : ParentNode | Statement ,
482+ current_node : ParentNode | ClauseGroup | Statement ,
476483 raw_current_token : str ,
477484 current_token : str ,
478485 tokens : list [str ],
@@ -482,8 +489,17 @@ def _parse_token(
482489 return _parse_clause (current_node , tokens )
483490 elif current_token == ";" :
484491 statements .append (Statement ())
492+ statements [- 1 ].separator = ";"
485493 return statements [- 1 ], 1
486- elif not isinstance (current_node , Statement ):
494+ elif current_token == "union" :
495+ statements .append (Statement ())
496+ statements [- 1 ].separator = raw_current_token
497+ consumed = 1
498+ if tokens [1 ].lower () == "all" :
499+ statements [- 1 ].separator += f" { tokens [1 ]} "
500+ consumed = 2
501+ return statements [- 1 ], consumed
502+ elif not isinstance (current_node , (ClauseGroup , Statement )):
487503 if current_token in OPERATORS :
488504 return _parse_operator (current_node , tokens )
489505 elif current_token == "'" :
@@ -494,17 +510,21 @@ def _parse_token(
494510 return _parse_function (current_node , raw_current_token [:- 1 ])
495511 elif current_token == ")" :
496512 current_node = _find_node ( # type: ignore[assignment]
497- current_node , (ExpressionGroup , Function , Group )
513+ current_node , (ExpressionGroup , Function , Group , ClauseGroup )
498514 )
499515 return current_node .parent , 1
500516 else :
501517 return _parse_part (current_node , raw_current_token )
518+ elif isinstance (current_node , Statement ) and current_token == "(" :
519+ statement_group = ClauseGroup (current_node )
520+ current_node .clauses .append (statement_group )
521+ return statement_group , 1
502522 else :
503523 raise ValueError ("Invalid syntax" )
504524
505525
506526def _parse_clause (
507- current_node : ParentNode | Statement ,
527+ current_node : ParentNode | ClauseGroup | Statement ,
508528 tokens : list [str ],
509529) -> tuple [Clause , int ]:
510530 index = 0
@@ -523,16 +543,16 @@ def _parse_clause(
523543 statement = Statement (parent = current_node )
524544 current_node .expressions [- 1 ].parts .append (statement )
525545 current_node = statement
526- else : # Clause | Expression | Statement
527- current_node = _find_node (current_node , Statement )
546+ else : # Clause | Expression | Statement | ClauseGroup
547+ current_node = _find_node (current_node , ( Statement , ClauseGroup )) # type: ignore[assignment] # noqa: E501
528548
529549 clause_properties = cast (ClauseProperties , clause_entry ["" ])
530550 clause = Clause (
531- parent = current_node ,
551+ parent = current_node , # type: ignore[arg-type]
532552 properties = clause_properties ,
533553 text = text ,
534554 )
535- current_node .clauses .append (clause )
555+ current_node .clauses .append (clause ) # type: ignore[union-attr]
536556 return clause , index
537557
538558
0 commit comments