*** a/contrib/test_decoding/expected/xact.out
--- b/contrib/test_decoding/expected/xact.out
***************
*** 6,14 **** SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_d
   init
  (1 row)
  
- -- bug #13844, xids in non-decoded records need to be inspected
  CREATE TABLE xact_test(data text);
  INSERT INTO xact_test VALUES ('before-test');
  BEGIN;
  -- perform operation in xact that creates and logs xid, but isn't decoded
  SELECT * FROM xact_test FOR UPDATE;
--- 6,14 ----
   init
  (1 row)
  
  CREATE TABLE xact_test(data text);
  INSERT INTO xact_test VALUES ('before-test');
+ -- bug #13844, xids in non-decoded records need to be inspected
  BEGIN;
  -- perform operation in xact that creates and logs xid, but isn't decoded
  SELECT * FROM xact_test FOR UPDATE;
***************
*** 33,38 **** SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'inc
--- 33,60 ----
   COMMIT
  (6 rows)
  
+ -- bug #14279
+ BEGIN;
+ -- first insert
+ INSERT INTO xact_test VALUES ('main-txn');
+ SAVEPOINT foo;
+ -- and then perform operation in subxact that creates and logs xid, but isn't decoded
+ SELECT 1 FROM xact_test FOR UPDATE LIMIT 1;
+  ?column? 
+ ----------
+         1
+ (1 row)
+ 
+ COMMIT;
+ -- and now show those changes
+ SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
+                          data                          
+ -------------------------------------------------------
+  BEGIN
+  table public.xact_test: INSERT: data[text]:'main-txn'
+  COMMIT
+ (3 rows)
+ 
  DROP TABLE xact_test;
  SELECT pg_drop_replication_slot('regression_slot');
   pg_drop_replication_slot 
*** a/contrib/test_decoding/sql/xact.sql
--- b/contrib/test_decoding/sql/xact.sql
***************
*** 3,12 **** SET synchronous_commit = on;
  
  SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding');
  
- -- bug #13844, xids in non-decoded records need to be inspected
  CREATE TABLE xact_test(data text);
  INSERT INTO xact_test VALUES ('before-test');
  
  BEGIN;
  -- perform operation in xact that creates and logs xid, but isn't decoded
  SELECT * FROM xact_test FOR UPDATE;
--- 3,12 ----
  
  SELECT 'init' FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding');
  
  CREATE TABLE xact_test(data text);
  INSERT INTO xact_test VALUES ('before-test');
  
+ -- bug #13844, xids in non-decoded records need to be inspected
  BEGIN;
  -- perform operation in xact that creates and logs xid, but isn't decoded
  SELECT * FROM xact_test FOR UPDATE;
***************
*** 17,22 **** COMMIT;
--- 17,33 ----
  -- and now show those changes
  SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
  
+ -- bug #14279
+ BEGIN;
+ -- first insert
+ INSERT INTO xact_test VALUES ('main-txn');
+ SAVEPOINT foo;
+ -- and then perform operation in subxact that creates and logs xid, but isn't decoded
+ SELECT 1 FROM xact_test FOR UPDATE LIMIT 1;
+ COMMIT;
+ -- and now show those changes
+ SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
+ 
  DROP TABLE xact_test;
  
  SELECT pg_drop_replication_slot('regression_slot');
*** a/src/backend/replication/logical/reorderbuffer.c
--- b/src/backend/replication/logical/reorderbuffer.c
***************
*** 744,756 **** ReorderBufferCommitChild(ReorderBuffer *rb, TransactionId xid,
  		elog(ERROR, "subxact logged without previous toplevel record");
  
  	/*
! 	 * Pass the our base snapshot to the parent transaction if it doesn't have
! 	 * one, or ours is older. That can happen if there are no changes in the
  	 * toplevel transaction but in one of the child transactions. This allows
! 	 * the parent to simply use it's base snapshot initially.
  	 */
! 	if (txn->base_snapshot == NULL ||
! 		txn->base_snapshot_lsn > subtxn->base_snapshot_lsn)
  	{
  		txn->base_snapshot = subtxn->base_snapshot;
  		txn->base_snapshot_lsn = subtxn->base_snapshot_lsn;
--- 744,757 ----
  		elog(ERROR, "subxact logged without previous toplevel record");
  
  	/*
! 	 * Pass our base snapshot to the parent transaction if it doesn't have one,
! 	 * or ours is older. That can happen if there are no changes in the
  	 * toplevel transaction but in one of the child transactions. This allows
! 	 * the parent to simply use its base snapshot initially.
  	 */
! 	if (subtxn->base_snapshot != NULL &&
! 		(txn->base_snapshot == NULL ||
! 		 txn->base_snapshot_lsn > subtxn->base_snapshot_lsn))
  	{
  		txn->base_snapshot = subtxn->base_snapshot;
  		txn->base_snapshot_lsn = subtxn->base_snapshot_lsn;
