11use pgt_query:: protobuf:: { AExpr , AExprKind } ;
2+ use pgt_query:: { Node , NodeEnum } ;
23
34use crate :: {
45 TokenKind ,
@@ -31,20 +32,62 @@ pub(super) fn emit_a_expr(e: &mut EventEmitter, n: &AExpr) {
3132
3233// Basic binary operator: left op right
3334fn emit_aexpr_op ( e : & mut EventEmitter , n : & AExpr ) {
34- if let Some ( ref lexpr) = n. lexpr {
35- super :: emit_node ( lexpr, e) ;
36- }
37-
38- if !n. name . is_empty ( ) {
39- e. space ( ) ;
40- for name in & n. name {
41- super :: emit_node ( name, e) ;
35+ if n. name . is_empty ( ) {
36+ if let Some ( ref lexpr) = n. lexpr {
37+ super :: emit_node ( lexpr, e) ;
4238 }
43- e. space ( ) ;
39+ if let Some ( ref rexpr) = n. rexpr {
40+ if n. lexpr . is_some ( ) {
41+ e. space ( ) ;
42+ }
43+ super :: emit_node ( rexpr, e) ;
44+ }
45+ return ;
4446 }
4547
46- if let Some ( ref rexpr) = n. rexpr {
47- super :: emit_node ( rexpr, e) ;
48+ let lexpr = n. lexpr . as_ref ( ) ;
49+ let rexpr = n. rexpr . as_ref ( ) ;
50+
51+ match ( lexpr, rexpr) {
52+ ( Some ( lexpr) , Some ( rexpr) ) => {
53+ super :: emit_node ( lexpr, e) ;
54+ e. space ( ) ;
55+ emit_operator ( e, & n. name ) ;
56+ e. space ( ) ;
57+ super :: emit_node ( rexpr, e) ;
58+ }
59+ ( None , Some ( rexpr) ) => {
60+ if let Some ( op) = extract_simple_operator ( & n. name ) {
61+ if op. eq_ignore_ascii_case ( "not" ) {
62+ e. token ( TokenKind :: NOT_KW ) ;
63+ e. space ( ) ;
64+ super :: emit_node ( rexpr, e) ;
65+ } else {
66+ emit_simple_operator ( e, op) ;
67+ if operator_needs_space ( op) {
68+ e. space ( ) ;
69+ }
70+ super :: emit_node ( rexpr, e) ;
71+ }
72+ } else {
73+ emit_operator ( e, & n. name ) ;
74+ e. space ( ) ;
75+ super :: emit_node ( rexpr, e) ;
76+ }
77+ }
78+ ( Some ( lexpr) , None ) => {
79+ super :: emit_node ( lexpr, e) ;
80+ if let Some ( op) = extract_simple_operator ( & n. name ) {
81+ if operator_needs_space ( op) {
82+ e. space ( ) ;
83+ }
84+ emit_simple_operator ( e, op) ;
85+ } else {
86+ e. space ( ) ;
87+ emit_operator ( e, & n. name ) ;
88+ }
89+ }
90+ ( None , None ) => { }
4891 }
4992}
5093
@@ -56,8 +99,10 @@ fn emit_aexpr_op_any(e: &mut EventEmitter, n: &AExpr) {
5699 }
57100
58101 if !n. name . is_empty ( ) {
59- for name in & n. name {
60- super :: emit_node ( name, e) ;
102+ if let Some ( op) = extract_simple_operator ( & n. name ) {
103+ emit_simple_operator ( e, op) ;
104+ } else {
105+ emit_operator ( e, & n. name ) ;
61106 }
62107 e. space ( ) ;
63108 }
@@ -78,8 +123,10 @@ fn emit_aexpr_op_all(e: &mut EventEmitter, n: &AExpr) {
78123 }
79124
80125 if !n. name . is_empty ( ) {
81- for name in & n. name {
82- super :: emit_node ( name, e) ;
126+ if let Some ( op) = extract_simple_operator ( & n. name ) {
127+ emit_simple_operator ( e, op) ;
128+ } else {
129+ emit_operator ( e, & n. name ) ;
83130 }
84131 e. space ( ) ;
85132 }
@@ -158,16 +205,31 @@ fn emit_aexpr_in(e: &mut EventEmitter, n: &AExpr) {
158205 e. space ( ) ;
159206 }
160207
208+ let is_not = extract_simple_operator ( & n. name )
209+ . map ( |op| op == "<>" )
210+ . unwrap_or ( false ) ;
211+
212+ if is_not {
213+ e. token ( TokenKind :: NOT_KW ) ;
214+ e. space ( ) ;
215+ }
216+
161217 e. token ( TokenKind :: IN_KW ) ;
162218 e. space ( ) ;
163219
164220 // The rexpr is typically a List node, which emits comma-separated items
165221 // We need to wrap it in parentheses for IN clause
166- e. token ( TokenKind :: L_PAREN ) ;
167222 if let Some ( ref rexpr) = n. rexpr {
168- super :: emit_node ( rexpr, e) ;
223+ match rexpr. node . as_ref ( ) {
224+ Some ( NodeEnum :: SubLink ( _) ) => super :: emit_node ( rexpr, e) ,
225+ _ => {
226+ e. token ( TokenKind :: L_PAREN ) ;
227+ super :: emit_node ( rexpr, e) ;
228+ e. token ( TokenKind :: R_PAREN ) ;
229+ return ;
230+ }
231+ }
169232 }
170- e. token ( TokenKind :: R_PAREN ) ;
171233}
172234
173235// expr LIKE pattern [ESCAPE escape]
@@ -177,6 +239,15 @@ fn emit_aexpr_like(e: &mut EventEmitter, n: &AExpr) {
177239 e. space ( ) ;
178240 }
179241
242+ let is_not = extract_simple_operator ( & n. name )
243+ . map ( |op| op == "!~~" )
244+ . unwrap_or ( false ) ;
245+
246+ if is_not {
247+ e. token ( TokenKind :: NOT_KW ) ;
248+ e. space ( ) ;
249+ }
250+
180251 e. token ( TokenKind :: LIKE_KW ) ;
181252 e. space ( ) ;
182253
@@ -192,6 +263,15 @@ fn emit_aexpr_ilike(e: &mut EventEmitter, n: &AExpr) {
192263 e. space ( ) ;
193264 }
194265
266+ let is_not = extract_simple_operator ( & n. name )
267+ . map ( |op| op == "!~~*" )
268+ . unwrap_or ( false ) ;
269+
270+ if is_not {
271+ e. token ( TokenKind :: NOT_KW ) ;
272+ e. space ( ) ;
273+ }
274+
195275 e. token ( TokenKind :: ILIKE_KW ) ;
196276 e. space ( ) ;
197277
@@ -207,6 +287,15 @@ fn emit_aexpr_similar(e: &mut EventEmitter, n: &AExpr) {
207287 e. space ( ) ;
208288 }
209289
290+ let is_not = extract_simple_operator ( & n. name )
291+ . map ( |op| op == "!~" )
292+ . unwrap_or ( false ) ;
293+
294+ if is_not {
295+ e. token ( TokenKind :: NOT_KW ) ;
296+ e. space ( ) ;
297+ }
298+
210299 e. token ( TokenKind :: SIMILAR_KW ) ;
211300 e. space ( ) ;
212301 e. token ( TokenKind :: TO_KW ) ;
@@ -336,3 +425,51 @@ fn emit_aexpr_not_between_sym(e: &mut EventEmitter, n: &AExpr) {
336425 }
337426 }
338427}
428+
429+ fn emit_operator ( e : & mut EventEmitter , name : & [ Node ] ) {
430+ if name. len ( ) > 1 {
431+ emit_qualified_operator ( e, name) ;
432+ } else if let Some ( first) = name. first ( ) {
433+ emit_operator_part ( e, first) ;
434+ }
435+ }
436+
437+ fn emit_qualified_operator ( e : & mut EventEmitter , name : & [ Node ] ) {
438+ e. token ( TokenKind :: OPERATOR_KW ) ;
439+ e. token ( TokenKind :: L_PAREN ) ;
440+
441+ for ( idx, part) in name. iter ( ) . enumerate ( ) {
442+ if idx > 0 {
443+ e. token ( TokenKind :: DOT ) ;
444+ }
445+ emit_operator_part ( e, part) ;
446+ }
447+
448+ e. token ( TokenKind :: R_PAREN ) ;
449+ }
450+
451+ fn emit_operator_part ( e : & mut EventEmitter , node : & Node ) {
452+ match node. node . as_ref ( ) {
453+ Some ( NodeEnum :: String ( s) ) => e. token ( TokenKind :: IDENT ( s. sval . clone ( ) ) ) ,
454+ _ => super :: emit_node ( node, e) ,
455+ }
456+ }
457+
458+ fn emit_simple_operator ( e : & mut EventEmitter , op : & str ) {
459+ e. token ( TokenKind :: IDENT ( op. to_string ( ) ) ) ;
460+ }
461+
462+ fn extract_simple_operator < ' a > ( name : & ' a [ Node ] ) -> Option < & ' a str > {
463+ if name. len ( ) != 1 {
464+ return None ;
465+ }
466+
467+ match name[ 0 ] . node . as_ref ( ) {
468+ Some ( NodeEnum :: String ( s) ) => Some ( & s. sval ) ,
469+ _ => None ,
470+ }
471+ }
472+
473+ fn operator_needs_space ( op : & str ) -> bool {
474+ op. chars ( ) . any ( |c| c. is_alphabetic ( ) )
475+ }
0 commit comments