Add NpgsqlTransactionOptions for read-only/deferrable transactions - #6629
Add NpgsqlTransactionOptions for read-only/deferrable transactions#6629bjornharrtell wants to merge 2 commits into
Conversation
Adds NpgsqlConnection.BeginTransaction(Async) overloads accepting a new NpgsqlTransactionOptions flags enum (ReadOnly, Deferrable), allowing transactions to be started with these options without an extra roundtrip (e.g. SET TRANSACTION READ ONLY). Fixes npgsql#867
There was a problem hiding this comment.
Pull request overview
This PR introduces a new NpgsqlTransactionOptions flags enum (e.g., ReadOnly, Deferrable) and adds BeginTransaction/BeginTransactionAsync overloads on NpgsqlConnection to start transactions with these options directly in the initial BEGIN statement (avoiding a follow-up SET TRANSACTION roundtrip).
Changes:
- Add
NpgsqlTransactionOptionsenum to represent Npgsql-specific transaction start options. - Add new sync/async
BeginTransactionoverloads acceptingNpgsqlTransactionOptions, and wire them into transaction initialization. - Add tests verifying
READ ONLYandDEFERRABLEbehavior (sync path).
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| test/Npgsql.Tests/TransactionTests.cs | Adds coverage for read-only and deferrable transaction options. |
| src/Npgsql/PublicAPI.Unshipped.txt | Registers the newly added public overloads in the public API tracking file. |
| src/Npgsql/NpgsqlTransactionOptions.cs | Introduces the new flags enum for transaction start options. |
| src/Npgsql/NpgsqlTransaction.cs | Extends transaction initialization to emit a dynamic BEGIN statement when options are requested. |
| src/Npgsql/NpgsqlConnection.cs | Adds new BeginTransaction/BeginTransactionAsync overloads that accept NpgsqlTransactionOptions. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- Remove single-arg BeginTransaction(Options)/BeginTransactionAsync(Options, ...) overloads: combined with the existing IsolationLevel overloads, these made calls like BeginTransaction(default) ambiguous. - Thread async/cancellationToken through NpgsqlTransaction.Init into WriteQuery instead of always blocking synchronously. - Update PublicAPI.Unshipped.txt accordingly. - Add async test coverage for the ReadOnly/Deferrable options.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/Npgsql/NpgsqlTransaction.cs:136
NpgsqlTransactionOptionsisn't validated before generating the BEGIN statement. Invalid flag values (unknown bits) will be silently ignored, andDeferrablewithoutReadOnlyandSerializablewill cause a server-side error at execution time. Consider validating flags/combinations and throwing an argument exception early with a clear message.
var sb = new StringBuilder("BEGIN TRANSACTION ISOLATION LEVEL ").Append(isolationLevelText);
if ((options & NpgsqlTransactionOptions.ReadOnly) != 0)
sb.Append(" READ ONLY");
if ((options & NpgsqlTransactionOptions.Deferrable) != 0)
sb.Append(" DEFERRABLE");
roji
left a comment
There was a problem hiding this comment.
Thanks, looks good! See one small nit, other than that looks ready to merge.
|
|
||
| // Unlike the isolation levels above, these options can be combined in many ways, making it impractical to pregenerate | ||
| // messages for all combinations; the BEGIN statement is written out and sent like a regular (prepended) query instead. | ||
| await _connector.WriteQuery(sb.ToString(), async, cancellationToken).ConfigureAwait(false); |
There was a problem hiding this comment.
(from @vonzshik) you can just do a synchronous write here, assuming that there will always be enough space in the buffer; we already make that assumption above when we call PrependInternalMessage. At that point everything here is sync and you can also inline the local method.
Adds NpgsqlConnection.BeginTransaction(Async) overloads accepting a new NpgsqlTransactionOptions flags enum (ReadOnly, Deferrable), allowing transactions to be started with these options without an extra roundtrip (e.g. SET TRANSACTION READ ONLY).
Ref #867