diff --git a/dbms_test.go b/dbms_test.go index bbecee5..d78da9c 100644 --- a/dbms_test.go +++ b/dbms_test.go @@ -36,6 +36,7 @@ func TestQueriesPerDBMS(t *testing.T) { dbmsTypes := []DBMSType{ DBMSPostgres, DBMSOracle, + DBMSSQLServer, } for _, dbms := range dbmsTypes { diff --git a/obfuscator.go b/obfuscator.go index f7e105e..ae2d464 100644 --- a/obfuscator.go +++ b/obfuscator.go @@ -109,7 +109,7 @@ func (o *Obfuscator) ObfuscateTokenValue(token Token, lexerOpts ...lexerOption) } else { return token.Value } - case IDENT: + case IDENT, QUOTED_IDENT: if o.config.ReplaceBoolean && isBoolean(token.Value) { return StringPlaceholder } diff --git a/testdata/mssql/complex/extremely-complex-poorly-written-sql.json b/testdata/mssql/complex/extremely-complex-poorly-written-sql.json new file mode 100644 index 0000000..a8442bd --- /dev/null +++ b/testdata/mssql/complex/extremely-complex-poorly-written-sql.json @@ -0,0 +1,16 @@ +{ + "input": "WITH ComplexCTE AS (SELECT t1.id, t2.amount, ROW_NUMBER() OVER(PARTITION BY t1.customer_id ORDER BY t2.amount DESC) AS rn FROM (SELECT id, customer_id, status FROM orders WHERE YEAR(order_date) = YEAR(GETDATE()) AND status NOT IN ('Cancelled', 'Returned')) t1 INNER JOIN (SELECT order_id, SUM(amount) AS amount FROM order_details GROUP BY order_id) t2 ON t1.id = t2.order_id WHERE t2.amount > 500), SecondCTE AS (SELECT c1.*, c2.name, c2.region FROM ComplexCTE c1 INNER JOIN customers c2 ON c1.customer_id = c2.id WHERE c2.region IN ('East', 'West') AND c1.rn < 5) SELECT s.id, s.name, s.amount, p.product_name, CASE WHEN s.amount > 1000 THEN 'High' ELSE 'Low' END AS ValueCategory FROM SecondCTE s LEFT JOIN (SELECT DISTINCT p1.order_id, p2.product_name FROM order_products p1 INNER JOIN products p2 ON p1.product_id = p2.id) p ON s.id = p.order_id WHERE s.region = 'East' AND s.status LIKE '%Active%' ORDER BY s.amount DESC, s.name;", + "outputs": [ + { + "expected": "WITH ComplexCTE AS ( SELECT t?.id, t?.amount, ROW_NUMBER ( ) OVER ( PARTITION BY t?.customer_id ORDER BY t?.amount DESC ) FROM ( SELECT id, customer_id, status FROM orders WHERE YEAR ( order_date ) = YEAR ( GETDATE ( ) ) AND status NOT IN ( ? ) ) t? INNER JOIN ( SELECT order_id, SUM ( amount ) FROM order_details GROUP BY order_id ) t? ON t?.id = t?.order_id WHERE t?.amount > ? ), SecondCTE AS ( SELECT c?. *, c?.name, c?.region FROM ComplexCTE c? INNER JOIN customers c? ON c?.customer_id = c?.id WHERE c?.region IN ( ? ) AND c?.rn < ? ) SELECT s.id, s.name, s.amount, p.product_name, CASE WHEN s.amount > ? THEN ? ELSE ? END FROM SecondCTE s LEFT JOIN ( SELECT DISTINCT p?.order_id, p?.product_name FROM order_products p? INNER JOIN products p? ON p?.product_id = p?.id ) p ON s.id = p.order_id WHERE s.region = ? AND s.status LIKE ? ORDER BY s.amount DESC, s.name", + "statement_metadata": { + "size": 79, + "tables": ["orders", "order_details", "ComplexCTE", "customers", "SecondCTE", "order_products", "products"], + "commands": ["SELECT", "JOIN"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/complex/indexed-views.json b/testdata/mssql/complex/indexed-views.json new file mode 100644 index 0000000..5d78886 --- /dev/null +++ b/testdata/mssql/complex/indexed-views.json @@ -0,0 +1,17 @@ +{ + "input": "CREATE VIEW dbo.OrderSummary WITH SCHEMABINDING AS SELECT customer_id, COUNT_BIG(*) AS TotalOrders, SUM(amount) AS TotalAmount FROM dbo.orders GROUP BY customer_id; CREATE UNIQUE CLUSTERED INDEX IDX_V1 ON dbo.OrderSummary(customer_id);", + "outputs": [ + { + "expected": "CREATE VIEW dbo.OrderSummary WITH SCHEMABINDING AS SELECT customer_id, COUNT_BIG ( * ), SUM ( amount ) FROM dbo.orders GROUP BY customer_id; CREATE UNIQUE CLUSTERED INDEX IDX_V? ON dbo.OrderSummary ( customer_id )", + "statement_metadata": { + "size": 22, + "tables": ["dbo.orders"], + "commands": ["CREATE", "SELECT"], + "comments": [], + "procedures": [], + "views": ["dbo.OrderSummary"] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/complex/partitioned-tables-indexes.json b/testdata/mssql/complex/partitioned-tables-indexes.json new file mode 100644 index 0000000..c06612e --- /dev/null +++ b/testdata/mssql/complex/partitioned-tables-indexes.json @@ -0,0 +1,16 @@ +{ + "input": "CREATE PARTITION FUNCTION myRangePF1 (INT) AS RANGE LEFT FOR VALUES (1, 100, 1000); CREATE PARTITION SCHEME myScheme AS PARTITION myRangePF1 TO ([PRIMARY], [SECONDARY], [TERTIARY]); CREATE TABLE partitionedTable (id INT) ON myScheme(id);", + "outputs": [ + { + "expected": "CREATE PARTITION FUNCTION myRangePF? ( INT ) LEFT FOR VALUES ( ? ); CREATE PARTITION SCHEME myScheme myRangePF? TO ( PRIMARY, SECONDARY, TERTIARY ); CREATE TABLE partitionedTable ( id INT ) ON myScheme ( id )", + "statement_metadata": { + "size": 22, + "tables": ["partitionedTable"], + "commands": ["CREATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/complex/super-complex-poorly-written-sql.json b/testdata/mssql/complex/super-complex-poorly-written-sql.json new file mode 100644 index 0000000..41bd0e0 --- /dev/null +++ b/testdata/mssql/complex/super-complex-poorly-written-sql.json @@ -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 FROM (SELECT id, name, status, customer_id FROM orders WHERE order_date > DATEADD(month, -6, GETDATE()) AND status IN ('Pending', 'Completed') AND customer_id IN (SELECT customer_id FROM customers WHERE region IN ('East', 'West') AND last_order_date > DATEADD(year, -1, GETDATE())) ORDER BY name DESC) a INNER JOIN (SELECT order_id, SUM(amount) AS totalAmount 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 '%test%' AND (b.totalAmount > 1000 OR b.totalAmount IS NULL) ORDER 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 > DATEADD ( month, ?, GETDATE ( ) ) AND status IN ( ? ) AND customer_id IN ( SELECT customer_id FROM customers WHERE region IN ( ? ) AND last_order_date > DATEADD ( year, ?, GETDATE ( ) ) ) 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": 66, + "tables": ["orders", "customers", "order_details", "audit_log", "status_descriptions"], + "commands": ["SELECT", "JOIN"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/delete/conditional-delete-case.json b/testdata/mssql/delete/conditional-delete-case.json new file mode 100644 index 0000000..66a0da8 --- /dev/null +++ b/testdata/mssql/delete/conditional-delete-case.json @@ -0,0 +1,16 @@ +{ + "input": "DELETE FROM orders WHERE status = CASE WHEN order_date < GETDATE() - 90 THEN 'Expired' ELSE 'Active' END;", + "outputs": [ + { + "expected": "DELETE FROM orders WHERE status = CASE WHEN order_date < GETDATE ( ) - ? THEN ? ELSE ? END", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["DELETE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/delete/delete-basic.json b/testdata/mssql/delete/delete-basic.json new file mode 100644 index 0000000..eb9025d --- /dev/null +++ b/testdata/mssql/delete/delete-basic.json @@ -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": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/delete/delete-cascade.json b/testdata/mssql/delete/delete-cascade.json new file mode 100644 index 0000000..2e4a3b5 --- /dev/null +++ b/testdata/mssql/delete/delete-cascade.json @@ -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": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/delete/delete-rowlock-hint.json b/testdata/mssql/delete/delete-rowlock-hint.json new file mode 100644 index 0000000..b564965 --- /dev/null +++ b/testdata/mssql/delete/delete-rowlock-hint.json @@ -0,0 +1,16 @@ +{ + "input": "DELETE FROM orders WITH (ROWLOCK) WHERE status = 'Pending';", + "outputs": [ + { + "expected": "DELETE FROM orders WITH ( ROWLOCK ) WHERE status = ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["DELETE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/delete/delete-using-subquery.json b/testdata/mssql/delete/delete-using-subquery.json new file mode 100644 index 0000000..2d739ca --- /dev/null +++ b/testdata/mssql/delete/delete-using-subquery.json @@ -0,0 +1,16 @@ +{ + "input": "DELETE FROM orders WHERE customer_id IN (SELECT id FROM customers WHERE region = 'West');", + "outputs": [ + { + "expected": "DELETE FROM orders WHERE customer_id IN ( SELECT id FROM customers WHERE region = ? )", + "statement_metadata": { + "size": 27, + "tables": ["orders", "customers"], + "commands": ["DELETE", "SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/delete/delete-using-table-variable.json b/testdata/mssql/delete/delete-using-table-variable.json new file mode 100644 index 0000000..91809fe --- /dev/null +++ b/testdata/mssql/delete/delete-using-table-variable.json @@ -0,0 +1,16 @@ +{ + "input": "DECLARE @ExpiredOrders TABLE (id INT); INSERT INTO @ExpiredOrders (id) SELECT id FROM orders WHERE order_date < GETDATE() - 365; DELETE FROM orders WHERE id IN (SELECT id FROM @ExpiredOrders);", + "outputs": [ + { + "expected": "DECLARE @ExpiredOrders TABLE ( id INT ); INSERT INTO @ExpiredOrders ( id ) SELECT id FROM orders WHERE order_date < GETDATE ( ) - ?; DELETE FROM orders WHERE id IN ( SELECT id FROM @ExpiredOrders )", + "statement_metadata": { + "size": 24, + "tables": ["orders"], + "commands": ["INSERT", "SELECT", "DELETE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/delete/delete-with-cte.json b/testdata/mssql/delete/delete-with-cte.json new file mode 100644 index 0000000..6912195 --- /dev/null +++ b/testdata/mssql/delete/delete-with-cte.json @@ -0,0 +1,16 @@ +{ + "input": "WITH OldOrders AS (SELECT id FROM orders WHERE order_date < '2022-01-01') DELETE FROM orders WHERE id IN (SELECT id FROM OldOrders);", + "outputs": [ + { + "expected": "WITH OldOrders AS ( SELECT id FROM orders WHERE order_date < ? ) DELETE FROM orders WHERE id IN ( SELECT id FROM OldOrders )", + "statement_metadata": { + "size": 27, + "tables": ["orders", "OldOrders"], + "commands": ["SELECT", "DELETE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/delete/delete-with-join.json b/testdata/mssql/delete/delete-with-join.json new file mode 100644 index 0000000..7fa63f3 --- /dev/null +++ b/testdata/mssql/delete/delete-with-join.json @@ -0,0 +1,16 @@ +{ + "input": "DELETE o FROM orders o INNER JOIN customers c ON o.customer_id = c.id WHERE c.region = 'East' AND o.status = 'Pending';", + "outputs": [ + { + "expected": "DELETE o FROM orders o INNER JOIN customers c ON o.customer_id = c.id WHERE c.region = ? AND o.status = ?", + "statement_metadata": { + "size": 25, + "tables": ["orders", "customers"], + "commands": ["DELETE", "JOIN"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/delete/delete-with-output.json b/testdata/mssql/delete/delete-with-output.json new file mode 100644 index 0000000..b3373cc --- /dev/null +++ b/testdata/mssql/delete/delete-with-output.json @@ -0,0 +1,16 @@ +{ + "input": "DELETE FROM orders OUTPUT DELETED.* WHERE status = 'Shipped';", + "outputs": [ + { + "expected": "DELETE FROM orders OUTPUT DELETED. * WHERE status = ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["DELETE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/delete/delete-with-top.json b/testdata/mssql/delete/delete-with-top.json new file mode 100644 index 0000000..12116c3 --- /dev/null +++ b/testdata/mssql/delete/delete-with-top.json @@ -0,0 +1,16 @@ +{ + "input": "DELETE TOP (10) FROM orders WHERE status = 'Pending';", + "outputs": [ + { + "expected": "DELETE TOP ( ? ) FROM orders WHERE status = ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["DELETE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/insert/insert-basic.json b/testdata/mssql/insert/insert-basic.json new file mode 100644 index 0000000..fe1d97f --- /dev/null +++ b/testdata/mssql/insert/insert-basic.json @@ -0,0 +1,16 @@ +{ + "input": "INSERT INTO orders (customer_id, order_date, status) VALUES (1, GETDATE(), 'Pending');", + "outputs": [ + { + "expected": "INSERT INTO orders ( customer_id, order_date, status ) VALUES ( ?, GETDATE ( ), ? )", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["INSERT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/insert/insert-default-values.json b/testdata/mssql/insert/insert-default-values.json new file mode 100644 index 0000000..9c8a08a --- /dev/null +++ b/testdata/mssql/insert/insert-default-values.json @@ -0,0 +1,16 @@ +{ + "input": "INSERT INTO orders DEFAULT VALUES;", + "outputs": [ + { + "expected": "INSERT INTO orders DEFAULT VALUES", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["INSERT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/insert/insert-identity-insert.json b/testdata/mssql/insert/insert-identity-insert.json new file mode 100644 index 0000000..5fdc3e0 --- /dev/null +++ b/testdata/mssql/insert/insert-identity-insert.json @@ -0,0 +1,16 @@ +{ + "input": "SET IDENTITY_INSERT orders ON; INSERT INTO orders (id, customer_id, order_date, status) VALUES (100, 3, GETDATE(), 'Pending'); SET IDENTITY_INSERT orders OFF;", + "outputs": [ + { + "expected": "SET IDENTITY_INSERT orders ON; INSERT INTO orders ( id, customer_id, order_date, status ) VALUES ( ?, GETDATE ( ), ? ); SET IDENTITY_INSERT orders OFF", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["INSERT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/insert/insert-merge.json b/testdata/mssql/insert/insert-merge.json new file mode 100644 index 0000000..81d75e6 --- /dev/null +++ b/testdata/mssql/insert/insert-merge.json @@ -0,0 +1,16 @@ +{ + "input": "MERGE INTO orders AS target USING (SELECT customer_id, order_date, status FROM incoming_orders) AS source ON target.id = source.id WHEN NOT MATCHED THEN INSERT (customer_id, order_date, status) VALUES (source.customer_id, source.order_date, source.status);", + "outputs": [ + { + "expected": "MERGE INTO orders USING ( SELECT customer_id, order_date, status FROM incoming_orders ) ON target.id = source.id WHEN NOT MATCHED THEN INSERT ( customer_id, order_date, status ) VALUES ( source.customer_id, source.order_date, source.status )", + "statement_metadata": { + "size": 38, + "tables": ["orders", "incoming_orders"], + "commands": ["MERGE", "SELECT", "INSERT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/insert/insert-output.json b/testdata/mssql/insert/insert-output.json new file mode 100644 index 0000000..d16031f --- /dev/null +++ b/testdata/mssql/insert/insert-output.json @@ -0,0 +1,16 @@ +{ + "input": "INSERT INTO orders (customer_id, order_date, status) OUTPUT INSERTED.id VALUES (3, GETDATE(), 'Processing');", + "outputs": [ + { + "expected": "INSERT INTO orders ( customer_id, order_date, status ) OUTPUT INSERTED.id VALUES ( ?, GETDATE ( ), ? )", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["INSERT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/insert/insert-select-into.json b/testdata/mssql/insert/insert-select-into.json new file mode 100644 index 0000000..7470011 --- /dev/null +++ b/testdata/mssql/insert/insert-select-into.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT * INTO new_orders FROM orders WHERE status = 'Pending';", + "outputs": [ + { + "expected": "SELECT * INTO new_orders FROM orders WHERE status = ?", + "statement_metadata": { + "size": 22, + "tables": ["new_orders", "orders"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/insert/insert-subquery-values.json b/testdata/mssql/insert/insert-subquery-values.json new file mode 100644 index 0000000..af7a2a0 --- /dev/null +++ b/testdata/mssql/insert/insert-subquery-values.json @@ -0,0 +1,16 @@ +{ + "input": "INSERT INTO order_totals (order_id, total_amount) VALUES ((SELECT MAX(id) FROM orders), 500);", + "outputs": [ + { + "expected": "INSERT INTO order_totals ( order_id, total_amount ) VALUES ( ( SELECT MAX ( id ) FROM orders ), ? )", + "statement_metadata": { + "size": 30, + "tables": ["order_totals", "orders"], + "commands": ["INSERT", "SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/insert/insert-top-orderby.json b/testdata/mssql/insert/insert-top-orderby.json new file mode 100644 index 0000000..2469fd3 --- /dev/null +++ b/testdata/mssql/insert/insert-top-orderby.json @@ -0,0 +1,16 @@ +{ + "input": "INSERT INTO top_orders (id, amount) SELECT TOP 5 id, amount FROM orders ORDER BY amount DESC;", + "outputs": [ + { + "expected": "INSERT INTO top_orders ( id, amount ) SELECT TOP ? id, amount FROM orders ORDER BY amount DESC", + "statement_metadata": { + "size": 28, + "tables": ["top_orders", "orders"], + "commands": ["INSERT", "SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/insert/insert-values-multiple-rows.json b/testdata/mssql/insert/insert-values-multiple-rows.json new file mode 100644 index 0000000..ec79720 --- /dev/null +++ b/testdata/mssql/insert/insert-values-multiple-rows.json @@ -0,0 +1,16 @@ +{ + "input": "INSERT INTO customers (name, region) VALUES ('John Doe', 'North'), ('Jane Smith', 'South');", + "outputs": [ + { + "expected": "INSERT INTO customers ( name, region ) VALUES ( ? ), ( ? )", + "statement_metadata": { + "size": 15, + "tables": ["customers"], + "commands": ["INSERT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/insert/insert-with-select.json b/testdata/mssql/insert/insert-with-select.json new file mode 100644 index 0000000..3039280 --- /dev/null +++ b/testdata/mssql/insert/insert-with-select.json @@ -0,0 +1,16 @@ +{ + "input": "INSERT INTO orders_archive (id, customer_id, order_date, status) SELECT id, customer_id, order_date, status FROM orders WHERE status = 'Completed';", + "outputs": [ + { + "expected": "INSERT INTO orders_archive ( id, customer_id, order_date, status ) SELECT id, customer_id, order_date, status FROM orders WHERE status = ?", + "statement_metadata": { + "size": 32, + "tables": ["orders_archive", "orders"], + "commands": ["INSERT", "SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/insert/using-throw-error-handling.json b/testdata/mssql/insert/using-throw-error-handling.json new file mode 100644 index 0000000..8458f77 --- /dev/null +++ b/testdata/mssql/insert/using-throw-error-handling.json @@ -0,0 +1,16 @@ +{ + "input": "BEGIN TRY INSERT INTO orders (customer_id, amount) VALUES (1, -100); END TRY BEGIN CATCH THROW; END CATCH;", + "outputs": [ + { + "expected": "BEGIN TRY INSERT INTO orders ( customer_id, amount ) VALUES ( ? ); END TRY BEGIN CATCH THROW; END CATCH", + "statement_metadata": { + "size": 17, + "tables": ["orders"], + "commands": ["BEGIN", "INSERT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/procedure/complex-stored-procedure-multiple-operations.json b/testdata/mssql/procedure/complex-stored-procedure-multiple-operations.json new file mode 100644 index 0000000..485e68d --- /dev/null +++ b/testdata/mssql/procedure/complex-stored-procedure-multiple-operations.json @@ -0,0 +1,27 @@ +{ + "input": "CREATE OR ALTER PROCEDURE ManageCustomerOrders @customerId INT AS BEGIN SET NOCOUNT ON; IF NOT EXISTS (SELECT 1 FROM customers WHERE id = @customerId) BEGIN THROW 50001, 'Customer not found.', 1; END; UPDATE orders SET status = 'Reviewed' WHERE customer_id = @customerId AND status = 'Pending'; INSERT INTO audit_log (description) VALUES ('Orders reviewed for customer ' + CAST(@customerId AS NVARCHAR(10))); END;", + "outputs": [ + { + "expected": "CREATE OR ALTER PROCEDURE ManageCustomerOrders @customerId INT AS BEGIN SET NOCOUNT ON; IF NOT EXISTS (SELECT ? FROM customers WHERE id = @customerId) BEGIN THROW ?, ?, ?; END; UPDATE orders SET status = ? WHERE customer_id = @customerId AND status = ?; INSERT INTO audit_log (description) VALUES (? + CAST(@customerId AS NVARCHAR(?))); END;", + "statement_metadata": { + "size": 78, + "tables": ["customers", "orders", "audit_log"], + "commands": ["CREATE", "ALTER", "BEGIN", "SELECT", "UPDATE", "INSERT"], + "comments": [], + "procedures": ["ManageCustomerOrders"] + }, + "obfuscator_config": { + "replace_digits": true + }, + "normalizer_config": { + "collect_tables": true, + "collect_commands": true, + "collect_comments": true, + "collect_procedure": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/procedure/complex-stored-procedure-multiple-statements.json b/testdata/mssql/procedure/complex-stored-procedure-multiple-statements.json new file mode 100644 index 0000000..886e455 --- /dev/null +++ b/testdata/mssql/procedure/complex-stored-procedure-multiple-statements.json @@ -0,0 +1,27 @@ +{ + "input": "CREATE OR ALTER PROCEDURE FullOrderManagement AS\nBEGIN\n-- Comprehensive procedure to manage order lifecycle\n-- It checks, processes, and logs orders.\nSET NOCOUNT ON;\n-- Check for new orders\nUPDATE orders SET status = 'Processing' WHERE status = 'New';\n-- Log the update\nINSERT INTO audit_log (description) VALUES ('Processed new orders.');\n-- Finalize processed orders\nUPDATE orders SET status = 'Finalized' WHERE status = 'Processing';\nEND;", + "outputs": [ + { + "expected": "CREATE OR ALTER PROCEDURE FullOrderManagement AS BEGIN SET NOCOUNT ON; UPDATE orders SET status = ? WHERE status = ?; INSERT INTO audit_log (description) VALUES (?); UPDATE orders SET status = ? WHERE status = ?; END;", + "statement_metadata": { + "size": 223, + "tables": ["orders", "audit_log"], + "commands": ["CREATE", "ALTER", "BEGIN", "UPDATE", "INSERT"], + "comments": ["-- Comprehensive procedure to manage order lifecycle", "-- It checks, processes, and logs orders.", "-- Check for new orders", "-- Log the update", "-- Finalize processed orders"], + "procedures": ["FullOrderManagement"] + }, + "obfuscator_config": { + "replace_digits": true + }, + "normalizer_config": { + "collect_tables": true, + "collect_commands": true, + "collect_comments": true, + "collect_procedure": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/procedure/stored-procedure-comprehensive-logic-explanation.json b/testdata/mssql/procedure/stored-procedure-comprehensive-logic-explanation.json new file mode 100644 index 0000000..3036098 --- /dev/null +++ b/testdata/mssql/procedure/stored-procedure-comprehensive-logic-explanation.json @@ -0,0 +1,27 @@ +{ + "input": "CREATE OR ALTER PROCEDURE ValidateOrderDetails AS\nBEGIN\n/*\n Procedure Name: ValidateOrderDetails\n Purpose: To validate the details of orders before processing.\n Detailed Description:\n This procedure runs through each order in the 'orders' table\n and checks if all required details are present.\n It updates the 'order_status' table with 'Valid' or 'Invalid'.\n It's a critical part of the order processing pipeline to ensure data integrity.\n*/\n-- Validation logic\nUPDATE orders SET status = CASE WHEN customer_id IS NOT NULL AND total_amount IS NOT NULL THEN 'Valid' ELSE 'Invalid' END;\nEND;", + "outputs": [ + { + "expected": "CREATE OR ALTER PROCEDURE ValidateOrderDetails AS BEGIN UPDATE orders SET status = CASE WHEN customer_id IS NOT NULL AND total_amount IS NOT NULL THEN ? ELSE ? END; END;", + "statement_metadata": { + "size": 466, + "tables": ["orders"], + "commands": ["CREATE", "ALTER", "BEGIN", "UPDATE"], + "comments": ["/*\n Procedure Name: ValidateOrderDetails\n Purpose: To validate the details of orders before processing.\n Detailed Description:\n This procedure runs through each order in the 'orders' table\n and checks if all required details are present.\n It updates the 'order_status' table with 'Valid' or 'Invalid'.\n It's a critical part of the order processing pipeline to ensure data integrity.\n*/", "-- Validation logic"], + "procedures": ["ValidateOrderDetails"] + }, + "obfuscator_config": { + "replace_digits": true + }, + "normalizer_config": { + "collect_tables": true, + "collect_commands": true, + "collect_comments": true, + "collect_procedure": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/procedure/stored-procedure-conditional-logic.json b/testdata/mssql/procedure/stored-procedure-conditional-logic.json new file mode 100644 index 0000000..8100841 --- /dev/null +++ b/testdata/mssql/procedure/stored-procedure-conditional-logic.json @@ -0,0 +1,27 @@ +{ + "input": "CREATE OR ALTER PROCEDURE CheckOrderStatus @orderId INT AS\nBEGIN\n-- Checks the status of an order and logs if it's delayed.\n-- This is part of our order monitoring system.\nSET NOCOUNT ON;\nDECLARE @status NVARCHAR(50);\nSELECT @status = status FROM orders WHERE id = @orderId;\nIF @status = 'Delayed'\nBEGIN\n INSERT INTO audit_log (description) VALUES ('Order ' + CAST(@orderId AS NVARCHAR(10)) + ' is delayed.');\nEND\nEND;", + "outputs": [ + { + "expected": "CREATE OR ALTER PROCEDURE CheckOrderStatus @orderId INT AS BEGIN SET NOCOUNT ON; DECLARE @status NVARCHAR(?); SELECT @status = status FROM orders WHERE id = @orderId; IF @status = ? BEGIN INSERT INTO audit_log (description) VALUES (? + CAST(@orderId AS NVARCHAR(?)) + ?); END END;", + "statement_metadata": { + "size": 164, + "tables": ["orders", "audit_log"], + "commands": ["CREATE", "ALTER", "BEGIN", "SELECT", "INSERT"], + "comments": ["-- Checks the status of an order and logs if it's delayed.", "-- This is part of our order monitoring system."], + "procedures": ["CheckOrderStatus"] + }, + "obfuscator_config": { + "replace_digits": true + }, + "normalizer_config": { + "collect_tables": true, + "collect_commands": true, + "collect_comments": true, + "collect_procedure": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/procedure/stored-procedure-cursor-temp-table.json b/testdata/mssql/procedure/stored-procedure-cursor-temp-table.json new file mode 100644 index 0000000..7f6ad14 --- /dev/null +++ b/testdata/mssql/procedure/stored-procedure-cursor-temp-table.json @@ -0,0 +1,27 @@ +{ + "input": "CREATE OR ALTER PROCEDURE ArchiveOldOrders AS BEGIN SET NOCOUNT ON; DECLARE @orderId INT; DECLARE orderCursor CURSOR FOR SELECT id FROM orders WHERE order_date < GETDATE() - 365; OPEN orderCursor; FETCH NEXT FROM orderCursor INTO @orderId; WHILE @@FETCH_STATUS = 0 BEGIN INSERT INTO orders_archive (id, status) SELECT id, status FROM orders WHERE id = @orderId; FETCH NEXT FROM orderCursor INTO @orderId; END; CLOSE orderCursor; DEALLOCATE orderCursor; END;", + "outputs": [ + { + "expected": "CREATE OR ALTER PROCEDURE ArchiveOldOrders AS BEGIN SET NOCOUNT ON; DECLARE @orderId INT; DECLARE orderCursor CURSOR FOR SELECT id FROM orders WHERE order_date < GETDATE() - ?; OPEN orderCursor; FETCH NEXT FROM orderCursor INTO @orderId; WHILE @@FETCH_STATUS = ? BEGIN INSERT INTO orders_archive (id, status) SELECT id, status FROM orders WHERE id = @orderId; FETCH NEXT FROM orderCursor INTO @orderId; END; CLOSE orderCursor; DEALLOCATE orderCursor; END;", + "statement_metadata": { + "size": 75, + "tables": ["orders", "orderCursor", "orders_archive"], + "commands": ["CREATE", "ALTER", "BEGIN", "SELECT", "INSERT"], + "comments": [], + "procedures": ["ArchiveOldOrders"] + }, + "obfuscator_config": { + "replace_digits": true + }, + "normalizer_config": { + "collect_tables": true, + "collect_commands": true, + "collect_comments": true, + "collect_procedure": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/procedure/stored-procedure-detailed-documentation.json b/testdata/mssql/procedure/stored-procedure-detailed-documentation.json new file mode 100644 index 0000000..68166fd --- /dev/null +++ b/testdata/mssql/procedure/stored-procedure-detailed-documentation.json @@ -0,0 +1,27 @@ +{ + "input": "CREATE OR ALTER PROCEDURE AuditOrderProcessing AS\nBEGIN\n/*\n Procedure: AuditOrderProcessing\n Author: Jane Doe\n Created: 2023-04-15\n Description: This procedure is designed to audit order processing steps.\n It checks each step of the order processing workflow and logs it into the audit_log table.\n Modifications:\n - 2023-04-20: Added additional logging for failed orders.\n - 2023-05-01: Updated logic to include new order status.\n*/\nSET NOCOUNT ON;\n-- Insert audit records\nINSERT INTO audit_log (description) SELECT 'Order processed: ' + CAST(id AS NVARCHAR(10)) FROM orders WHERE status = 'Processed';\nEND;", + "outputs": [ + { + "expected": "CREATE OR ALTER PROCEDURE AuditOrderProcessing AS BEGIN SET NOCOUNT ON; INSERT INTO audit_log (description) SELECT ? + CAST(id AS NVARCHAR(?)) FROM orders WHERE status = ?; END;", + "statement_metadata": { + "size": 478, + "tables": ["audit_log", "orders"], + "commands": ["CREATE", "ALTER", "BEGIN", "INSERT", "SELECT"], + "comments": ["/*\n Procedure: AuditOrderProcessing\n Author: Jane Doe\n Created: 2023-04-15\n Description: This procedure is designed to audit order processing steps.\n It checks each step of the order processing workflow and logs it into the audit_log table.\n Modifications:\n - 2023-04-20: Added additional logging for failed orders.\n - 2023-05-01: Updated logic to include new order status.\n*/", "-- Insert audit records"], + "procedures": ["AuditOrderProcessing"] + }, + "obfuscator_config": { + "replace_digits": true + }, + "normalizer_config": { + "collect_tables": true, + "collect_commands": true, + "collect_comments": true, + "collect_procedure": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/procedure/stored-procedure-dynamic-sql-error-handling.json b/testdata/mssql/procedure/stored-procedure-dynamic-sql-error-handling.json new file mode 100644 index 0000000..8600e30 --- /dev/null +++ b/testdata/mssql/procedure/stored-procedure-dynamic-sql-error-handling.json @@ -0,0 +1,27 @@ +{ + "input": "CREATE OR ALTER PROCEDURE UpdateOrderStatus @orderId INT, @newStatus NVARCHAR(50) AS BEGIN SET NOCOUNT ON; BEGIN TRY BEGIN TRANSACTION; DECLARE @sql NVARCHAR(MAX) = N'UPDATE orders SET status = ''' + @newStatus + ''' WHERE id = ' + CAST(@orderId AS NVARCHAR(10)) + ';'; EXEC sp_executesql @sql; COMMIT TRANSACTION; END TRY BEGIN CATCH ROLLBACK TRANSACTION; THROW; END CATCH; END;", + "outputs": [ + { + "expected": "CREATE OR ALTER PROCEDURE UpdateOrderStatus @orderId INT, @newStatus NVARCHAR(?) AS BEGIN SET NOCOUNT ON; BEGIN TRY BEGIN TRANSACTION; DECLARE @sql NVARCHAR(MAX) = N ? ? + @newStatus + ? ? + CAST(@orderId AS NVARCHAR(?)) + ?; EXEC sp_executesql @sql; COMMIT TRANSACTION; END TRY BEGIN CATCH ROLLBACK TRANSACTION; THROW; END CATCH; END;", + "statement_metadata": { + "size": 43, + "tables": [], + "commands": ["CREATE", "ALTER", "BEGIN", "EXEC", "COMMIT"], + "comments": [], + "procedures": ["UpdateOrderStatus"] + }, + "obfuscator_config": { + "replace_digits": true + }, + "normalizer_config": { + "collect_tables": true, + "collect_commands": true, + "collect_comments": true, + "collect_procedure": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/procedure/stored-procedure-dynamic-sql-execution.json b/testdata/mssql/procedure/stored-procedure-dynamic-sql-execution.json new file mode 100644 index 0000000..9d3e043 --- /dev/null +++ b/testdata/mssql/procedure/stored-procedure-dynamic-sql-execution.json @@ -0,0 +1,27 @@ +{ + "input": "CREATE OR ALTER PROCEDURE DynamicCustomerQuery @query NVARCHAR(MAX) AS\nBEGIN\n-- Executes a dynamic SQL query based on the input.\n-- Used for flexible customer data retrieval.\nSET NOCOUNT ON;\nEXEC sp_executesql @query;\nEND;", + "outputs": [ + { + "expected": "CREATE OR ALTER PROCEDURE DynamicCustomerQuery @query NVARCHAR(MAX) AS BEGIN SET NOCOUNT ON; EXEC sp_executesql @query; END;", + "statement_metadata": { + "size": 136, + "tables": [], + "commands": ["CREATE", "ALTER", "BEGIN", "EXEC"], + "comments": ["-- Executes a dynamic SQL query based on the input.", "-- Used for flexible customer data retrieval."], + "procedures": ["DynamicCustomerQuery"] + }, + "obfuscator_config": { + "replace_digits": true + }, + "normalizer_config": { + "collect_tables": true, + "collect_commands": true, + "collect_comments": true, + "collect_procedure": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/procedure/stored-procedure-executing-another.json b/testdata/mssql/procedure/stored-procedure-executing-another.json new file mode 100644 index 0000000..abf6151 --- /dev/null +++ b/testdata/mssql/procedure/stored-procedure-executing-another.json @@ -0,0 +1,27 @@ +{ + "input": "CREATE OR ALTER PROCEDURE FullOrderProcessing AS BEGIN SET NOCOUNT ON; EXEC ProcessOrders; EXEC UpdateOrderStatus 1, 'Dispatched'; END;", + "outputs": [ + { + "expected": "CREATE OR ALTER PROCEDURE FullOrderProcessing AS BEGIN SET NOCOUNT ON; EXEC ProcessOrders; EXEC UpdateOrderStatus ?, ?; END;", + "statement_metadata": { + "size": 39, + "tables": [], + "commands": ["CREATE", "ALTER", "BEGIN", "EXEC"], + "comments": [], + "procedures": ["FullOrderProcessing"] + }, + "obfuscator_config": { + "replace_digits": true + }, + "normalizer_config": { + "collect_tables": true, + "collect_commands": true, + "collect_comments": true, + "collect_procedure": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/procedure/stored-procedure-temp-tables-transaction.json b/testdata/mssql/procedure/stored-procedure-temp-tables-transaction.json new file mode 100644 index 0000000..d83db6b --- /dev/null +++ b/testdata/mssql/procedure/stored-procedure-temp-tables-transaction.json @@ -0,0 +1,27 @@ +{ + "input": "CREATE OR ALTER PROCEDURE ProcessOrders AS BEGIN SET NOCOUNT ON; BEGIN TRANSACTION; CREATE TABLE #TempOrders (id INT, status NVARCHAR(50)); INSERT INTO #TempOrders (id, status) SELECT id, status FROM orders WHERE status = 'Pending'; UPDATE orders SET status = 'Processing' WHERE status = 'Pending'; COMMIT TRANSACTION; SELECT * FROM #TempOrders; DROP TABLE #TempOrders; END;", + "outputs": [ + { + "expected": "CREATE OR ALTER PROCEDURE ProcessOrders AS BEGIN SET NOCOUNT ON; BEGIN TRANSACTION; CREATE TABLE #TempOrders (id INT, status NVARCHAR(?)); INSERT INTO #TempOrders (id, status) SELECT id, status FROM orders WHERE status = ?; UPDATE orders SET status = ? WHERE status = ?; COMMIT TRANSACTION; SELECT * FROM #TempOrders; DROP TABLE #TempOrders; END;", + "statement_metadata": { + "size": 74, + "tables": ["#TempOrders", "orders"], + "commands": ["CREATE", "ALTER", "BEGIN", "INSERT", "SELECT", "UPDATE", "COMMIT", "DROP"], + "comments": [], + "procedures": ["ProcessOrders"] + }, + "obfuscator_config": { + "replace_digits": true + }, + "normalizer_config": { + "collect_tables": true, + "collect_commands": true, + "collect_comments": true, + "collect_procedure": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/procedure/stored-procedure-try-catch-error.json b/testdata/mssql/procedure/stored-procedure-try-catch-error.json new file mode 100644 index 0000000..909c288 --- /dev/null +++ b/testdata/mssql/procedure/stored-procedure-try-catch-error.json @@ -0,0 +1,27 @@ +{ + "input": "CREATE OR ALTER PROCEDURE ProcessPayment @orderId INT, @amount MONEY AS\nBEGIN\n-- This procedure processes payments for orders.\n-- It includes error handling using TRY-CATCH.\nSET NOCOUNT ON;\nBEGIN TRY\n -- Attempt to process the payment\n UPDATE orders SET payment_received = 1, payment_amount = @amount WHERE id = @orderId;\nEND TRY\nBEGIN CATCH\n -- Handle the error\n INSERT INTO error_log (error_message) VALUES (ERROR_MESSAGE());\nEND CATCH\nEND;", + "outputs": [ + { + "expected": "CREATE OR ALTER PROCEDURE ProcessPayment @orderId INT, @amount MONEY AS BEGIN SET NOCOUNT ON; BEGIN TRY UPDATE orders SET payment_received = ?, payment_amount = @amount WHERE id = @orderId; END TRY BEGIN CATCH INSERT INTO error_log (error_message) VALUES (ERROR_MESSAGE()); END CATCH END;", + "statement_metadata": { + "size": 203, + "tables": ["orders", "error_log"], + "commands": ["CREATE", "ALTER", "BEGIN", "UPDATE", "INSERT"], + "comments": ["-- This procedure processes payments for orders.", "-- It includes error handling using TRY-CATCH.", "-- Attempt to process the payment", "-- Handle the error"], + "procedures": ["ProcessPayment"] + }, + "obfuscator_config": { + "replace_digits": true + }, + "normalizer_config": { + "collect_tables": true, + "collect_commands": true, + "collect_comments": true, + "collect_procedure": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/procedure/stored-procedure-version-control.json b/testdata/mssql/procedure/stored-procedure-version-control.json new file mode 100644 index 0000000..68166fd --- /dev/null +++ b/testdata/mssql/procedure/stored-procedure-version-control.json @@ -0,0 +1,27 @@ +{ + "input": "CREATE OR ALTER PROCEDURE AuditOrderProcessing AS\nBEGIN\n/*\n Procedure: AuditOrderProcessing\n Author: Jane Doe\n Created: 2023-04-15\n Description: This procedure is designed to audit order processing steps.\n It checks each step of the order processing workflow and logs it into the audit_log table.\n Modifications:\n - 2023-04-20: Added additional logging for failed orders.\n - 2023-05-01: Updated logic to include new order status.\n*/\nSET NOCOUNT ON;\n-- Insert audit records\nINSERT INTO audit_log (description) SELECT 'Order processed: ' + CAST(id AS NVARCHAR(10)) FROM orders WHERE status = 'Processed';\nEND;", + "outputs": [ + { + "expected": "CREATE OR ALTER PROCEDURE AuditOrderProcessing AS BEGIN SET NOCOUNT ON; INSERT INTO audit_log (description) SELECT ? + CAST(id AS NVARCHAR(?)) FROM orders WHERE status = ?; END;", + "statement_metadata": { + "size": 478, + "tables": ["audit_log", "orders"], + "commands": ["CREATE", "ALTER", "BEGIN", "INSERT", "SELECT"], + "comments": ["/*\n Procedure: AuditOrderProcessing\n Author: Jane Doe\n Created: 2023-04-15\n Description: This procedure is designed to audit order processing steps.\n It checks each step of the order processing workflow and logs it into the audit_log table.\n Modifications:\n - 2023-04-20: Added additional logging for failed orders.\n - 2023-05-01: Updated logic to include new order status.\n*/", "-- Insert audit records"], + "procedures": ["AuditOrderProcessing"] + }, + "obfuscator_config": { + "replace_digits": true + }, + "normalizer_config": { + "collect_tables": true, + "collect_commands": true, + "collect_comments": true, + "collect_procedure": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/procedure/stored-procedure-with-params-and-execution.json.json b/testdata/mssql/procedure/stored-procedure-with-params-and-execution.json.json new file mode 100644 index 0000000..9c3d20a --- /dev/null +++ b/testdata/mssql/procedure/stored-procedure-with-params-and-execution.json.json @@ -0,0 +1,26 @@ +{ + "input": "CREATE OR ALTER PROCEDURE UpdateCustomerStatus @customerId INT, @newStatus NVARCHAR(50) AS\nBEGIN\n-- This procedure updates the status of a customer.\n-- It takes the customer ID and the new status as parameters.\nSET NOCOUNT ON;\nUPDATE customers SET status = @newStatus WHERE id = @customerId;\nEND;\nEXEC UpdateCustomerStatus 123, 'Active';", + "outputs": [ + { + "expected": "CREATE OR ALTER PROCEDURE UpdateCustomerStatus @customerId INT, @newStatus NVARCHAR(?) AS BEGIN SET NOCOUNT ON; UPDATE customers SET status = @newStatus WHERE id = @customerId; END; EXEC UpdateCustomerStatus ?, ?;", + "statement_metadata": { + "size": 167, + "tables": ["customers"], + "commands": ["CREATE", "ALTER", "BEGIN", "UPDATE", "EXEC"], + "comments": ["-- This procedure updates the status of a customer.", "-- It takes the customer ID and the new status as parameters."], + "procedures": ["UpdateCustomerStatus"] + }, + "obfuscator_config": { + "replace_digits": true + }, + "normalizer_config": { + "collect_tables": true, + "collect_commands": true, + "collect_comments": true, + "collect_procedure": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] +} diff --git a/testdata/mssql/select/basic-select.json b/testdata/mssql/select/basic-select.json new file mode 100644 index 0000000..1c103a2 --- /dev/null +++ b/testdata/mssql/select/basic-select.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT id, name, email FROM customers WHERE active = 1;", + "outputs": [ + { + "expected": "SELECT id, name, email FROM customers WHERE active = ?", + "statement_metadata": { + "size": 15, + "tables": ["customers"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/data-compression-features.json b/testdata/mssql/select/data-compression-features.json new file mode 100644 index 0000000..96ca517 --- /dev/null +++ b/testdata/mssql/select/data-compression-features.json @@ -0,0 +1,16 @@ +{ + "input": "CREATE TABLE orders_compressed WITH (DATA_COMPRESSION = PAGE) AS SELECT * FROM orders;", + "outputs": [ + { + "expected": "CREATE TABLE orders_compressed WITH ( DATA_COMPRESSION = PAGE ) AS SELECT * FROM orders", + "statement_metadata": { + "size": 35, + "tables": ["orders_compressed", "orders"], + "commands": ["CREATE", "SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/filetable-storage.json b/testdata/mssql/select/filetable-storage.json new file mode 100644 index 0000000..15c83fd --- /dev/null +++ b/testdata/mssql/select/filetable-storage.json @@ -0,0 +1,16 @@ +{ + "input": "CREATE TABLE DocumentStore AS FileTable;", + "outputs": [ + { + "expected": "CREATE TABLE DocumentStore", + "statement_metadata": { + "size": 19, + "tables": ["DocumentStore"], + "commands": ["CREATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/pivot-unpivot-operations.json b/testdata/mssql/select/pivot-unpivot-operations.json new file mode 100644 index 0000000..a2e5b22 --- /dev/null +++ b/testdata/mssql/select/pivot-unpivot-operations.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT * FROM (SELECT customer_id, product_id, amount FROM order_details) AS SourceTable PIVOT (SUM(amount) FOR product_id IN ([1], [2], [3])) AS PivotTable;", + "outputs": [ + { + "expected": "SELECT * FROM ( SELECT customer_id, product_id, amount FROM order_details ) PIVOT ( SUM ( amount ) FOR product_id IN ( ? ) )", + "statement_metadata": { + "size": 19, + "tables": ["order_details"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-choose.json b/testdata/mssql/select/select-choose.json new file mode 100644 index 0000000..821d727 --- /dev/null +++ b/testdata/mssql/select/select-choose.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT id, name, CHOOSE(department_id, 'Sales', 'Engineering', 'HR') AS DepartmentName FROM employees;", + "outputs": [ + { + "expected": "SELECT id, name, CHOOSE ( department_id, ?, ?, ? ) FROM employees", + "statement_metadata": { + "size": 15, + "tables": ["employees"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-format.json b/testdata/mssql/select/select-format.json new file mode 100644 index 0000000..e1129aa --- /dev/null +++ b/testdata/mssql/select/select-format.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT name, FORMAT(joining_date, 'dd-MM-yyyy') AS FormattedJoiningDate FROM employees;", + "outputs": [ + { + "expected": "SELECT name, FORMAT ( joining_date, ? ) FROM employees", + "statement_metadata": { + "size": 15, + "tables": ["employees"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-full-outer-join.json b/testdata/mssql/select/select-full-outer-join.json new file mode 100644 index 0000000..d209676 --- /dev/null +++ b/testdata/mssql/select/select-full-outer-join.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT c.name, o.order_date FROM customers c FULL OUTER JOIN orders o ON c.id = o.customer_id WHERE c.region = 'West' OR o.amount > 500;", + "outputs": [ + { + "expected": "SELECT c.name, o.order_date FROM customers c FULL OUTER JOIN orders o ON c.id = o.customer_id WHERE c.region = ? OR o.amount > ?", + "statement_metadata": { + "size": 25, + "tables": ["customers", "orders"], + "commands": ["SELECT", "JOIN"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-identity.json b/testdata/mssql/select/select-identity.json new file mode 100644 index 0000000..18bb4e1 --- /dev/null +++ b/testdata/mssql/select/select-identity.json @@ -0,0 +1,16 @@ +{ + "input": "INSERT INTO employees (name, department) VALUES ('John Doe', 'Sales'); SELECT @@IDENTITY AS LastInsertedIdentity;", + "outputs": [ + { + "expected": "INSERT INTO employees ( name, department ) VALUES ( ? ); SELECT @@IDENTITY", + "statement_metadata": { + "size": 21, + "tables": ["employees"], + "commands": ["INSERT", "SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-iif.json b/testdata/mssql/select/select-iif.json new file mode 100644 index 0000000..9ecc3b4 --- /dev/null +++ b/testdata/mssql/select/select-iif.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT name, IIF(gender = 'M', 'Male', 'Female') AS GenderDescription FROM employees;", + "outputs": [ + { + "expected": "SELECT name, IIF ( gender = ?, ?, ? ) FROM employees", + "statement_metadata": { + "size": 15, + "tables": ["employees"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-join-aggregation.json b/testdata/mssql/select/select-join-aggregation.json new file mode 100644 index 0000000..1de7846 --- /dev/null +++ b/testdata/mssql/select/select-join-aggregation.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT c.name, SUM(o.amount) AS total_sales FROM customers c INNER JOIN orders o ON c.id = o.customer_id GROUP BY c.name;", + "outputs": [ + { + "expected": "SELECT c.name, SUM ( o.amount ) FROM customers c INNER JOIN orders o ON c.id = o.customer_id GROUP BY c.name", + "statement_metadata": { + "size": 25, + "tables": ["customers", "orders"], + "commands": ["SELECT", "JOIN"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-system-user.json b/testdata/mssql/select/select-system-user.json new file mode 100644 index 0000000..f841baa --- /dev/null +++ b/testdata/mssql/select/select-system-user.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT SYSTEM_USER AS CurrentSystemUser, USER_NAME() AS CurrentDatabaseUser, NEWID() AS UniqueIdentifier;", + "outputs": [ + { + "expected": "SELECT SYSTEM_USER, USER_NAME ( ), NEWID ( )", + "statement_metadata": { + "size": 6, + "tables": [], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-using-pivot.json b/testdata/mssql/select/select-using-pivot.json new file mode 100644 index 0000000..3c6c8ce --- /dev/null +++ b/testdata/mssql/select/select-using-pivot.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT * FROM (SELECT customer_id, product_id, amount FROM orders) AS SourceTable PIVOT (SUM(amount) FOR product_id IN ([1], [2], [3])) AS PivotTable;", + "outputs": [ + { + "expected": "SELECT * FROM ( SELECT customer_id, product_id, amount FROM orders ) PIVOT ( SUM ( amount ) FOR product_id IN ( ? ) )", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-using-try-convert.json b/testdata/mssql/select/select-using-try-convert.json new file mode 100644 index 0000000..aed4952 --- /dev/null +++ b/testdata/mssql/select/select-using-try-convert.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT id, TRY_CONVERT(float, total_amount) AS TotalFloat FROM orders WHERE TRY_CONVERT(float, total_amount) IS NOT NULL;", + "outputs": [ + { + "expected": "SELECT id, TRY_CONVERT ( float, total_amount ) FROM orders WHERE TRY_CONVERT ( float, total_amount ) IS NOT ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-with-cte.json b/testdata/mssql/select/select-with-cte.json new file mode 100644 index 0000000..48add7e --- /dev/null +++ b/testdata/mssql/select/select-with-cte.json @@ -0,0 +1,24 @@ +{ + "input": "WITH RankedOrders AS (SELECT o.id, o.customer_id, RANK() OVER (PARTITION BY o.customer_id ORDER BY o.amount DESC) AS rnk FROM orders o) SELECT id FROM RankedOrders WHERE rnk = 1;", + "outputs": [ + { + "expected": "WITH RankedOrders AS ( SELECT o.id, o.customer_id, RANK ( ) OVER ( PARTITION BY o.customer_id ORDER BY o.amount DESC ) FROM orders o ) SELECT id FROM RankedOrders WHERE rnk = ?", + "statement_metadata": { + "size": 24, + "tables": ["orders", "RankedOrders"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + }, + { + "expected": "WITH RankedOrders AS (SELECT o.id, o.customer_id, RANK() OVER (PARTITION BY o.customer_id ORDER BY o.amount DESC) AS rnk FROM orders o) SELECT id FROM RankedOrders WHERE rnk = ?;", + "normalizer_config": { + "keep_sql_alias": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-with-offset-fetch.json b/testdata/mssql/select/select-with-offset-fetch.json new file mode 100644 index 0000000..c00765a --- /dev/null +++ b/testdata/mssql/select/select-with-offset-fetch.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT id, name FROM customers ORDER BY name OFFSET 10 ROWS FETCH NEXT 5 ROWS ONLY;", + "outputs": [ + { + "expected": "SELECT id, name FROM customers ORDER BY name OFFSET ? ROWS FETCH NEXT ? ROWS ONLY", + "statement_metadata": { + "size": 15, + "tables": ["customers"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-with-string-agg.json b/testdata/mssql/select/select-with-string-agg.json new file mode 100644 index 0000000..838f137 --- /dev/null +++ b/testdata/mssql/select/select-with-string-agg.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT STRING_AGG(name, ', ') AS names FROM customers WHERE region = 'East';", + "outputs": [ + { + "expected": "SELECT STRING_AGG ( name, ? ) FROM customers WHERE region = ?", + "statement_metadata": { + "size": 15, + "tables": ["customers"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-with-table-sample.json b/testdata/mssql/select/select-with-table-sample.json new file mode 100644 index 0000000..4953ab6 --- /dev/null +++ b/testdata/mssql/select/select-with-table-sample.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT * FROM customers TABLESAMPLE (10 PERCENT);", + "outputs": [ + { + "expected": "SELECT * FROM customers TABLESAMPLE ( ? PERCENT )", + "statement_metadata": { + "size": 15, + "tables": ["customers"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/select-with-window-function.json b/testdata/mssql/select/select-with-window-function.json new file mode 100644 index 0000000..cf91883 --- /dev/null +++ b/testdata/mssql/select/select-with-window-function.json @@ -0,0 +1,24 @@ +{ + "input": "SELECT id, amount, ROW_NUMBER() OVER (ORDER BY amount DESC) AS rownum FROM orders;", + "outputs": [ + { + "expected": "SELECT id, amount, ROW_NUMBER ( ) OVER ( ORDER BY amount DESC ) AS rownum FROM orders", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + }, + { + "expected": "SELECT id, amount, ROW_NUMBER() OVER (ORDER BY amount DESC) AS rownum FROM orders;", + "normalizer_config": { + "keep_sql_alias": true, + "keep_trailing_semicolon": true, + "remove_space_between_parentheses": true + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/service-broker.json b/testdata/mssql/select/service-broker.json new file mode 100644 index 0000000..4f6cc45 --- /dev/null +++ b/testdata/mssql/select/service-broker.json @@ -0,0 +1,16 @@ +{ + "input": "CREATE MESSAGE TYPE RequestMessage VALIDATION = WELL_FORMED_XML; CREATE CONTRACT RequestContract (RequestMessage SENT BY INITIATOR);", + "outputs": [ + { + "expected": "CREATE MESSAGE TYPE RequestMessage VALIDATION = WELL_FORMED_XML; CREATE CONTRACT RequestContract ( RequestMessage SENT BY INITIATOR )", + "statement_metadata": { + "size": 6, + "tables": [], + "commands": ["CREATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/spatial-data-types-functions.json b/testdata/mssql/select/spatial-data-types-functions.json new file mode 100644 index 0000000..92519e1 --- /dev/null +++ b/testdata/mssql/select/spatial-data-types-functions.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT geography::Point(latitude, longitude, 4326).ToString() FROM locations;", + "outputs": [ + { + "expected": "SELECT geography :: Point ( latitude, longitude, ? ) . ToString ( ) FROM locations", + "statement_metadata": { + "size": 15, + "tables": ["locations"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/select/xml-data-types-queries.json b/testdata/mssql/select/xml-data-types-queries.json new file mode 100644 index 0000000..ad9cae9 --- /dev/null +++ b/testdata/mssql/select/xml-data-types-queries.json @@ -0,0 +1,16 @@ +{ + "input": "SELECT xmlData.value('(/Customer/Name)[1]', 'nvarchar(100)') AS CustomerName FROM customerRecords;", + "outputs": [ + { + "expected": "SELECT xmlData.value ( ? ) FROM customerRecords", + "statement_metadata": { + "size": 21, + "tables": ["customerRecords"], + "commands": ["SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/conditional-update-case.json b/testdata/mssql/update/conditional-update-case.json new file mode 100644 index 0000000..bc0c0f6 --- /dev/null +++ b/testdata/mssql/update/conditional-update-case.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE orders SET status = CASE WHEN amount >= 1000 THEN 'High Value' ELSE 'Regular' END;", + "outputs": [ + { + "expected": "UPDATE orders SET status = CASE WHEN amount >= ? THEN ? ELSE ? END", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-basic.json b/testdata/mssql/update/update-basic.json new file mode 100644 index 0000000..5fe74fe --- /dev/null +++ b/testdata/mssql/update/update-basic.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE orders SET status = 'Processed' WHERE order_date < GETDATE() - 30;", + "outputs": [ + { + "expected": "UPDATE orders SET status = ? WHERE order_date < GETDATE ( ) - ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-complex-where.json b/testdata/mssql/update/update-complex-where.json new file mode 100644 index 0000000..68e5c7f --- /dev/null +++ b/testdata/mssql/update/update-complex-where.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE orders SET status = 'Review Needed' WHERE customer_id IN (SELECT id FROM customers WHERE last_order_date < GETDATE() - 365) AND status = 'Pending';", + "outputs": [ + { + "expected": "UPDATE orders SET status = ? WHERE customer_id IN ( SELECT id FROM customers WHERE last_order_date < GETDATE ( ) - ? ) AND status = ?", + "statement_metadata": { + "size": 27, + "tables": ["orders", "customers"], + "commands": ["UPDATE", "SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-from-aliases.json b/testdata/mssql/update/update-from-aliases.json new file mode 100644 index 0000000..b16fadd --- /dev/null +++ b/testdata/mssql/update/update-from-aliases.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE o SET o.status = 'Completed' FROM orders o WHERE o.order_date > '2023-01-01' AND o.amount > 500;", + "outputs": [ + { + "expected": "UPDATE o SET o.status = ? FROM orders o WHERE o.order_date > ? AND o.amount > ?", + "statement_metadata": { + "size": 13, + "tables": ["o", "orders"], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-join-top.json b/testdata/mssql/update/update-join-top.json new file mode 100644 index 0000000..7d26871 --- /dev/null +++ b/testdata/mssql/update/update-join-top.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE TOP (5) o SET o.status = 'Pending Review' FROM orders o INNER JOIN customers c ON o.customer_id = c.id WHERE c.region = 'North';", + "outputs": [ + { + "expected": "UPDATE TOP ( ? ) o SET o.status = ? FROM orders o INNER JOIN customers c ON o.customer_id = c.id WHERE c.region = ?", + "statement_metadata": { + "size": 25, + "tables": ["orders", "customers"], + "commands": ["UPDATE", "JOIN"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-rowlock-hint.json b/testdata/mssql/update/update-rowlock-hint.json new file mode 100644 index 0000000..f5a6d59 --- /dev/null +++ b/testdata/mssql/update/update-rowlock-hint.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE orders WITH (ROWLOCK) SET status = 'Processing' WHERE status = 'Pending';", + "outputs": [ + { + "expected": "UPDATE orders WITH ( ROWLOCK ) SET status = ? WHERE status = ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-using-quoted-identifiers.json b/testdata/mssql/update/update-using-quoted-identifiers.json new file mode 100644 index 0000000..f2e6265 --- /dev/null +++ b/testdata/mssql/update/update-using-quoted-identifiers.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE [orders] SET [status] = 'Confirmed' WHERE [order_date] >= '2023-01-01';", + "outputs": [ + { + "expected": "UPDATE orders SET status = ? WHERE order_date >= ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-using-top.json b/testdata/mssql/update/update-using-top.json new file mode 100644 index 0000000..e2c36d0 --- /dev/null +++ b/testdata/mssql/update/update-using-top.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE TOP (10) orders SET status = 'Reviewed' WHERE status = 'Pending';", + "outputs": [ + { + "expected": "UPDATE TOP ( ? ) orders SET status = ? WHERE status = ?", + "statement_metadata": { + "size": 6, + "tables": [], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-using-variable-store-value.json b/testdata/mssql/update/update-using-variable-store-value.json new file mode 100644 index 0000000..c7d21a3 --- /dev/null +++ b/testdata/mssql/update/update-using-variable-store-value.json @@ -0,0 +1,16 @@ +{ + "input": "DECLARE @maxDate DATETIME; SET @maxDate = (SELECT MAX(order_date) FROM orders); UPDATE orders SET status = 'Old Order' WHERE order_date < @maxDate;", + "outputs": [ + { + "expected": "DECLARE @maxDate DATETIME; SET @maxDate = ( SELECT MAX ( order_date ) FROM orders ); UPDATE orders SET status = ? WHERE order_date < @maxDate", + "statement_metadata": { + "size": 18, + "tables": ["orders"], + "commands": ["SELECT", "UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-with-boolean-logic.json b/testdata/mssql/update/update-with-boolean-logic.json new file mode 100644 index 0000000..470f395 --- /dev/null +++ b/testdata/mssql/update/update-with-boolean-logic.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE orders SET is_priority = CASE WHEN total_amount > 1000 THEN 1 ELSE 0 END WHERE order_date > '2023-01-01';", + "outputs": [ + { + "expected": "UPDATE orders SET is_priority = CASE WHEN total_amount > ? THEN ? ELSE ? END WHERE order_date > ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-with-case.json b/testdata/mssql/update/update-with-case.json new file mode 100644 index 0000000..b9a20bb --- /dev/null +++ b/testdata/mssql/update/update-with-case.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE orders SET status = CASE WHEN amount > 1000 THEN 'High Value' ELSE 'Standard' END WHERE order_date >= '2023-01-01';", + "outputs": [ + { + "expected": "UPDATE orders SET status = CASE WHEN amount > ? THEN ? ELSE ? END WHERE order_date >= ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-with-cte.json b/testdata/mssql/update/update-with-cte.json new file mode 100644 index 0000000..c167ed3 --- /dev/null +++ b/testdata/mssql/update/update-with-cte.json @@ -0,0 +1,16 @@ +{ + "input": "WITH UpdatedOrders AS (SELECT id FROM orders WHERE order_date < GETDATE() - 30) UPDATE o SET o.status = 'Archived' FROM orders o JOIN UpdatedOrders uo ON o.id = uo.id;", + "outputs": [ + { + "expected": "WITH UpdatedOrders AS ( SELECT id FROM orders WHERE order_date < GETDATE ( ) - ? ) UPDATE o SET o.status = ? FROM orders o JOIN UpdatedOrders uo ON o.id = uo.id", + "statement_metadata": { + "size": 36, + "tables": ["orders", "o", "UpdatedOrders"], + "commands": ["SELECT", "UPDATE", "JOIN"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-with-date-manipulation.json b/testdata/mssql/update/update-with-date-manipulation.json new file mode 100644 index 0000000..6a4fd85 --- /dev/null +++ b/testdata/mssql/update/update-with-date-manipulation.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE orders SET due_date = DATEADD(day, 10, order_date) WHERE status = 'Pending';", + "outputs": [ + { + "expected": "UPDATE orders SET due_date = DATEADD ( day, ?, order_date ) WHERE status = ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-with-join.json b/testdata/mssql/update/update-with-join.json new file mode 100644 index 0000000..e17a742 --- /dev/null +++ b/testdata/mssql/update/update-with-join.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE o SET o.status = 'Dispatched' FROM orders o INNER JOIN customers c ON o.customer_id = c.id WHERE c.region = 'West' AND o.status = 'Processed';", + "outputs": [ + { + "expected": "UPDATE o SET o.status = ? FROM orders o INNER JOIN customers c ON o.customer_id = c.id WHERE c.region = ? AND o.status = ?", + "statement_metadata": { + "size": 26, + "tables": ["o", "orders", "customers"], + "commands": ["UPDATE", "JOIN"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-with-named-variables.json b/testdata/mssql/update/update-with-named-variables.json new file mode 100644 index 0000000..67b8447 --- /dev/null +++ b/testdata/mssql/update/update-with-named-variables.json @@ -0,0 +1,16 @@ +{ + "input": "DECLARE @status NVARCHAR(50); SET @status = 'Delayed'; UPDATE orders SET status = @status WHERE order_date < GETDATE() - 60;", + "outputs": [ + { + "expected": "DECLARE @status NVARCHAR ( ? ); SET @status = ?; UPDATE orders SET status = @status WHERE order_date < GETDATE ( ) - ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-with-null-handling.json b/testdata/mssql/update/update-with-null-handling.json new file mode 100644 index 0000000..bcfce2b --- /dev/null +++ b/testdata/mssql/update/update-with-null-handling.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE orders SET delivery_date = NULLIF(order_date, due_date) WHERE status = 'Cancelled';", + "outputs": [ + { + "expected": "UPDATE orders SET delivery_date = NULLIF ( order_date, due_date ) WHERE status = ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-with-numeric-calculation.json b/testdata/mssql/update/update-with-numeric-calculation.json new file mode 100644 index 0000000..6b8ec4b --- /dev/null +++ b/testdata/mssql/update/update-with-numeric-calculation.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE orders SET total_amount = quantity * unit_price WHERE status = 'Pending';", + "outputs": [ + { + "expected": "UPDATE orders SET total_amount = quantity * unit_price WHERE status = ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-with-output.json b/testdata/mssql/update/update-with-output.json new file mode 100644 index 0000000..a5edfb6 --- /dev/null +++ b/testdata/mssql/update/update-with-output.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE orders SET status = 'Cancelled' OUTPUT deleted.id, deleted.status WHERE status = 'Pending' AND order_date < GETDATE() - 90;", + "outputs": [ + { + "expected": "UPDATE orders SET status = ? OUTPUT deleted.id, deleted.status WHERE status = ? AND order_date < GETDATE ( ) - ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-with-string-concatenation.json b/testdata/mssql/update/update-with-string-concatenation.json new file mode 100644 index 0000000..b81b813 --- /dev/null +++ b/testdata/mssql/update/update-with-string-concatenation.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE orders SET notes = CONCAT(notes, ' Updated on ', CONVERT(VARCHAR, GETDATE(), 101)) WHERE status = 'Shipped';", + "outputs": [ + { + "expected": "UPDATE orders SET notes = CONCAT ( notes, ?, CONVERT ( VARCHAR, GETDATE ( ), ? ) ) WHERE status = ?", + "statement_metadata": { + "size": 12, + "tables": ["orders"], + "commands": ["UPDATE"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file diff --git a/testdata/mssql/update/update-with-subquery.json b/testdata/mssql/update/update-with-subquery.json new file mode 100644 index 0000000..00d3be2 --- /dev/null +++ b/testdata/mssql/update/update-with-subquery.json @@ -0,0 +1,16 @@ +{ + "input": "UPDATE orders SET status = 'High Priority' WHERE id IN (SELECT order_id FROM order_details WHERE quantity > 10);", + "outputs": [ + { + "expected": "UPDATE orders SET status = ? WHERE id IN ( SELECT order_id FROM order_details WHERE quantity > ? )", + "statement_metadata": { + "size": 31, + "tables": ["orders", "order_details"], + "commands": ["UPDATE", "SELECT"], + "comments": [], + "procedures": [] + } + } + ] + } + \ No newline at end of file