@@ -421,24 +421,31 @@ def visit_list_expression(self, node, unmangle_names):
421421 else :
422422 return "(%s)" % self ._join_expressions (node .values , unmangle_names )
423423
424+ def visit_window_func (self , node , unmangle_names ):
425+ args = ", " .join ([self .process (arg , unmangle_names ) for arg in node .func_args ])
426+ ignore_null = f" { node .ignore_null } NULLS" if node .ignore_null else ""
427+ window_spec = " OVER (" + self .process (node .window_spec , unmangle_names ) + ")"
428+ return f"{ node .func_name .upper ()} ({ args } ){ ignore_null } { window_spec } "
429+
424430 def visit_window_spec (self , node , unmangle_names ):
425431 parts = []
426-
427432 if node .partition_by :
428- parts .append (
429- "PARTITION BY "
430- + self ._join_expressions (node .partition_by , unmangle_names )
431- )
433+ self .process (node .partition_by , unmangle_names )
432434 if node .order_by :
433435 parts .append ("ORDER BY " + format_sort_items (node .order_by , unmangle_names ))
434- if node .frame :
435- parts .append (self .process (node .frame , unmangle_names ))
436+ if node .frame_clause :
437+ parts .append (self .process (node .frame_clause , unmangle_names ))
436438
437- return '(' + ' ' .join (parts ) + ')'
439+ return ' ' .join (parts )
438440
439- def visit_window_frame (self , node , unmangle_names ):
440- ret = node .type + " "
441+ def visit_partition_by_clause (self , node , unmangle_names ):
442+ return "PARTITION BY " + self ._join_expressions (node .items , unmangle_names )
443+
444+ def visit_frame_clause (self , node , unmangle_names ):
445+ return f"{ node .type } { self .process (node .frame_range , unmangle_names )} "
441446
447+ def visit_window_frame (self , node , unmangle_names ):
448+ ret = ""
442449 if node .end :
443450 ret += "BETWEEN %s AND %s" % (
444451 self .process (node .start , unmangle_names ),
@@ -449,6 +456,19 @@ def visit_window_frame(self, node, unmangle_names):
449456
450457 return ret
451458
459+ def visit_frame_bound (self , node , unmangle_names ):
460+ if node .type .upper () == "ROW" :
461+ return "CURRENT ROW"
462+ expr = (
463+ self .process (node .expr , unmangle_names )
464+ if node .expr is not None
465+ else "UNBOUNDED "
466+ )
467+ return f"{ expr } { node .type .upper ()} "
468+
469+ def visit_frame_expr (self , node , unmangle_names ):
470+ return self .process (node .value , unmangle_names )
471+
452472 def visit_single_column (self , node , indent ):
453473 format_expression (node .expression )
454474
@@ -468,6 +488,9 @@ def visit_match_against_expression(self, node, unmangle_names):
468488 full_text_search_modifier = full_text_search_modifier .upper ()
469489 return f"MATCH({ columns } ) AGAINST ({ self .process (node .expr , unmangle_names )} { full_text_search_modifier } )"
470490
491+ def visit_sound_like (self , node , unmangle_names ):
492+ return f"{ self .process (node .arguments [0 ])} SOUNDS LIKE { self .process (node .arguments [1 ])} "
493+
471494 def _format_binary_expression (self , operator , left , right , unmangle_names ):
472495 return "%s %s %s" % (
473496 self .process (left , unmangle_names ),
@@ -689,13 +712,14 @@ def visit_table_subquery(self, node, indent):
689712 return None
690713
691714 def visit_union (self , node , indent ):
692- all = node .all
693715 for i , relation in enumerate (node .relations ):
694716 self ._process_relation (relation , indent )
695717 self .builder .append ("\n " )
696718 if i != len (node .relations ) - 1 :
697- if all :
719+ if node . all :
698720 self ._append (indent , "UNION ALL" )
721+ elif node .distinct :
722+ self ._append (indent , "UNION DISTINCT" )
699723 else :
700724 self ._append (indent , "UNION" )
701725 self .builder .append ("\n " )
@@ -704,7 +728,12 @@ def visit_union(self, node, indent):
704728
705729 def visit_except (self , node , indent ):
706730 self ._process_relation (node .left , indent )
707- self .builder .append ("EXCEPT " + "ALL " if not node .distinct else "" )
731+ if node .all is not None :
732+ self ._append (indent , "EXCEPT ALL" )
733+ elif node .distinct is not None :
734+ self ._append (indent , "EXCEPT DISTINCT" )
735+ else :
736+ self ._append (indent , "EXCEPT" )
708737 self ._process_relation (node .right , indent )
709738
710739 return None
@@ -756,7 +785,11 @@ def visit_intersect(self, node, indent):
756785 relations = [
757786 self ._process_relation (relation , indent ) for relation in node .relations
758787 ]
759- intersect = "INTERSECT " + "ALL " if not node .distinct else ""
788+ intersect = "INTERSECT"
789+ if node .all is not None :
790+ intersect += " ALL"
791+ elif node .distinct is not None :
792+ intersect += " DISTINCT"
760793 self .builder .append (intersect .join (relations ))
761794 return None
762795
0 commit comments