transaction method Null safety

Future transaction(
  1. Future queryBlock(
    1. PostgreSQLExecutionContext connection
    ),
  2. {int? commitTimeoutInSeconds}
)

Executes a series of queries inside a transaction on this connection.

Queries executed inside queryBlock will be grouped together in a transaction. The return value of the queryBlock will be the wrapped in the Future returned by this method if the transaction completes successfully.

If a query or execution fails - for any reason - within a transaction block, the transaction will fail and previous statements within the transaction will not be committed. The Future returned from this method will be completed with the error from the first failing query.

Transactions may be cancelled by invoking PostgreSQLExecutionContext.cancelTransaction within the transaction. This will cause this method to return a Future with a value of PostgreSQLRollback. This method does not throw an exception if the transaction is cancelled in this way.

All queries within a transaction block must be executed using the PostgreSQLExecutionContext passed into the queryBlock. You must not issue queries to the receiver of this method from within the queryBlock, otherwise the connection will deadlock.

Queries within a transaction may be executed asynchronously or be awaited on. The order is still guaranteed. Example:

    connection.transaction((ctx) {
      var rows = await ctx.query("SELECT id FROM t");
      if (!rows.contains([2])) {
        ctx.query("INSERT INTO t (id) VALUES (2)");
      }
    });

If specified, the final "COMMIT" query of the transaction will use commitTimeoutInSeconds as its timeout, otherwise the connection's default query timeout will be used.

Implementation

Future transaction(
  Future Function(PostgreSQLExecutionContext connection) queryBlock, {
  int? commitTimeoutInSeconds,
}) async {
  if (isClosed) {
    throw PostgreSQLException(
        'Attempting to execute query, but connection is not open.');
  }

  final proxy = _TransactionProxy(this, queryBlock, commitTimeoutInSeconds);

  await _enqueue(proxy._beginQuery);

  return await proxy.future;
}