Skip to content

Commit

Permalink
create mysql test suite (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
lu-zhengda authored Nov 22, 2023
1 parent a535049 commit d6baeb5
Show file tree
Hide file tree
Showing 109 changed files with 1,729 additions and 22 deletions.
1 change: 1 addition & 0 deletions dbms_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func TestQueriesPerDBMS(t *testing.T) {
DBMSPostgres,
DBMSOracle,
DBMSSQLServer,
DBMSMySQL,
}

for _, dbms := range dbmsTypes {
Expand Down
46 changes: 24 additions & 22 deletions sqllexer_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,33 @@ const (
)

var commands = map[string]bool{
"SELECT": true,
"INSERT": true,
"UPDATE": true,
"DELETE": true,
"CREATE": true,
"ALTER": true,
"DROP": true,
"JOIN": true,
"GRANT": true,
"REVOKE": true,
"COMMIT": true,
"BEGIN": true,
"TRUNCATE": true,
"MERGE": true,
"EXECUTE": true,
"EXEC": true,
"EXPLAIN": true,
"SELECT": true,
"INSERT": true,
"UPDATE": true,
"DELETE": true,
"CREATE": true,
"ALTER": true,
"DROP": true,
"JOIN": true,
"GRANT": true,
"REVOKE": true,
"COMMIT": true,
"BEGIN": true,
"TRUNCATE": true,
"MERGE": true,
"EXECUTE": true,
"EXEC": true,
"EXPLAIN": true,
"STRAIGHT_JOIN": true,
}

var tableIndicators = map[string]bool{
"FROM": true,
"JOIN": true,
"INTO": true,
"UPDATE": true,
"TABLE": true,
"FROM": true,
"JOIN": true,
"INTO": true,
"UPDATE": true,
"TABLE": true,
"STRAIGHT_JOIN": true, // MySQL
}

var keywords = map[string]bool{
Expand Down
16 changes: 16 additions & 0 deletions testdata/mysql/complex/super-complex-poorly-written-sql.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "SELECT a.*, b.totalAmount, CASE WHEN c.id IS NOT NULL THEN d.description ELSE 'N/A' END AS description\n-- Joining table a with b to get total amounts. If c.id is not null, get description from d\nFROM (SELECT id, name, status, customer_id\n FROM orders\n WHERE order_date > DATE_ADD(CURDATE(), INTERVAL -6 MONTH)\n AND status IN ('Pending', 'Completed')\n AND customer_id IN (SELECT customer_id FROM customers WHERE region IN ('East', 'West') AND last_order_date > DATE_ADD(CURDATE(), INTERVAL -1 YEAR))\n ORDER BY name DESC) a\nINNER JOIN (SELECT order_id, SUM(amount) AS totalAmount FROM order_details GROUP BY order_id) b ON a.id = b.order_id\nLEFT JOIN audit_log c ON a.id = c.order_id\nLEFT JOIN (SELECT DISTINCT status, description FROM status_descriptions) d ON a.status = d.status\nWHERE a.name LIKE '%test%'\n-- Filtering on name containing 'test'\nAND (b.totalAmount > 1000 OR b.totalAmount IS NULL)\nORDER BY a.order_date DESC, a.name;",
"outputs": [
{
"expected": "SELECT a. *, b.totalAmount, CASE WHEN c.id IS NOT ? THEN d.description ELSE ? END FROM ( SELECT id, name, status, customer_id FROM orders WHERE order_date > DATE_ADD ( CURDATE ( ), INTERVAL ? MONTH ) AND status IN ( ? ) AND customer_id IN ( SELECT customer_id FROM customers WHERE region IN ( ? ) AND last_order_date > DATE_ADD ( CURDATE ( ), INTERVAL ? YEAR ) ) ORDER BY name DESC ) a INNER JOIN ( SELECT order_id, SUM ( amount ) FROM order_details GROUP BY order_id ) b ON a.id = b.order_id LEFT JOIN audit_log c ON a.id = c.order_id LEFT JOIN ( SELECT DISTINCT status, description FROM status_descriptions ) d ON a.status = d.status WHERE a.name LIKE ? AND ( b.totalAmount > ? OR b.totalAmount IS ? ) ORDER BY a.order_date DESC, a.name",
"statement_metadata": {
"size": 195,
"tables": ["orders", "customers", "order_details", "audit_log", "status_descriptions"],
"commands": ["SELECT", "JOIN"],
"comments": ["-- Joining table a with b to get total amounts. If c.id is not null, get description from d", "-- Filtering on name containing 'test'"],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/complex/super-complex-sql-multiple-joins.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "SELECT a.id, a.name, IFNULL(b.totalAmount, 0) AS totalAmount, c.comment, d.productCount, e.latestOrderDate\n-- Extremely complex query combining multiple joins, subqueries, and inline views\nFROM (SELECT id, name FROM customers WHERE status = 'Active') a\nJOIN (SELECT customer_id, SUM(amount) AS totalAmount FROM orders GROUP BY customer_id) b ON a.id = b.customer_id\nLEFT JOIN (SELECT customer_id, comment FROM customer_feedback WHERE rating = 5 ORDER BY feedback_date DESC LIMIT 1) c ON a.id = c.customer_id\nLEFT JOIN (SELECT customer_id, COUNT(*) AS productCount FROM order_details GROUP BY customer_id) d ON a.id = d.customer_id\nLEFT JOIN (SELECT customer_id, MAX(order_date) AS latestOrderDate FROM orders WHERE status IN ('Completed', 'Shipped') GROUP BY customer_id) e ON a.id = e.customer_id\nWHERE a.name LIKE '%Corp%' AND (b.totalAmount > 1000 OR d.productCount > 5)\nORDER BY a.name, totalAmount DESC;",
"outputs": [
{
"expected": "SELECT a.id, a.name, IFNULL ( b.totalAmount, ? ), c.comment, d.productCount, e.latestOrderDate FROM ( SELECT id, name FROM customers WHERE status = ? ) a JOIN ( SELECT customer_id, SUM ( amount ) FROM orders GROUP BY customer_id ) b ON a.id = b.customer_id LEFT JOIN ( SELECT customer_id, comment FROM customer_feedback WHERE rating = ? ORDER BY feedback_date DESC LIMIT ? ) c ON a.id = c.customer_id LEFT JOIN ( SELECT customer_id, COUNT ( * ) FROM order_details GROUP BY customer_id ) d ON a.id = d.customer_id LEFT JOIN ( SELECT customer_id, MAX ( order_date ) FROM orders WHERE status IN ( ? ) GROUP BY customer_id ) e ON a.id = e.customer_id WHERE a.name LIKE ? AND ( b.totalAmount > ? OR d.productCount > ? ) ORDER BY a.name, totalAmount DESC",
"statement_metadata": {
"size": 136,
"tables": ["customers", "orders", "customer_feedback", "order_details"],
"commands": ["SELECT", "JOIN"],
"comments": ["-- Extremely complex query combining multiple joins, subqueries, and inline views"],
"procedures": []
}
}
]
}

15 changes: 15 additions & 0 deletions testdata/mysql/complex/super-complex-sql-nested-subqueries.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"input": "SELECT t1.id, t1.status, t3.totalAmount, t4.commentsCount, CASE WHEN t5.latestCommentDate IS NOT NULL THEN t5.latestCommentDate ELSE 'No Comments' END AS latestComment\n-- Complex query joining multiple subqueries and using conditional logic\nFROM (SELECT id, status FROM orders WHERE customer_id IN (SELECT id FROM customers WHERE region = 'North') AND order_date > (SELECT MAX(order_date) FROM orders WHERE status = 'Pending')) t1\nJOIN (SELECT order_id, SUM(amount) AS totalAmount FROM order_details WHERE product_id IN (SELECT id FROM products WHERE name LIKE '%Premium%') GROUP BY order_id) t3 ON t1.id = t3.order_id\nLEFT JOIN (SELECT order_id, COUNT(*) AS commentsCount FROM order_comments GROUP BY order_id) t4 ON t1.id = t4.order_id\nLEFT JOIN (SELECT order_id, MAX(comment_date) AS latestCommentDate FROM order_comments WHERE comment LIKE '%urgent%' GROUP BY order_id) t5 ON t1.id = t5.order_id\nWHERE t1.status NOT IN ('Cancelled', 'Returned') AND (t3.totalAmount > 500 OR t4.commentsCount > 10)\nORDER BY t1.id, latestComment DESC;",
"outputs": [
{
"expected": "SELECT t?.id, t?.status, t?.totalAmount, t?.commentsCount, CASE WHEN t?.latestCommentDate IS NOT ? THEN t?.latestCommentDate ELSE ? END FROM ( SELECT id, status FROM orders WHERE customer_id IN ( SELECT id FROM customers WHERE region = ? ) AND order_date > ( SELECT MAX ( order_date ) FROM orders WHERE status = ? ) ) t? JOIN ( SELECT order_id, SUM ( amount ) FROM order_details WHERE product_id IN ( SELECT id FROM products WHERE name LIKE ? ) GROUP BY order_id ) t? ON t?.id = t?.order_id LEFT JOIN ( SELECT order_id, COUNT ( * ) FROM order_comments GROUP BY order_id ) t? ON t?.id = t?.order_id LEFT JOIN ( SELECT order_id, MAX ( comment_date ) FROM order_comments WHERE comment LIKE ? GROUP BY order_id ) t? ON t?.id = t?.order_id WHERE t?.status NOT IN ( ? ) AND ( t?.totalAmount > ? OR t?.commentsCount > ? ) ORDER BY t?.id, latestComment DESC",
"statement_metadata": {
"size": 132,
"tables": ["orders", "customers", "order_details", "products", "order_comments"],
"commands": ["SELECT", "JOIN"],
"comments": ["-- Complex query joining multiple subqueries and using conditional logic"],
"procedures": []
}
}
]
}
16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-basic.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "DELETE FROM orders WHERE status = 'Cancelled';",
"outputs": [
{
"expected": "DELETE FROM orders WHERE status = ?",
"statement_metadata": {
"size": 12,
"tables": ["orders"],
"commands": ["DELETE"],
"comments": [],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-cascade.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "DELETE FROM customers WHERE region = 'North'; -- Assuming CASCADE DELETE is set up on the foreign key in the orders table",
"outputs": [
{
"expected": "DELETE FROM customers WHERE region = ?",
"statement_metadata": {
"size": 90,
"tables": ["customers"],
"commands": ["DELETE"],
"comments": ["-- Assuming CASCADE DELETE is set up on the foreign key in the orders table"],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-cascading-triggers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "DELETE FROM customers WHERE id = 1; -- Assumes a trigger exists for cascading delete to orders",
"outputs": [
{
"expected": "DELETE FROM customers WHERE id = ?",
"statement_metadata": {
"size": 73,
"tables": ["customers"],
"commands": ["DELETE"],
"comments": ["-- Assumes a trigger exists for cascading delete to orders"],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-conditional-logic.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "DELETE FROM orders WHERE status = IF(DAYOFWEEK(CURDATE()) = 1, 'Pending', 'Completed');",
"outputs": [
{
"expected": "DELETE FROM orders WHERE status = IF ( DAYOFWEEK ( CURDATE ( ) ) = ?, ?, ? )",
"statement_metadata": {
"size": 12,
"tables": ["orders"],
"commands": ["DELETE"],
"comments": [],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-foreign-key-constraints.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "DELETE FROM orders WHERE id IN (SELECT order_id FROM order_details WHERE quantity = 0);",
"outputs": [
{
"expected": "DELETE FROM orders WHERE id IN ( SELECT order_id FROM order_details WHERE quantity = ? )",
"statement_metadata": {
"size": 31,
"tables": ["orders", "order_details"],
"commands": ["DELETE", "SELECT"],
"comments": [],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-free-disk-space.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "DELETE FROM orders WHERE order_date < '2020-01-01'; OPTIMIZE TABLE orders;",
"outputs": [
{
"expected": "DELETE FROM orders WHERE order_date < ?; OPTIMIZE TABLE orders",
"statement_metadata": {
"size": 12,
"tables": ["orders"],
"commands": ["DELETE"],
"comments": [],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-join-multiple-conditions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "DELETE o FROM orders o JOIN customers c ON o.customer_id = c.id WHERE o.status = 'Completed' AND c.region = 'South';",
"outputs": [
{
"expected": "DELETE o FROM orders o JOIN customers c ON o.customer_id = c.id WHERE o.status = ? AND c.region = ?",
"statement_metadata": {
"size": 25,
"tables": ["orders", "customers"],
"commands": ["DELETE", "JOIN"],
"comments": [],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-lock-tables.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "LOCK TABLES orders WRITE; DELETE FROM orders WHERE status = 'Failed'; UNLOCK TABLES;",
"outputs": [
{
"expected": "LOCK TABLES orders WRITE; DELETE FROM orders WHERE status = ?; UNLOCK TABLES",
"statement_metadata": {
"size": 12,
"tables": ["orders"],
"commands": ["DELETE"],
"comments": [],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-multiple-tables.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "DELETE orders, order_details FROM orders INNER JOIN order_details ON orders.id = order_details.order_id WHERE orders.status = 'Obsolete';",
"outputs": [
{
"expected": "DELETE orders, order_details FROM orders INNER JOIN order_details ON orders.id = order_details.order_id WHERE orders.status = ?",
"statement_metadata": {
"size": 29,
"tables": ["orders", "order_details"],
"commands": ["DELETE", "JOIN"],
"comments": [],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-optimized-conditions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "DELETE FROM orders WHERE status = 'Completed' AND order_date < DATE_SUB(NOW(), INTERVAL 1 YEAR);",
"outputs": [
{
"expected": "DELETE FROM orders WHERE status = ? AND order_date < DATE_SUB ( NOW ( ), INTERVAL ? YEAR )",
"statement_metadata": {
"size": 12,
"tables": ["orders"],
"commands": ["DELETE"],
"comments": [],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-order-by-limit.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "DELETE FROM orders WHERE status = 'Completed' ORDER BY order_date DESC LIMIT 5;",
"outputs": [
{
"expected": "DELETE FROM orders WHERE status = ? ORDER BY order_date DESC LIMIT ?",
"statement_metadata": {
"size": 12,
"tables": ["orders"],
"commands": ["DELETE"],
"comments": [],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-range-conditions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "DELETE FROM orders WHERE amount BETWEEN 100 AND 500;",
"outputs": [
{
"expected": "DELETE FROM orders WHERE amount BETWEEN ? AND ?",
"statement_metadata": {
"size": 12,
"tables": ["orders"],
"commands": ["DELETE"],
"comments": [],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-regular-expressions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "DELETE FROM orders WHERE status REGEXP '^C.*';",
"outputs": [
{
"expected": "DELETE FROM orders WHERE status REGEXP ?",
"statement_metadata": {
"size": 12,
"tables": ["orders"],
"commands": ["DELETE"],
"comments": [],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-safe-update-mode.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "SET SQL_SAFE_UPDATES = 0; DELETE FROM orders WHERE customer_id = 1; SET SQL_SAFE_UPDATES = 1;",
"outputs": [
{
"expected": "SET SQL_SAFE_UPDATES = ?; DELETE FROM orders WHERE customer_id = ?; SET SQL_SAFE_UPDATES = ?",
"statement_metadata": {
"size": 12,
"tables": ["orders"],
"commands": ["DELETE"],
"comments": [],
"procedures": []
}
}
]
}

16 changes: 16 additions & 0 deletions testdata/mysql/delete/delete-subquery-optimization.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"input": "DELETE FROM orders WHERE id IN (SELECT id FROM orders WHERE status = 'Failed' LIMIT 10);",
"outputs": [
{
"expected": "DELETE FROM orders WHERE id IN ( SELECT id FROM orders WHERE status = ? LIMIT ? )",
"statement_metadata": {
"size": 18,
"tables": ["orders"],
"commands": ["DELETE", "SELECT"],
"comments": [],
"procedures": []
}
}
]
}

Loading

0 comments on commit d6baeb5

Please sign in to comment.