@@ -46,25 +46,53 @@ class _PreservingGenerator(Generator):
4646 }
4747
4848 def coalesce_sql (self , expression : exp .Expression ) -> str :
49+ """Render ``COALESCE`` back to ``IFNULL`` for two-argument calls.
50+
51+ :param expression: The ``exp.Coalesce`` AST node.
52+ :type expression: exp.Expression
53+ :returns: SQL string using ``IFNULL`` (2 args) or ``COALESCE``.
54+ :rtype: str
55+ """
4956 args = [expression .this ] + expression .expressions
5057 if len (args ) == 2 :
5158 return f"IFNULL({ self .sql (args [0 ])} , { self .sql (args [1 ])} )"
5259 args_sql = ", " .join (self .sql (a ) for a in args )
5360 return f"COALESCE({ args_sql } )"
5461
5562 def dateadd_sql (self , expression : exp .Expression ) -> str :
63+ """Render ``exp.DateAdd`` back to ``DATE_ADD(…)`` syntax.
64+
65+ :param expression: The ``exp.DateAdd`` AST node.
66+ :type expression: exp.Expression
67+ :rtype: str
68+ """
5669 return (
5770 f"DATE_ADD({ self .sql (expression , 'this' )} , "
5871 f"{ self .sql (expression , 'expression' )} )"
5972 )
6073
6174 def datesub_sql (self , expression : exp .Expression ) -> str :
75+ """Render ``exp.DateSub`` back to ``DATE_SUB(…)`` syntax.
76+
77+ :param expression: The ``exp.DateSub`` AST node.
78+ :type expression: exp.Expression
79+ :rtype: str
80+ """
6281 return (
6382 f"DATE_SUB({ self .sql (expression , 'this' )} , "
6483 f"{ self .sql (expression , 'expression' )} )"
6584 )
6685
6786 def tsordsadd_sql (self , expression : exp .Expression ) -> str :
87+ """Render ``exp.TsOrDsAdd`` as ``DATE_ADD`` or ``DATE_SUB``.
88+
89+ When the interval multiplier is ``-1`` the expression is rendered
90+ as ``DATE_SUB`` instead, preserving the original SQL intent.
91+
92+ :param expression: The ``exp.TsOrDsAdd`` AST node.
93+ :type expression: exp.Expression
94+ :rtype: str
95+ """
6896 this = self .sql (expression , "this" )
6997 expr_node = expression .expression
7098 if isinstance (expr_node , exp .Mul ):
@@ -79,6 +107,16 @@ def tsordsadd_sql(self, expression: exp.Expression) -> str:
79107 return f"DATE_ADD({ this } , { self .sql (expression , 'expression' )} )"
80108
81109 def not_sql (self , expression : exp .Expression ) -> str :
110+ """Render ``NOT`` expressions preserving ``IS NOT NULL`` and ``NOT IN``.
111+
112+ sqlglot normalises ``IS NOT NULL`` to ``NOT (x IS NULL)`` and
113+ ``NOT IN`` to ``NOT (x IN (...))``; this override renders them
114+ back to their original idiomatic forms.
115+
116+ :param expression: The ``exp.Not`` AST node.
117+ :type expression: exp.Expression
118+ :rtype: str
119+ """
82120 child = expression .this
83121 if isinstance (child , exp .Is ) and isinstance (child .expression , exp .Null ):
84122 return f"{ self .sql (child , 'this' )} IS NOT NULL"
@@ -96,14 +134,26 @@ def not_sql(self, expression: exp.Expression) -> str:
96134
97135
98136def _is_qualified_reference (result : list [str ]) -> bool :
99- """Check if result is a single dotted reference like ``['cte.col']``."""
137+ """Check if *result* is a single dotted reference like ``['cte.col']``.
138+
139+ :param result: Resolved column list to inspect.
140+ :type result: list[str]
141+ :rtype: bool
142+ """
100143 return len (result ) == 1 and "." in result [0 ]
101144
102145
103146def _is_not_already_resolved_qualified_reference (
104147 result : list [str ], column : str
105148) -> bool :
106- """Check if result is a qualified reference that changed from the input."""
149+ """Check if *result* is a qualified reference that differs from *column*.
150+
151+ :param result: Resolved column list to inspect.
152+ :type result: list[str]
153+ :param column: The original column name before resolution.
154+ :type column: str
155+ :rtype: bool
156+ """
107157 return _is_qualified_reference (result ) and result != [column ]
108158
109159
0 commit comments