Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DBMON-3186] create mysql test suite #32

Merged
merged 1 commit into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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