diff --git a/src/backend/access/rmgrdesc/standbydesc.c b/src/backend/access/rmgrdesc/standbydesc.c
index c295358..a7f367c 100644
*** a/src/backend/access/rmgrdesc/standbydesc.c
--- b/src/backend/access/rmgrdesc/standbydesc.c
*************** standby_desc_invalidations(StringInfo bu
*** 111,131 ****
  	{
  		SharedInvalidationMessage *msg = &msgs[i];
  
! 		if (msg->id >= 0)
! 			appendStringInfo(buf, " catcache %d", msg->id);
! 		else if (msg->id == SHAREDINVALCATALOG_ID)
! 			appendStringInfo(buf, " catalog %u", msg->cat.catId);
! 		else if (msg->id == SHAREDINVALRELCACHE_ID)
! 			appendStringInfo(buf, " relcache %u", msg->rc.relId);
! 		/* not expected, but print something anyway */
! 		else if (msg->id == SHAREDINVALSMGR_ID)
! 			appendStringInfoString(buf, " smgr");
! 		/* not expected, but print something anyway */
! 		else if (msg->id == SHAREDINVALRELMAP_ID)
! 			appendStringInfo(buf, " relmap db %u", msg->rm.dbId);
! 		else if (msg->id == SHAREDINVALSNAPSHOT_ID)
! 			appendStringInfo(buf, " snapshot %u", msg->sn.relId);
! 		else
! 			appendStringInfo(buf, " unrecognized id %d", msg->id);
  	}
  }
