1212
1313//! Recursive visitors for ast Nodes. See [`Visitor`] for more details.
1414
15- use crate :: ast:: { Expr , ObjectName , Statement , TableFactor } ;
15+ use crate :: ast:: { Expr , ObjectName , Query , Statement , TableFactor } ;
1616use core:: ops:: ControlFlow ;
1717
1818/// A type that can be visited by a [`Visitor`]. See [`Visitor`] for
@@ -179,6 +179,16 @@ pub trait Visitor {
179179 /// Type returned when the recursion returns early.
180180 type Break ;
181181
182+ /// Invoked for any queries that appear in the AST before visiting children
183+ fn pre_visit_query ( & mut self , _query : & Query ) -> ControlFlow < Self :: Break > {
184+ ControlFlow :: Continue ( ( ) )
185+ }
186+
187+ /// Invoked for any queries that appear in the AST after visiting children
188+ fn post_visit_query ( & mut self , _query : & Query ) -> ControlFlow < Self :: Break > {
189+ ControlFlow :: Continue ( ( ) )
190+ }
191+
182192 /// Invoked for any relations (e.g. tables) that appear in the AST before visiting children
183193 fn pre_visit_relation ( & mut self , _relation : & ObjectName ) -> ControlFlow < Self :: Break > {
184194 ControlFlow :: Continue ( ( ) )
@@ -267,6 +277,16 @@ pub trait VisitorMut {
267277 /// Type returned when the recursion returns early.
268278 type Break ;
269279
280+ /// Invoked for any queries that appear in the AST before visiting children
281+ fn pre_visit_query ( & mut self , _query : & mut Query ) -> ControlFlow < Self :: Break > {
282+ ControlFlow :: Continue ( ( ) )
283+ }
284+
285+ /// Invoked for any queries that appear in the AST after visiting children
286+ fn post_visit_query ( & mut self , _query : & mut Query ) -> ControlFlow < Self :: Break > {
287+ ControlFlow :: Continue ( ( ) )
288+ }
289+
270290 /// Invoked for any relations (e.g. tables) that appear in the AST before visiting children
271291 fn pre_visit_relation ( & mut self , _relation : & mut ObjectName ) -> ControlFlow < Self :: Break > {
272292 ControlFlow :: Continue ( ( ) )
@@ -626,6 +646,18 @@ mod tests {
626646 impl Visitor for TestVisitor {
627647 type Break = ( ) ;
628648
649+ /// Invoked for any queries that appear in the AST before visiting children
650+ fn pre_visit_query ( & mut self , query : & Query ) -> ControlFlow < Self :: Break > {
651+ self . visited . push ( format ! ( "PRE: QUERY: {query}" ) ) ;
652+ ControlFlow :: Continue ( ( ) )
653+ }
654+
655+ /// Invoked for any queries that appear in the AST after visiting children
656+ fn post_visit_query ( & mut self , query : & Query ) -> ControlFlow < Self :: Break > {
657+ self . visited . push ( format ! ( "POST: QUERY: {query}" ) ) ;
658+ ControlFlow :: Continue ( ( ) )
659+ }
660+
629661 fn pre_visit_relation ( & mut self , relation : & ObjectName ) -> ControlFlow < Self :: Break > {
630662 self . visited . push ( format ! ( "PRE: RELATION: {relation}" ) ) ;
631663 ControlFlow :: Continue ( ( ) )
@@ -695,17 +727,20 @@ mod tests {
695727 "SELECT * from table_name as my_table" ,
696728 vec![
697729 "PRE: STATEMENT: SELECT * FROM table_name AS my_table" ,
730+ "PRE: QUERY: SELECT * FROM table_name AS my_table" ,
698731 "PRE: TABLE FACTOR: table_name AS my_table" ,
699732 "PRE: RELATION: table_name" ,
700733 "POST: RELATION: table_name" ,
701734 "POST: TABLE FACTOR: table_name AS my_table" ,
735+ "POST: QUERY: SELECT * FROM table_name AS my_table" ,
702736 "POST: STATEMENT: SELECT * FROM table_name AS my_table" ,
703737 ] ,
704738 ) ,
705739 (
706740 "SELECT * from t1 join t2 on t1.id = t2.t1_id" ,
707741 vec![
708742 "PRE: STATEMENT: SELECT * FROM t1 JOIN t2 ON t1.id = t2.t1_id" ,
743+ "PRE: QUERY: SELECT * FROM t1 JOIN t2 ON t1.id = t2.t1_id" ,
709744 "PRE: TABLE FACTOR: t1" ,
710745 "PRE: RELATION: t1" ,
711746 "POST: RELATION: t1" ,
@@ -720,70 +755,108 @@ mod tests {
720755 "PRE: EXPR: t2.t1_id" ,
721756 "POST: EXPR: t2.t1_id" ,
722757 "POST: EXPR: t1.id = t2.t1_id" ,
758+ "POST: QUERY: SELECT * FROM t1 JOIN t2 ON t1.id = t2.t1_id" ,
723759 "POST: STATEMENT: SELECT * FROM t1 JOIN t2 ON t1.id = t2.t1_id" ,
724760 ] ,
725761 ) ,
726762 (
727763 "SELECT * from t1 where EXISTS(SELECT column from t2)" ,
728764 vec![
729765 "PRE: STATEMENT: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2)" ,
766+ "PRE: QUERY: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2)" ,
730767 "PRE: TABLE FACTOR: t1" ,
731768 "PRE: RELATION: t1" ,
732769 "POST: RELATION: t1" ,
733770 "POST: TABLE FACTOR: t1" ,
734771 "PRE: EXPR: EXISTS (SELECT column FROM t2)" ,
772+ "PRE: QUERY: SELECT column FROM t2" ,
735773 "PRE: EXPR: column" ,
736774 "POST: EXPR: column" ,
737775 "PRE: TABLE FACTOR: t2" ,
738776 "PRE: RELATION: t2" ,
739777 "POST: RELATION: t2" ,
740778 "POST: TABLE FACTOR: t2" ,
779+ "POST: QUERY: SELECT column FROM t2" ,
741780 "POST: EXPR: EXISTS (SELECT column FROM t2)" ,
781+ "POST: QUERY: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2)" ,
742782 "POST: STATEMENT: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2)" ,
743783 ] ,
744784 ) ,
745785 (
746786 "SELECT * from t1 where EXISTS(SELECT column from t2)" ,
747787 vec![
748788 "PRE: STATEMENT: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2)" ,
789+ "PRE: QUERY: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2)" ,
749790 "PRE: TABLE FACTOR: t1" ,
750791 "PRE: RELATION: t1" ,
751792 "POST: RELATION: t1" ,
752793 "POST: TABLE FACTOR: t1" ,
753794 "PRE: EXPR: EXISTS (SELECT column FROM t2)" ,
795+ "PRE: QUERY: SELECT column FROM t2" ,
754796 "PRE: EXPR: column" ,
755797 "POST: EXPR: column" ,
756798 "PRE: TABLE FACTOR: t2" ,
757799 "PRE: RELATION: t2" ,
758800 "POST: RELATION: t2" ,
759801 "POST: TABLE FACTOR: t2" ,
802+ "POST: QUERY: SELECT column FROM t2" ,
760803 "POST: EXPR: EXISTS (SELECT column FROM t2)" ,
804+ "POST: QUERY: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2)" ,
761805 "POST: STATEMENT: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2)" ,
762806 ] ,
763807 ) ,
764808 (
765809 "SELECT * from t1 where EXISTS(SELECT column from t2) UNION SELECT * from t3" ,
766810 vec![
767811 "PRE: STATEMENT: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2) UNION SELECT * FROM t3" ,
812+ "PRE: QUERY: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2) UNION SELECT * FROM t3" ,
768813 "PRE: TABLE FACTOR: t1" ,
769814 "PRE: RELATION: t1" ,
770815 "POST: RELATION: t1" ,
771816 "POST: TABLE FACTOR: t1" ,
772817 "PRE: EXPR: EXISTS (SELECT column FROM t2)" ,
818+ "PRE: QUERY: SELECT column FROM t2" ,
773819 "PRE: EXPR: column" ,
774820 "POST: EXPR: column" ,
775821 "PRE: TABLE FACTOR: t2" ,
776822 "PRE: RELATION: t2" ,
777823 "POST: RELATION: t2" ,
778824 "POST: TABLE FACTOR: t2" ,
825+ "POST: QUERY: SELECT column FROM t2" ,
779826 "POST: EXPR: EXISTS (SELECT column FROM t2)" ,
780827 "PRE: TABLE FACTOR: t3" ,
781828 "PRE: RELATION: t3" ,
782829 "POST: RELATION: t3" ,
783830 "POST: TABLE FACTOR: t3" ,
831+ "POST: QUERY: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2) UNION SELECT * FROM t3" ,
784832 "POST: STATEMENT: SELECT * FROM t1 WHERE EXISTS (SELECT column FROM t2) UNION SELECT * FROM t3" ,
785833 ] ,
786834 ) ,
835+ (
836+ concat!(
837+ "SELECT * FROM monthly_sales " ,
838+ "PIVOT(SUM(a.amount) FOR a.MONTH IN ('JAN', 'FEB', 'MAR', 'APR')) AS p (c, d) " ,
839+ "ORDER BY EMPID"
840+ ) ,
841+ vec![
842+ "PRE: STATEMENT: SELECT * FROM monthly_sales PIVOT(SUM(a.amount) FOR a.MONTH IN ('JAN', 'FEB', 'MAR', 'APR')) AS p (c, d) ORDER BY EMPID" ,
843+ "PRE: QUERY: SELECT * FROM monthly_sales PIVOT(SUM(a.amount) FOR a.MONTH IN ('JAN', 'FEB', 'MAR', 'APR')) AS p (c, d) ORDER BY EMPID" ,
844+ "PRE: TABLE FACTOR: monthly_sales PIVOT(SUM(a.amount) FOR a.MONTH IN ('JAN', 'FEB', 'MAR', 'APR')) AS p (c, d)" ,
845+ "PRE: TABLE FACTOR: monthly_sales" ,
846+ "PRE: RELATION: monthly_sales" ,
847+ "POST: RELATION: monthly_sales" ,
848+ "POST: TABLE FACTOR: monthly_sales" ,
849+ "PRE: EXPR: SUM(a.amount)" ,
850+ "PRE: EXPR: a.amount" ,
851+ "POST: EXPR: a.amount" ,
852+ "POST: EXPR: SUM(a.amount)" ,
853+ "POST: TABLE FACTOR: monthly_sales PIVOT(SUM(a.amount) FOR a.MONTH IN ('JAN', 'FEB', 'MAR', 'APR')) AS p (c, d)" ,
854+ "PRE: EXPR: EMPID" ,
855+ "POST: EXPR: EMPID" ,
856+ "POST: QUERY: SELECT * FROM monthly_sales PIVOT(SUM(a.amount) FOR a.MONTH IN ('JAN', 'FEB', 'MAR', 'APR')) AS p (c, d) ORDER BY EMPID" ,
857+ "POST: STATEMENT: SELECT * FROM monthly_sales PIVOT(SUM(a.amount) FOR a.MONTH IN ('JAN', 'FEB', 'MAR', 'APR')) AS p (c, d) ORDER BY EMPID" ,
858+ ]
859+ )
787860 ] ;
788861 for ( sql, expected) in tests {
789862 let actual = do_visit ( sql) ;
0 commit comments