Auto-wrap in a transaction

✓ functional

Put non-read work inside a transaction you can inspect and roll back before it becomes permanent.

With auto-wrap on, anything beyond a plain read runs inside an outer transaction that SQLly rolls back for you. The statement really executes - you see the row counts, the constraint violation, the trigger firing - and then the database is left exactly as it was.

What actually gets sent

SQLly rewrites the batch in your engine's own transaction syntax:

EngineWrap
SQL ServerSET XACT_ABORT ON; BEGIN TRANSACTION; …; ROLLBACK TRANSACTION;
MySQL / MariaDBSTART TRANSACTION; …; ROLLBACK;
PostgreSQL, SQLite, DuckDBBEGIN; …; ROLLBACK;

XACT_ABORT ON on SQL Server matters: it makes the server abandon the whole transaction on the first error instead of continuing with part of the batch applied. A batch that is nothing but USE <database> is left alone - there is nothing to undo, and wrapping it would only confuse the session context.

The cases it refuses rather than fakes

  • MySQL DDL. MySQL implicitly commits CREATE, ALTER, DROP, TRUNCATE, RENAME, GRANT, and REVOKE. Inside the wrap those changes - and everything before them - would silently persist, which breaks the setting's whole promise. SQLly refuses the batch and says so, naming the verb, rather than pretending it rolled back. (CREATE/DROP TEMPORARY TABLE is exempt; MySQL does not commit those.)
  • T-SQL routine definitions. CREATE/ALTER PROCEDURE, FUNCTION, TRIGGER, and VIEW must lead their batch, so a BEGIN TRANSACTION in front would make SQL Server reject the whole thing with error 111. SQLly instead gives the definition a batch of its own inside the transaction via EXEC(N'…'), so the deploy runs, is observable, and still rolls back.
Preview before you run. The same logic powers a non-executing preview, so a staging or production connection can show you the exact SQL that would be sent - wrapped or refused, with the reason - without touching the server.

Things the wrap cannot undo

A transaction only covers what the engine puts inside it. Sequence and identity values consumed by an insert are not returned, work done by a linked server or an autonomous transaction is outside the scope, and any engine that commits DDL implicitly behaves the way that engine behaves. The wrap is an excellent rehearsal; it is not a time machine.