@@ -122,7 +122,9 @@ class Emitter {
122122 case NodeType::NODE_ARRAY_CONSTRUCTOR : emit_array_constructor (node); break ;
123123 case NodeType::NODE_ARRAY_SUBSCRIPT : emit_array_subscript (node); break ;
124124 case NodeType::NODE_FIELD_ACCESS : emit_field_access (node); break ;
125- case NodeType::NODE_SUBQUERY : emit_value (node); break ;
125+ case NodeType::NODE_SUBQUERY : emit_subquery (node); break ;
126+ case NodeType::NODE_EXPRESSION : emit_parenthesized_expression (node); break ;
127+ case NodeType::NODE_USER_VARIABLE : emit_user_variable (node); break ;
126128
127129 // ---- Leaf nodes (emit value directly) ----
128130 case NodeType::NODE_PLACEHOLDER :
@@ -131,6 +133,8 @@ class Emitter {
131133 // ---- Leaf nodes (emit value directly) ----
132134 case NodeType::NODE_LITERAL_INT :
133135 case NodeType::NODE_LITERAL_FLOAT :
136+ case NodeType::NODE_LITERAL_HEX :
137+ case NodeType::NODE_LITERAL_BIT :
134138 if (mode_ == EmitMode::DIGEST ) { sb_.append_char (' ?' ); break ; }
135139 emit_value (node); break ;
136140 case NodeType::NODE_LITERAL_NULL :
@@ -152,6 +156,30 @@ class Emitter {
152156 sb_.append (node->value_ptr , node->value_len );
153157 }
154158
159+ void emit_user_variable (const AstNode* node) {
160+ if (mode_ == EmitMode::DIGEST ) {
161+ StringRef source = node->source ();
162+ if (source.len >= 2 &&
163+ (source.ptr [1 ] == ' \' ' || source.ptr [1 ] == ' "' || source.ptr [1 ] == ' `' )) {
164+ sb_.append (" @?" , 2 );
165+ return ;
166+ }
167+ }
168+ StringRef source = node->source ();
169+ if (!source.empty ()) {
170+ sb_.append (source.ptr , source.len );
171+ return ;
172+ }
173+ sb_.append_char (' @' );
174+ emit_value (node);
175+ }
176+
177+ void emit_parenthesized_expression (const AstNode* node) {
178+ sb_.append_char (' (' );
179+ if (node->first_child ) emit_node (node->first_child );
180+ sb_.append_char (' )' );
181+ }
182+
155183 void emit_string_literal (const AstNode* node) {
156184 sb_.append_char (' \' ' );
157185 sb_.append (node->value_ptr , node->value_len );
@@ -1061,10 +1089,28 @@ class Emitter {
10611089 }
10621090
10631091 void emit_unary_op (const AstNode* node) {
1092+ const AstNode* child = node->first_child ;
1093+ if (is_not_operator (node) && child) {
1094+ if (child->type == NodeType::NODE_IN_LIST ) {
1095+ emit_not_in_list (child);
1096+ return ;
1097+ }
1098+ if (child->type == NodeType::NODE_BETWEEN ) {
1099+ emit_not_between (child);
1100+ return ;
1101+ }
1102+ if (child->type == NodeType::NODE_BINARY_OP &&
1103+ (child->value ().equals_ci (" LIKE" , 4 ) ||
1104+ child->value ().equals_ci (" REGEXP" , 6 ))) {
1105+ emit_not_binary_op (child);
1106+ return ;
1107+ }
1108+ }
1109+
10641110 emit_value (node);
10651111 // Add space for keyword operators like NOT, no space for - or +
10661112 if (node->value_len > 1 ) sb_.append_char (' ' );
1067- if (node-> first_child ) emit_node (node-> first_child );
1113+ if (child ) emit_node (child );
10681114 }
10691115
10701116 void emit_function_call (const AstNode* node) {
@@ -1102,13 +1148,20 @@ class Emitter {
11021148
11031149 void emit_in_list (const AstNode* node) {
11041150 const AstNode* expr = node->first_child ;
1151+ const AstNode* first_val = expr ? expr->next_sibling : nullptr ;
11051152 if (expr) emit_node (expr);
1153+ if (first_val && first_val->type == NodeType::NODE_SUBQUERY &&
1154+ !first_val->next_sibling ) {
1155+ sb_.append (" IN " );
1156+ emit_node (first_val);
1157+ return ;
1158+ }
11061159 sb_.append (" IN (" );
11071160 if (mode_ == EmitMode::DIGEST ) {
11081161 sb_.append_char (' ?' );
11091162 } else {
11101163 bool first = true ;
1111- for (const AstNode* val = expr ? expr-> next_sibling : nullptr ; val; val = val->next_sibling ) {
1164+ for (const AstNode* val = first_val ; val; val = val->next_sibling ) {
11121165 if (!first) sb_.append (" , " );
11131166 first = false ;
11141167 emit_node (val);
@@ -1117,6 +1170,68 @@ class Emitter {
11171170 sb_.append_char (' )' );
11181171 }
11191172
1173+ void emit_subquery (const AstNode* node) {
1174+ if (node->flags == 1 ) {
1175+ sb_.append (" EXISTS " );
1176+ }
1177+ sb_.append_char (' (' );
1178+ if (node->first_child ) {
1179+ emit_node (node->first_child );
1180+ } else {
1181+ emit_value (node);
1182+ }
1183+ sb_.append_char (' )' );
1184+ }
1185+
1186+ bool is_not_operator (const AstNode* node) const {
1187+ return node && node->value ().equals_ci (" NOT" , 3 );
1188+ }
1189+
1190+ void emit_not_in_list (const AstNode* node) {
1191+ const AstNode* expr = node->first_child ;
1192+ const AstNode* first_val = expr ? expr->next_sibling : nullptr ;
1193+ if (expr) emit_node (expr);
1194+ if (first_val && first_val->type == NodeType::NODE_SUBQUERY &&
1195+ !first_val->next_sibling ) {
1196+ sb_.append (" NOT IN " );
1197+ emit_node (first_val);
1198+ return ;
1199+ }
1200+ sb_.append (" NOT IN (" );
1201+ if (mode_ == EmitMode::DIGEST ) {
1202+ sb_.append_char (' ?' );
1203+ } else {
1204+ bool first = true ;
1205+ for (const AstNode* val = first_val; val; val = val->next_sibling ) {
1206+ if (!first) sb_.append (" , " );
1207+ first = false ;
1208+ emit_node (val);
1209+ }
1210+ }
1211+ sb_.append_char (' )' );
1212+ }
1213+
1214+ void emit_not_between (const AstNode* node) {
1215+ const AstNode* expr = node->first_child ;
1216+ const AstNode* low = expr ? expr->next_sibling : nullptr ;
1217+ const AstNode* high = low ? low->next_sibling : nullptr ;
1218+ if (expr) emit_node (expr);
1219+ sb_.append (" NOT BETWEEN " );
1220+ if (low) emit_node (low);
1221+ sb_.append (" AND " );
1222+ if (high) emit_node (high);
1223+ }
1224+
1225+ void emit_not_binary_op (const AstNode* node) {
1226+ const AstNode* left = node->first_child ;
1227+ const AstNode* right = left ? left->next_sibling : nullptr ;
1228+ if (left) emit_node (left);
1229+ sb_.append (" NOT " );
1230+ emit_value (node);
1231+ sb_.append_char (' ' );
1232+ if (right) emit_node (right);
1233+ }
1234+
11201235 void emit_case_when (const AstNode* node) {
11211236 sb_.append (" CASE " );
11221237 for (const AstNode* child = node->first_child ; child; child = child->next_sibling ) {
0 commit comments