@@ -479,8 +479,7 @@ class Parser(parser.Parser):
479479
480480 RANGE_PARSERS = {
481481 ** parser .Parser .RANGE_PARSERS ,
482- TokenType .GLOBAL : lambda self , this : self ._match (TokenType .IN )
483- and self ._parse_in (this , is_global = True ),
482+ TokenType .GLOBAL : lambda self , this : self ._parse_global_in (this ),
484483 }
485484
486485 # The PLACEHOLDER entry is popped because 1) it doesn't affect Clickhouse (it corresponds to
@@ -634,6 +633,11 @@ def _parse_in(self, this: t.Optional[exp.Expression], is_global: bool = False) -
634633 this .set ("is_global" , is_global )
635634 return this
636635
636+ def _parse_global_in (self , this : t .Optional [exp .Expression ]) -> exp .Not | exp .In :
637+ is_negated = self ._match (TokenType .NOT )
638+ this = self ._match (TokenType .IN ) and self ._parse_in (this , is_global = True )
639+ return self .expression (exp .Not , this = this ) if is_negated else this
640+
637641 def _parse_table (
638642 self ,
639643 schema : bool = False ,
@@ -1290,3 +1294,18 @@ def is_sql(self, expression: exp.Is) -> str:
12901294 is_sql = self .wrap (is_sql )
12911295
12921296 return is_sql
1297+
1298+ def in_sql (self , expression : exp .In ) -> str :
1299+ in_sql = super ().in_sql (expression )
1300+
1301+ if isinstance (expression .parent , exp .Not ) and expression .args .get ("is_global" ):
1302+ in_sql = in_sql .replace ("GLOBAL IN" , "GLOBAL NOT IN" , 1 )
1303+
1304+ return in_sql
1305+
1306+ def not_sql (self , expression : exp .Not ) -> str :
1307+ if isinstance (expression .this , exp .In ) and expression .this .args .get ("is_global" ):
1308+ # let `GLOBAL IN` child interpose `NOT`
1309+ return self .sql (expression , "this" )
1310+
1311+ return super ().not_sql (expression )
0 commit comments