22#include < iostream>
33#include < vector>
44#include < string>
5+ #include < memory> // Required for std::unique_ptr
56
6- void parse_and_print (MysqlParser::Parser& parser, const std::string& query_type, const std::string& query) {
7- std::cout << " ------------------------------------------\n " ;
8- std::cout << " Parsing MySQL " << query_type << " query: " << query << std::endl;
7+ bool verbose_print = true ;
8+ unsigned long int queries = 0 ;
99
10- parser.clearErrors ();
10+ // Function to parse a query and print the AST or errors
11+ void parse_and_print (MysqlParser::Parser& parser, const std::string& query_type, const std::string& query) {
12+ queries++;
13+ if (verbose_print) {
14+ std::cout << " ------------------------------------------\n " ;
15+ std::cout << " Parsing MySQL " << query_type << " query: " << query << std::endl;
16+ }
17+ // std::cout << "AAA" << std::endl;
18+ parser.clearErrors (); // Clear any errors from previous parses
19+ // std::cout << "BBB" << std::endl;
1120 std::unique_ptr<MysqlParser::AstNode> ast = parser.parse (query);
21+ // std::cout << "CCC" << std::endl;
1222
23+ if (verbose_print == false ) {
24+ return ;
25+ }
1326 if (ast) {
1427 std::cout << " Parsing successful!" << std::endl;
15- MysqlParser::print_ast (ast.get ());
28+ MysqlParser::print_ast (ast.get ()); // Print the AST
1629 } else {
1730 std::cout << " Parsing failed." << std::endl;
1831 const auto & errors = parser.getErrors ();
1932 if (errors.empty ()) {
20- std::cout << " (No specific error messages, check parser logic or mysql_yyerror)" << std::endl;
33+ std::cout << " (No specific error messages, check parser logic or mysql_yyerror implementation )" << std::endl;
2134 } else {
2235 for (const auto & error : errors) {
2336 std::cout << " Error: " << error << std::endl;
2437 }
2538 }
2639 }
40+ std::cout << " ------------------------------------------\n\n " ;
2741}
2842
2943int main () {
3044 MysqlParser::Parser parser;
3145
3246 std::vector<std::string> select_queries = {
47+ // Basic SELECTs (from original)
3348 " SELECT name FROM users;" ,
3449 " SELECT * FROM `orders`;" ,
35- " SELECT * FROM tablenameB" // No semicolon
50+ " SELECT `col1`, `col2` FROM tablenameB" , // No semicolon
51+
52+ // SELECT with ALIAS
53+ " SELECT column1 AS first_column, column2 AS second_column FROM my_table;" ,
54+ " SELECT column1 first_column, column2 second_column FROM my_table;" , // Implicit AS
55+
56+ // SELECT with WHERE
57+ " SELECT product_name, price FROM products WHERE category = 'Electronics';" ,
58+ " SELECT * FROM employees WHERE salary > 50000 AND department_id = 3;" ,
59+
60+ // SELECT with ORDER BY
61+ " SELECT student_name, score FROM results ORDER BY score DESC;" ,
62+ " SELECT item, quantity FROM inventory ORDER BY item ASC, quantity DESC;" ,
63+
64+ // SELECT with LIMIT
65+ " SELECT event_name FROM event_log LIMIT 10;" ,
66+ " SELECT message FROM messages ORDER BY created_at DESC LIMIT 5, 10;" , // LIMIT offset, count
67+
68+ // SELECT with GROUP BY
69+ " SELECT department, COUNT(*) AS num_employees FROM employees GROUP BY department;" ,
70+ " SELECT product_category, AVG(price) AS avg_price FROM products GROUP BY product_category;" ,
71+
72+ // SELECT with GROUP BY and HAVING
73+ " SELECT department, COUNT(*) AS num_employees FROM employees GROUP BY department HAVING COUNT(*) > 10;" ,
74+ " SELECT product_category, AVG(price) AS avg_price FROM products GROUP BY product_category HAVING AVG(price) > 100.00;" ,
75+
76+ // Basic JOIN clauses
77+ " SELECT c.customer_name, o.order_id FROM customers c JOIN orders o ON c.customer_id = o.customer_id;" ,
78+ " SELECT s.name, p.product_name FROM suppliers s INNER JOIN products p ON s.supplier_id = p.supplier_id;" ,
79+ " SELECT e.name, d.department_name FROM employees e LEFT JOIN departments d ON e.department_id = d.department_id;" ,
80+ " SELECT e.name, p.project_name FROM employees e RIGHT OUTER JOIN projects p ON e.employee_id = p.lead_employee_id;" ,
81+ " SELECT c1.name, c2.name AS city_pair FROM cities c1 CROSS JOIN cities c2 WHERE c1.id <> c2.id;" , // Comma join will be CROSS JOIN
82+ " SELECT c1.name, c2.name AS city_pair_comma FROM cities c1, cities c2 WHERE c1.id <> c2.id;" ,
83+ " SELECT e.name, d.name FROM employees e NATURAL JOIN departments d;" , // Natural Join
84+ " SELECT s.student_name, c.course_name FROM students s NATURAL LEFT JOIN courses c;" ,
85+
86+ // JOIN with USING
87+ " SELECT c.customer_name, o.order_date FROM customers c JOIN orders o USING (customer_id);" ,
88+ " SELECT a.val, b.val FROM tableA a LEFT JOIN tableB b USING (id, common_column);" ,
89+
90+ // More complex JOINs (multiple joins)
91+ " SELECT c.name, o.order_date, p.product_name, oi.quantity "
92+ " FROM customers c "
93+ " JOIN orders o ON c.customer_id = o.customer_id "
94+ " JOIN order_items oi ON o.order_id = oi.order_id "
95+ " JOIN products p ON oi.product_id = p.product_id "
96+ " WHERE c.country = 'USA' ORDER BY o.order_date DESC;" ,
97+
98+ // Subquery in FROM clause (Derived Table)
99+ " SELECT dt.category_name, dt.total_sales "
100+ " FROM (SELECT category, SUM(sales_amount) AS total_sales FROM sales GROUP BY category) AS dt "
101+ " WHERE dt.total_sales > 10000;" ,
102+
103+ " SELECT emp_details.name, emp_details.dept "
104+ " FROM (SELECT e.name, d.department_name AS dept FROM employees e JOIN departments d ON e.dept_id = d.id) emp_details "
105+ " ORDER BY emp_details.name;" ,
106+
107+ " SELECT * FROM (SELECT id FROM t1) AS derived_t1 JOIN (SELECT id FROM t2) AS derived_t2 ON derived_t1.id = derived_t2.id;" ,
108+
109+
110+ // SELECT ... INTO OUTFILE / DUMPFILE
111+ " SELECT user_id, username, email INTO OUTFILE '/tmp/users.txt' FROM user_accounts WHERE is_active = 1;" ,
112+ " SELECT * INTO OUTFILE '/tmp/products_export.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\" ' LINES TERMINATED BY '\\ n' FROM products;" ,
113+ " SELECT data_column INTO DUMPFILE '/tmp/data_blob.dat' FROM large_objects WHERE id = 42;" ,
114+ " SELECT col1, col2 INTO OUTFILE 'test_char_set.txt' CHARACTER SET 'utf8mb4' FIELDS ENCLOSED BY '`' FROM my_data;" ,
115+
116+
117+ // SELECT ... INTO variables
118+ " SELECT COUNT(*), MAX(salary) INTO @user_count, @max_sal FROM employees;" ,
119+ " SELECT name, email INTO @emp_name, @emp_email FROM employees WHERE id = 101;" ,
120+
121+ // SELECT ... FOR UPDATE / FOR SHARE
122+ " SELECT account_balance FROM accounts WHERE account_id = 123 FOR UPDATE;" ,
123+ " SELECT product_name, quantity FROM inventory WHERE product_id = 789 FOR SHARE;" ,
124+ " SELECT c.name, o.status FROM customers c JOIN orders o ON c.id = o.customer_id WHERE o.id = 500 FOR UPDATE OF c, o;" ,
125+ " SELECT item_name FROM stock_items WHERE category = 'electronics' FOR SHARE NOWAIT;" ,
126+ " SELECT * FROM pending_tasks FOR UPDATE SKIP LOCKED;" ,
127+ " SELECT id FROM users WHERE status = 'pending' FOR SHARE OF users SKIP LOCKED;" ,
128+
129+
130+ // Combined query
131+ " SELECT c.name AS customer_name, COUNT(o.order_id) AS total_orders, SUM(oi.price * oi.quantity) AS total_spent "
132+ " FROM customers AS c "
133+ " LEFT JOIN orders AS o ON c.customer_id = o.customer_id "
134+ " JOIN order_items AS oi ON o.order_id = oi.order_id "
135+ " WHERE c.registration_date > '2022-01-01' "
136+ " GROUP BY c.customer_id, c.name "
137+ " HAVING COUNT(o.order_id) > 2 AND SUM(oi.price * oi.quantity) > 500 "
138+ " ORDER BY total_spent DESC, customer_name ASC "
139+ " LIMIT 10, 5 "
140+ " FOR UPDATE OF c, o NOWAIT;"
36141 };
37142
38143 std::vector<std::string> insert_queries = {
39144 " INSERT INTO products VALUES ('a new gadget');" ,
40- " INSERT INTO logs VALUES (\" Error message with double quotes\" )" , // No semicolon
145+ " INSERT INTO logs VALUES (\" Error message with double quotes\" )" ,
41146 " INSERT INTO `special-table` VALUES ('escaped value \\ 'single quote\\ ' and \\\\ backslash');"
42147 };
43148
44149 std::vector<std::string> set_queries = {
45150 " SET @my_user_var = 'hello world';" ,
46151 " SET @anotherVar = 12345;" ,
47- " SET global max_connections = 1000" , // No semicolon
152+ " SET global max_connections = 1000" ,
48153 " SET @@session.net_write_timeout = 120;" ,
49154 " SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci';" ,
50155 " SET CHARACTER SET DEFAULT" ,
@@ -56,49 +161,47 @@ int main() {
56161 " DELETE FROM customers WHERE customer_id = 101;" ,
57162 " DELETE LOW_PRIORITY FROM orders WHERE order_date < '2023-01-01'" ,
58163 " DELETE QUICK IGNORE FROM logs WHERE log_level = 'DEBUG' ORDER BY timestamp DESC LIMIT 1000;" ,
59- " DELETE FROM events WHERE event_name = `expired-event`" , // Backticked identifier for value
60-
61- // Multi-table DELETE statements (simplified, based on current grammar)
62- " DELETE t1 FROM table1 AS t1, table2 AS t2 WHERE t1.id = t2.ref_id;" , // Needs table_reference_list_placeholder to be more robust
63- " DELETE FROM t1, t2 USING table1 AS t1 INNER JOIN table2 AS t2 ON t1.key = t2.key WHERE t1.value > 100;" , // Also simplified
164+ " DELETE FROM events WHERE event_name = `expired-event`" ,
64165
65- // DELETE without semicolon
66- " DELETE FROM old_records WHERE last_accessed < '2020-01-01'" ,
67-
68- // Potentially problematic or error cases for DELETE
69- " DELETE quick low_priority from test_table" , // Order of options might matter or not be fully supported yet
70- " DELETE FROM table1 WHERE id = " , // Incomplete WHERE
71- " DELETE tbl1 tbl2 FROM table_references" // Common MySQL multi-table, current grammar might simplify tbl1, tbl2 part
166+ // Multi-table DELETE statements
167+ " DELETE t1 FROM table1 AS t1, table2 AS t2 WHERE t1.id = t2.ref_id;" ,
168+ " DELETE FROM t1, t2 USING table1 AS t1 INNER JOIN table2 AS t2 ON t1.key = t2.key WHERE t1.value > 100;" ,
169+ " DELETE FROM old_records WHERE last_accessed < '2020-01-01'"
72170 };
73171
74-
75- std::cout << " \n ======= SELECT QUERIES =======\n " ;
76- for (const auto & query : select_queries) {
77- parse_and_print (parser, " SELECT" , query);
78- }
79-
80- std::cout << " \n ======= INSERT QUERIES =======\n " ;
81- for (const auto & query : insert_queries) {
82- parse_and_print (parser, " INSERT" , query);
83- }
84-
85- std::cout << " \n ======= SET QUERIES =======\n " ;
86- for (const auto & query : set_queries) {
87- parse_and_print (parser, " SET" , query);
88- }
89-
90- std::cout << " \n ======= DELETE QUERIES =======\n " ;
91- for (const auto & query : delete_queries) {
92- parse_and_print (parser, " DELETE" , query);
172+ const int iterations = 10000 ;
173+ for (int i = 0 ; i < iterations; i++) {
174+ if (verbose_print == true ) std::cout << " \n ======= SELECT QUERIES =======\n " ;
175+ for (const auto & query : select_queries) {
176+ parse_and_print (parser, " SELECT" , query);
177+ }
178+ if (verbose_print == true ) std::cout << " \n ======= INSERT QUERIES =======\n " ;
179+ for (const auto & query : insert_queries) {
180+ parse_and_print (parser, " INSERT" , query);
181+ }
182+
183+ if (verbose_print == true ) std::cout << " \n ======= SET QUERIES =======\n " ;
184+ for (const auto & query : set_queries) {
185+ parse_and_print (parser, " SET" , query);
186+ }
187+
188+ if (verbose_print == true ) std::cout << " \n ======= DELETE QUERIES =======\n " ;
189+ for (const auto & query : delete_queries) {
190+ parse_and_print (parser, " DELETE" , query);
191+ }
192+
193+ // Example of a known failing query (due to function call in expression_placeholder)
194+ if (verbose_print == true ) std::cout << " \n ======= KNOWN FAILING SET QUERY (Function Call) =======\n " ;
195+ parse_and_print (parser, " SET" , " SET @myvar = some_function(1, 'a');" );
196+
197+ if (verbose_print == true ) std::cout << " \n ======= KNOWN FAILING SET QUERY (Invalid Identifier) =======\n " ;
198+ parse_and_print (parser, " SET" , " SET global invalid-variable = 100;" );
199+ if (verbose_print == true ) { verbose_print=false ; }
200+ if ((i+1 ) % 1000 == 0 ) {
201+ std::cout << i+1 << std::endl;
202+ }
93203 }
94-
95- // Example of a known failing query (due to function call in expression_placeholder)
96- std::cout << " \n ======= KNOWN FAILING SET QUERY (Function Call) =======\n " ;
97- parse_and_print (parser, " SET" , " SET @myvar = some_function(1, 'a');" );
98-
99- std::cout << " \n ======= KNOWN FAILING SET QUERY (Invalid Identifier) =======\n " ;
100- parse_and_print (parser, " SET" , " SET global invalid-variable = 100;" );
101-
102-
204+ std::cout << " Queries: " << queries << std::endl;
103205 return 0 ;
104206}
207+
0 commit comments