--- 111,141 ----
  	{
  		SharedInvalidationMessage *msg = &msgs[i];
  
! 		switch ((SharedInvalMsgType) msg->id)
! 		{
! 			case SharedInvalCatcache:
! 				appendStringInfo(buf, " catcache %d", msg->cc.cacheId);
! 				break;
! 			case SharedInvalCatalog:
! 				appendStringInfo(buf, " catalog %u", msg->cat.catId);
! 				break;
! 			case SharedInvalRelcache:
! 				appendStringInfo(buf, " relcache %u", msg->rc.relId);
! 				break;
! 			case SharedInvalSmgr:
! 				/* not expected, but print something anyway */
! 				appendStringInfoString(buf, " smgr");
! 				break;
! 			case SharedInvalRelmap:
! 				/* not expected, but print something anyway */
! 				appendStringInfo(buf, " relmap db %u", msg->rm.dbId);
! 				break;
! 			case SharedInvalSnapshot:
! 				appendStringInfo(buf, " snapshot %u", msg->sn.relId);
! 				break;
! 			default:
! 				appendStringInfo(buf, " unrecognized id %d", msg->id);
! 				break;
! 		}
  	}
  }
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 80d7a76..5bc08b0 100644
*** a/src/backend/utils/cache/inval.c
--- b/src/backend/utils/cache/inval.c
*************** AddCatcacheInvalidationMessage(Invalidat
*** 340,346 ****
  	SharedInvalidationMessage msg;
  
  	Assert(id < CHAR_MAX);
! 	msg.cc.id = (int8) id;
  	msg.cc.dbId = dbId;
  	msg.cc.hashValue = hashValue;
  
--- 340,347 ----
  	SharedInvalidationMessage msg;
  
  	Assert(id < CHAR_MAX);
! 	msg.cc.id = SharedInvalCatcache;
! 	msg.cc.cacheId = (int8) id;
  	msg.cc.dbId = dbId;
  	msg.cc.hashValue = hashValue;
  
*************** AddCatalogInvalidationMessage(Invalidati
*** 367,373 ****
  {
  	SharedInvalidationMessage msg;
  
! 	msg.cat.id = SHAREDINVALCATALOG_ID;
  	msg.cat.dbId = dbId;
  	msg.cat.catId = catId;
  	/* check AddCatcacheInvalidationMessage() for an explanation */
--- 368,374 ----
  {
  	SharedInvalidationMessage msg;
  
! 	msg.cat.id = SharedInvalCatalog;
  	msg.cat.dbId = dbId;
  	msg.cat.catId = catId;
  	/* check AddCatcacheInvalidationMessage() for an explanation */
*************** AddRelcacheInvalidationMessage(Invalidat
*** 391,403 ****
  	 * don't need to add individual ones when it is present.
  	 */
  	ProcessMessageList(hdr->rclist,
! 					   if (msg->rc.id == SHAREDINVALRELCACHE_ID &&
  						   (msg->rc.relId == relId ||
  							msg->rc.relId == InvalidOid))
  					   return);
  
  	/* OK, add the item */
! 	msg.rc.id = SHAREDINVALRELCACHE_ID;
  	msg.rc.dbId = dbId;
  	msg.rc.relId = relId;
  	/* check AddCatcacheInvalidationMessage() for an explanation */
--- 392,404 ----
  	 * don't need to add individual ones when it is present.
  	 */
  	ProcessMessageList(hdr->rclist,
! 					   if (msg->rc.id == SharedInvalRelcache &&
  						   (msg->rc.relId == relId ||
  							msg->rc.relId == InvalidOid))
  					   return);
  
  	/* OK, add the item */
! 	msg.rc.id = SharedInvalRelcache;
  	msg.rc.dbId = dbId;
  	msg.rc.relId = relId;
  	/* check AddCatcacheInvalidationMessage() for an explanation */
*************** AddSnapshotInvalidationMessage(Invalidat
*** 418,429 ****
  	/* Don't add a duplicate item */
  	/* We assume dbId need not be checked because it will never change */
  	ProcessMessageList(hdr->rclist,
! 					   if (msg->sn.id == SHAREDINVALSNAPSHOT_ID &&
  						   msg->sn.relId == relId)
  					   return);
  
  	/* OK, add the item */
! 	msg.sn.id = SHAREDINVALSNAPSHOT_ID;
  	msg.sn.dbId = dbId;
  	msg.sn.relId = relId;
  	/* check AddCatcacheInvalidationMessage() for an explanation */
--- 419,430 ----
  	/* Don't add a duplicate item */
  	/* We assume dbId need not be checked because it will never change */
  	ProcessMessageList(hdr->rclist,
! 					   if (msg->sn.id == SharedInvalSnapshot &&
  						   msg->sn.relId == relId)
  					   return);
  
  	/* OK, add the item */
! 	msg.sn.id = SharedInvalSnapshot;
  	msg.sn.dbId = dbId;
  	msg.sn.relId = relId;
  	/* check AddCatcacheInvalidationMessage() for an explanation */
*************** RegisterSnapshotInvalidation(Oid dbId, O
*** 553,629 ****
  void
  LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
  {
! 	if (msg->id >= 0)
  	{
! 		if (msg->cc.dbId == MyDatabaseId || msg->cc.dbId == InvalidOid)
! 		{
! 			InvalidateCatalogSnapshot();
  
! 			SysCacheInvalidate(msg->cc.id, msg->cc.hashValue);
  
! 			CallSyscacheCallbacks(msg->cc.id, msg->cc.hashValue);
! 		}
! 	}
! 	else if (msg->id == SHAREDINVALCATALOG_ID)
! 	{
! 		if (msg->cat.dbId == MyDatabaseId || msg->cat.dbId == InvalidOid)
! 		{
! 			InvalidateCatalogSnapshot();
  
! 			CatalogCacheFlushCatalog(msg->cat.catId);
  
! 			/* CatalogCacheFlushCatalog calls CallSyscacheCallbacks as needed */
! 		}
! 	}
! 	else if (msg->id == SHAREDINVALRELCACHE_ID)
! 	{
! 		if (msg->rc.dbId == MyDatabaseId || msg->rc.dbId == InvalidOid)
! 		{
! 			int			i;
  
! 			if (msg->rc.relId == InvalidOid)
! 				RelationCacheInvalidate();
! 			else
! 				RelationCacheInvalidateEntry(msg->rc.relId);
  
! 			for (i = 0; i < relcache_callback_count; i++)
! 			{
! 				struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
  
! 				ccitem->function(ccitem->arg, msg->rc.relId);
  			}
! 		}
! 	}
! 	else if (msg->id == SHAREDINVALSMGR_ID)
! 	{
! 		/*
! 		 * We could have smgr entries for relations of other databases, so no
! 		 * short-circuit test is possible here.
! 		 */
! 		RelFileNodeBackend rnode;
  
! 		rnode.node = msg->sm.rnode;
! 		rnode.backend = (msg->sm.backend_hi << 16) | (int) msg->sm.backend_lo;
! 		smgrclosenode(rnode);
! 	}
! 	else if (msg->id == SHAREDINVALRELMAP_ID)
! 	{
! 		/* We only care about our own database and shared catalogs */
! 		if (msg->rm.dbId == InvalidOid)
! 			RelationMapInvalidate(true);
! 		else if (msg->rm.dbId == MyDatabaseId)
! 			RelationMapInvalidate(false);
! 	}
! 	else if (msg->id == SHAREDINVALSNAPSHOT_ID)
! 	{
! 		/* We only care about our own database and shared catalogs */
! 		if (msg->rm.dbId == InvalidOid)
! 			InvalidateCatalogSnapshot();
! 		else if (msg->rm.dbId == MyDatabaseId)
! 			InvalidateCatalogSnapshot();
  	}
- 	else
- 		elog(FATAL, "unrecognized SI message ID: %d", msg->id);
  }
  
  /*
--- 554,633 ----
  void
  LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
  {
! 	switch ((SharedInvalMsgType) msg->id)
  	{
! 		case SharedInvalCatcache:
! 			if (msg->cc.dbId == MyDatabaseId || msg->cc.dbId == InvalidOid)
! 			{
! 				InvalidateCatalogSnapshot();
  
! 				SysCacheInvalidate(msg->cc.cacheId, msg->cc.hashValue);
  
! 				CallSyscacheCallbacks(msg->cc.cacheId, msg->cc.hashValue);
! 			}
! 			break;
! 		case SharedInvalCatalog:
! 			if (msg->cat.dbId == MyDatabaseId || msg->cat.dbId == InvalidOid)
! 			{
! 				InvalidateCatalogSnapshot();
  
! 				CatalogCacheFlushCatalog(msg->cat.catId);
  
! 				/*
! 				 * CatalogCacheFlushCatalog calls CallSyscacheCallbacks as
! 				 * needed
! 				 */
! 			}
! 			break;
! 		case SharedInvalRelcache:
! 			if (msg->rc.dbId == MyDatabaseId || msg->rc.dbId == InvalidOid)
! 			{
! 				int			i;
  
! 				if (msg->rc.relId == InvalidOid)
! 					RelationCacheInvalidate();
! 				else
! 					RelationCacheInvalidateEntry(msg->rc.relId);
  
! 				for (i = 0; i < relcache_callback_count; i++)
! 				{
! 					struct RELCACHECALLBACK *ccitem = relcache_callback_list + i;
  
! 					ccitem->function(ccitem->arg, msg->rc.relId);
! 				}
  			}
! 			break;
! 		case SharedInvalSmgr:
! 			{
! 				/*
! 				 * We could have smgr entries for relations of other
! 				 * databases, so no short-circuit test is possible here.
! 				 */
! 				RelFileNodeBackend rnode;
  
! 				rnode.node = msg->sm.rnode;
! 				rnode.backend = (msg->sm.backend_hi << 16) | (int) msg->sm.backend_lo;
! 				smgrclosenode(rnode);
! 				break;
! 			}
! 		case SharedInvalRelmap:
! 			/* We only care about our own database and shared catalogs */
! 			if (msg->rm.dbId == InvalidOid)
! 				RelationMapInvalidate(true);
! 			else if (msg->rm.dbId == MyDatabaseId)
! 				RelationMapInvalidate(false);
! 			break;
! 		case SharedInvalSnapshot:
! 			/* We only care about our own database and shared catalogs */
! 			if (msg->rm.dbId == InvalidOid)
! 				InvalidateCatalogSnapshot();
! 			else if (msg->rm.dbId == MyDatabaseId)
! 				InvalidateCatalogSnapshot();
! 			break;
! 		default:
! 			elog(FATAL, "unrecognized SI message ID: %d", msg->id);
! 			break;
  	}
  }
  
  /*
*************** CacheInvalidateSmgr(RelFileNodeBackend r
*** 1351,1357 ****
  {
  	SharedInvalidationMessage msg;
  
! 	msg.sm.id = SHAREDINVALSMGR_ID;
  	msg.sm.backend_hi = rnode.backend >> 16;
  	msg.sm.backend_lo = rnode.backend & 0xffff;
  	msg.sm.rnode = rnode.node;
--- 1355,1361 ----
  {
  	SharedInvalidationMessage msg;
  
! 	msg.sm.id = SharedInvalSmgr;
  	msg.sm.backend_hi = rnode.backend >> 16;
  	msg.sm.backend_lo = rnode.backend & 0xffff;
  	msg.sm.rnode = rnode.node;
*************** CacheInvalidateRelmap(Oid databaseId)
*** 1381,1387 ****
  {
  	SharedInvalidationMessage msg;
  
! 	msg.rm.id = SHAREDINVALRELMAP_ID;
  	msg.rm.dbId = databaseId;
  	/* check AddCatcacheInvalidationMessage() for an explanation */
  	VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
--- 1385,1391 ----
  {
  	SharedInvalidationMessage msg;
  
! 	msg.rm.id = SharedInvalRelmap;
  	msg.rm.dbId = databaseId;
  	/* check AddCatcacheInvalidationMessage() for an explanation */
  	VALGRIND_MAKE_MEM_DEFINED(&msg, sizeof(msg));
diff --git a/src/include/storage/sinval.h b/src/include/storage/sinval.h
index 635acda..d0d9ece 100644
*** a/src/include/storage/sinval.h
--- b/src/include/storage/sinval.h
***************
*** 28,36 ****
   *	* invalidate the mapped-relation mapping for a given database
   *	* invalidate any saved snapshot that might be used to scan a given relation
   * More types could be added if needed.  The message type is identified by
!  * the first "int8" field of the message struct.  Zero or positive means a
!  * specific-catcache inval message (and also serves as the catcache ID field).
!  * Negative values identify the other message types, as per codes below.
   *
   * Catcache inval events are initially driven by detecting tuple inserts,
   * updates and deletions in system catalogs (see CacheInvalidateHeapTuple).
--- 28,34 ----
   *	* invalidate the mapped-relation mapping for a given database
   *	* invalidate any saved snapshot that might be used to scan a given relation
   * More types could be added if needed.  The message type is identified by
!  * the first "int8" field of the message struct.
   *
   * Catcache inval events are initially driven by detecting tuple inserts,
   * updates and deletions in system catalogs (see CacheInvalidateHeapTuple).
***************
*** 57,71 ****
   * sent immediately when the underlying file change is made.
   */
  
  typedef struct
  {
! 	int8		id;				/* cache ID --- must be first */
  	Oid			dbId;			/* database ID, or 0 if a shared relation */
  	uint32		hashValue;		/* hash value of key for this catcache */
  } SharedInvalCatcacheMsg;
  
- #define SHAREDINVALCATALOG_ID	(-1)
- 
  typedef struct
  {
  	int8		id;				/* type field --- must be first */
--- 55,78 ----
   * sent immediately when the underlying file change is made.
   */
  
+ typedef enum SharedInvalMsgType
+ {
+ 	SharedInvalCatcache,
+ 	SharedInvalCatalog,
+ 	SharedInvalRelcache,
+ 	SharedInvalSmgr,
+ 	SharedInvalRelmap,
+ 	SharedInvalSnapshot
+ } SharedInvalMsgType;
+ 
  typedef struct
  {
! 	int8		id;				/* type field --- must be first */
! 	int8		cacheId;		/* cache ID */
  	Oid			dbId;			/* database ID, or 0 if a shared relation */
  	uint32		hashValue;		/* hash value of key for this catcache */
  } SharedInvalCatcacheMsg;
  
  typedef struct
  {
  	int8		id;				/* type field --- must be first */
*************** typedef struct
*** 73,80 ****
  	Oid			catId;			/* ID of catalog whose contents are invalid */
  } SharedInvalCatalogMsg;
  
- #define SHAREDINVALRELCACHE_ID	(-2)
- 
  typedef struct
  {
  	int8		id;				/* type field --- must be first */
--- 80,85 ----
*************** typedef struct
*** 82,89 ****
  	Oid			relId;			/* relation ID, or 0 if whole relcache */
  } SharedInvalRelcacheMsg;
  
- #define SHAREDINVALSMGR_ID		(-3)
- 
  typedef struct
  {
  	/* note: field layout chosen to pack into 16 bytes */
--- 87,92 ----
*************** typedef struct
*** 93,108 ****
  	RelFileNode rnode;			/* spcNode, dbNode, relNode */
  } SharedInvalSmgrMsg;
  
- #define SHAREDINVALRELMAP_ID	(-4)
- 
  typedef struct
  {
  	int8		id;				/* type field --- must be first */
  	Oid			dbId;			/* database ID, or 0 for shared catalogs */
  } SharedInvalRelmapMsg;
  
- #define SHAREDINVALSNAPSHOT_ID	(-5)
- 
  typedef struct
  {
  	int8		id;				/* type field --- must be first */
--- 96,107 ----
