EndTransactionBlock执行一个commit命令。COMMIT命令有可能做的是ROLLBACK操作,EndTransactionBlock函数返回true代表COMMIT,false代表ROLLBACK。在该函数中处理改变事物状态块的状态,其他工作由后续CommitTransactionCommand函数处理。

  • 事务状态由TBLOCK_INPROGRESS改变为TBLOCK_END,标记result为true代表COMMIT
  • 事务状态TBLOCK_IMPLICIT_INPROGRESS,如果处于事务链chain,直接报错,否则直接将事务状态改变为TBLOCK_END,标记result为true代表COMMIT
bool EndTransactionBlock(bool chain) {
TransactionState s = CurrentTransactionState;
bool result = false;
switch (s->blockState) {
/* We are in a transaction block, so tell CommitTransactionCommand to COMMIT. */
case TBLOCK_INPROGRESS:
s->blockState = TBLOCK_END;
result = true;
break;
/* We are in an implicit transaction block. If AND CHAIN was specified, error. Otherwise commit, but issue a warning because there was no explicit BEGIN before this. */
case TBLOCK_IMPLICIT_INPROGRESS:
if (chain) ereport(ERROR, (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),/* translator: %s represents an SQL statement name */ errmsg("%s can only be used in transaction blocks","COMMIT AND CHAIN")));
else ereport(WARNING, (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION), errmsg("there is no transaction in progress")));
s->blockState = TBLOCK_END;
result = true;
break;
  • 事务状态由TBLOCK_ABORT改变为TBLOCK_ABORT_END,标记result为fasle代表ROLLBACK
/* We are in a failed transaction block.  Tell CommitTransactionCommand it's time to exit the block. */
case TBLOCK_ABORT:
s->blockState = TBLOCK_ABORT_END;
break;
  • 事务状态处于TBLOCK_SUBINPROGRESS子事务中,将子事务状态改为TBLOCK_SUBCOMMIT,循环处理父事务。最后处理顶层事务将事务状态由TBLOCK_INPROGRESS转变为TBLOCK_END,标记result为true代表COMMIT
/* We are in a live subtransaction block.  Set up to subcommit all open subtransactions and then commit the main transaction. */
case TBLOCK_SUBINPROGRESS:
while (s->parent != NULL) {
if (s->blockState == TBLOCK_SUBINPROGRESS) s->blockState = TBLOCK_SUBCOMMIT;
else elog(FATAL, "EndTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState));
s = s->parent;
}
if (s->blockState == TBLOCK_INPROGRESS) s->blockState = TBLOCK_END;
else elog(FATAL, "EndTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState));
result = true;
break;
  • 事务状态处于TBLOCK_SUBABORT子事务中,将子事务状态改变为TBLOCK_SUBABORT,否则如果处于TBLOCK_SUBINPROGRESS则改变为TBLOCK_SUBABORT_PENDING。循环处理父事务。最后处理顶层事务将事务状态,标记result为fasle代表ROLLBACK
/* Here we are inside an aborted subtransaction.  Treat the COMMIT as ROLLBACK: set up to abort everything and exit the main transaction. */
case TBLOCK_SUBABORT:
while (s->parent != NULL){
if (s->blockState == TBLOCK_SUBINPROGRESS) s->blockState = TBLOCK_SUBABORT_PENDING;
else if (s->blockState == TBLOCK_SUBABORT)
s->blockState = TBLOCK_SUBABORT_END;
else elog(FATAL, "EndTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState));
s = s->parent;
}
if (s->blockState == TBLOCK_INPROGRESS)s->blockState = TBLOCK_ABORT_PENDING;
else if (s->blockState == TBLOCK_ABORT) s->blockState = TBLOCK_ABORT_END;
else elog(FATAL, "EndTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState));
break;
  • 其他事务状态属于异常处理
/* The user issued COMMIT when not inside a transaction.  For
* COMMIT without CHAIN, issue a WARNING, staying in
* TBLOCK_STARTED state. The upcoming call to
* CommitTransactionCommand() will then close the transaction and
* put us back into the default state. For COMMIT AND CHAIN,
* error. */
case TBLOCK_STARTED:
if (chain)
ereport(ERROR, (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION), /* translator: %s represents an SQL statement name */ errmsg("%s can only be used in transaction blocks", "COMMIT AND CHAIN")));
else
ereport(WARNING, (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION), errmsg("there is no transaction in progress")));
result = true;
break;

/* The user issued a COMMIT that somehow ran inside a parallel worker. We can't cope with that. */
case TBLOCK_PARALLEL_INPROGRESS:
ereport(FATAL, (errcode(ERRCODE_INVALID_TRANSACTION_STATE),errmsg("cannot commit during a parallel operation")));
break;
/* These cases are invalid. */
case TBLOCK_DEFAULT:
case TBLOCK_BEGIN:
case TBLOCK_SUBBEGIN:
case TBLOCK_END:
case TBLOCK_SUBRELEASE:
case TBLOCK_SUBCOMMIT:
case TBLOCK_ABORT_END:
case TBLOCK_SUBABORT_END:
case TBLOCK_ABORT_PENDING:
case TBLOCK_SUBABORT_PENDING:
case TBLOCK_SUBRESTART:
case TBLOCK_SUBABORT_RESTART:
case TBLOCK_PREPARE:
elog(FATAL, "EndTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState));
break;
}
Assert(s->blockState == TBLOCK_STARTED || s->blockState == TBLOCK_END || s->blockState == TBLOCK_ABORT_END || s->blockState == TBLOCK_ABORT_PENDING);

s->chain = chain;
return result;
}