Hi, I think the difference between abort and abort prepared should be explained better (I am not quite sure I get it myself).
> + The required <function>abort_cb</function> callback is called whenever Also, why is this one required when all the 2pc stuff is optional? > +static void > +DecodePrepare(LogicalDecodingContext *ctx, XLogRecordBuffer *buf, > + xl_xact_parsed_prepare * parsed) > +{ > + XLogRecPtr origin_lsn = parsed->origin_lsn; > + TimestampTz commit_time = parsed->origin_timestamp; > + XLogRecPtr origin_id = XLogRecGetOrigin(buf->record); > + TransactionId xid = parsed->twophase_xid; > + bool skip; > + > + Assert(parsed->dbId != InvalidOid); > + Assert(TransactionIdIsValid(parsed->twophase_xid)); > + > + /* Whether or not this PREPARE needs to be skipped. */ > + skip = DecodeEndOfTxn(ctx, buf, parsed, xid); > + > + FinalizeTxnDecoding(ctx, buf, parsed, xid, skip); Given that DecodeEndOfTxn calls SnapBuildCommitTxn, won't this make the catalog changes done by prepared transaction visible to other transactions (which is undesirable as they should only be visible after it's committed) ? > + if (unlikely(TransactionIdIsValid(CheckXidAlive) && > + !(IsCatalogRelation(scan->rs_rd) || > + RelationIsUsedAsCatalogTable(scan->rs_rd)))) > + ereport(ERROR, > + (errcode(ERRCODE_INVALID_TRANSACTION_STATE), > + errmsg("improper heap_getnext call"))); > + I think we should log the relation oid as well so that plugin developers have easier time debugging this (for all variants of this). -- Petr Jelinek http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services