From 1e9e92b90c3cc69008babe766292f932bdda0f73 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sat, 29 Sep 2018 18:48:23 -0700
Subject: [PATCH] Super-Heavy-WIP: Remove WITH OIDs support.

System table oids are now normal-ish columns.

Issues:
- objectaddress.c usage isn't acceptable (or needs to be complete)
- the nodeModifyTable.c hack is ugly as hell
- now some bootstrap oids are assigned by genbki.pl and some assigned
  at runtime. Different ranges.

Author: Andres Freund
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 contrib/adminpack/adminpack.c                 |   2 +-
 contrib/dblink/dblink.c                       |   8 +-
 contrib/pageinspect/heapfuncs.c               |   7 +-
 contrib/pg_buffercache/pg_buffercache_pages.c |   2 +-
 contrib/pg_visibility/pg_visibility.c         |   4 +-
 contrib/postgres_fdw/postgres_fdw.c           |  12 +-
 contrib/sepgsql/label.c                       |   8 +-
 contrib/test_decoding/test_decoding.c         |   6 -
 src/backend/access/brin/brin_tuple.c          |   2 +-
 src/backend/access/common/heaptuple.c         |  29 +-
 src/backend/access/common/tupconvert.c        |  16 +-
 src/backend/access/common/tupdesc.c           |  18 +-
 src/backend/access/gin/ginutil.c              |   2 +-
 src/backend/access/gist/gistscan.c            |   2 +-
 src/backend/access/heap/heapam.c              |  71 +---
 src/backend/access/heap/tuptoaster.c          |  19 +-
 src/backend/access/transam/commit_ts.c        |   2 +-
 src/backend/access/transam/multixact.c        |   2 +-
 src/backend/access/transam/twophase.c         |   2 +-
 src/backend/access/transam/xlogfuncs.c        |   2 +-
 src/backend/bootstrap/bootparse.y             |  18 +-
 src/backend/bootstrap/bootscanner.l           |   1 -
 src/backend/bootstrap/bootstrap.c             |  10 +-
 src/backend/catalog/Catalog.pm                |   6 +-
 src/backend/catalog/aclchk.c                  |  48 ++-
 src/backend/catalog/catalog.c                 |  32 +-
 src/backend/catalog/genbki.pl                 |  18 +-
 src/backend/catalog/heap.c                    |  81 ++---
 src/backend/catalog/index.c                   |   9 +-
 src/backend/catalog/indexing.c                |  15 +-
 src/backend/catalog/namespace.c               |  15 +-
 src/backend/catalog/objectaddress.c           | 129 +++++--
 src/backend/catalog/pg_aggregate.c            |   5 +-
 src/backend/catalog/pg_collation.c            |  10 +-
 src/backend/catalog/pg_constraint.c           |  23 +-
 src/backend/catalog/pg_conversion.c           |  13 +-
 src/backend/catalog/pg_enum.c                 |   6 +-
 src/backend/catalog/pg_largeobject.c          |  18 +-
 src/backend/catalog/pg_namespace.c            |  11 +-
 src/backend/catalog/pg_operator.c             |  32 +-
 src/backend/catalog/pg_proc.c                 |  20 +-
 src/backend/catalog/pg_publication.c          |   8 +-
 src/backend/catalog/pg_subscription.c         |  14 +-
 src/backend/catalog/pg_type.c                 |  55 ++-
 src/backend/catalog/toasting.c                |   4 +-
 src/backend/commands/alter.c                  |   8 +-
 src/backend/commands/amcmds.c                 |   7 +-
 src/backend/commands/cluster.c                |  14 +-
 src/backend/commands/copy.c                   | 142 +-------
 src/backend/commands/createas.c               |  21 +-
 src/backend/commands/dbcommands.c             |  40 +--
 src/backend/commands/event_trigger.c          |  23 +-
 src/backend/commands/explain.c                |   2 +-
 src/backend/commands/extension.c              |  23 +-
 src/backend/commands/foreigncmds.c            |  36 +-
 src/backend/commands/functioncmds.c           |  21 +-
 src/backend/commands/indexcmds.c              |  29 +-
 src/backend/commands/matview.c                |   5 +-
 src/backend/commands/opclasscmds.c            |  39 +-
 src/backend/commands/policy.c                 |  17 +-
 src/backend/commands/prepare.c                |   2 +-
 src/backend/commands/proclang.c               |  11 +-
 src/backend/commands/publicationcmds.c        |  33 +-
 src/backend/commands/schemacmds.c             |  20 +-
 src/backend/commands/seclabel.c               |   1 +
 src/backend/commands/sequence.c               |   2 +-
 src/backend/commands/statscmds.c              |  10 +-
 src/backend/commands/subscriptioncmds.c       |  26 +-
 src/backend/commands/tablecmds.c              | 323 ++---------------
 src/backend/commands/tablespace.c             |  22 +-
 src/backend/commands/trigger.c                |  32 +-
 src/backend/commands/tsearchcmds.c            |  64 ++--
 src/backend/commands/typecmds.c               |  25 +-
 src/backend/commands/user.c                   |  40 ++-
 src/backend/commands/vacuum.c                 |   6 +-
 src/backend/commands/vacuumlazy.c             |   6 -
 src/backend/commands/variable.c               |  12 +-
 src/backend/commands/view.c                   |   1 -
 src/backend/executor/execExpr.c               |   1 -
 src/backend/executor/execJunk.c               |   7 +-
 src/backend/executor/execMain.c               |  64 ----
 src/backend/executor/execPartition.c          |   2 +-
 src/backend/executor/execSRF.c                |   4 +-
 src/backend/executor/execTuples.c             |  31 +-
 src/backend/executor/execUtils.c              |  10 -
 src/backend/executor/functions.c              |   6 +-
 src/backend/executor/nodeAgg.c                |   4 +-
 src/backend/executor/nodeCustom.c             |   2 +-
 src/backend/executor/nodeForeignscan.c        |   2 +-
 src/backend/executor/nodeFunctionscan.c       |   4 +-
 src/backend/executor/nodeIndexonlyscan.c      |   2 +-
 src/backend/executor/nodeModifyTable.c        |  65 ++--
 src/backend/executor/nodeSubplan.c            |   4 +-
 src/backend/executor/spi.c                    |  20 +-
 src/backend/foreign/foreign.c                 |   2 +-
 src/backend/optimizer/util/plancat.c          |   3 +-
 src/backend/parser/gram.y                     |  45 +--
 src/backend/parser/parse_clause.c             |  40 ---
 src/backend/parser/parse_oper.c               |   2 +-
 src/backend/parser/parse_relation.c           |  20 +-
 src/backend/parser/parse_target.c             |   2 +-
 src/backend/parser/parse_type.c               |  18 +-
 src/backend/parser/parse_utilcmd.c            |  46 +--
 src/backend/postmaster/autovacuum.c           |   6 +-
 src/backend/postmaster/pgstat.c               |   7 +-
 .../libpqwalreceiver/libpqwalreceiver.c       |   2 +-
 src/backend/replication/logical/launcher.c    |   2 +-
 src/backend/replication/walsender.c           |   6 +-
 src/backend/rewrite/rewriteDefine.c           |  24 +-
 src/backend/rewrite/rewriteRemove.c           |   2 +-
 src/backend/rewrite/rewriteSupport.c          |   6 +-
 src/backend/statistics/extended_stats.c       |   2 +-
 src/backend/storage/large_object/inv_api.c    |   2 +-
 src/backend/tcop/pquery.c                     |   9 +-
 src/backend/tsearch/wparser.c                 |   4 +-
 src/backend/utils/adt/acl.c                   |   2 +-
 src/backend/utils/adt/datetime.c              |   4 +-
 src/backend/utils/adt/enum.c                  |   8 +-
 src/backend/utils/adt/expandedrecord.c        |   8 +-
 src/backend/utils/adt/genfile.c               |   4 +-
 src/backend/utils/adt/lockfuncs.c             |   2 +-
 src/backend/utils/adt/misc.c                  |   2 +-
 src/backend/utils/adt/orderedsetaggs.c        |   4 +-
 src/backend/utils/adt/pgstatfuncs.c           |   2 +-
 src/backend/utils/adt/ruleutils.c             |   9 +-
 src/backend/utils/adt/selfuncs.c              |   1 -
 src/backend/utils/adt/trigfuncs.c             |  11 -
 src/backend/utils/adt/tsvector_op.c           |   4 +-
 src/backend/utils/cache/catcache.c            |  86 ++---
 src/backend/utils/cache/inval.c               |   4 +-
 src/backend/utils/cache/lsyscache.c           |   2 +-
 src/backend/utils/cache/plancache.c           |   4 +-
 src/backend/utils/cache/relcache.c            | 118 +++---
 src/backend/utils/cache/relfilenodemap.c      |  22 +-
 src/backend/utils/cache/syscache.c            |  64 ++--
 src/backend/utils/cache/typcache.c            |   2 +-
 src/backend/utils/fmgr/fmgr.c                 |   4 +-
 src/backend/utils/fmgr/funcapi.c              |   4 +-
 src/backend/utils/init/miscinit.c             |   2 +-
 src/backend/utils/init/postinit.c             |   8 +-
 src/backend/utils/misc/guc.c                  |  12 +-
 src/backend/utils/misc/pg_controldata.c       |   8 +-
 src/backend/utils/mmgr/portalmem.c            |   2 +-
 src/bin/pg_dump/pg_dump.c                     |   2 -
 src/bin/psql/describe.c                       |  19 +-
 src/include/access/heapam.h                   |   4 +-
 src/include/access/htup_details.h             |  18 +-
 src/include/access/sysattr.h                  |  14 +-
 src/include/access/transam.h                  |   2 +-
 src/include/access/tupdesc.h                  |   8 +-
 src/include/catalog/heap.h                    |   8 +-
 src/include/catalog/indexing.h                |   4 +-
 src/include/catalog/objectaddress.h           |   3 +-
 src/include/catalog/pg_aggregate.h            |   2 +-
 src/include/catalog/pg_am.h                   |   2 +
 src/include/catalog/pg_amop.h                 |   2 +
 src/include/catalog/pg_amproc.h               |   2 +
 src/include/catalog/pg_attrdef.h              |   2 +
 src/include/catalog/pg_attribute.h            |   2 +-
 src/include/catalog/pg_auth_members.h         |   2 +-
 src/include/catalog/pg_authid.h               |   1 +
 src/include/catalog/pg_cast.h                 |   2 +
 src/include/catalog/pg_class.dat              |  12 +-
 src/include/catalog/pg_class.h                |   2 +-
 src/include/catalog/pg_collation.h            |   1 +
 src/include/catalog/pg_constraint.h           |   2 +
 src/include/catalog/pg_conversion.h           |   1 +
 src/include/catalog/pg_database.h             |   1 +
 src/include/catalog/pg_db_role_setting.h      |   2 +-
 src/include/catalog/pg_default_acl.h          |   1 +
 src/include/catalog/pg_depend.h               |   2 +-
 src/include/catalog/pg_description.h          |   2 +-
 src/include/catalog/pg_enum.h                 |   1 +
 src/include/catalog/pg_event_trigger.h        |   1 +
 src/include/catalog/pg_extension.h            |   1 +
 src/include/catalog/pg_foreign_data_wrapper.h |   1 +
 src/include/catalog/pg_foreign_server.h       |   1 +
 src/include/catalog/pg_foreign_table.h        |   2 +-
 src/include/catalog/pg_index.h                |   2 +-
 src/include/catalog/pg_inherits.h             |   2 +-
 src/include/catalog/pg_init_privs.h           |   2 +-
 src/include/catalog/pg_language.h             |   2 +
 src/include/catalog/pg_largeobject.h          |   2 +-
 src/include/catalog/pg_largeobject_metadata.h |   2 +
 src/include/catalog/pg_namespace.h            |   2 +
 src/include/catalog/pg_opclass.h              |   2 +
 src/include/catalog/pg_operator.h             |   2 +
 src/include/catalog/pg_opfamily.h             |   2 +
 src/include/catalog/pg_partitioned_table.h    |   2 +-
 src/include/catalog/pg_pltemplate.h           |   2 +-
 src/include/catalog/pg_policy.h               |   1 +
 src/include/catalog/pg_proc.h                 |   2 +
 src/include/catalog/pg_publication.h          |   2 +
 src/include/catalog/pg_publication_rel.h      |   1 +
 src/include/catalog/pg_range.h                |   2 +-
 src/include/catalog/pg_replication_origin.h   |   2 +-
 src/include/catalog/pg_rewrite.h              |   1 +
 src/include/catalog/pg_seclabel.h             |   2 +-
 src/include/catalog/pg_sequence.h             |   2 +-
 src/include/catalog/pg_shdepend.h             |   2 +-
 src/include/catalog/pg_shdescription.h        |   2 +-
 src/include/catalog/pg_shseclabel.h           |   2 +-
 src/include/catalog/pg_statistic.h            |   2 +-
 src/include/catalog/pg_statistic_ext.h        |   2 +
 src/include/catalog/pg_subscription.h         |   2 +
 src/include/catalog/pg_subscription_rel.h     |   6 +-
 src/include/catalog/pg_tablespace.h           |   1 +
 src/include/catalog/pg_transform.h            |   1 +
 src/include/catalog/pg_trigger.h              |   1 +
 src/include/catalog/pg_ts_config.h            |   1 +
 src/include/catalog/pg_ts_config_map.h        |   2 +-
 src/include/catalog/pg_ts_dict.h              |   1 +
 src/include/catalog/pg_ts_parser.h            |   2 +
 src/include/catalog/pg_ts_template.h          |   2 +
 src/include/catalog/pg_type.h                 |   2 +
 src/include/catalog/pg_user_mapping.h         |   2 +
 src/include/commands/copy.h                   |   2 +-
 src/include/commands/event_trigger.h          |   1 -
 src/include/executor/executor.h               |  14 +-
 src/include/executor/spi_priv.h               |   2 -
 src/include/nodes/execnodes.h                 |   1 -
 src/include/nodes/parsenodes.h                |   6 +-
 src/include/parser/parse_clause.h             |   1 -
 src/include/utils/rel.h                       |   2 +
 src/include/utils/relcache.h                  |   1 -
 src/interfaces/ecpg/preproc/ecpg.addons       |   2 +-
 src/pl/plperl/plperl.c                        |   2 +-
 src/pl/plpgsql/src/pl_comp.c                  |   4 +-
 .../modules/test_predtest/test_predtest.c     |   2 +-
 src/test/regress/expected/alter_table.out     | 160 +--------
 src/test/regress/expected/copy2.out           |  16 +-
 src/test/regress/expected/create_index.out    |  16 +-
 src/test/regress/expected/create_table.out    |  32 +-
 .../regress/expected/create_table_like.out    |  34 --
 src/test/regress/expected/enum.out            |   4 +-
 src/test/regress/expected/errors.out          |   4 +-
 src/test/regress/expected/foreign_data.out    |  70 +---
 src/test/regress/expected/inherit.out         |  49 ---
 src/test/regress/expected/insert_conflict.out |  67 +---
 src/test/regress/expected/misc_sanity.out     |   2 +-
 src/test/regress/expected/opr_sanity.out      |  24 +-
 src/test/regress/expected/prepare.out         |  46 +--
 src/test/regress/expected/privileges.out      |  24 +-
 src/test/regress/expected/reloptions.out      |   9 -
 .../regress/expected/replica_identity.out     |   9 +-
 src/test/regress/expected/roleattributes.out  |  64 ++--
 src/test/regress/expected/rowsecurity.out     | 340 +++++++++---------
 src/test/regress/expected/rowtypes.out        |  10 +-
 src/test/regress/expected/sanity_check.out    |  12 +-
 src/test/regress/expected/triggers.out        |  26 +-
 src/test/regress/expected/without_oid.out     | 103 ------
 src/test/regress/parallel_schedule            |   2 +-
 src/test/regress/serial_schedule              |   1 -
 src/test/regress/sql/alter_table.sql          | 101 +-----
 src/test/regress/sql/copy2.sql                |  23 +-
 src/test/regress/sql/create_index.sql         |  15 +-
 src/test/regress/sql/create_table.sql         |  25 +-
 src/test/regress/sql/create_table_like.sql    |  16 -
 src/test/regress/sql/errors.sql               |   2 +-
 src/test/regress/sql/foreign_data.sql         |  11 -
 src/test/regress/sql/inherit.sql              |  26 --
 src/test/regress/sql/insert_conflict.sql      |  27 +-
 src/test/regress/sql/misc_sanity.sql          |   2 +-
 src/test/regress/sql/prepare.sql              |  10 +-
 src/test/regress/sql/privileges.sql           |  12 +-
 src/test/regress/sql/reloptions.sql           |   5 -
 src/test/regress/sql/replica_identity.sql     |   6 +-
 src/test/regress/sql/roleattributes.sql       |  65 ++--
 src/test/regress/sql/rowsecurity.sql          |  24 +-
 src/test/regress/sql/rowtypes.sql             |   6 +-
 src/test/regress/sql/sanity_check.sql         |  12 +-
 src/test/regress/sql/triggers.sql             |  25 +-
 src/test/regress/sql/without_oid.sql          |  92 -----
 273 files changed, 1610 insertions(+), 3024 deletions(-)
 delete mode 100644 src/test/regress/expected/without_oid.out
 delete mode 100644 src/test/regress/sql/without_oid.sql

diff --git a/contrib/adminpack/adminpack.c b/contrib/adminpack/adminpack.c
index 0a27701e9c6..ea0ec201f0d 100644
--- a/contrib/adminpack/adminpack.c
+++ b/contrib/adminpack/adminpack.c
@@ -502,7 +502,7 @@ pg_logdir_ls_internal(FunctionCallInfo fcinfo)
 
 		fctx = palloc(sizeof(directory_fctx));
 
-		tupdesc = CreateTemplateTupleDesc(2, false);
+		tupdesc = CreateTemplateTupleDesc(2);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "starttime",
 						   TIMESTAMPOID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "filename",
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index c6460688486..3b73ff13f19 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -849,7 +849,7 @@ materializeResult(FunctionCallInfo fcinfo, PGconn *conn, PGresult *res)
 			 * need a tuple descriptor representing one TEXT column to return
 			 * the command status string as our result tuple
 			 */
-			tupdesc = CreateTemplateTupleDesc(1, false);
+			tupdesc = CreateTemplateTupleDesc(1);
 			TupleDescInitEntry(tupdesc, (AttrNumber) 1, "status",
 							   TEXTOID, -1, 0);
 			ntuples = 1;
@@ -1032,7 +1032,7 @@ materializeQueryResult(FunctionCallInfo fcinfo,
 			 * need a tuple descriptor representing one TEXT column to return
 			 * the command status string as our result tuple
 			 */
-			tupdesc = CreateTemplateTupleDesc(1, false);
+			tupdesc = CreateTemplateTupleDesc(1);
 			TupleDescInitEntry(tupdesc, (AttrNumber) 1, "status",
 							   TEXTOID, -1, 0);
 			attinmeta = TupleDescGetAttInMetadata(tupdesc);
@@ -1526,7 +1526,7 @@ dblink_get_pkey(PG_FUNCTION_ARGS)
 		/*
 		 * need a tuple descriptor representing one INT and one TEXT column
 		 */
-		tupdesc = CreateTemplateTupleDesc(2, false);
+		tupdesc = CreateTemplateTupleDesc(2);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "position",
 						   INT4OID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "colname",
@@ -1904,7 +1904,7 @@ dblink_get_notify(PG_FUNCTION_ARGS)
 	per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
 	oldcontext = MemoryContextSwitchTo(per_query_ctx);
 
-	tupdesc = CreateTemplateTupleDesc(DBLINK_NOTIFY_COLS, false);
+	tupdesc = CreateTemplateTupleDesc(DBLINK_NOTIFY_COLS);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "notify_name",
 					   TEXTOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "be_pid",
diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c
index 7438257c5bb..b488577c97a 100644
--- a/contrib/pageinspect/heapfuncs.c
+++ b/contrib/pageinspect/heapfuncs.c
@@ -241,14 +241,13 @@ heap_page_items(PG_FUNCTION_ARGS)
 				else
 					nulls[11] = true;
 
-				if (tuphdr->t_infomask & HEAP_HASOID)
-					values[12] = HeapTupleHeaderGetOid(tuphdr);
-				else
-					nulls[12] = true;
+				// XXX: remove
+				nulls[12] = true;
 			}
 			else
 			{
 				nulls[11] = true;
+				// XXX: remove
 				nulls[12] = true;
 			}
 		}
diff --git a/contrib/pg_buffercache/pg_buffercache_pages.c b/contrib/pg_buffercache/pg_buffercache_pages.c
index b410aafa5a9..1bd579fcbb0 100644
--- a/contrib/pg_buffercache/pg_buffercache_pages.c
+++ b/contrib/pg_buffercache/pg_buffercache_pages.c
@@ -99,7 +99,7 @@ pg_buffercache_pages(PG_FUNCTION_ARGS)
 			elog(ERROR, "incorrect number of output arguments");
 
 		/* Construct a tuple descriptor for the result rows. */
-		tupledesc = CreateTemplateTupleDesc(expected_tupledesc->natts, false);
+		tupledesc = CreateTemplateTupleDesc(expected_tupledesc->natts);
 		TupleDescInitEntry(tupledesc, (AttrNumber) 1, "bufferid",
 						   INT4OID, -1, 0);
 		TupleDescInitEntry(tupledesc, (AttrNumber) 2, "relfilenode",
diff --git a/contrib/pg_visibility/pg_visibility.c b/contrib/pg_visibility/pg_visibility.c
index 944dea66fc8..c1aae9d6551 100644
--- a/contrib/pg_visibility/pg_visibility.c
+++ b/contrib/pg_visibility/pg_visibility.c
@@ -292,7 +292,7 @@ pg_visibility_map_summary(PG_FUNCTION_ARGS)
 		ReleaseBuffer(vmbuffer);
 	relation_close(rel, AccessShareLock);
 
-	tupdesc = CreateTemplateTupleDesc(2, false);
+	tupdesc = CreateTemplateTupleDesc(2);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "all_visible", INT8OID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "all_frozen", INT8OID, -1, 0);
 	tupdesc = BlessTupleDesc(tupdesc);
@@ -447,7 +447,7 @@ pg_visibility_tupdesc(bool include_blkno, bool include_pd)
 		++maxattr;
 	if (include_pd)
 		++maxattr;
-	tupdesc = CreateTemplateTupleDesc(maxattr, false);
+	tupdesc = CreateTemplateTupleDesc(maxattr);
 	if (include_blkno)
 		TupleDescInitEntry(tupdesc, ++a, "blkno", INT8OID, -1, 0);
 	TupleDescInitEntry(tupdesc, ++a, "all_visible", BOOLOID, -1, 0);
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 6cbba97c223..70a4c2cf618 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -3966,15 +3966,6 @@ apply_returning_filter(PgFdwDirectModifyState *dmstate,
 			resultTup->t_self = *ctid;
 		}
 
-		/* oid */
-		if (dmstate->oidAttno)
-		{
-			Oid			oid = InvalidOid;
-
-			oid = DatumGetObjectId(old_values[dmstate->oidAttno - 1]);
-			HeapTupleSetOid(resultTup, oid);
-		}
-
 		/*
 		 * And remaining columns
 		 *
@@ -5699,8 +5690,7 @@ make_tuple_from_result_row(PGresult *res,
 	/*
 	 * If we have an OID to return, install it.
 	 */
-	if (OidIsValid(oid))
-		HeapTupleSetOid(tuple, oid);
+	// FIXME: do we need to convert this into a normal col?
 
 	/* Clean up */
 	MemoryContextReset(temp_context);
diff --git a/contrib/sepgsql/label.c b/contrib/sepgsql/label.c
index dba0986e02a..acffc468d28 100644
--- a/contrib/sepgsql/label.c
+++ b/contrib/sepgsql/label.c
@@ -758,7 +758,7 @@ exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
 											NULL, NULL, NULL);
 
 				object.classId = DatabaseRelationId;
-				object.objectId = HeapTupleGetOid(tuple);
+				object.objectId = datForm->oid;
 				object.objectSubId = 0;
 				break;
 
@@ -772,7 +772,7 @@ exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
 											NULL, NULL);
 
 				object.classId = NamespaceRelationId;
-				object.objectId = HeapTupleGetOid(tuple);
+				object.objectId = nspForm->oid;
 				object.objectSubId = 0;
 				break;
 
@@ -797,7 +797,7 @@ exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
 				pfree(namespace_name);
 
 				object.classId = RelationRelationId;
-				object.objectId = HeapTupleGetOid(tuple);
+				object.objectId = relForm->oid;
 				object.objectSubId = 0;
 				break;
 
@@ -838,7 +838,7 @@ exec_object_restorecon(struct selabel_handle *sehnd, Oid catalogId)
 				pfree(namespace_name);
 
 				object.classId = ProcedureRelationId;
-				object.objectId = HeapTupleGetOid(tuple);
+				object.objectId = proForm->oid;
 				object.objectSubId = 0;
 				break;
 
diff --git a/contrib/test_decoding/test_decoding.c b/contrib/test_decoding/test_decoding.c
index 1c439b57b0e..0ce3014f95e 100644
--- a/contrib/test_decoding/test_decoding.c
+++ b/contrib/test_decoding/test_decoding.c
@@ -321,12 +321,6 @@ tuple_to_stringinfo(StringInfo s, TupleDesc tupdesc, HeapTuple tuple, bool skip_
 	int			natt;
 	Oid			oid;
 
-	/* print oid of tuple, it's not included in the TupleDesc */
-	if ((oid = HeapTupleHeaderGetOid(tuple->t_data)) != InvalidOid)
-	{
-		appendStringInfo(s, " oid[oid]:%u", oid);
-	}
-
 	/* print all columns individually */
 	for (natt = 0; natt < tupdesc->natts; natt++)
 	{
diff --git a/src/backend/access/brin/brin_tuple.c b/src/backend/access/brin/brin_tuple.c
index 00316b899c8..c82bbbaa7f8 100644
--- a/src/backend/access/brin/brin_tuple.c
+++ b/src/backend/access/brin/brin_tuple.c
@@ -62,7 +62,7 @@ brtuple_disk_tupdesc(BrinDesc *brdesc)
 		/* make sure it's in the bdesc's context */
 		oldcxt = MemoryContextSwitchTo(brdesc->bd_context);
 
-		tupdesc = CreateTemplateTupleDesc(brdesc->bd_totalstored, false);
+		tupdesc = CreateTemplateTupleDesc(brdesc->bd_totalstored);
 
 		for (i = 0; i < brdesc->bd_tupdesc->natts; i++)
 		{
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 7fc2fee74ab..b05a77eb6ce 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -419,7 +419,6 @@ heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
 	{
 		case TableOidAttributeNumber:
 		case SelfItemPointerAttributeNumber:
-		case ObjectIdAttributeNumber:
 		case MinTransactionIdAttributeNumber:
 		case MinCommandIdAttributeNumber:
 		case MaxTransactionIdAttributeNumber:
@@ -677,9 +676,6 @@ heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
 			/* pass-by-reference datatype */
 			result = PointerGetDatum(&(tup->t_self));
 			break;
-		case ObjectIdAttributeNumber:
-			result = ObjectIdGetDatum(HeapTupleGetOid(tup));
-			break;
 		case MinTransactionIdAttributeNumber:
 			result = TransactionIdGetDatum(HeapTupleHeaderGetRawXmin(tup->t_data));
 			break;
@@ -874,9 +870,6 @@ expand_tuple(HeapTuple *targetHeapTuple,
 	else
 		targetNullLen = 0;
 
-	if (tupleDesc->tdhasoid)
-		len += sizeof(Oid);
-
 	/*
 	 * Allocate and zero the space needed.  Note that the tuple body and
 	 * HeapTupleData management structure are allocated in one chunk.
@@ -1100,9 +1093,6 @@ heap_form_tuple(TupleDesc tupleDescriptor,
 	if (hasnull)
 		len += BITMAPLEN(numberOfAttributes);
 
-	if (tupleDescriptor->tdhasoid)
-		len += sizeof(Oid);
-
 	hoff = len = MAXALIGN(len); /* align user data safely */
 
 	data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
@@ -1134,9 +1124,6 @@ heap_form_tuple(TupleDesc tupleDescriptor,
 	HeapTupleHeaderSetNatts(td, numberOfAttributes);
 	td->t_hoff = hoff;
 
-	if (tupleDescriptor->tdhasoid)	/* else leave infomask = 0 */
-		td->t_infomask = HEAP_HASOID;
-
 	heap_fill_tuple(tupleDescriptor,
 					values,
 					isnull,
@@ -1206,14 +1193,11 @@ heap_modify_tuple(HeapTuple tuple,
 	pfree(isnull);
 
 	/*
-	 * copy the identification info of the old tuple: t_ctid, t_self, and OID
-	 * (if any)
+	 * copy the identification info of the old tuple: t_ctid, t_self
 	 */
 	newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
 	newTuple->t_self = tuple->t_self;
 	newTuple->t_tableOid = tuple->t_tableOid;
-	if (tupleDesc->tdhasoid)
-		HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
 
 	return newTuple;
 }
@@ -1272,14 +1256,11 @@ heap_modify_tuple_by_cols(HeapTuple tuple,
 	pfree(isnull);
 
 	/*
-	 * copy the identification info of the old tuple: t_ctid, t_self, and OID
-	 * (if any)
+	 * copy the identification info of the old tuple: t_ctid, t_self
 	 */
 	newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
 	newTuple->t_self = tuple->t_self;
 	newTuple->t_tableOid = tuple->t_tableOid;
-	if (tupleDesc->tdhasoid)
-		HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
 
 	return newTuple;
 }
@@ -1771,9 +1752,6 @@ heap_form_minimal_tuple(TupleDesc tupleDescriptor,
 	if (hasnull)
 		len += BITMAPLEN(numberOfAttributes);
 
-	if (tupleDescriptor->tdhasoid)
-		len += sizeof(Oid);
-
 	hoff = len = MAXALIGN(len); /* align user data safely */
 
 	data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
@@ -1792,9 +1770,6 @@ heap_form_minimal_tuple(TupleDesc tupleDescriptor,
 	HeapTupleHeaderSetNatts(tuple, numberOfAttributes);
 	tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
 
-	if (tupleDescriptor->tdhasoid)	/* else leave infomask = 0 */
-		tuple->t_infomask = HEAP_HASOID;
-
 	heap_fill_tuple(tupleDescriptor,
 					values,
 					isnull,
diff --git a/src/backend/access/common/tupconvert.c b/src/backend/access/common/tupconvert.c
index 3bc67b846d4..6cda8e49faa 100644
--- a/src/backend/access/common/tupconvert.c
+++ b/src/backend/access/common/tupconvert.c
@@ -139,13 +139,9 @@ convert_tuples_by_position(TupleDesc indesc,
 
 	/*
 	 * Check to see if the map is one-to-one, in which case we need not do a
-	 * tuple conversion.  We must also insist that both tupdescs either
-	 * specify or don't specify an OID column, else we need a conversion to
-	 * add/remove space for that.  (For some callers, presence or absence of
-	 * an OID column perhaps would not really matter, but let's be safe.)
+	 * tuple conversion.
 	 */
-	if (indesc->natts == outdesc->natts &&
-		indesc->tdhasoid == outdesc->tdhasoid)
+	if (indesc->natts == outdesc->natts)
 	{
 		for (i = 0; i < n; i++)
 		{
@@ -222,13 +218,9 @@ convert_tuples_by_name(TupleDesc indesc,
 
 	/*
 	 * Check to see if the map is one-to-one, in which case we need not do a
-	 * tuple conversion.  We must also insist that both tupdescs either
-	 * specify or don't specify an OID column, else we need a conversion to
-	 * add/remove space for that.  (For some callers, presence or absence of
-	 * an OID column perhaps would not really matter, but let's be safe.)
+	 * tuple conversion.
 	 */
-	if (indesc->natts == outdesc->natts &&
-		indesc->tdhasoid == outdesc->tdhasoid)
+	if (indesc->natts == outdesc->natts)
 	{
 		same = true;
 		for (i = 0; i < n; i++)
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index b0434b46720..5354a04639b 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -42,7 +42,7 @@
  * caller can overwrite this if needed.
  */
 TupleDesc
-CreateTemplateTupleDesc(int natts, bool hasoid)
+CreateTemplateTupleDesc(int natts)
 {
 	TupleDesc	desc;
 
@@ -73,7 +73,6 @@ CreateTemplateTupleDesc(int natts, bool hasoid)
 	desc->constr = NULL;
 	desc->tdtypeid = RECORDOID;
 	desc->tdtypmod = -1;
-	desc->tdhasoid = hasoid;
 	desc->tdrefcount = -1;		/* assume not reference-counted */
 
 	return desc;
@@ -88,12 +87,12 @@ CreateTemplateTupleDesc(int natts, bool hasoid)
  * caller can overwrite this if needed.
  */
 TupleDesc
-CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
+CreateTupleDesc(int natts, Form_pg_attribute *attrs)
 {
 	TupleDesc	desc;
 	int			i;
 
-	desc = CreateTemplateTupleDesc(natts, hasoid);
+	desc = CreateTemplateTupleDesc(natts);
 
 	for (i = 0; i < natts; ++i)
 		memcpy(TupleDescAttr(desc, i), attrs[i], ATTRIBUTE_FIXED_PART_SIZE);
@@ -114,7 +113,7 @@ CreateTupleDescCopy(TupleDesc tupdesc)
 	TupleDesc	desc;
 	int			i;
 
-	desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
+	desc = CreateTemplateTupleDesc(tupdesc->natts);
 
 	/* Flat-copy the attribute array */
 	memcpy(TupleDescAttr(desc, 0),
@@ -154,7 +153,7 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
 	TupleConstr *constr = tupdesc->constr;
 	int			i;
 
-	desc = CreateTemplateTupleDesc(tupdesc->natts, tupdesc->tdhasoid);
+	desc = CreateTemplateTupleDesc(tupdesc->natts);
 
 	/* Flat-copy the attribute array */
 	memcpy(TupleDescAttr(desc, 0),
@@ -416,8 +415,6 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
 		return false;
 	if (tupdesc1->tdtypeid != tupdesc2->tdtypeid)
 		return false;
-	if (tupdesc1->tdhasoid != tupdesc2->tdhasoid)
-		return false;
 
 	for (i = 0; i < tupdesc1->natts; i++)
 	{
@@ -574,7 +571,6 @@ hashTupleDesc(TupleDesc desc)
 
 	s = hash_combine(0, hash_uint32(desc->natts));
 	s = hash_combine(s, hash_uint32(desc->tdtypeid));
-	s = hash_combine(s, hash_uint32(desc->tdhasoid));
 	for (i = 0; i < desc->natts; ++i)
 		s = hash_combine(s, hash_uint32(TupleDescAttr(desc, i)->atttypid));
 
@@ -800,7 +796,7 @@ BuildDescForRelation(List *schema)
 	 * allocate a new tuple descriptor
 	 */
 	natts = list_length(schema);
-	desc = CreateTemplateTupleDesc(natts, false);
+	desc = CreateTemplateTupleDesc(natts);
 	has_not_null = false;
 
 	attnum = 0;
@@ -900,7 +896,7 @@ BuildDescFromLists(List *names, List *types, List *typmods, List *collations)
 	/*
 	 * allocate a new tuple descriptor
 	 */
-	desc = CreateTemplateTupleDesc(natts, false);
+	desc = CreateTemplateTupleDesc(natts);
 
 	attnum = 0;
 
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index 0a32182dd7f..d7696a1ad03 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -104,7 +104,7 @@ initGinState(GinState *state, Relation index)
 			state->tupdesc[i] = state->origTupdesc;
 		else
 		{
-			state->tupdesc[i] = CreateTemplateTupleDesc(2, false);
+			state->tupdesc[i] = CreateTemplateTupleDesc(2);
 
 			TupleDescInitEntry(state->tupdesc[i], (AttrNumber) 1, NULL,
 							   INT2OID, -1, 0);
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index 4d97ff1d5d2..6b18bd3afb8 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -167,7 +167,7 @@ gistrescan(IndexScanDesc scan, ScanKey key, int nkeys,
 		 * types.
 		 */
 		natts = RelationGetNumberOfAttributes(scan->indexRelation);
-		so->giststate->fetchTupdesc = CreateTemplateTupleDesc(natts, false);
+		so->giststate->fetchTupdesc = CreateTemplateTupleDesc(natts);
 		for (attno = 1; attno <= natts; attno++)
 		{
 			TupleDescInitEntry(so->giststate->fetchTupdesc, attno, NULL,
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 3395445a9a4..9d53de6e3d6 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -2437,7 +2437,7 @@ ReleaseBulkInsertStatePin(BulkInsertState bistate)
  * TID where the tuple was stored.  But note that any toasting of fields
  * within the tuple data is NOT reflected into *tup.
  */
-Oid
+void
 heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 			int options, BulkInsertState bistate)
 {
@@ -2610,8 +2610,6 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 		tup->t_self = heaptup->t_self;
 		heap_freetuple(heaptup);
 	}
-
-	return HeapTupleGetOid(tup);
 }
 
 /*
@@ -2638,30 +2636,6 @@ heap_prepare_insert(Relation relation, HeapTuple tup, TransactionId xid,
 				(errcode(ERRCODE_INVALID_TRANSACTION_STATE),
 				 errmsg("cannot insert tuples in a parallel worker")));
 
-	if (relation->rd_rel->relhasoids)
-	{
-#ifdef NOT_USED
-		/* this is redundant with an Assert in HeapTupleSetOid */
-		Assert(tup->t_data->t_infomask & HEAP_HASOID);
-#endif
-
-		/*
-		 * If the object id of this tuple has already been assigned, trust the
-		 * caller.  There are a couple of ways this can happen.  At initial db
-		 * creation, the backend program sets oids for tuples. When we define
-		 * an index, we set the oid.  Finally, in the future, we may allow
-		 * users to set their own object ids in order to support a persistent
-		 * object store (objects need to contain pointers to one another).
-		 */
-		if (!OidIsValid(HeapTupleGetOid(tup)))
-			HeapTupleSetOid(tup, GetNewOid(relation));
-	}
-	else
-	{
-		/* check there is not space for an OID */
-		Assert(!(tup->t_data->t_infomask & HEAP_HASOID));
-	}
-
 	tup->t_data->t_infomask &= ~(HEAP_XACT_MASK);
 	tup->t_data->t_infomask2 &= ~(HEAP2_XACT_MASK);
 	tup->t_data->t_infomask |= HEAP_XMAX_INVALID;
@@ -2974,10 +2948,10 @@ heap_multi_insert(Relation relation, HeapTuple *tuples, int ntuples,
  * This should be used rather than using heap_insert directly in most places
  * where we are modifying system catalogs.
  */
-Oid
+void
 simple_heap_insert(Relation relation, HeapTuple tup)
 {
-	return heap_insert(relation, tup, GetCurrentCommandId(true), 0, NULL);
+	heap_insert(relation, tup, GetCurrentCommandId(true), 0, NULL);
 }
 
 /*
@@ -3635,21 +3609,6 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
 	/* the new tuple is ready, except for this: */
 	newtup->t_tableOid = RelationGetRelid(relation);
 
-	/* Fill in OID for newtup */
-	if (relation->rd_rel->relhasoids)
-	{
-#ifdef NOT_USED
-		/* this is redundant with an Assert in HeapTupleSetOid */
-		Assert(newtup->t_data->t_infomask & HEAP_HASOID);
-#endif
-		HeapTupleSetOid(newtup, HeapTupleGetOid(&oldtup));
-	}
-	else
-	{
-		/* check there is not space for an OID */
-		Assert(!(newtup->t_data->t_infomask & HEAP_HASOID));
-	}
-
 	/* Determine columns modified by the update. */
 	modified_attrs = HeapDetermineModifiedColumns(relation, interesting_attrs,
 												  &oldtup, newtup);
@@ -4416,13 +4375,12 @@ heap_tuple_attr_equals(TupleDesc tupdesc, int attrnum,
 
 	/*
 	 * Likewise, automatically say "not equal" for any system attribute other
-	 * than OID and tableOID; we cannot expect these to be consistent in a HOT
-	 * chain, or even to be set correctly yet in the new tuple.
+	 * than tableOID; we cannot expect these to be consistent in a HOT chain,
+	 * or even to be set correctly yet in the new tuple.
 	 */
 	if (attrnum < 0)
 	{
-		if (attrnum != ObjectIdAttributeNumber &&
-			attrnum != TableOidAttributeNumber)
+		if (attrnum != TableOidAttributeNumber)
 			return false;
 	}
 
@@ -8099,16 +8057,7 @@ ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_changed, bool *
 		int			attno = idx_rel->rd_index->indkey.values[natt];
 
 		if (attno < 0)
-		{
-			/*
-			 * The OID column can appear in an index definition, but that's
-			 * OK, because we always copy the OID if present (see below).
-			 * Other system columns may not.
-			 */
-			if (attno == ObjectIdAttributeNumber)
-				continue;
 			elog(ERROR, "system column in index");
-		}
 		nulls[attno - 1] = false;
 	}
 
@@ -8116,14 +8065,6 @@ ExtractReplicaIdentity(Relation relation, HeapTuple tp, bool key_changed, bool *
 	*copy = true;
 	RelationClose(idx_rel);
 
-	/*
-	 * Always copy oids if the table has them, even if not included in the
-	 * index. The space in the logged tuple is used anyway, so there's little
-	 * point in not including the information.
-	 */
-	if (relation->rd_rel->relhasoids)
-		HeapTupleSetOid(key_tuple, HeapTupleGetOid(tp));
-
 	/*
 	 * If the tuple, which by here only contains indexed columns, still has
 	 * toasted columns, force them to be inlined. This is somewhat unlikely
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index cd42c50b09c..62f6011dffc 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -723,8 +723,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
 	hoff = SizeofHeapTupleHeader;
 	if (has_nulls)
 		hoff += BITMAPLEN(numAttrs);
-	if (newtup->t_data->t_infomask & HEAP_HASOID)
-		hoff += sizeof(Oid);
 	hoff = MAXALIGN(hoff);
 	/* now convert to a limit on the tuple data size */
 	maxDataLen = RelationGetToastTupleTarget(rel, TOAST_TUPLE_TARGET) - hoff;
@@ -1013,8 +1011,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
 		new_header_len = SizeofHeapTupleHeader;
 		if (has_nulls)
 			new_header_len += BITMAPLEN(numAttrs);
-		if (olddata->t_infomask & HEAP_HASOID)
-			new_header_len += sizeof(Oid);
 		new_header_len = MAXALIGN(new_header_len);
 		new_data_len = heap_compute_data_size(tupleDesc,
 											  toast_values, toast_isnull);
@@ -1036,8 +1032,6 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup,
 		memcpy(new_data, olddata, SizeofHeapTupleHeader);
 		HeapTupleHeaderSetNatts(new_data, numAttrs);
 		new_data->t_hoff = new_header_len;
-		if (olddata->t_infomask & HEAP_HASOID)
-			HeapTupleHeaderSetOid(new_data, HeapTupleHeaderGetOid(olddata));
 
 		/* Copy over the data, and fill the null bitmap if needed */
 		heap_fill_tuple(tupleDesc,
@@ -1124,13 +1118,10 @@ toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
 	new_tuple = heap_form_tuple(tupleDesc, toast_values, toast_isnull);
 
 	/*
-	 * Be sure to copy the tuple's OID and identity fields.  We also make a
-	 * point of copying visibility info, just in case anybody looks at those
-	 * fields in a syscache entry.
+	 * Be sure to copy the tuple's identity fields.  We also make a point of
+	 * copying visibility info, just in case anybody looks at those fields in
+	 * a syscache entry.
 	 */
-	if (tupleDesc->tdhasoid)
-		HeapTupleSetOid(new_tuple, HeapTupleGetOid(tup));
-
 	new_tuple->t_self = tup->t_self;
 	new_tuple->t_tableOid = tup->t_tableOid;
 
@@ -1244,8 +1235,6 @@ toast_flatten_tuple_to_datum(HeapTupleHeader tup,
 	new_header_len = SizeofHeapTupleHeader;
 	if (has_nulls)
 		new_header_len += BITMAPLEN(numAttrs);
-	if (tup->t_infomask & HEAP_HASOID)
-		new_header_len += sizeof(Oid);
 	new_header_len = MAXALIGN(new_header_len);
 	new_data_len = heap_compute_data_size(tupleDesc,
 										  toast_values, toast_isnull);
@@ -1259,8 +1248,6 @@ toast_flatten_tuple_to_datum(HeapTupleHeader tup,
 	memcpy(new_data, tup, SizeofHeapTupleHeader);
 	HeapTupleHeaderSetNatts(new_data, numAttrs);
 	new_data->t_hoff = new_header_len;
-	if (tup->t_infomask & HEAP_HASOID)
-		HeapTupleHeaderSetOid(new_data, HeapTupleHeaderGetOid(tup));
 
 	/* Set the composite-Datum header fields correctly */
 	HeapTupleHeaderSetDatumLength(new_data, new_tuple_len);
diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c
index 599203c96ce..66b940c66cc 100644
--- a/src/backend/access/transam/commit_ts.c
+++ b/src/backend/access/transam/commit_ts.c
@@ -434,7 +434,7 @@ pg_last_committed_xact(PG_FUNCTION_ARGS)
 	 * Construct a tuple descriptor for the result row.  This must match this
 	 * function's pg_proc entry!
 	 */
-	tupdesc = CreateTemplateTupleDesc(2, false);
+	tupdesc = CreateTemplateTupleDesc(2);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "xid",
 					   XIDOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "timestamp",
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 365daf153ab..82346f1000d 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -3368,7 +3368,7 @@ pg_get_multixact_members(PG_FUNCTION_ARGS)
 												false);
 		multi->iter = 0;
 
-		tupdesc = CreateTemplateTupleDesc(2, false);
+		tupdesc = CreateTemplateTupleDesc(2);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "xid",
 						   XIDOID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "mode",
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 3942734e5ae..e65dccc6a2c 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -734,7 +734,7 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
 
 		/* build tupdesc for result tuples */
 		/* this had better match pg_prepared_xacts view in system_views.sql */
-		tupdesc = CreateTemplateTupleDesc(5, false);
+		tupdesc = CreateTemplateTupleDesc(5);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "transaction",
 						   XIDOID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "gid",
diff --git a/src/backend/access/transam/xlogfuncs.c b/src/backend/access/transam/xlogfuncs.c
index 97317429786..6eb7c3f16aa 100644
--- a/src/backend/access/transam/xlogfuncs.c
+++ b/src/backend/access/transam/xlogfuncs.c
@@ -468,7 +468,7 @@ pg_walfile_name_offset(PG_FUNCTION_ARGS)
 	 * Construct a tuple descriptor for the result row.  This must match this
 	 * function's pg_proc entry!
 	 */
-	resultTupleDesc = CreateTemplateTupleDesc(2, false);
+	resultTupleDesc = CreateTemplateTupleDesc(2);
 	TupleDescInitEntry(resultTupleDesc, (AttrNumber) 1, "file_name",
 					   TEXTOID, -1, 0);
 	TupleDescInitEntry(resultTupleDesc, (AttrNumber) 2, "file_offset",
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index 4c72989cc25..f49c808eeb7 100644
--- a/src/backend/bootstrap/bootparse.y
+++ b/src/backend/bootstrap/bootparse.y
@@ -113,7 +113,7 @@ static int num_columns_read = 0;
 %type <list>  boot_index_params
 %type <ielem> boot_index_param
 %type <str>   boot_ident
-%type <ival>  optbootstrap optsharedrelation optwithoutoids boot_column_nullness
+%type <ival>  optbootstrap optsharedrelation boot_column_nullness
 %type <oidval> oidspec optoideq optrowtypeoid
 
 %token <str> ID
@@ -123,7 +123,7 @@ static int num_columns_read = 0;
 /* All the rest are unreserved, and should be handled in boot_ident! */
 %token <kw> OPEN XCLOSE XCREATE INSERT_TUPLE
 %token <kw> XDECLARE INDEX ON USING XBUILD INDICES UNIQUE XTOAST
-%token <kw> OBJ_ID XBOOTSTRAP XSHARED_RELATION XWITHOUT_OIDS XROWTYPE_OID
+%token <kw> OBJ_ID XBOOTSTRAP XSHARED_RELATION XROWTYPE_OID
 %token <kw> XFORCE XNOT XNULL
 
 %start TopLevel
@@ -170,7 +170,7 @@ Boot_CloseStmt:
 		;
 
 Boot_CreateStmt:
-		  XCREATE boot_ident oidspec optbootstrap optsharedrelation optwithoutoids optrowtypeoid LPAREN
+		  XCREATE boot_ident oidspec optbootstrap optsharedrelation optrowtypeoid LPAREN
 				{
 					do_start();
 					numattr = 0;
@@ -192,7 +192,7 @@ Boot_CreateStmt:
 
 					do_start();
 
-					tupdesc = CreateTupleDesc(numattr, !($6), attrtypes);
+					tupdesc = CreateTupleDesc(numattr, attrtypes);
 
 					shared_relation = $5;
 
@@ -236,7 +236,7 @@ Boot_CreateStmt:
 													  PG_CATALOG_NAMESPACE,
 													  shared_relation ? GLOBALTABLESPACE_OID : 0,
 													  $3,
-													  $7,
+													  $6,
 													  InvalidOid,
 													  BOOTSTRAP_SUPERUSERID,
 													  tupdesc,
@@ -245,8 +245,6 @@ Boot_CreateStmt:
 													  RELPERSISTENCE_PERMANENT,
 													  shared_relation,
 													  mapped_relation,
-													  true,
-													  0,
 													  ONCOMMIT_NOOP,
 													  (Datum) 0,
 													  false,
@@ -432,11 +430,6 @@ optsharedrelation:
 		|						{ $$ = 0; }
 		;
 
-optwithoutoids:
-			XWITHOUT_OIDS	{ $$ = 1; }
-		|					{ $$ = 0; }
-		;
-
 optrowtypeoid:
 			XROWTYPE_OID oidspec	{ $$ = $2; }
 		|							{ $$ = InvalidOid; }
@@ -501,7 +494,6 @@ boot_ident:
 		| OBJ_ID		{ $$ = pstrdup($1); }
 		| XBOOTSTRAP	{ $$ = pstrdup($1); }
 		| XSHARED_RELATION	{ $$ = pstrdup($1); }
-		| XWITHOUT_OIDS	{ $$ = pstrdup($1); }
 		| XROWTYPE_OID	{ $$ = pstrdup($1); }
 		| XFORCE		{ $$ = pstrdup($1); }
 		| XNOT			{ $$ = pstrdup($1); }
diff --git a/src/backend/bootstrap/bootscanner.l b/src/backend/bootstrap/bootscanner.l
index 739087b786f..14bc0888979 100644
--- a/src/backend/bootstrap/bootscanner.l
+++ b/src/backend/bootstrap/bootscanner.l
@@ -91,7 +91,6 @@ create			{ yylval.kw = "create"; return XCREATE; }
 OID				{ yylval.kw = "OID"; return OBJ_ID; }
 bootstrap		{ yylval.kw = "bootstrap"; return XBOOTSTRAP; }
 shared_relation	{ yylval.kw = "shared_relation"; return XSHARED_RELATION; }
-without_oids	{ yylval.kw = "without_oids"; return XWITHOUT_OIDS; }
 rowtype_oid		{ yylval.kw = "rowtype_oid"; return XROWTYPE_OID; }
 
 insert			{ yylval.kw = "insert"; return INSERT_TUPLE; }
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 578af2e66d8..2989b13d74e 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -616,7 +616,7 @@ boot_openrel(char *relname)
 		app = Typ;
 		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
 		{
-			(*app)->am_oid = HeapTupleGetOid(tup);
+			(*app)->am_oid = *(Oid *) GETSTRUCT(tup);
 			memcpy((char *) &(*app)->am_typ,
 				   (char *) GETSTRUCT(tup),
 				   sizeof((*app)->am_typ));
@@ -807,12 +807,12 @@ InsertOneTuple(Oid objectid)
 
 	elog(DEBUG4, "inserting row oid %u, %d columns", objectid, numattr);
 
-	tupDesc = CreateTupleDesc(numattr,
-							  RelationGetForm(boot_reldesc)->relhasoids,
-							  attrtypes);
+	tupDesc = CreateTupleDesc(numattr, attrtypes);
 	tuple = heap_form_tuple(tupDesc, values, Nulls);
+#ifdef NOT_ANYMORE
 	if (objectid != (Oid) 0)
 		HeapTupleSetOid(tuple, objectid);
+#endif
 	pfree(tupDesc);				/* just free's tupDesc, not the attrtypes */
 
 	simple_heap_insert(boot_reldesc, tuple);
@@ -946,7 +946,7 @@ gettype(char *type)
 		app = Typ;
 		while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
 		{
-			(*app)->am_oid = HeapTupleGetOid(tup);
+			(*app)->am_oid = *(Oid *) GETSTRUCT(tup);
 			memmove((char *) &(*app++)->am_typ,
 					(char *) GETSTRUCT(tup),
 					sizeof((*app)->am_typ));
diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
index 9699dfd8d52..d5c096f7d1b 100644
--- a/src/backend/catalog/Catalog.pm
+++ b/src/backend/catalog/Catalog.pm
@@ -111,8 +111,6 @@ sub ParseHeader
 			$catalog{bootstrap} = /BKI_BOOTSTRAP/ ? ' bootstrap' : '';
 			$catalog{shared_relation} =
 			  /BKI_SHARED_RELATION/ ? ' shared_relation' : '';
-			$catalog{without_oids} =
-			  /BKI_WITHOUT_OIDS/ ? ' without_oids' : '';
 			if (/BKI_ROWTYPE_OID\((\d+),(\w+)\)/)
 			{
 				$catalog{rowtype_oid}        = $1;
@@ -337,6 +335,10 @@ sub AddDefaultValues
 		{
 			;
 		}
+		elsif ($attname eq 'oid')
+		{
+			;
+		}
 		elsif (defined $column->{default})
 		{
 			$row->{$attname} = $column->{default};
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 578e4c65927..daf93f22b1c 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -848,7 +848,7 @@ objectsInSchemaToOids(ObjectType objtype, List *nspnames)
 
 					while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 					{
-						objects = lappend_oid(objects, HeapTupleGetOid(tuple));
+						objects = lappend_oid(objects, *(Oid *) GETSTRUCT(tuple));
 					}
 
 					heap_endscan(scan);
@@ -893,7 +893,7 @@ getRelationsInNamespace(Oid namespaceId, char relkind)
 
 	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
-		relations = lappend_oid(relations, HeapTupleGetOid(tuple));
+		relations = lappend_oid(relations, *(Oid *) GETSTRUCT(tuple));
 	}
 
 	heap_endscan(scan);
@@ -1299,7 +1299,7 @@ SetDefaultACL(InternalDefaultACL *iacls)
 			 * there shouldn't be anything depending on this entry.
 			 */
 			myself.classId = DefaultAclRelationId;
-			myself.objectId = HeapTupleGetOid(tuple);
+			myself.objectId = *(Oid *) GETSTRUCT(tuple);
 			myself.objectSubId = 0;
 
 			performDeletion(&myself, DROP_RESTRICT, 0);
@@ -1315,6 +1315,8 @@ SetDefaultACL(InternalDefaultACL *iacls)
 		if (isNew)
 		{
 			/* insert new entry */
+			values[Anum_pg_default_acl_oid - 1] =
+				GetNewOidWithIndex(rel, DefaultAclOidIndexId, Anum_pg_default_acl_oid);
 			values[Anum_pg_default_acl_defaclrole - 1] = ObjectIdGetDatum(iacls->roleid);
 			values[Anum_pg_default_acl_defaclnamespace - 1] = ObjectIdGetDatum(iacls->nspid);
 			values[Anum_pg_default_acl_defaclobjtype - 1] = CharGetDatum(objtype);
@@ -1339,7 +1341,7 @@ SetDefaultACL(InternalDefaultACL *iacls)
 		{
 			/* dependency on role */
 			recordDependencyOnOwner(DefaultAclRelationId,
-									HeapTupleGetOid(newtuple),
+									*(Oid *) GETSTRUCT(newtuple),
 									iacls->roleid);
 
 			/* dependency on namespace */
@@ -1349,7 +1351,7 @@ SetDefaultACL(InternalDefaultACL *iacls)
 							referenced;
 
 				myself.classId = DefaultAclRelationId;
-				myself.objectId = HeapTupleGetOid(newtuple);
+				myself.objectId = *(Oid *) GETSTRUCT(newtuple);
 				myself.objectSubId = 0;
 
 				referenced.classId = NamespaceRelationId;
@@ -1366,17 +1368,17 @@ SetDefaultACL(InternalDefaultACL *iacls)
 		nnewmembers = aclmembers(new_acl, &newmembers);
 
 		updateAclDependencies(DefaultAclRelationId,
-							  HeapTupleGetOid(newtuple), 0,
+							  *(Oid *) GETSTRUCT(newtuple), 0,
 							  iacls->roleid,
 							  noldmembers, oldmembers,
 							  nnewmembers, newmembers);
 
 		if (isNew)
 			InvokeObjectPostCreateHook(DefaultAclRelationId,
-									   HeapTupleGetOid(newtuple), 0);
+									   *(Oid *) GETSTRUCT(newtuple), 0);
 		else
 			InvokeObjectPostAlterHook(DefaultAclRelationId,
-									  HeapTupleGetOid(newtuple), 0);
+									  *(Oid *) GETSTRUCT(newtuple), 0);
 	}
 
 	if (HeapTupleIsValid(tuple))
@@ -1407,7 +1409,7 @@ RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
 		rel = heap_open(DefaultAclRelationId, AccessShareLock);
 
 		ScanKeyInit(&skey[0],
-					ObjectIdAttributeNumber,
+					Anum_pg_default_acl_oid,
 					BTEqualStrategyNumber, F_OIDEQ,
 					ObjectIdGetDatum(objid));
 
@@ -1530,7 +1532,7 @@ RemoveDefaultACLById(Oid defaclOid)
 	rel = heap_open(DefaultAclRelationId, RowExclusiveLock);
 
 	ScanKeyInit(&skey[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_default_acl_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(defaclOid));
 
@@ -1608,10 +1610,6 @@ expand_all_col_privileges(Oid table_oid, Form_pg_class classForm,
 		if (curr_att == InvalidAttrNumber)
 			continue;
 
-		/* Skip OID column if it doesn't exist */
-		if (curr_att == ObjectIdAttributeNumber && !classForm->relhasoids)
-			continue;
-
 		/* Views don't have any system columns at all */
 		if (classForm->relkind == RELKIND_VIEW && curr_att < 0)
 			continue;
@@ -2223,7 +2221,7 @@ ExecGrant_Database(InternalGrant *istmt)
 		CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
 
 		/* Update the shared dependency ACL info */
-		updateAclDependencies(DatabaseRelationId, HeapTupleGetOid(tuple), 0,
+		updateAclDependencies(DatabaseRelationId, pg_database_tuple->oid, 0,
 							  ownerId,
 							  noldmembers, oldmembers,
 							  nnewmembers, newmembers);
@@ -2350,7 +2348,7 @@ ExecGrant_Fdw(InternalGrant *istmt)
 
 		/* Update the shared dependency ACL info */
 		updateAclDependencies(ForeignDataWrapperRelationId,
-							  HeapTupleGetOid(tuple), 0,
+							  pg_fdw_tuple->oid, 0,
 							  ownerId,
 							  noldmembers, oldmembers,
 							  nnewmembers, newmembers);
@@ -2475,7 +2473,7 @@ ExecGrant_ForeignServer(InternalGrant *istmt)
 
 		/* Update the shared dependency ACL info */
 		updateAclDependencies(ForeignServerRelationId,
-							  HeapTupleGetOid(tuple), 0,
+							  pg_server_tuple->oid, 0,
 							  ownerId,
 							  noldmembers, oldmembers,
 							  nnewmembers, newmembers);
@@ -2729,7 +2727,7 @@ ExecGrant_Language(InternalGrant *istmt)
 		recordExtensionInitPriv(langId, LanguageRelationId, 0, new_acl);
 
 		/* Update the shared dependency ACL info */
-		updateAclDependencies(LanguageRelationId, HeapTupleGetOid(tuple), 0,
+		updateAclDependencies(LanguageRelationId, pg_language_tuple->oid, 0,
 							  ownerId,
 							  noldmembers, oldmembers,
 							  nnewmembers, newmembers);
@@ -2784,7 +2782,7 @@ ExecGrant_Largeobject(InternalGrant *istmt)
 
 		/* There's no syscache for pg_largeobject_metadata */
 		ScanKeyInit(&entry[0],
-					ObjectIdAttributeNumber,
+					Anum_pg_largeobject_metadata_oid,
 					BTEqualStrategyNumber, F_OIDEQ,
 					ObjectIdGetDatum(loid));
 
@@ -2869,7 +2867,7 @@ ExecGrant_Largeobject(InternalGrant *istmt)
 
 		/* Update the shared dependency ACL info */
 		updateAclDependencies(LargeObjectRelationId,
-							  HeapTupleGetOid(tuple), 0,
+							  form_lo_meta->oid, 0,
 							  ownerId,
 							  noldmembers, oldmembers,
 							  nnewmembers, newmembers);
@@ -2993,7 +2991,7 @@ ExecGrant_Namespace(InternalGrant *istmt)
 		recordExtensionInitPriv(nspid, NamespaceRelationId, 0, new_acl);
 
 		/* Update the shared dependency ACL info */
-		updateAclDependencies(NamespaceRelationId, HeapTupleGetOid(tuple), 0,
+		updateAclDependencies(NamespaceRelationId, pg_namespace_tuple->oid, 0,
 							  ownerId,
 							  noldmembers, oldmembers,
 							  nnewmembers, newmembers);
@@ -4116,7 +4114,7 @@ pg_largeobject_aclmask_snapshot(Oid lobj_oid, Oid roleid,
 						   AccessShareLock);
 
 	ScanKeyInit(&entry[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_largeobject_metadata_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(lobj_oid));
 
@@ -4898,7 +4896,7 @@ pg_largeobject_ownercheck(Oid lobj_oid, Oid roleid)
 						   AccessShareLock);
 
 	ScanKeyInit(&entry[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_largeobject_metadata_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(lobj_oid));
 
@@ -5260,7 +5258,7 @@ pg_extension_ownercheck(Oid ext_oid, Oid roleid)
 	pg_extension = heap_open(ExtensionRelationId, AccessShareLock);
 
 	ScanKeyInit(&entry[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_extension_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(ext_oid));
 
@@ -5699,7 +5697,7 @@ recordExtObjInitPriv(Oid objoid, Oid classoid)
 
 		/* There's no syscache for pg_largeobject_metadata */
 		ScanKeyInit(&entry[0],
-					ObjectIdAttributeNumber,
+					Anum_pg_largeobject_metadata_oid,
 					BTEqualStrategyNumber, F_OIDEQ,
 					ObjectIdGetDatum(objoid));
 
diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c
index 6061428bccd..76d750666c5 100644
--- a/src/backend/catalog/catalog.c
+++ b/src/backend/catalog/catalog.c
@@ -305,34 +305,26 @@ Oid
 GetNewOid(Relation relation)
 {
 	Oid			oidIndex;
-
-	/* If relation doesn't have OIDs at all, caller is confused */
-	Assert(relation->rd_rel->relhasoids);
+	AttrNumber	oidAttr;
 
 	/* In bootstrap mode, we don't have any indexes to use */
 	if (IsBootstrapProcessingMode())
 		return GetNewObjectId();
 
-	/* The relcache will cache the identity of the OID index for us */
-	oidIndex = RelationGetOidIndex(relation);
+	if (!IsSystemRelation(relation))
+		elog(ERROR, "only system relations can have oids");
 
-	/* If no OID index, just hand back the next OID counter value */
-	if (!OidIsValid(oidIndex))
-	{
-		/*
-		 * System catalogs that have OIDs should *always* have a unique OID
-		 * index; we should only take this path for user tables. Give a
-		 * warning if it looks like somebody forgot an index.
-		 */
-		if (IsSystemRelation(relation))
-			elog(WARNING, "generating possibly-non-unique OID for \"%s\"",
-				 RelationGetRelationName(relation));
+	oidIndex = get_object_oid_index(RelationGetRelid(relation));
 
-		return GetNewObjectId();
-	}
+	/*
+	 * System catalogs that have OIDs should *always* have a unique OID index.
+	 */
+	Assert(OidIsValid(oidIndex));
 
-	/* Otherwise, use the index to find a nonconflicting OID */
-	return GetNewOidWithIndex(relation, oidIndex, ObjectIdAttributeNumber);
+	oidAttr =  get_object_attnum_oid(RelationGetRelid(relation));
+
+	/* Use the index to find a nonconflicting OID */
+	return GetNewOidWithIndex(relation, oidIndex, oidAttr);
 }
 
 /*
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
index 649200260a4..cfdffac822a 100644
--- a/src/backend/catalog/genbki.pl
+++ b/src/backend/catalog/genbki.pl
@@ -65,6 +65,8 @@ my @toast_decls;
 my @index_decls;
 my %oidcounts;
 
+my $bootstrap_nextoid = 10000;
+
 foreach my $header (@input_files)
 {
 	$header =~ /(.+)\.h$/
@@ -283,6 +285,8 @@ foreach my $catname (@catnames)
 	open my $def, '>', $def_file . $tmpext
 	  or die "can't open $def_file$tmpext: $!";
 
+	print STDERR "building $catname\n";
+
 	# Opening boilerplate for pg_*_d.h
 	printf $def <<EOM, $catname, $catname, uc $catname, uc $catname;
 /*-------------------------------------------------------------------------
@@ -320,7 +324,6 @@ EOM
 	print $bki "create $catname $catalog->{relation_oid}"
 	  . $catalog->{shared_relation}
 	  . $catalog->{bootstrap}
-	  . $catalog->{without_oids}
 	  . $catalog->{rowtype_oid_clause};
 
 	my $first = 1;
@@ -409,6 +412,13 @@ EOM
 			my $attname = $column->{name};
 			my $atttype = $column->{type};
 
+			# XXX
+			if ($attname eq "oid" and not defined $bki_values{$attname})
+			{
+				$bki_values{$attname} = $bootstrap_nextoid;
+				$bootstrap_nextoid++;
+			}
+
 			# Substitute constant values we acquired above.
 			# (It's intentional that this can apply to parts of a field).
 			$bki_values{$attname} =~ s/\bPGUID\b/$BOOTSTRAP_SUPERUSERID/g;
@@ -627,7 +637,6 @@ sub gen_pg_attribute
 			$attnum = 0;
 			my @SYS_ATTRS = (
 				{ name => 'ctid',     type => 'tid' },
-				{ name => 'oid',      type => 'oid' },
 				{ name => 'xmin',     type => 'xid' },
 				{ name => 'cmin',     type => 'cid' },
 				{ name => 'xmax',     type => 'xid' },
@@ -641,11 +650,6 @@ sub gen_pg_attribute
 				$row{attrelid}      = $table->{relation_oid};
 				$row{attstattarget} = '0';
 
-				# Omit the oid column if the catalog doesn't have them
-				next
-				  if $table->{without_oids}
-				  && $attr->{name} eq 'oid';
-
 				morph_row_for_pgattr(\%row, $schema, $attr, 1);
 				print_bki_insert(\%row, $schema);
 			}
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 9176f6280b0..5881ede2b2c 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -159,20 +159,6 @@ static FormData_pg_attribute a1 = {
 };
 
 static FormData_pg_attribute a2 = {
-	.attname = {"oid"},
-	.atttypid = OIDOID,
-	.attlen = sizeof(Oid),
-	.attnum = ObjectIdAttributeNumber,
-	.attcacheoff = -1,
-	.atttypmod = -1,
-	.attbyval = true,
-	.attstorage = 'p',
-	.attalign = 'i',
-	.attnotnull = true,
-	.attislocal = true,
-};
-
-static FormData_pg_attribute a3 = {
 	.attname = {"xmin"},
 	.atttypid = XIDOID,
 	.attlen = sizeof(TransactionId),
@@ -186,7 +172,7 @@ static FormData_pg_attribute a3 = {
 	.attislocal = true,
 };
 
-static FormData_pg_attribute a4 = {
+static FormData_pg_attribute a3 = {
 	.attname = {"cmin"},
 	.atttypid = CIDOID,
 	.attlen = sizeof(CommandId),
@@ -200,7 +186,7 @@ static FormData_pg_attribute a4 = {
 	.attislocal = true,
 };
 
-static FormData_pg_attribute a5 = {
+static FormData_pg_attribute a4 = {
 	.attname = {"xmax"},
 	.atttypid = XIDOID,
 	.attlen = sizeof(TransactionId),
@@ -214,7 +200,7 @@ static FormData_pg_attribute a5 = {
 	.attislocal = true,
 };
 
-static FormData_pg_attribute a6 = {
+static FormData_pg_attribute a5 = {
 	.attname = {"cmax"},
 	.atttypid = CIDOID,
 	.attlen = sizeof(CommandId),
@@ -234,7 +220,7 @@ static FormData_pg_attribute a6 = {
  * table of a particular class/type. In any case table is still the word
  * used in SQL.
  */
-static FormData_pg_attribute a7 = {
+static FormData_pg_attribute a6 = {
 	.attname = {"tableoid"},
 	.atttypid = OIDOID,
 	.attlen = sizeof(Oid),
@@ -248,7 +234,7 @@ static FormData_pg_attribute a7 = {
 	.attislocal = true,
 };
 
-static const Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7};
+static const Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6};
 
 /*
  * This function returns a Form_pg_attribute pointer for a system attribute.
@@ -256,12 +242,10 @@ static const Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7};
  * happen if there's a problem upstream.
  */
 Form_pg_attribute
-SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
+SystemAttributeDefinition(AttrNumber attno)
 {
 	if (attno >= 0 || attno < -(int) lengthof(SysAtt))
 		elog(ERROR, "invalid system attribute number %d", attno);
-	if (attno == ObjectIdAttributeNumber && !relhasoids)
-		elog(ERROR, "invalid system attribute number %d", attno);
 	return SysAtt[-attno - 1];
 }
 
@@ -270,7 +254,7 @@ SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
  * pointer for a prototype definition.  If not, return NULL.
  */
 Form_pg_attribute
-SystemAttributeByName(const char *attname, bool relhasoids)
+SystemAttributeByName(const char *attname)
 {
 	int			j;
 
@@ -278,11 +262,8 @@ SystemAttributeByName(const char *attname, bool relhasoids)
 	{
 		Form_pg_attribute att = SysAtt[j];
 
-		if (relhasoids || att->attnum != ObjectIdAttributeNumber)
-		{
-			if (strcmp(NameStr(att->attname), attname) == 0)
-				return att;
-		}
+		if (strcmp(NameStr(att->attname), attname) == 0)
+			return att;
 	}
 
 	return NULL;
@@ -493,8 +474,7 @@ CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind,
 		{
 			Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
 
-			if (SystemAttributeByName(NameStr(attr->attname),
-									  tupdesc->tdhasoid) != NULL)
+			if (SystemAttributeByName(NameStr(attr->attname)) != NULL)
 				ereport(ERROR,
 						(errcode(ERRCODE_DUPLICATE_COLUMN),
 						 errmsg("column name \"%s\" conflicts with a system column name",
@@ -717,9 +697,7 @@ InsertPgAttributeTuple(Relation pg_attribute_rel,
 static void
 AddNewAttributeTuples(Oid new_rel_oid,
 					  TupleDesc tupdesc,
-					  char relkind,
-					  bool oidislocal,
-					  int oidinhcount)
+					  char relkind)
 {
 	Form_pg_attribute attr;
 	int			i;
@@ -781,23 +759,11 @@ AddNewAttributeTuples(Oid new_rel_oid,
 		{
 			FormData_pg_attribute attStruct;
 
-			/* skip OID where appropriate */
-			if (!tupdesc->tdhasoid &&
-				SysAtt[i]->attnum == ObjectIdAttributeNumber)
-				continue;
-
 			memcpy(&attStruct, (char *) SysAtt[i], sizeof(FormData_pg_attribute));
 
 			/* Fill in the correct relation OID in the copied tuple */
 			attStruct.attrelid = new_rel_oid;
 
-			/* Fill in correct inheritance info for the OID column */
-			if (attStruct.attnum == ObjectIdAttributeNumber)
-			{
-				attStruct.attislocal = oidislocal;
-				attStruct.attinhcount = oidinhcount;
-			}
-
 			InsertPgAttributeTuple(rel, &attStruct, indstate);
 		}
 	}
@@ -839,6 +805,8 @@ InsertPgClassTuple(Relation pg_class_desc,
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 
+
+	values[Anum_pg_class_oid - 1] = ObjectIdGetDatum(new_rel_oid);
 	values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname);
 	values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace);
 	values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype);
@@ -857,7 +825,6 @@ InsertPgClassTuple(Relation pg_class_desc,
 	values[Anum_pg_class_relkind - 1] = CharGetDatum(rd_rel->relkind);
 	values[Anum_pg_class_relnatts - 1] = Int16GetDatum(rd_rel->relnatts);
 	values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
-	values[Anum_pg_class_relhasoids - 1] = BoolGetDatum(rd_rel->relhasoids);
 	values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
 	values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
 	values[Anum_pg_class_relrowsecurity - 1] = BoolGetDatum(rd_rel->relrowsecurity);
@@ -883,12 +850,6 @@ InsertPgClassTuple(Relation pg_class_desc,
 
 	tup = heap_form_tuple(RelationGetDescr(pg_class_desc), values, nulls);
 
-	/*
-	 * The new tuple must have the oid already chosen for the rel.  Sure would
-	 * be embarrassing to do this sort of thing in polite company.
-	 */
-	HeapTupleSetOid(tup, new_rel_oid);
-
 	/* finally insert the new tuple, update the indexes, and clean up */
 	CatalogTupleInsert(pg_class_desc, tup);
 
@@ -1063,8 +1024,6 @@ AddNewRelationType(const char *typeName,
  *	relpersistence: rel's persistence status (permanent, temp, or unlogged)
  *	shared_relation: true if it's to be a shared relation
  *	mapped_relation: true if the relation will use the relfilenode map
- *	oidislocal: true if oid column (if any) should be marked attislocal
- *	oidinhcount: attinhcount to assign to oid column (if any)
  *	oncommit: ON COMMIT marking (only relevant if it's a temp table)
  *	reloptions: reloptions in Datum form, or (Datum) 0 if none
  *	use_user_acl: true if should look for user-defined default permissions;
@@ -1092,8 +1051,6 @@ heap_create_with_catalog(const char *relname,
 						 char relpersistence,
 						 bool shared_relation,
 						 bool mapped_relation,
-						 bool oidislocal,
-						 int oidinhcount,
 						 OnCommitAction oncommit,
 						 Datum reloptions,
 						 bool use_user_acl,
@@ -1339,8 +1296,7 @@ heap_create_with_catalog(const char *relname,
 	/*
 	 * now add tuples to pg_attribute for the attributes in our new relation.
 	 */
-	AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind,
-						  oidislocal, oidinhcount);
+	AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind);
 
 	/*
 	 * Make a dependency link to force the relation to be deleted if its
@@ -1742,9 +1698,10 @@ RemoveAttrDefault(Oid relid, AttrNumber attnum,
 	while (HeapTupleIsValid(tuple = systable_getnext(scan)))
 	{
 		ObjectAddress object;
+		Form_pg_attrdef attrtuple = (Form_pg_attrdef) GETSTRUCT(tuple);
 
 		object.classId = AttrDefaultRelationId;
-		object.objectId = HeapTupleGetOid(tuple);
+		object.objectId = attrtuple->oid;
 		object.objectSubId = 0;
 
 		performDeletion(&object, behavior,
@@ -1785,7 +1742,7 @@ RemoveAttrDefaultById(Oid attrdefId)
 
 	/* Find the pg_attrdef tuple */
 	ScanKeyInit(&scankeys[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_attrdef_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(attrdefId));
 
@@ -2180,6 +2137,8 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
 	/*
 	 * Make the pg_attrdef entry.
 	 */
+	attrdefOid = GetNewOidWithIndex(rel, AttrDefaultOidIndexId, Anum_pg_attrdef_oid);
+	values[Anum_pg_attrdef_oid - 1] = ObjectIdGetDatum(attrdefOid);
 	values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
 	values[Anum_pg_attrdef_adnum - 1] = attnum;
 	values[Anum_pg_attrdef_adbin - 1] = CStringGetTextDatum(adbin);
@@ -2188,7 +2147,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum,
 	adrel = heap_open(AttrDefaultRelationId, RowExclusiveLock);
 
 	tuple = heap_form_tuple(adrel->rd_att, values, nulls);
-	attrdefOid = CatalogTupleInsert(adrel, tuple);
+	CatalogTupleInsert(adrel, tuple);
 
 	defobject.classId = AttrDefaultRelationId;
 	defobject.objectId = attrdefOid;
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 9229f619d29..4c449d86334 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -316,7 +316,7 @@ ConstructTupleDescriptor(Relation heapRelation,
 	/*
 	 * allocate the new tuple descriptor
 	 */
-	indexTupDesc = CreateTemplateTupleDesc(numatts, false);
+	indexTupDesc = CreateTemplateTupleDesc(numatts);
 
 	/*
 	 * Fill in the pg_attribute row.
@@ -350,11 +350,11 @@ ConstructTupleDescriptor(Relation heapRelation,
 
 			if (atnum < 0)
 			{
+				elog(ERROR, "ain't possible anymore no?");
 				/*
 				 * here we are indexing on a system attribute (-1...-n)
 				 */
-				from = SystemAttributeDefinition(atnum,
-												 heapRelation->rd_rel->relhasoids);
+				from = SystemAttributeDefinition(atnum);
 			}
 			else
 			{
@@ -939,7 +939,6 @@ index_create(Relation heapRelation,
 	 */
 	indexRelation->rd_rel->relowner = heapRelation->rd_rel->relowner;
 	indexRelation->rd_rel->relam = accessMethodObjectId;
-	indexRelation->rd_rel->relhasoids = false;
 	indexRelation->rd_rel->relispartition = OidIsValid(parentIndexRelid);
 
 	/*
@@ -2137,7 +2136,7 @@ index_update_stats(Relation rel,
 		ScanKeyData key[1];
 
 		ScanKeyInit(&key[0],
-					ObjectIdAttributeNumber,
+					Anum_pg_class_oid,
 					BTEqualStrategyNumber, F_OIDEQ,
 					ObjectIdGetDatum(relid));
 
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 4674beaf3e7..24f3eac79b5 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -159,20 +159,17 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
  * and building the index info structures is moderately expensive.
  * (Use CatalogTupleInsertWithInfo in such cases.)
  */
-Oid
+void
 CatalogTupleInsert(Relation heapRel, HeapTuple tup)
 {
 	CatalogIndexState indstate;
-	Oid			oid;
 
 	indstate = CatalogOpenIndexes(heapRel);
 
-	oid = simple_heap_insert(heapRel, tup);
+	simple_heap_insert(heapRel, tup);
 
 	CatalogIndexInsert(indstate, tup);
 	CatalogCloseIndexes(indstate);
-
-	return oid;
 }
 
 /*
@@ -183,17 +180,13 @@ CatalogTupleInsert(Relation heapRel, HeapTuple tup)
  * might cache the CatalogIndexState data somewhere (perhaps in the relcache)
  * so that callers needn't trouble over this ... but we don't do so today.
  */
-Oid
+void
 CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup,
 						   CatalogIndexState indstate)
 {
-	Oid			oid;
-
-	oid = simple_heap_insert(heapRel, tup);
+	simple_heap_insert(heapRel, tup);
 
 	CatalogIndexInsert(indstate, tup);
-
-	return oid;
 }
 
 /*
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 5d13e6a3d70..bdd0c042981 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -1084,7 +1084,7 @@ FuncnameGetCandidates(List *names, int nargs, List *argnames,
 			palloc(offsetof(struct _FuncCandidateList, args) +
 				   effective_nargs * sizeof(Oid));
 		newResult->pathpos = pathpos;
-		newResult->oid = HeapTupleGetOid(proctup);
+		newResult->oid = procform->oid;
 		newResult->nargs = effective_nargs;
 		newResult->argnumbers = argnumbers;
 		if (argnumbers)
@@ -1488,7 +1488,8 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
 									  ObjectIdGetDatum(namespaceId));
 			if (HeapTupleIsValid(opertup))
 			{
-				Oid			result = HeapTupleGetOid(opertup);
+				Form_pg_operator operclass = (Form_pg_operator) GETSTRUCT(opertup);
+				Oid			result = operclass->oid;
 
 				ReleaseSysCache(opertup);
 				return result;
@@ -1533,7 +1534,7 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright)
 
 			if (operform->oprnamespace == namespaceId)
 			{
-				Oid			result = HeapTupleGetOid(opertup);
+				Oid			result = operform->oid;
 
 				ReleaseSysCacheList(catlist);
 				return result;
@@ -1687,7 +1688,7 @@ OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
 						continue;	/* keep previous result */
 					/* replace previous result */
 					prevResult->pathpos = pathpos;
-					prevResult->oid = HeapTupleGetOid(opertup);
+					prevResult->oid = operform->oid;
 					continue;	/* args are same, of course */
 				}
 			}
@@ -1700,7 +1701,7 @@ OpernameGetCandidates(List *names, char oprkind, bool missing_schema_ok)
 		nextResult += SPACE_PER_OP;
 
 		newResult->pathpos = pathpos;
-		newResult->oid = HeapTupleGetOid(opertup);
+		newResult->oid = operform->oid;
 		newResult->nargs = 2;
 		newResult->nvargs = 0;
 		newResult->ndargs = 0;
@@ -1969,13 +1970,13 @@ lookup_collation(const char *collname, Oid collnamespace, int32 encoding)
 	if (collform->collprovider == COLLPROVIDER_ICU)
 	{
 		if (is_encoding_supported_by_icu(encoding))
-			collid = HeapTupleGetOid(colltup);
+			collid = collform->oid;
 		else
 			collid = InvalidOid;
 	}
 	else
 	{
-		collid = HeapTupleGetOid(colltup);
+		collid = collform->oid;
 	}
 	ReleaseSysCache(colltup);
 	return collid;
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 593e6f7022d..7a8759cad31 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -27,6 +27,7 @@
 #include "catalog/pg_authid.h"
 #include "catalog/pg_cast.h"
 #include "catalog/pg_default_acl.h"
+#include "catalog/pg_enum.h"
 #include "catalog/pg_event_trigger.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_constraint.h"
@@ -94,6 +95,7 @@
 typedef struct
 {
 	Oid			class_oid;		/* oid of catalog */
+	AttrNumber	attnum_oid;		/* attribute number of oid column */
 	Oid			oid_index_oid;	/* oid of index on system oid column */
 	int			oid_catcache_id;	/* id of catcache on system oid column	*/
 	int			name_catcache_id;	/* id of catcache on (name,namespace), or
@@ -114,6 +116,7 @@ static const ObjectPropertyType ObjectProperty[] =
 {
 	{
 		AccessMethodRelationId,
+		Anum_pg_am_oid,
 		AmOidIndexId,
 		AMOID,
 		AMNAME,
@@ -126,6 +129,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		CastRelationId,
+		Anum_pg_cast_oid,
 		CastOidIndexId,
 		-1,
 		-1,
@@ -138,6 +142,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		CollationRelationId,
+		Anum_pg_collation_oid,
 		CollationOidIndexId,
 		COLLOID,
 		-1,						/* COLLNAMEENCNSP also takes encoding */
@@ -150,6 +155,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		ConstraintRelationId,
+		Anum_pg_constraint_oid,
 		ConstraintOidIndexId,
 		CONSTROID,
 		-1,
@@ -162,6 +168,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		ConversionRelationId,
+		Anum_pg_conversion_oid,
 		ConversionOidIndexId,
 		CONVOID,
 		CONNAMENSP,
@@ -174,6 +181,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		DatabaseRelationId,
+		Anum_pg_database_oid,
 		DatabaseOidIndexId,
 		DATABASEOID,
 		-1,
@@ -186,6 +194,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		ExtensionRelationId,
+		Anum_pg_extension_oid,
 		ExtensionOidIndexId,
 		-1,
 		-1,
@@ -198,6 +207,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		ForeignDataWrapperRelationId,
+		Anum_pg_foreign_data_wrapper_oid,
 		ForeignDataWrapperOidIndexId,
 		FOREIGNDATAWRAPPEROID,
 		FOREIGNDATAWRAPPERNAME,
@@ -210,6 +220,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		ForeignServerRelationId,
+		Anum_pg_foreign_server_oid,
 		ForeignServerOidIndexId,
 		FOREIGNSERVEROID,
 		FOREIGNSERVERNAME,
@@ -222,6 +233,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		ProcedureRelationId,
+		Anum_pg_proc_oid,
 		ProcedureOidIndexId,
 		PROCOID,
 		-1,						/* PROCNAMEARGSNSP also takes argument types */
@@ -234,6 +246,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		LanguageRelationId,
+		Anum_pg_language_oid,
 		LanguageOidIndexId,
 		LANGOID,
 		LANGNAME,
@@ -246,6 +259,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		LargeObjectMetadataRelationId,
+		Anum_pg_largeobject_metadata_oid,
 		LargeObjectMetadataOidIndexId,
 		-1,
 		-1,
@@ -258,6 +272,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		OperatorClassRelationId,
+		Anum_pg_opclass_oid,
 		OpclassOidIndexId,
 		CLAOID,
 		-1,						/* CLAAMNAMENSP also takes opcmethod */
@@ -270,6 +285,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		OperatorRelationId,
+		Anum_pg_operator_oid,
 		OperatorOidIndexId,
 		OPEROID,
 		-1,						/* OPERNAMENSP also takes left and right type */
@@ -282,6 +298,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		OperatorFamilyRelationId,
+		Anum_pg_opfamily_oid,
 		OpfamilyOidIndexId,
 		OPFAMILYOID,
 		-1,						/* OPFAMILYAMNAMENSP also takes opfmethod */
@@ -294,6 +311,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		AuthIdRelationId,
+		Anum_pg_authid_oid,
 		AuthIdOidIndexId,
 		AUTHOID,
 		AUTHNAME,
@@ -306,6 +324,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		RewriteRelationId,
+		Anum_pg_rewrite_oid,
 		RewriteOidIndexId,
 		-1,
 		-1,
@@ -318,6 +337,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		NamespaceRelationId,
+		Anum_pg_namespace_oid,
 		NamespaceOidIndexId,
 		NAMESPACEOID,
 		NAMESPACENAME,
@@ -330,6 +350,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		RelationRelationId,
+		Anum_pg_class_oid,
 		ClassOidIndexId,
 		RELOID,
 		RELNAMENSP,
@@ -342,6 +363,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		TableSpaceRelationId,
+		Anum_pg_tablespace_oid,
 		TablespaceOidIndexId,
 		TABLESPACEOID,
 		-1,
@@ -354,12 +376,14 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		TransformRelationId,
+		Anum_pg_transform_oid,
 		TransformOidIndexId,
 		TRFOID,
 		InvalidAttrNumber
 	},
 	{
 		TriggerRelationId,
+		Anum_pg_trigger_oid,
 		TriggerOidIndexId,
 		-1,
 		-1,
@@ -372,6 +396,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		PolicyRelationId,
+		Anum_pg_policy_oid,
 		PolicyOidIndexId,
 		-1,
 		-1,
@@ -384,6 +409,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		EventTriggerRelationId,
+		Anum_pg_event_trigger_oid,
 		EventTriggerOidIndexId,
 		EVENTTRIGGEROID,
 		EVENTTRIGGERNAME,
@@ -396,6 +422,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		TSConfigRelationId,
+		Anum_pg_ts_config_oid,
 		TSConfigOidIndexId,
 		TSCONFIGOID,
 		TSCONFIGNAMENSP,
@@ -408,6 +435,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		TSDictionaryRelationId,
+		Anum_pg_ts_dict_oid,
 		TSDictionaryOidIndexId,
 		TSDICTOID,
 		TSDICTNAMENSP,
@@ -420,6 +448,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		TSParserRelationId,
+		Anum_pg_ts_parser_oid,
 		TSParserOidIndexId,
 		TSPARSEROID,
 		TSPARSERNAMENSP,
@@ -432,6 +461,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		TSTemplateRelationId,
+		Anum_pg_ts_template_oid,
 		TSTemplateOidIndexId,
 		TSTEMPLATEOID,
 		TSTEMPLATENAMENSP,
@@ -444,6 +474,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		TypeRelationId,
+		Anum_pg_type_oid,
 		TypeOidIndexId,
 		TYPEOID,
 		TYPENAMENSP,
@@ -456,6 +487,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		PublicationRelationId,
+		Anum_pg_publication_oid,
 		PublicationObjectIndexId,
 		PUBLICATIONOID,
 		PUBLICATIONNAME,
@@ -468,6 +500,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		SubscriptionRelationId,
+		Anum_pg_subscription_oid,
 		SubscriptionObjectIndexId,
 		SUBSCRIPTIONOID,
 		SUBSCRIPTIONNAME,
@@ -480,6 +513,7 @@ static const ObjectPropertyType ObjectProperty[] =
 	},
 	{
 		StatisticExtRelationId,
+		Anum_pg_statistic_ext_oid,
 		StatisticExtOidIndexId,
 		STATEXTOID,
 		STATEXTNAMENSP,
@@ -489,7 +523,22 @@ static const ObjectPropertyType ObjectProperty[] =
 		InvalidAttrNumber,		/* no ACL (same as relation) */
 		OBJECT_STATISTIC_EXT,
 		true
+	},
+
+	{
+		EnumRelationId,
+		Anum_pg_enum_oid,
+		EnumOidIndexId,
+		ENUMOID,
+		-1,
+		InvalidAttrNumber,
+		InvalidAttrNumber,
+		InvalidAttrNumber,
+		InvalidAttrNumber,		/* no ACL (same as relation) */
+		OBJECT_ENUM,
+		false
 	}
+
 };
 
 /*
@@ -1459,7 +1508,11 @@ get_object_address_attrdef(ObjectType objtype, List *object,
 		scan = systable_beginscan(attrdef, AttrDefaultIndexId, true,
 								  NULL, 2, keys);
 		if (HeapTupleIsValid(tup = systable_getnext(scan)))
-			defoid = HeapTupleGetOid(tup);
+		{
+			Form_pg_attrdef atdform = (Form_pg_attrdef) GETSTRUCT(tup);
+
+			defoid = atdform->oid;
+		}
 
 		systable_endscan(scan);
 		relation_close(attrdef, AccessShareLock);
@@ -1633,7 +1686,7 @@ get_object_address_opf_member(ObjectType objtype,
 				}
 				else
 				{
-					address.objectId = HeapTupleGetOid(tp);
+					address.objectId = ((Form_pg_amop) GETSTRUCT(tp))->oid;
 					ReleaseSysCache(tp);
 				}
 			}
@@ -1664,7 +1717,7 @@ get_object_address_opf_member(ObjectType objtype,
 				}
 				else
 				{
-					address.objectId = HeapTupleGetOid(tp);
+					address.objectId = ((Form_pg_amproc) GETSTRUCT(tp))->oid;
 					ReleaseSysCache(tp);
 				}
 			}
@@ -1711,7 +1764,7 @@ get_object_address_usermapping(List *object, bool missing_ok)
 								username, servername)));
 			return address;
 		}
-		userid = HeapTupleGetOid(tp);
+		userid = ((Form_pg_authid) GETSTRUCT(tp))->oid;
 		ReleaseSysCache(tp);
 	}
 
@@ -1738,7 +1791,7 @@ get_object_address_usermapping(List *object, bool missing_ok)
 		return address;
 	}
 
-	address.objectId = HeapTupleGetOid(tp);
+	address.objectId = ((Form_pg_user_mapping) GETSTRUCT(tp))->oid;
 
 	ReleaseSysCache(tp);
 
@@ -1868,7 +1921,7 @@ get_object_address_defacl(List *object, bool missing_ok)
 						 CStringGetDatum(username));
 	if (!HeapTupleIsValid(tp))
 		goto not_found;
-	userid = HeapTupleGetOid(tp);
+	userid = ((Form_pg_authid) GETSTRUCT(tp))->oid;
 	ReleaseSysCache(tp);
 
 	/*
@@ -1892,7 +1945,7 @@ get_object_address_defacl(List *object, bool missing_ok)
 	if (!HeapTupleIsValid(tp))
 		goto not_found;
 
-	address.objectId = HeapTupleGetOid(tp);
+	address.objectId = ((Form_pg_default_acl) GETSTRUCT(tp))->oid;
 	ReleaseSysCache(tp);
 
 	return address;
@@ -2186,6 +2239,8 @@ pg_get_object_address(PG_FUNCTION_ARGS)
 				objnode = (Node *) owa;
 				break;
 			}
+		case OBJECT_ENUM:
+			elog(ERROR, "frak");
 		case OBJECT_LARGEOBJECT:
 			/* already handled above */
 			break;
@@ -2202,7 +2257,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
 	if (relation)
 		relation_close(relation, AccessShareLock);
 
-	tupdesc = CreateTemplateTupleDesc(3, false);
+	tupdesc = CreateTemplateTupleDesc(3);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "classid",
 					   OIDOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "objid",
@@ -2486,6 +2541,14 @@ read_objtype_from_string(const char *objtype)
 /*
  * Interfaces to reference fields of ObjectPropertyType
  */
+AttrNumber
+get_object_attnum_oid(Oid class_id)
+{
+	const ObjectPropertyType *prop = get_object_property_data(class_id);
+
+	return prop->attnum_oid;
+}
+
 Oid
 get_object_oid_index(Oid class_id)
 {
@@ -2625,7 +2688,7 @@ get_object_property_data(Oid class_id)
  * We try a syscache first, if available.
  */
 HeapTuple
-get_catalog_object_by_oid(Relation catalog, Oid objectId)
+get_catalog_object_by_oid(Relation catalog, AttrNumber oidcol, Oid objectId)
 {
 	HeapTuple	tuple;
 	Oid			classId = RelationGetRelid(catalog);
@@ -2646,7 +2709,7 @@ get_catalog_object_by_oid(Relation catalog, Oid objectId)
 		Assert(OidIsValid(oidIndexId));
 
 		ScanKeyInit(&skey,
-					ObjectIdAttributeNumber,
+					oidcol,
 					BTEqualStrategyNumber, F_OIDEQ,
 					ObjectIdGetDatum(objectId));
 
@@ -2721,7 +2784,7 @@ getObjectDescription(const ObjectAddress *object)
 				castDesc = heap_open(CastRelationId, AccessShareLock);
 
 				ScanKeyInit(&skey[0],
-							ObjectIdAttributeNumber,
+							Anum_pg_cast_oid,
 							BTEqualStrategyNumber, F_OIDEQ,
 							ObjectIdGetDatum(object->objectId));
 
@@ -2842,7 +2905,7 @@ getObjectDescription(const ObjectAddress *object)
 				attrdefDesc = heap_open(AttrDefaultRelationId, AccessShareLock);
 
 				ScanKeyInit(&skey[0],
-							ObjectIdAttributeNumber,
+							Anum_pg_attrdef_oid,
 							BTEqualStrategyNumber, F_OIDEQ,
 							ObjectIdGetDatum(object->objectId));
 
@@ -2955,7 +3018,7 @@ getObjectDescription(const ObjectAddress *object)
 									 AccessShareLock);
 
 				ScanKeyInit(&skey[0],
-							ObjectIdAttributeNumber,
+							Anum_pg_amop_oid,
 							BTEqualStrategyNumber, F_OIDEQ,
 							ObjectIdGetDatum(object->objectId));
 
@@ -3005,7 +3068,7 @@ getObjectDescription(const ObjectAddress *object)
 									   AccessShareLock);
 
 				ScanKeyInit(&skey[0],
-							ObjectIdAttributeNumber,
+							Anum_pg_amproc_oid,
 							BTEqualStrategyNumber, F_OIDEQ,
 							ObjectIdGetDatum(object->objectId));
 
@@ -3054,7 +3117,7 @@ getObjectDescription(const ObjectAddress *object)
 				ruleDesc = heap_open(RewriteRelationId, AccessShareLock);
 
 				ScanKeyInit(&skey[0],
-							ObjectIdAttributeNumber,
+							Anum_pg_rewrite_oid,
 							BTEqualStrategyNumber, F_OIDEQ,
 							ObjectIdGetDatum(object->objectId));
 
@@ -3092,7 +3155,7 @@ getObjectDescription(const ObjectAddress *object)
 				trigDesc = heap_open(TriggerRelationId, AccessShareLock);
 
 				ScanKeyInit(&skey[0],
-							ObjectIdAttributeNumber,
+							Anum_pg_trigger_oid,
 							BTEqualStrategyNumber, F_OIDEQ,
 							ObjectIdGetDatum(object->objectId));
 
@@ -3352,7 +3415,7 @@ getObjectDescription(const ObjectAddress *object)
 				defaclrel = heap_open(DefaultAclRelationId, AccessShareLock);
 
 				ScanKeyInit(&skey[0],
-							ObjectIdAttributeNumber,
+							Anum_pg_default_acl_oid,
 							BTEqualStrategyNumber, F_OIDEQ,
 							ObjectIdGetDatum(object->objectId));
 
@@ -3479,7 +3542,7 @@ getObjectDescription(const ObjectAddress *object)
 				policy_rel = heap_open(PolicyRelationId, AccessShareLock);
 
 				ScanKeyInit(&skey[0],
-							ObjectIdAttributeNumber,
+							Anum_pg_policy_oid,
 							BTEqualStrategyNumber, F_OIDEQ,
 							ObjectIdGetDatum(object->objectId));
 
@@ -3753,7 +3816,7 @@ pg_identify_object(PG_FUNCTION_ARGS)
 	 * Construct a tuple descriptor for the result row.  This must match this
 	 * function's pg_proc entry!
 	 */
-	tupdesc = CreateTemplateTupleDesc(4, false);
+	tupdesc = CreateTemplateTupleDesc(4);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "type",
 					   TEXTOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "schema",
@@ -3770,7 +3833,9 @@ pg_identify_object(PG_FUNCTION_ARGS)
 		HeapTuple	objtup;
 		Relation	catalog = heap_open(address.classId, AccessShareLock);
 
-		objtup = get_catalog_object_by_oid(catalog, address.objectId);
+		objtup = get_catalog_object_by_oid(catalog,
+										   get_object_attnum_oid(address.classId),
+										   address.objectId);
 		if (objtup != NULL)
 		{
 			bool		isnull;
@@ -3870,7 +3935,7 @@ pg_identify_object_as_address(PG_FUNCTION_ARGS)
 	 * Construct a tuple descriptor for the result row.  This must match this
 	 * function's pg_proc entry!
 	 */
-	tupdesc = CreateTemplateTupleDesc(3, false);
+	tupdesc = CreateTemplateTupleDesc(3);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "type",
 					   TEXTOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "object_names",
@@ -4147,7 +4212,7 @@ getConstraintTypeDescription(StringInfo buffer, Oid constroid)
 	Form_pg_constraint constrForm;
 
 	constrRel = heap_open(ConstraintRelationId, AccessShareLock);
-	constrTup = get_catalog_object_by_oid(constrRel, constroid);
+	constrTup = get_catalog_object_by_oid(constrRel, Anum_pg_constraint_oid, constroid);
 	if (!HeapTupleIsValid(constrTup))
 		elog(ERROR, "cache lookup failed for constraint %u", constroid);
 
@@ -4158,7 +4223,7 @@ getConstraintTypeDescription(StringInfo buffer, Oid constroid)
 	else if (OidIsValid(constrForm->contypid))
 		appendStringInfoString(buffer, "domain constraint");
 	else
-		elog(ERROR, "invalid constraint %u", HeapTupleGetOid(constrTup));
+		elog(ERROR, "invalid constraint %u", constrForm->oid);
 
 	heap_close(constrRel, AccessShareLock);
 }
@@ -4271,7 +4336,7 @@ getObjectIdentityParts(const ObjectAddress *object,
 
 				castRel = heap_open(CastRelationId, AccessShareLock);
 
-				tup = get_catalog_object_by_oid(castRel, object->objectId);
+				tup = get_catalog_object_by_oid(castRel, Anum_pg_cast_oid, object->objectId);
 
 				if (!HeapTupleIsValid(tup))
 					elog(ERROR, "could not find tuple for cast %u",
@@ -4393,7 +4458,7 @@ getObjectIdentityParts(const ObjectAddress *object,
 				attrdefDesc = heap_open(AttrDefaultRelationId, AccessShareLock);
 
 				ScanKeyInit(&skey[0],
-							ObjectIdAttributeNumber,
+							Anum_pg_attrdef_oid,
 							BTEqualStrategyNumber, F_OIDEQ,
 							ObjectIdGetDatum(object->objectId));
 
@@ -4523,7 +4588,7 @@ getObjectIdentityParts(const ObjectAddress *object,
 									 AccessShareLock);
 
 				ScanKeyInit(&skey[0],
-							ObjectIdAttributeNumber,
+							Anum_pg_amop_oid,
 							BTEqualStrategyNumber, F_OIDEQ,
 							ObjectIdGetDatum(object->objectId));
 
@@ -4577,7 +4642,7 @@ getObjectIdentityParts(const ObjectAddress *object,
 									   AccessShareLock);
 
 				ScanKeyInit(&skey[0],
-							ObjectIdAttributeNumber,
+							Anum_pg_amproc_oid,
 							BTEqualStrategyNumber, F_OIDEQ,
 							ObjectIdGetDatum(object->objectId));
 
@@ -4624,7 +4689,7 @@ getObjectIdentityParts(const ObjectAddress *object,
 
 				ruleDesc = heap_open(RewriteRelationId, AccessShareLock);
 
-				tup = get_catalog_object_by_oid(ruleDesc, object->objectId);
+				tup = get_catalog_object_by_oid(ruleDesc, Anum_pg_rewrite_oid, object->objectId);
 
 				if (!HeapTupleIsValid(tup))
 					elog(ERROR, "could not find tuple for rule %u",
@@ -4650,7 +4715,7 @@ getObjectIdentityParts(const ObjectAddress *object,
 
 				trigDesc = heap_open(TriggerRelationId, AccessShareLock);
 
-				tup = get_catalog_object_by_oid(trigDesc, object->objectId);
+				tup = get_catalog_object_by_oid(trigDesc, Anum_pg_trigger_oid, object->objectId);
 
 				if (!HeapTupleIsValid(tup))
 					elog(ERROR, "could not find tuple for trigger %u",
@@ -4912,7 +4977,7 @@ getObjectIdentityParts(const ObjectAddress *object,
 				defaclrel = heap_open(DefaultAclRelationId, AccessShareLock);
 
 				ScanKeyInit(&skey[0],
-							ObjectIdAttributeNumber,
+							Anum_pg_default_acl_oid,
 							BTEqualStrategyNumber, F_OIDEQ,
 							ObjectIdGetDatum(object->objectId));
 
@@ -5022,7 +5087,7 @@ getObjectIdentityParts(const ObjectAddress *object,
 
 				polDesc = heap_open(PolicyRelationId, AccessShareLock);
 
-				tup = get_catalog_object_by_oid(polDesc, object->objectId);
+				tup = get_catalog_object_by_oid(polDesc, Anum_pg_policy_oid, object->objectId);
 
 				if (!HeapTupleIsValid(tup))
 					elog(ERROR, "could not find tuple for policy %u",
@@ -5099,7 +5164,7 @@ getObjectIdentityParts(const ObjectAddress *object,
 
 				transformDesc = heap_open(TransformRelationId, AccessShareLock);
 
-				tup = get_catalog_object_by_oid(transformDesc, object->objectId);
+				tup = get_catalog_object_by_oid(transformDesc, Anum_pg_transform_oid, object->objectId);
 
 				if (!HeapTupleIsValid(tup))
 					elog(ERROR, "could not find tuple for transform %u",
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 246776093ec..4b12e9f2748 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -639,6 +639,8 @@ AggregateCreate(const char *aggName,
 	/*
 	 * Okay to create the pg_aggregate entry.
 	 */
+	aggdesc = heap_open(AggregateRelationId, RowExclusiveLock);
+	tupDesc = aggdesc->rd_att;
 
 	/* initialize nulls and values */
 	for (i = 0; i < Natts_pg_aggregate; i++)
@@ -675,9 +677,6 @@ AggregateCreate(const char *aggName,
 	else
 		nulls[Anum_pg_aggregate_aggminitval - 1] = true;
 
-	aggdesc = heap_open(AggregateRelationId, RowExclusiveLock);
-	tupDesc = aggdesc->rd_att;
-
 	tup = heap_form_tuple(tupDesc, values, nulls);
 	CatalogTupleInsert(aggdesc, tup);
 
diff --git a/src/backend/catalog/pg_collation.c b/src/backend/catalog/pg_collation.c
index ce7e5fb5cc1..54c5b57cbd7 100644
--- a/src/backend/catalog/pg_collation.c
+++ b/src/backend/catalog/pg_collation.c
@@ -18,6 +18,7 @@
 #include "access/heapam.h"
 #include "access/htup_details.h"
 #include "access/sysattr.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
@@ -153,6 +154,8 @@ CollationCreate(const char *collname, Oid collnamespace,
 	memset(nulls, 0, sizeof(nulls));
 
 	namestrcpy(&name_name, collname);
+	oid = GetNewOidWithIndex(rel, CollationOidIndexId, Anum_pg_collation_oid);
+	values[Anum_pg_collation_oid - 1] = oid;
 	values[Anum_pg_collation_collname - 1] = NameGetDatum(&name_name);
 	values[Anum_pg_collation_collnamespace - 1] = ObjectIdGetDatum(collnamespace);
 	values[Anum_pg_collation_collowner - 1] = ObjectIdGetDatum(collowner);
@@ -170,7 +173,7 @@ CollationCreate(const char *collname, Oid collnamespace,
 	tup = heap_form_tuple(tupDesc, values, nulls);
 
 	/* insert a new tuple */
-	oid = CatalogTupleInsert(rel, tup);
+	CatalogTupleInsert(rel, tup);
 	Assert(OidIsValid(oid));
 
 	/* set up dependencies for the new collation */
@@ -185,7 +188,8 @@ CollationCreate(const char *collname, Oid collnamespace,
 	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
 
 	/* create dependency on owner */
-	recordDependencyOnOwner(CollationRelationId, HeapTupleGetOid(tup),
+	recordDependencyOnOwner(CollationRelationId,
+							((Form_pg_collation) GETSTRUCT(tup))->oid,
 							collowner);
 
 	/* dependency on extension */
@@ -217,7 +221,7 @@ RemoveCollationById(Oid collationOid)
 	rel = heap_open(CollationRelationId, RowExclusiveLock);
 
 	ScanKeyInit(&scanKeyData,
-				ObjectIdAttributeNumber,
+				Anum_pg_collation_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(collationOid));
 
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 6781b00c6e6..cb25044fea3 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -19,6 +19,7 @@
 #include "access/htup_details.h"
 #include "access/sysattr.h"
 #include "access/tupconvert.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
@@ -165,6 +166,8 @@ CreateConstraintEntry(const char *constraintName,
 		values[i] = (Datum) NULL;
 	}
 
+	conOid = GetNewOidWithIndex(conDesc, ConstraintOidIndexId, Anum_pg_constraint_oid);
+	values[Anum_pg_constraint_oid - 1] = conOid;
 	values[Anum_pg_constraint_conname - 1] = NameGetDatum(&cname);
 	values[Anum_pg_constraint_connamespace - 1] = ObjectIdGetDatum(constraintNamespace);
 	values[Anum_pg_constraint_contype - 1] = CharGetDatum(constraintType);
@@ -231,7 +234,7 @@ CreateConstraintEntry(const char *constraintName,
 
 	tup = heap_form_tuple(RelationGetDescr(conDesc), values, nulls);
 
-	conOid = CatalogTupleInsert(conDesc, tup);
+	CatalogTupleInsert(conDesc, tup);
 
 	conobject.classId = ConstraintRelationId;
 	conobject.objectId = conOid;
@@ -450,7 +453,7 @@ CloneForeignKeyConstraints(Oid parentId, Oid relationId, List **cloned)
 			continue;
 
 		ObjectAddressSet(parentAddr, ConstraintRelationId,
-						 HeapTupleGetOid(tuple));
+						 constrForm->oid);
 
 		datum = fastgetattr(tuple, Anum_pg_constraint_conkey,
 							tupdesc, &isnull);
@@ -546,7 +549,7 @@ CloneForeignKeyConstraints(Oid parentId, Oid relationId, List **cloned)
 								  constrForm->condeferrable,
 								  constrForm->condeferred,
 								  constrForm->convalidated,
-								  HeapTupleGetOid(tuple),
+								  constrForm->oid,
 								  relationId,
 								  mapped_conkey,
 								  nelem,
@@ -971,7 +974,7 @@ AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
 		ObjectAddress thisobj;
 
 		thisobj.classId = ConstraintRelationId;
-		thisobj.objectId = HeapTupleGetOid(tup);
+		thisobj.objectId = conform->oid;
 		thisobj.objectSubId = 0;
 
 		if (object_address_present(&thisobj, objsMoved))
@@ -1076,7 +1079,7 @@ get_relation_constraint_oid(Oid relid, const char *conname, bool missing_ok)
 
 	/* There can be at most one matching row */
 	if (HeapTupleIsValid(tuple = systable_getnext(scan)))
-		conOid = HeapTupleGetOid(tuple);
+		conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
 
 	systable_endscan(scan);
 
@@ -1141,7 +1144,7 @@ get_relation_constraint_attnos(Oid relid, const char *conname,
 		Datum		adatum;
 		bool		isNull;
 
-		*constraintOid = HeapTupleGetOid(tuple);
+		*constraintOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
 
 		/* Extract the conkey array, ie, attnums of constrained columns */
 		adatum = heap_getattr(tuple, Anum_pg_constraint_conkey,
@@ -1214,7 +1217,7 @@ get_relation_idx_constraint_oid(Oid relationId, Oid indexId)
 		constrForm = (Form_pg_constraint) GETSTRUCT(tuple);
 		if (constrForm->conindid == indexId)
 		{
-			constraintId = HeapTupleGetOid(tuple);
+			constraintId = constrForm->oid;
 			break;
 		}
 	}
@@ -1258,7 +1261,7 @@ get_domain_constraint_oid(Oid typid, const char *conname, bool missing_ok)
 
 	/* There can be at most one matching row */
 	if (HeapTupleIsValid(tuple = systable_getnext(scan)))
-		conOid = HeapTupleGetOid(tuple);
+		conOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
 
 	systable_endscan(scan);
 
@@ -1338,7 +1341,7 @@ get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
 							  RelationGetDescr(pg_constraint), &isNull);
 		if (isNull)
 			elog(ERROR, "null conkey for constraint %u",
-				 HeapTupleGetOid(tuple));
+				 ((Form_pg_constraint) GETSTRUCT(tuple))->oid);
 		arr = DatumGetArrayTypeP(adatum);	/* ensure not toasted */
 		numkeys = ARR_DIMS(arr)[0];
 		if (ARR_NDIM(arr) != 1 ||
@@ -1354,7 +1357,7 @@ get_primary_key_attnos(Oid relid, bool deferrableOk, Oid *constraintOid)
 			pkattnos = bms_add_member(pkattnos,
 									  attnums[i] - FirstLowInvalidHeapAttributeNumber);
 		}
-		*constraintOid = HeapTupleGetOid(tuple);
+		*constraintOid = ((Form_pg_constraint) GETSTRUCT(tuple))->oid;
 
 		/* No need to search further */
 		break;
diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c
index fd5c18426bf..f01f7117330 100644
--- a/src/backend/catalog/pg_conversion.c
+++ b/src/backend/catalog/pg_conversion.c
@@ -17,6 +17,7 @@
 #include "access/heapam.h"
 #include "access/htup_details.h"
 #include "access/sysattr.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
@@ -46,6 +47,7 @@ ConversionCreate(const char *conname, Oid connamespace,
 	Relation	rel;
 	TupleDesc	tupDesc;
 	HeapTuple	tup;
+	Oid			oid;
 	bool		nulls[Natts_pg_conversion];
 	Datum		values[Natts_pg_conversion];
 	NameData	cname;
@@ -93,6 +95,8 @@ ConversionCreate(const char *conname, Oid connamespace,
 
 	/* form a tuple */
 	namestrcpy(&cname, conname);
+	oid = GetNewOidWithIndex(rel, ConversionOidIndexId, Anum_pg_conversion_oid);
+	values[Anum_pg_conversion_oid - 1] = oid;
 	values[Anum_pg_conversion_conname - 1] = NameGetDatum(&cname);
 	values[Anum_pg_conversion_connamespace - 1] = ObjectIdGetDatum(connamespace);
 	values[Anum_pg_conversion_conowner - 1] = ObjectIdGetDatum(conowner);
@@ -107,7 +111,7 @@ ConversionCreate(const char *conname, Oid connamespace,
 	CatalogTupleInsert(rel, tup);
 
 	myself.classId = ConversionRelationId;
-	myself.objectId = HeapTupleGetOid(tup);
+	myself.objectId = oid;
 	myself.objectSubId = 0;
 
 	/* create dependency on conversion procedure */
@@ -123,14 +127,13 @@ ConversionCreate(const char *conname, Oid connamespace,
 	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
 
 	/* create dependency on owner */
-	recordDependencyOnOwner(ConversionRelationId, HeapTupleGetOid(tup),
-							conowner);
+	recordDependencyOnOwner(ConversionRelationId, oid, conowner);
 
 	/* dependency on extension */
 	recordDependencyOnCurrentExtension(&myself, false);
 
 	/* Post creation hook for new conversion */
-	InvokeObjectPostCreateHook(ConversionRelationId, HeapTupleGetOid(tup), 0);
+	InvokeObjectPostCreateHook(ConversionRelationId, oid, 0);
 
 	heap_freetuple(tup);
 	heap_close(rel, RowExclusiveLock);
@@ -153,7 +156,7 @@ RemoveConversionById(Oid conversionOid)
 	ScanKeyData scanKeyData;
 
 	ScanKeyInit(&scanKeyData,
-				ObjectIdAttributeNumber,
+				Anum_pg_conversion_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(conversionOid));
 
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index fde361f3675..9acdb65a8a5 100644
--- a/src/backend/catalog/pg_enum.c
+++ b/src/backend/catalog/pg_enum.c
@@ -116,13 +116,13 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
 					 errdetail("Labels must be %d characters or less.",
 							   NAMEDATALEN - 1)));
 
+		values[Anum_pg_enum_oid - 1] = oids[elemno];
 		values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid);
 		values[Anum_pg_enum_enumsortorder - 1] = Float4GetDatum(elemno + 1);
 		namestrcpy(&enumlabel, lab);
 		values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel);
 
 		tup = heap_form_tuple(RelationGetDescr(pg_enum), values, nulls);
-		HeapTupleSetOid(tup, oids[elemno]);
 
 		CatalogTupleInsert(pg_enum, tup);
 		heap_freetuple(tup);
@@ -389,7 +389,7 @@ restart:
 			{
 				HeapTuple	exists_tup = existing[i];
 				Form_pg_enum exists_en = (Form_pg_enum) GETSTRUCT(exists_tup);
-				Oid			exists_oid = HeapTupleGetOid(exists_tup);
+				Oid			exists_oid = exists_en->oid;
 
 				if (exists_oid & 1)
 					continue;	/* ignore odd Oids */
@@ -450,12 +450,12 @@ restart:
 
 	/* Create the new pg_enum entry */
 	memset(nulls, false, sizeof(nulls));
+	values[Anum_pg_enum_oid - 1] = newOid;
 	values[Anum_pg_enum_enumtypid - 1] = ObjectIdGetDatum(enumTypeOid);
 	values[Anum_pg_enum_enumsortorder - 1] = Float4GetDatum(newelemorder);
 	namestrcpy(&enumlabel, newVal);
 	values[Anum_pg_enum_enumlabel - 1] = NameGetDatum(&enumlabel);
 	enum_tup = heap_form_tuple(RelationGetDescr(pg_enum), values, nulls);
-	HeapTupleSetOid(enum_tup, newOid);
 	CatalogTupleInsert(pg_enum, enum_tup);
 	heap_freetuple(enum_tup);
 
diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c
index a876473976a..82c14b401a3 100644
--- a/src/backend/catalog/pg_largeobject.c
+++ b/src/backend/catalog/pg_largeobject.c
@@ -18,6 +18,7 @@
 #include "access/heapam.h"
 #include "access/htup_details.h"
 #include "access/sysattr.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_largeobject.h"
@@ -54,17 +55,22 @@ LargeObjectCreate(Oid loid)
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 
+	if (OidIsValid(loid))
+		loid_new = loid;
+	else
+		loid_new =
+			GetNewOidWithIndex(pg_lo_meta, LargeObjectMetadataOidIndexId, Anum_pg_largeobject_metadata_oid);
+
+
+	values[Anum_pg_largeobject_metadata_oid - 1] = ObjectIdGetDatum(loid_new);
 	values[Anum_pg_largeobject_metadata_lomowner - 1]
 		= ObjectIdGetDatum(GetUserId());
 	nulls[Anum_pg_largeobject_metadata_lomacl - 1] = true;
 
 	ntup = heap_form_tuple(RelationGetDescr(pg_lo_meta),
 						   values, nulls);
-	if (OidIsValid(loid))
-		HeapTupleSetOid(ntup, loid);
 
-	loid_new = CatalogTupleInsert(pg_lo_meta, ntup);
-	Assert(!OidIsValid(loid) || loid == loid_new);
+	CatalogTupleInsert(pg_lo_meta, ntup);
 
 	heap_freetuple(ntup);
 
@@ -96,7 +102,7 @@ LargeObjectDrop(Oid loid)
 	 * Delete an entry from pg_largeobject_metadata
 	 */
 	ScanKeyInit(&skey[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_largeobject_metadata_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(loid));
 
@@ -159,7 +165,7 @@ LargeObjectExists(Oid loid)
 	bool		retval = false;
 
 	ScanKeyInit(&skey[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_largeobject_metadata_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(loid));
 
diff --git a/src/backend/catalog/pg_namespace.c b/src/backend/catalog/pg_namespace.c
index 2cf52be0255..085dc19780b 100644
--- a/src/backend/catalog/pg_namespace.c
+++ b/src/backend/catalog/pg_namespace.c
@@ -16,6 +16,7 @@
 
 #include "access/heapam.h"
 #include "access/htup_details.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
@@ -68,12 +69,18 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
 	else
 		nspacl = NULL;
 
+	nspdesc = heap_open(NamespaceRelationId, RowExclusiveLock);
+	tupDesc = nspdesc->rd_att;
+
 	/* initialize nulls and values */
 	for (i = 0; i < Natts_pg_namespace; i++)
 	{
 		nulls[i] = false;
 		values[i] = (Datum) NULL;
 	}
+
+	nspoid = GetNewOidWithIndex(nspdesc, NamespaceOidIndexId, Anum_pg_namespace_oid);
+	values[Anum_pg_namespace_oid - 1] = nspoid;
 	namestrcpy(&nname, nspName);
 	values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname);
 	values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId);
@@ -82,12 +89,10 @@ NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
 	else
 		nulls[Anum_pg_namespace_nspacl - 1] = true;
 
-	nspdesc = heap_open(NamespaceRelationId, RowExclusiveLock);
-	tupDesc = nspdesc->rd_att;
 
 	tup = heap_form_tuple(tupDesc, values, nulls);
 
-	nspoid = CatalogTupleInsert(nspdesc, tup);
+	CatalogTupleInsert(nspdesc, tup);
 	Assert(OidIsValid(nspoid));
 
 	heap_close(nspdesc, RowExclusiveLock);
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 6dde75ed252..b7c8ea7ebd3 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -20,6 +20,7 @@
 #include "access/heapam.h"
 #include "access/htup_details.h"
 #include "access/xact.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
@@ -142,10 +143,10 @@ OperatorGet(const char *operatorName,
 						  ObjectIdGetDatum(operatorNamespace));
 	if (HeapTupleIsValid(tup))
 	{
-		RegProcedure oprcode = ((Form_pg_operator) GETSTRUCT(tup))->oprcode;
+		Form_pg_operator oprform = (Form_pg_operator) GETSTRUCT(tup);
 
-		operatorObjectId = HeapTupleGetOid(tup);
-		*defined = RegProcedureIsValid(oprcode);
+		operatorObjectId = oprform->oid;
+		*defined = RegProcedureIsValid(oprform->oprcode);
 		ReleaseSysCache(tup);
 	}
 	else
@@ -218,6 +219,12 @@ OperatorShellMake(const char *operatorName,
 				 errmsg("\"%s\" is not a valid operator name",
 						operatorName)));
 
+	/*
+	 * open pg_operator
+	 */
+	pg_operator_desc = heap_open(OperatorRelationId, RowExclusiveLock);
+	tupDesc = pg_operator_desc->rd_att;
+
 	/*
 	 * initialize our *nulls and *values arrays
 	 */
@@ -231,6 +238,8 @@ OperatorShellMake(const char *operatorName,
 	 * initialize values[] with the operator name and input data types. Note
 	 * that oprcode is set to InvalidOid, indicating it's a shell.
 	 */
+	operatorObjectId = GetNewOidWithIndex(pg_operator_desc, OperatorOidIndexId, Anum_pg_operator_oid);
+	values[Anum_pg_operator_oid - 1] = operatorObjectId;
 	namestrcpy(&oname, operatorName);
 	values[Anum_pg_operator_oprname - 1] = NameGetDatum(&oname);
 	values[Anum_pg_operator_oprnamespace - 1] = ObjectIdGetDatum(operatorNamespace);
@@ -247,12 +256,6 @@ OperatorShellMake(const char *operatorName,
 	values[Anum_pg_operator_oprrest - 1] = ObjectIdGetDatum(InvalidOid);
 	values[Anum_pg_operator_oprjoin - 1] = ObjectIdGetDatum(InvalidOid);
 
-	/*
-	 * open pg_operator
-	 */
-	pg_operator_desc = heap_open(OperatorRelationId, RowExclusiveLock);
-	tupDesc = pg_operator_desc->rd_att;
-
 	/*
 	 * create a new operator tuple
 	 */
@@ -261,7 +264,7 @@ OperatorShellMake(const char *operatorName,
 	/*
 	 * insert our "shell" operator tuple
 	 */
-	operatorObjectId = CatalogTupleInsert(pg_operator_desc, tup);
+	CatalogTupleInsert(pg_operator_desc, tup);
 
 	/* Add dependencies for the entry */
 	makeOperatorDependencies(tup, false);
@@ -529,10 +532,13 @@ OperatorCreate(const char *operatorName,
 	{
 		isUpdate = false;
 
+		operatorObjectId = GetNewOidWithIndex(pg_operator_desc, OperatorOidIndexId, Anum_pg_operator_oid);
+		values[Anum_pg_operator_oid - 1] = operatorObjectId;
+
 		tup = heap_form_tuple(RelationGetDescr(pg_operator_desc),
 							  values, nulls);
 
-		operatorObjectId = CatalogTupleInsert(pg_operator_desc, tup);
+		CatalogTupleInsert(pg_operator_desc, tup);
 	}
 
 	/* Add dependencies for the entry */
@@ -767,7 +773,7 @@ makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
 				referenced;
 
 	myself.classId = OperatorRelationId;
-	myself.objectId = HeapTupleGetOid(tuple);
+	myself.objectId = oper->oid;
 	myself.objectSubId = 0;
 
 	/*
@@ -853,7 +859,7 @@ makeOperatorDependencies(HeapTuple tuple, bool isUpdate)
 	}
 
 	/* Dependency on owner */
-	recordDependencyOnOwner(OperatorRelationId, HeapTupleGetOid(tuple),
+	recordDependencyOnOwner(OperatorRelationId, oper->oid,
 							oper->oprowner);
 
 	/* Dependency on extension */
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 0c817047cd1..053cf2f1795 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -16,6 +16,7 @@
 
 #include "access/htup_details.h"
 #include "access/xact.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
@@ -382,7 +383,7 @@ ProcedureCreate(const char *procedureName,
 					(errcode(ERRCODE_DUPLICATE_FUNCTION),
 					 errmsg("function \"%s\" already exists with same argument types",
 							procedureName)));
-		if (!pg_proc_ownercheck(HeapTupleGetOid(oldtup), proowner))
+		if (!pg_proc_ownercheck(oldproc->oid, proowner))
 			aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_FUNCTION,
 						   procedureName);
 
@@ -421,7 +422,7 @@ ProcedureCreate(const char *procedureName,
 					 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
 					 errhint("Use %s %s first.",
 							 dropcmd,
-							 format_procedure(HeapTupleGetOid(oldtup)))));
+							 format_procedure(oldproc->oid))));
 
 		/*
 		 * If it returns RECORD, check for possible change of record type
@@ -448,7 +449,7 @@ ProcedureCreate(const char *procedureName,
 						 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
 						 errhint("Use %s %s first.",
 								 dropcmd,
-								 format_procedure(HeapTupleGetOid(oldtup)))));
+								 format_procedure(oldproc->oid))));
 		}
 
 		/*
@@ -493,7 +494,7 @@ ProcedureCreate(const char *procedureName,
 							 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
 							 errhint("Use %s %s first.",
 									 dropcmd,
-									 format_procedure(HeapTupleGetOid(oldtup)))));
+									 format_procedure(oldproc->oid))));
 			}
 		}
 
@@ -519,7 +520,7 @@ ProcedureCreate(const char *procedureName,
 						 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
 						 errhint("Use %s %s first.",
 								 dropcmd,
-								 format_procedure(HeapTupleGetOid(oldtup)))));
+								 format_procedure(oldproc->oid))));
 
 			proargdefaults = SysCacheGetAttr(PROCNAMEARGSNSP, oldtup,
 											 Anum_pg_proc_proargdefaults,
@@ -547,15 +548,16 @@ ProcedureCreate(const char *procedureName,
 							 /* translator: first %s is DROP FUNCTION or DROP PROCEDURE */
 							 errhint("Use %s %s first.",
 									 dropcmd,
-									 format_procedure(HeapTupleGetOid(oldtup)))));
+									 format_procedure(oldproc->oid))));
 				newlc = lnext(newlc);
 			}
 		}
 
 		/*
-		 * Do not change existing ownership or permissions, either.  Note
+		 * Do not change existing oid, ownership or permissions, either.  Note
 		 * dependency-update code below has to agree with this decision.
 		 */
+		replaces[Anum_pg_proc_oid - 1] = false;
 		replaces[Anum_pg_proc_proowner - 1] = false;
 		replaces[Anum_pg_proc_proacl - 1] = false;
 
@@ -578,13 +580,15 @@ ProcedureCreate(const char *procedureName,
 		else
 			nulls[Anum_pg_proc_proacl - 1] = true;
 
+		values[Anum_pg_proc_oid - 1] =
+			GetNewOidWithIndex(rel, ProcedureOidIndexId, Anum_pg_proc_oid);
 		tup = heap_form_tuple(tupDesc, values, nulls);
 		CatalogTupleInsert(rel, tup);
 		is_update = false;
 	}
 
 
-	retval = HeapTupleGetOid(tup);
+	retval = ((Form_pg_proc) GETSTRUCT(tup))->oid;
 
 	/*
 	 * Create dependencies for the new function.  If we are updating an
diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index 3ecf6d57bf0..45457507f61 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -182,6 +182,8 @@ publication_add_relation(Oid pubid, Relation targetrel,
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 
+	prrelid = GetNewOidWithIndex(rel, PublicationRelObjectIndexId, Anum_pg_publication_rel_oid);
+	values[Anum_pg_publication_rel_oid - 1] = prrelid;
 	values[Anum_pg_publication_rel_prpubid - 1] =
 		ObjectIdGetDatum(pubid);
 	values[Anum_pg_publication_rel_prrelid - 1] =
@@ -190,7 +192,7 @@ publication_add_relation(Oid pubid, Relation targetrel,
 	tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
 
 	/* Insert tuple into catalog. */
-	prrelid = CatalogTupleInsert(rel, tup);
+	CatalogTupleInsert(rel, tup);
 	heap_freetuple(tup);
 
 	ObjectAddressSet(myself, PublicationRelRelationId, prrelid);
@@ -306,7 +308,7 @@ GetAllTablesPublications(void)
 
 	result = NIL;
 	while (HeapTupleIsValid(tup = systable_getnext(scan)))
-		result = lappend_oid(result, HeapTupleGetOid(tup));
+		result = lappend_oid(result, ((Form_pg_publication) GETSTRUCT(tup))->oid);
 
 	systable_endscan(scan);
 	heap_close(rel, AccessShareLock);
@@ -337,8 +339,8 @@ GetAllTablesPublicationRelations(void)
 
 	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
-		Oid			relid = HeapTupleGetOid(tuple);
 		Form_pg_class relForm = (Form_pg_class) GETSTRUCT(tuple);
+		Oid			relid = relForm->oid;
 
 		if (is_publishable_class(relid, relForm))
 			result = lappend_oid(result, relid);
diff --git a/src/backend/catalog/pg_subscription.c b/src/backend/catalog/pg_subscription.c
index f891ff80543..077701fde0d 100644
--- a/src/backend/catalog/pg_subscription.c
+++ b/src/backend/catalog/pg_subscription.c
@@ -236,13 +236,12 @@ textarray_to_stringlist(ArrayType *textarray)
 /*
  * Add new state record for a subscription table.
  */
-Oid
+void
 AddSubscriptionRelState(Oid subid, Oid relid, char state,
 						XLogRecPtr sublsn)
 {
 	Relation	rel;
 	HeapTuple	tup;
-	Oid			subrelid;
 	bool		nulls[Natts_pg_subscription_rel];
 	Datum		values[Natts_pg_subscription_rel];
 
@@ -272,26 +271,23 @@ AddSubscriptionRelState(Oid subid, Oid relid, char state,
 	tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
 
 	/* Insert tuple into catalog. */
-	subrelid = CatalogTupleInsert(rel, tup);
+	CatalogTupleInsert(rel, tup);
 
 	heap_freetuple(tup);
 
 	/* Cleanup. */
 	heap_close(rel, NoLock);
-
-	return subrelid;
 }
 
 /*
  * Update the state of a subscription table.
  */
-Oid
+void
 UpdateSubscriptionRelState(Oid subid, Oid relid, char state,
 						   XLogRecPtr sublsn)
 {
 	Relation	rel;
 	HeapTuple	tup;
-	Oid			subrelid;
 	bool		nulls[Natts_pg_subscription_rel];
 	Datum		values[Natts_pg_subscription_rel];
 	bool		replaces[Natts_pg_subscription_rel];
@@ -328,12 +324,8 @@ UpdateSubscriptionRelState(Oid subid, Oid relid, char state,
 	/* Update the catalog. */
 	CatalogTupleUpdate(rel, &tup->t_self, tup);
 
-	subrelid = HeapTupleGetOid(tup);
-
 	/* Cleanup. */
 	heap_close(rel, NoLock);
-
-	return subrelid;
 }
 
 /*
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 2ddd46d48ed..95e2c9bfb9d 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -17,6 +17,7 @@
 #include "access/heapam.h"
 #include "access/htup_details.h"
 #include "access/xact.h"
+#include "catalog/catalog.h"
 #include "catalog/binary_upgrade.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
@@ -121,11 +122,6 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
 	nulls[Anum_pg_type_typdefault - 1] = true;
 	nulls[Anum_pg_type_typacl - 1] = true;
 
-	/*
-	 * create a new type tuple
-	 */
-	tup = heap_form_tuple(tupDesc, values, nulls);
-
 	/* Use binary-upgrade override for pg_type.oid? */
 	if (IsBinaryUpgrade)
 	{
@@ -134,14 +130,25 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("pg_type OID value not set when in binary upgrade mode")));
 
-		HeapTupleSetOid(tup, binary_upgrade_next_pg_type_oid);
+		typoid = binary_upgrade_next_pg_type_oid;
 		binary_upgrade_next_pg_type_oid = InvalidOid;
 	}
+	else
+	{
+		typoid = GetNewOidWithIndex(pg_type_desc, TypeOidIndexId, Anum_pg_type_oid);
+	}
+
+	values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typoid);
+
+	/*
+	 * create a new type tuple
+	 */
+	tup = heap_form_tuple(tupDesc, values, nulls);
 
 	/*
 	 * insert the tuple in the relation and get the tuple's oid.
 	 */
-	typoid = CatalogTupleInsert(pg_type_desc, tup);
+	CatalogTupleInsert(pg_type_desc, tup);
 
 	/*
 	 * Create dependencies.  We can/must skip this in bootstrap mode.
@@ -190,7 +197,7 @@ TypeShellMake(const char *typeName, Oid typeNamespace, Oid ownerId)
  *		otherwise we use exactly that OID.
  * ----------------------------------------------------------------
  */
-ObjectAddress
+ ObjectAddress
 TypeCreate(Oid newTypeOid,
 		   const char *typeName,
 		   Oid typeNamespace,
@@ -399,11 +406,13 @@ TypeCreate(Oid newTypeOid,
 							  ObjectIdGetDatum(typeNamespace));
 	if (HeapTupleIsValid(tup))
 	{
+		Form_pg_type typform = (Form_pg_type) GETSTRUCT(tup);
+
 		/*
 		 * check that the type is not already defined.  It may exist as a
 		 * shell type, however.
 		 */
-		if (((Form_pg_type) GETSTRUCT(tup))->typisdefined)
+		if (typform->typisdefined)
 			ereport(ERROR,
 					(errcode(ERRCODE_DUPLICATE_OBJECT),
 					 errmsg("type \"%s\" already exists", typeName)));
@@ -411,13 +420,15 @@ TypeCreate(Oid newTypeOid,
 		/*
 		 * shell type must have been created by same owner
 		 */
-		if (((Form_pg_type) GETSTRUCT(tup))->typowner != ownerId)
+		if (typform->typowner != ownerId)
 			aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TYPE, typeName);
 
 		/* trouble if caller wanted to force the OID */
 		if (OidIsValid(newTypeOid))
 			elog(ERROR, "cannot assign new OID to existing shell type");
 
+		replaces[Anum_pg_type_oid - 1] = false;
+
 		/*
 		 * Okay to update existing shell type tuple
 		 */
@@ -429,19 +440,15 @@ TypeCreate(Oid newTypeOid,
 
 		CatalogTupleUpdate(pg_type_desc, &tup->t_self, tup);
 
-		typeObjectId = HeapTupleGetOid(tup);
+		typeObjectId = typform->oid;
 
 		rebuildDeps = true;		/* get rid of shell type's dependencies */
 	}
 	else
 	{
-		tup = heap_form_tuple(RelationGetDescr(pg_type_desc),
-							  values,
-							  nulls);
-
 		/* Force the OID if requested by caller */
 		if (OidIsValid(newTypeOid))
-			HeapTupleSetOid(tup, newTypeOid);
+			typeObjectId = newTypeOid;
 		/* Use binary-upgrade override for pg_type.oid, if supplied. */
 		else if (IsBinaryUpgrade)
 		{
@@ -450,12 +457,22 @@ TypeCreate(Oid newTypeOid,
 						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 						 errmsg("pg_type OID value not set when in binary upgrade mode")));
 
-			HeapTupleSetOid(tup, binary_upgrade_next_pg_type_oid);
+			typeObjectId = binary_upgrade_next_pg_type_oid;
 			binary_upgrade_next_pg_type_oid = InvalidOid;
 		}
-		/* else allow system to assign oid */
+		else
+		{
+			typeObjectId = GetNewOidWithIndex(pg_type_desc, TypeOidIndexId, Anum_pg_type_oid);
+		}
 
-		typeObjectId = CatalogTupleInsert(pg_type_desc, tup);
+		values[Anum_pg_type_oid - 1] = ObjectIdGetDatum(typeObjectId);
+
+		tup = heap_form_tuple(RelationGetDescr(pg_type_desc),
+							  values,
+							  nulls);
+
+
+		CatalogTupleInsert(pg_type_desc, tup);
 	}
 
 	/*
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 3baaa082381..462969a8384 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -216,7 +216,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
 			 "pg_toast_%u_index", relOid);
 
 	/* this is pretty painful...  need a tuple descriptor */
-	tupdesc = CreateTemplateTupleDesc(3, false);
+	tupdesc = CreateTemplateTupleDesc(3);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1,
 					   "chunk_id",
 					   OIDOID,
@@ -272,8 +272,6 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
 										   rel->rd_rel->relpersistence,
 										   shared_relation,
 										   mapped_relation,
-										   true,
-										   0,
 										   ONCOMMIT_NOOP,
 										   reloptions,
 										   false,
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index eff325cc7d0..21e9d3916a1 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -903,6 +903,7 @@ void
 AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
 {
 	Oid			classId = RelationGetRelid(rel);
+	AttrNumber	Anum_oid = get_object_attnum_oid(classId);
 	AttrNumber	Anum_owner = get_object_attnum_owner(classId);
 	AttrNumber	Anum_namespace = get_object_attnum_namespace(classId);
 	AttrNumber	Anum_acl = get_object_attnum_acl(classId);
@@ -913,7 +914,7 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
 	Oid			old_ownerId;
 	Oid			namespaceId = InvalidOid;
 
-	oldtup = get_catalog_object_by_oid(rel, objectId);
+	oldtup = get_catalog_object_by_oid(rel, Anum_oid, objectId);
 	if (oldtup == NULL)
 		elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
 			 objectId, RelationGetRelationName(rel));
@@ -959,8 +960,7 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
 				}
 				else
 				{
-					snprintf(namebuf, sizeof(namebuf), "%u",
-							 HeapTupleGetOid(oldtup));
+					snprintf(namebuf, sizeof(namebuf), "%u", objectId);
 					objname = namebuf;
 				}
 				aclcheck_error(ACLCHECK_NOT_OWNER, objtype, objname);
@@ -1017,7 +1017,7 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
 		/* Update owner dependency reference */
 		if (classId == LargeObjectMetadataRelationId)
 			classId = LargeObjectRelationId;
-		changeDependencyOnOwner(classId, HeapTupleGetOid(newtup), new_ownerId);
+		changeDependencyOnOwner(classId, objectId, new_ownerId);
 
 		/* Release memory */
 		pfree(values);
diff --git a/src/backend/commands/amcmds.c b/src/backend/commands/amcmds.c
index f2173450ad3..9c820acac3f 100644
--- a/src/backend/commands/amcmds.c
+++ b/src/backend/commands/amcmds.c
@@ -15,6 +15,7 @@
 
 #include "access/heapam.h"
 #include "access/htup_details.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_am.h"
@@ -80,6 +81,8 @@ CreateAccessMethod(CreateAmStmt *stmt)
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 
+	amoid = GetNewOidWithIndex(rel, AmOidIndexId, Anum_pg_am_oid);
+	values[Anum_pg_am_oid - 1] = ObjectIdGetDatum(amoid);
 	values[Anum_pg_am_amname - 1] =
 		DirectFunctionCall1(namein, CStringGetDatum(stmt->amname));
 	values[Anum_pg_am_amhandler - 1] = ObjectIdGetDatum(amhandler);
@@ -87,7 +90,7 @@ CreateAccessMethod(CreateAmStmt *stmt)
 
 	tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
 
-	amoid = CatalogTupleInsert(rel, tup);
+	CatalogTupleInsert(rel, tup);
 	heap_freetuple(tup);
 
 	myself.classId = AccessMethodRelationId;
@@ -164,7 +167,7 @@ get_am_type_oid(const char *amname, char amtype, bool missing_ok)
 							NameStr(amform->amname),
 							get_am_type_string(amtype))));
 
-		oid = HeapTupleGetOid(tup);
+		oid = amform->oid;
 		ReleaseSysCache(tup);
 	}
 
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 68be4709771..d21211a5717 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -75,7 +75,7 @@ static List *get_tables_to_cluster(MemoryContext cluster_context);
 static void reform_and_rewrite_tuple(HeapTuple tuple,
 						 TupleDesc oldTupDesc, TupleDesc newTupDesc,
 						 Datum *values, bool *isnull,
-						 bool newRelHasOids, RewriteState rwstate);
+						 RewriteState rwstate);
 
 
 /*---------------------------------------------------------------------------
@@ -688,8 +688,6 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, char relpersistence,
 										  relpersistence,
 										  false,
 										  RelationIsMapped(OldHeap),
-										  true,
-										  0,
 										  ONCOMMIT_NOOP,
 										  reloptions,
 										  false,
@@ -1061,7 +1059,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
 			reform_and_rewrite_tuple(tuple,
 									 oldTupDesc, newTupDesc,
 									 values, isnull,
-									 NewHeap->rd_rel->relhasoids, rwstate);
+									 rwstate);
 	}
 
 	if (indexScan != NULL)
@@ -1090,7 +1088,7 @@ copy_heap_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, bool verbose,
 			reform_and_rewrite_tuple(tuple,
 									 oldTupDesc, newTupDesc,
 									 values, isnull,
-									 NewHeap->rd_rel->relhasoids, rwstate);
+									 rwstate);
 		}
 
 		tuplesort_end(tuplesort);
@@ -1763,7 +1761,7 @@ static void
 reform_and_rewrite_tuple(HeapTuple tuple,
 						 TupleDesc oldTupDesc, TupleDesc newTupDesc,
 						 Datum *values, bool *isnull,
-						 bool newRelHasOids, RewriteState rwstate)
+						 RewriteState rwstate)
 {
 	HeapTuple	copiedTuple;
 	int			i;
@@ -1779,10 +1777,6 @@ reform_and_rewrite_tuple(HeapTuple tuple,
 
 	copiedTuple = heap_form_tuple(newTupDesc, values, isnull);
 
-	/* Preserve OID, if any */
-	if (newRelHasOids)
-		HeapTupleSetOid(copiedTuple, HeapTupleGetOid(tuple));
-
 	/* The heap rewrite module does the rest */
 	rewrite_heap_tuple(rwstate, tuple, copiedTuple);
 
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index d06662bd32e..9a15e6d3a25 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -127,7 +127,6 @@ typedef struct CopyStateData
 	bool		is_program;		/* is 'filename' a program to popen? */
 	copy_data_source_cb data_source_cb; /* function for reading data */
 	bool		binary;			/* binary format? */
-	bool		oids;			/* include OIDs? */
 	bool		freeze;			/* freeze rows on loading? */
 	bool		csv_mode;		/* Comma Separated Value format? */
 	bool		header_line;	/* CSV header line? */
@@ -169,7 +168,6 @@ typedef struct CopyStateData
 	 * Working state for COPY FROM
 	 */
 	AttrNumber	num_defaults;
-	bool		file_has_oids;
 	FmgrInfo	oid_in_function;
 	Oid			oid_typioparam;
 	FmgrInfo   *in_functions;	/* array of input functions for each attrs */
@@ -309,7 +307,7 @@ static CopyState BeginCopyTo(ParseState *pstate, Relation rel, RawStmt *query,
 static void EndCopyTo(CopyState cstate);
 static uint64 DoCopyTo(CopyState cstate);
 static uint64 CopyTo(CopyState cstate);
-static void CopyOneRowTo(CopyState cstate, Oid tupleOid,
+static void CopyOneRowTo(CopyState cstate,
 			 Datum *values, bool *nulls);
 static void CopyFromInsertBatch(CopyState cstate, EState *estate,
 					CommandId mycid, int hi_options,
@@ -1077,15 +1075,6 @@ ProcessCopyOptions(ParseState *pstate,
 						 errmsg("COPY format \"%s\" not recognized", fmt),
 						 parser_errposition(pstate, defel->location)));
 		}
-		else if (strcmp(defel->defname, "oids") == 0)
-		{
-			if (cstate->oids)
-				ereport(ERROR,
-						(errcode(ERRCODE_SYNTAX_ERROR),
-						 errmsg("conflicting or redundant options"),
-						 parser_errposition(pstate, defel->location)));
-			cstate->oids = defGetBoolean(defel);
-		}
 		else if (strcmp(defel->defname, "freeze") == 0)
 		{
 			if (cstate->freeze)
@@ -1431,13 +1420,6 @@ BeginCopy(ParseState *pstate,
 		cstate->rel = rel;
 
 		tupDesc = RelationGetDescr(cstate->rel);
-
-		/* Don't allow COPY w/ OIDs to or from a table without them */
-		if (cstate->oids && !cstate->rel->rd_rel->relhasoids)
-			ereport(ERROR,
-					(errcode(ERRCODE_UNDEFINED_COLUMN),
-					 errmsg("table \"%s\" does not have OIDs",
-							RelationGetRelationName(cstate->rel))));
 	}
 	else
 	{
@@ -1449,12 +1431,6 @@ BeginCopy(ParseState *pstate,
 		Assert(!is_from);
 		cstate->rel = NULL;
 
-		/* Don't allow COPY w/ OIDs from a query */
-		if (cstate->oids)
-			ereport(ERROR,
-					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					 errmsg("COPY (query) WITH OIDS is not supported")));
-
 		/*
 		 * Run parse analysis and rewrite.  Note this also acquires sufficient
 		 * locks on the source table(s).
@@ -2007,8 +1983,6 @@ CopyTo(CopyState cstate)
 		CopySendData(cstate, BinarySignature, 11);
 		/* Flags field */
 		tmp = 0;
-		if (cstate->oids)
-			tmp |= (1 << 16);
 		CopySendInt32(cstate, tmp);
 		/* No header extension */
 		tmp = 0;
@@ -2070,7 +2044,7 @@ CopyTo(CopyState cstate)
 			heap_deform_tuple(tuple, tupDesc, values, nulls);
 
 			/* Format and send the data */
-			CopyOneRowTo(cstate, HeapTupleGetOid(tuple), values, nulls);
+			CopyOneRowTo(cstate, values, nulls);
 			processed++;
 		}
 
@@ -2103,7 +2077,7 @@ CopyTo(CopyState cstate)
  * Emit one row during CopyTo().
  */
 static void
-CopyOneRowTo(CopyState cstate, Oid tupleOid, Datum *values, bool *nulls)
+CopyOneRowTo(CopyState cstate, Datum *values, bool *nulls)
 {
 	bool		need_delim = false;
 	FmgrInfo   *out_functions = cstate->out_functions;
@@ -2118,25 +2092,6 @@ CopyOneRowTo(CopyState cstate, Oid tupleOid, Datum *values, bool *nulls)
 	{
 		/* Binary per-tuple header */
 		CopySendInt16(cstate, list_length(cstate->attnumlist));
-		/* Send OID if wanted --- note attnumlist doesn't include it */
-		if (cstate->oids)
-		{
-			/* Hack --- assume Oid is same size as int32 */
-			CopySendInt32(cstate, sizeof(int32));
-			CopySendInt32(cstate, tupleOid);
-		}
-	}
-	else
-	{
-		/* Text format has no per-tuple header, but send OID if wanted */
-		/* Assume digits don't need any quoting or encoding conversion */
-		if (cstate->oids)
-		{
-			string = DatumGetCString(DirectFunctionCall1(oidout,
-														 ObjectIdGetDatum(tupleOid)));
-			CopySendString(cstate, string);
-			need_delim = true;
-		}
 	}
 
 	foreach(cur, cstate->attnumlist)
@@ -2647,7 +2602,6 @@ CopyFrom(CopyState cstate)
 	{
 		TupleTableSlot *slot;
 		bool		skip_tuple;
-		Oid			loaded_oid = InvalidOid;
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -2664,15 +2618,12 @@ CopyFrom(CopyState cstate)
 		/* Switch into its memory context */
 		MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
 
-		if (!NextCopyFrom(cstate, econtext, values, nulls, &loaded_oid))
+		if (!NextCopyFrom(cstate, econtext, values, nulls))
 			break;
 
 		/* And now we can form the input tuple. */
 		tuple = heap_form_tuple(tupDesc, values, nulls);
 
-		if (loaded_oid != InvalidOid)
-			HeapTupleSetOid(tuple, loaded_oid);
-
 		/*
 		 * Constraints might reference the tableoid column, so initialize
 		 * t_tableOid before evaluating them.
@@ -3344,12 +3295,7 @@ BeginCopyFrom(ParseState *pstate,
 		}
 	}
 
-	if (!cstate->binary)
-	{
-		/* must rely on user to tell us... */
-		cstate->file_has_oids = cstate->oids;
-	}
-	else
+	if (cstate->binary)
 	{
 		/* Read and verify binary header */
 		char		readSig[11];
@@ -3366,7 +3312,10 @@ BeginCopyFrom(ParseState *pstate,
 			ereport(ERROR,
 					(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
 					 errmsg("invalid COPY file header (missing flags)")));
-		cstate->file_has_oids = (tmp & (1 << 16)) != 0;
+		if ((tmp & (1 << 16)) != 0)
+			ereport(ERROR,
+					(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
+					 errmsg("invalid COPY file header (WITH OIDS)")));
 		tmp &= ~(1 << 16);
 		if ((tmp >> 16) != 0)
 			ereport(ERROR,
@@ -3388,21 +3337,13 @@ BeginCopyFrom(ParseState *pstate,
 		}
 	}
 
-	if (cstate->file_has_oids && cstate->binary)
-	{
-		getTypeBinaryInputInfo(OIDOID,
-							   &in_func_oid, &cstate->oid_typioparam);
-		fmgr_info(in_func_oid, &cstate->oid_in_function);
-	}
-
 	/* create workspace for CopyReadAttributes results */
 	if (!cstate->binary)
 	{
 		AttrNumber	attr_count = list_length(cstate->attnumlist);
-		int			nfields = cstate->file_has_oids ? (attr_count + 1) : attr_count;
 
-		cstate->max_fields = nfields;
-		cstate->raw_fields = (char **) palloc(nfields * sizeof(char *));
+		cstate->max_fields = attr_count;
+		cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *));
 	}
 
 	MemoryContextSwitchTo(oldcontext);
@@ -3475,7 +3416,7 @@ NextCopyFromRawFields(CopyState cstate, char ***fields, int *nfields)
  */
 bool
 NextCopyFrom(CopyState cstate, ExprContext *econtext,
-			 Datum *values, bool *nulls, Oid *tupleOid)
+			 Datum *values, bool *nulls)
 {
 	TupleDesc	tupDesc;
 	AttrNumber	num_phys_attrs,
@@ -3484,16 +3425,12 @@ NextCopyFrom(CopyState cstate, ExprContext *econtext,
 	FmgrInfo   *in_functions = cstate->in_functions;
 	Oid		   *typioparams = cstate->typioparams;
 	int			i;
-	int			nfields;
-	bool		isnull;
-	bool		file_has_oids = cstate->file_has_oids;
 	int		   *defmap = cstate->defmap;
 	ExprState **defexprs = cstate->defexprs;
 
 	tupDesc = RelationGetDescr(cstate->rel);
 	num_phys_attrs = tupDesc->natts;
 	attr_count = list_length(cstate->attnumlist);
-	nfields = file_has_oids ? (attr_count + 1) : attr_count;
 
 	/* Initialize all values for row to NULL */
 	MemSet(values, 0, num_phys_attrs * sizeof(Datum));
@@ -3512,41 +3449,13 @@ NextCopyFrom(CopyState cstate, ExprContext *econtext,
 			return false;
 
 		/* check for overflowing fields */
-		if (nfields > 0 && fldct > nfields)
+		if (attr_count > 0 && fldct > attr_count)
 			ereport(ERROR,
 					(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
 					 errmsg("extra data after last expected column")));
 
 		fieldno = 0;
 
-		/* Read the OID field if present */
-		if (file_has_oids)
-		{
-			if (fieldno >= fldct)
-				ereport(ERROR,
-						(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
-						 errmsg("missing data for OID column")));
-			string = field_strings[fieldno++];
-
-			if (string == NULL)
-				ereport(ERROR,
-						(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
-						 errmsg("null OID in COPY data")));
-			else if (cstate->oids && tupleOid != NULL)
-			{
-				cstate->cur_attname = "oid";
-				cstate->cur_attval = string;
-				*tupleOid = DatumGetObjectId(DirectFunctionCall1(oidin,
-																 CStringGetDatum(string)));
-				if (*tupleOid == InvalidOid)
-					ereport(ERROR,
-							(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
-							 errmsg("invalid OID in COPY data")));
-				cstate->cur_attname = NULL;
-				cstate->cur_attval = NULL;
-			}
-		}
-
 		/* Loop to read the user attributes on the line. */
 		foreach(cur, cstate->attnumlist)
 		{
@@ -3604,7 +3513,7 @@ NextCopyFrom(CopyState cstate, ExprContext *econtext,
 			cstate->cur_attval = NULL;
 		}
 
-		Assert(fieldno == nfields);
+		Assert(fieldno == attr_count);
 	}
 	else
 	{
@@ -3650,27 +3559,6 @@ NextCopyFrom(CopyState cstate, ExprContext *econtext,
 					 errmsg("row field count is %d, expected %d",
 							(int) fld_count, attr_count)));
 
-		if (file_has_oids)
-		{
-			Oid			loaded_oid;
-
-			cstate->cur_attname = "oid";
-			loaded_oid =
-				DatumGetObjectId(CopyReadBinaryAttribute(cstate,
-														 0,
-														 &cstate->oid_in_function,
-														 cstate->oid_typioparam,
-														 -1,
-														 &isnull));
-			if (isnull || loaded_oid == InvalidOid)
-				ereport(ERROR,
-						(errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
-						 errmsg("invalid OID in COPY data")));
-			cstate->cur_attname = NULL;
-			if (cstate->oids && tupleOid != NULL)
-				*tupleOid = loaded_oid;
-		}
-
 		i = 0;
 		foreach(cur, cstate->attnumlist)
 		{
@@ -4998,7 +4886,7 @@ copy_dest_receive(TupleTableSlot *slot, DestReceiver *self)
 	slot_getallattrs(slot);
 
 	/* And send the data */
-	CopyOneRowTo(cstate, InvalidOid, slot->tts_values, slot->tts_isnull);
+	CopyOneRowTo(cstate, slot->tts_values, slot->tts_isnull);
 	myState->processed++;
 
 	return true;
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index 3d82edbf581..d6e056d4e60 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -391,20 +391,7 @@ ExecCreateTableAs(CreateTableAsStmt *stmt, const char *queryString,
 int
 GetIntoRelEFlags(IntoClause *intoClause)
 {
-	int			flags;
-
-	/*
-	 * We need to tell the executor whether it has to produce OIDs or not,
-	 * because it doesn't have enough information to do so itself (since we
-	 * can't build the target relation until after ExecutorStart).
-	 *
-	 * Disallow the OIDS option for materialized views.
-	 */
-	if (interpretOidsOption(intoClause->options,
-							(intoClause->viewQuery == NULL)))
-		flags = EXEC_FLAG_WITH_OIDS;
-	else
-		flags = EXEC_FLAG_WITHOUT_OIDS;
+	int			flags = 0;
 
 	if (intoClause->skipData)
 		flags |= EXEC_FLAG_WITH_NO_DATA;
@@ -590,12 +577,6 @@ intorel_receive(TupleTableSlot *slot, DestReceiver *self)
 	 */
 	tuple = ExecMaterializeSlot(slot);
 
-	/*
-	 * force assignment of new OID (see comments in ExecInsert)
-	 */
-	if (myState->rel->rd_rel->relhasoids)
-		HeapTupleSetOid(tuple, InvalidOid);
-
 	heap_insert(myState->rel,
 				tuple,
 				myState->output_cid,
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 5342f217c02..2d341c69a8c 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -504,7 +504,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
 
 	do
 	{
-		dboid = GetNewOid(pg_database_rel);
+		dboid = GetNewOidWithIndex(pg_database_rel, DatabaseOidIndexId, Anum_pg_database_oid);
 	} while (check_db_file_conflict(dboid));
 
 	/*
@@ -517,6 +517,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
 	MemSet(new_record, 0, sizeof(new_record));
 	MemSet(new_record_nulls, false, sizeof(new_record_nulls));
 
+	new_record[Anum_pg_database_oid - 1] = dboid;
 	new_record[Anum_pg_database_datname - 1] =
 		DirectFunctionCall1(namein, CStringGetDatum(dbname));
 	new_record[Anum_pg_database_datdba - 1] = ObjectIdGetDatum(datdba);
@@ -543,8 +544,6 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
 	tuple = heap_form_tuple(RelationGetDescr(pg_database_rel),
 							new_record, new_record_nulls);
 
-	HeapTupleSetOid(tuple, dboid);
-
 	CatalogTupleInsert(pg_database_rel, tuple);
 
 	/*
@@ -593,7 +592,8 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
 		scan = heap_beginscan_catalog(rel, 0, NULL);
 		while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 		{
-			Oid			srctablespace = HeapTupleGetOid(tuple);
+			Form_pg_tablespace spaceform = (Form_pg_tablespace) GETSTRUCT(tuple);
+			Oid			srctablespace = spaceform->oid;
 			Oid			dsttablespace;
 			char	   *srcpath;
 			char	   *dstpath;
@@ -1301,8 +1301,7 @@ movedb(const char *dbname, const char *tblspcname)
 									 new_record_nulls, new_record_repl);
 		CatalogTupleUpdate(pgdbrel, &oldtuple->t_self, newtuple);
 
-		InvokeObjectPostAlterHook(DatabaseRelationId,
-								  HeapTupleGetOid(newtuple), 0);
+		InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0);
 
 		systable_endscan(sysscan);
 
@@ -1400,6 +1399,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
 	Oid			dboid;
 	HeapTuple	tuple,
 				newtuple;
+	Form_pg_database datform;
 	ScanKeyData scankey;
 	SysScanDesc scan;
 	ListCell   *option;
@@ -1512,9 +1512,10 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
 				(errcode(ERRCODE_UNDEFINED_DATABASE),
 				 errmsg("database \"%s\" does not exist", stmt->dbname)));
 
-	dboid = HeapTupleGetOid(tuple);
+	datform = (Form_pg_database) GETSTRUCT(tuple);
+	dboid = datform->oid;
 
-	if (!pg_database_ownercheck(HeapTupleGetOid(tuple), GetUserId()))
+	if (!pg_database_ownercheck(dboid, GetUserId()))
 		aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_DATABASE,
 					   stmt->dbname);
 
@@ -1556,8 +1557,7 @@ AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
 								 new_record_nulls, new_record_repl);
 	CatalogTupleUpdate(rel, &tuple->t_self, newtuple);
 
-	InvokeObjectPostAlterHook(DatabaseRelationId,
-							  HeapTupleGetOid(newtuple), 0);
+	InvokeObjectPostAlterHook(DatabaseRelationId, dboid, 0);
 
 	systable_endscan(scan);
 
@@ -1626,8 +1626,8 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId)
 				(errcode(ERRCODE_UNDEFINED_DATABASE),
 				 errmsg("database \"%s\" does not exist", dbname)));
 
-	db_id = HeapTupleGetOid(tuple);
 	datForm = (Form_pg_database) GETSTRUCT(tuple);
+	db_id = datForm->oid;
 
 	/*
 	 * If the new owner is the same as the existing owner, consider the
@@ -1645,7 +1645,7 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId)
 		HeapTuple	newtuple;
 
 		/* Otherwise, must be owner of the existing object */
-		if (!pg_database_ownercheck(HeapTupleGetOid(tuple), GetUserId()))
+		if (!pg_database_ownercheck(db_id, GetUserId()))
 			aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_DATABASE,
 						   dbname);
 
@@ -1694,11 +1694,10 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId)
 		heap_freetuple(newtuple);
 
 		/* Update owner dependency reference */
-		changeDependencyOnOwner(DatabaseRelationId, HeapTupleGetOid(tuple),
-								newOwnerId);
+		changeDependencyOnOwner(DatabaseRelationId, db_id, newOwnerId);
 	}
 
-	InvokeObjectPostAlterHook(DatabaseRelationId, HeapTupleGetOid(tuple), 0);
+	InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0);
 
 	ObjectAddressSet(address, DatabaseRelationId, db_id);
 
@@ -1762,7 +1761,6 @@ get_db_info(const char *name, LOCKMODE lockmode,
 								  NULL, 1, &scanKey);
 
 		tuple = systable_getnext(scan);
-
 		if (!HeapTupleIsValid(tuple))
 		{
 			/* definitely no database of that name */
@@ -1770,7 +1768,7 @@ get_db_info(const char *name, LOCKMODE lockmode,
 			break;
 		}
 
-		dbOid = HeapTupleGetOid(tuple);
+		dbOid = ((Form_pg_database) GETSTRUCT(tuple))->oid;
 
 		systable_endscan(scan);
 
@@ -1878,7 +1876,8 @@ remove_dbtablespaces(Oid db_id)
 	scan = heap_beginscan_catalog(rel, 0, NULL);
 	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
-		Oid			dsttablespace = HeapTupleGetOid(tuple);
+		Form_pg_tablespace spcform = (Form_pg_tablespace) GETSTRUCT(tuple);
+		Oid			dsttablespace = spcform->oid;
 		char	   *dstpath;
 		struct stat st;
 
@@ -1945,7 +1944,8 @@ check_db_file_conflict(Oid db_id)
 	scan = heap_beginscan_catalog(rel, 0, NULL);
 	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
-		Oid			dsttablespace = HeapTupleGetOid(tuple);
+		Form_pg_tablespace spcform = (Form_pg_tablespace) GETSTRUCT(tuple);
+		Oid			dsttablespace = spcform->oid;
 		char	   *dstpath;
 		struct stat st;
 
@@ -2030,7 +2030,7 @@ get_database_oid(const char *dbname, bool missing_ok)
 
 	/* We assume that there can be at most one matching tuple */
 	if (HeapTupleIsValid(dbtuple))
-		oid = HeapTupleGetOid(dbtuple);
+		oid = ((Form_pg_database)GETSTRUCT(dbtuple))->oid;
 	else
 		oid = InvalidOid;
 
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index eecc85d14e5..5d61f8a4305 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -15,6 +15,7 @@
 
 #include "access/htup_details.h"
 #include "access/xact.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
@@ -391,6 +392,8 @@ insert_event_trigger_tuple(const char *trigname, const char *eventname, Oid evtO
 	tgrel = heap_open(EventTriggerRelationId, RowExclusiveLock);
 
 	/* Build the new pg_trigger tuple. */
+	trigoid = GetNewOidWithIndex(tgrel, EventTriggerOidIndexId, Anum_pg_event_trigger_oid);
+	values[Anum_pg_event_trigger_oid - 1] = ObjectIdGetDatum(trigoid);
 	memset(nulls, false, sizeof(nulls));
 	namestrcpy(&evtnamedata, trigname);
 	values[Anum_pg_event_trigger_evtname - 1] = NameGetDatum(&evtnamedata);
@@ -408,7 +411,7 @@ insert_event_trigger_tuple(const char *trigname, const char *eventname, Oid evtO
 
 	/* Insert heap tuple. */
 	tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
-	trigoid = CatalogTupleInsert(tgrel, tuple);
+	CatalogTupleInsert(tgrel, tuple);
 	heap_freetuple(tuple);
 
 	/* Depend on owner. */
@@ -516,14 +519,14 @@ AlterEventTrigger(AlterEventTrigStmt *stmt)
 				 errmsg("event trigger \"%s\" does not exist",
 						stmt->trigname)));
 
-	trigoid = HeapTupleGetOid(tup);
+	evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
+	trigoid = evtForm->oid;
 
 	if (!pg_event_trigger_ownercheck(trigoid, GetUserId()))
 		aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EVENT_TRIGGER,
 					   stmt->trigname);
 
 	/* tuple is a copy, so we can modify it below */
-	evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
 	evtForm->evtenabled = tgenabled;
 
 	CatalogTupleUpdate(tgrel, &tup->t_self, tup);
@@ -546,6 +549,7 @@ AlterEventTriggerOwner(const char *name, Oid newOwnerId)
 {
 	Oid			evtOid;
 	HeapTuple	tup;
+	Form_pg_event_trigger evtForm;
 	Relation	rel;
 	ObjectAddress address;
 
@@ -558,7 +562,8 @@ AlterEventTriggerOwner(const char *name, Oid newOwnerId)
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("event trigger \"%s\" does not exist", name)));
 
-	evtOid = HeapTupleGetOid(tup);
+	evtForm = (Form_pg_event_trigger) GETSTRUCT(tup);
+	evtOid = evtForm->oid;
 
 	AlterEventTriggerOwner_internal(rel, tup, newOwnerId);
 
@@ -609,7 +614,7 @@ AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
 	if (form->evtowner == newOwnerId)
 		return;
 
-	if (!pg_event_trigger_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+	if (!pg_event_trigger_ownercheck(form->oid, GetUserId()))
 		aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_EVENT_TRIGGER,
 					   NameStr(form->evtname));
 
@@ -626,11 +631,11 @@ AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
 
 	/* Update owner dependency reference */
 	changeDependencyOnOwner(EventTriggerRelationId,
-							HeapTupleGetOid(tup),
+							form->oid,
 							newOwnerId);
 
 	InvokeObjectPostAlterHook(EventTriggerRelationId,
-							  HeapTupleGetOid(tup), 0);
+							  form->oid, 0);
 }
 
 /*
@@ -1357,7 +1362,8 @@ EventTriggerSQLDropAddObject(const ObjectAddress *object, bool original, bool no
 		HeapTuple	tuple;
 
 		catalog = heap_open(obj->address.classId, AccessShareLock);
-		tuple = get_catalog_object_by_oid(catalog, obj->address.objectId);
+		tuple = get_catalog_object_by_oid(catalog, get_object_attnum_oid(object->classId),
+										  obj->address.objectId);
 
 		if (tuple)
 		{
@@ -2105,6 +2111,7 @@ pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
 
 							catalog = heap_open(addr.classId, AccessShareLock);
 							objtup = get_catalog_object_by_oid(catalog,
+															   get_object_attnum_oid(addr.classId),
 															   addr.objectId);
 							if (!HeapTupleIsValid(objtup))
 								elog(ERROR, "cache lookup failed for object %u/%u",
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index ed6afe79a9f..477e4674be0 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -323,7 +323,7 @@ ExplainResultDesc(ExplainStmt *stmt)
 	}
 
 	/* Need a tuple descriptor representing a single TEXT or XML column */
-	tupdesc = CreateTemplateTupleDesc(1, false);
+	tupdesc = CreateTemplateTupleDesc(1);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN",
 					   result_type, -1, 0);
 	return tupdesc;
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 2d761a5773f..168ceaf0c04 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -32,6 +32,7 @@
 #include "access/htup_details.h"
 #include "access/sysattr.h"
 #include "access/xact.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
@@ -154,7 +155,7 @@ get_extension_oid(const char *extname, bool missing_ok)
 
 	/* We assume that there can be at most one matching tuple */
 	if (HeapTupleIsValid(tuple))
-		result = HeapTupleGetOid(tuple);
+		result = ((Form_pg_extension) GETSTRUCT(tuple))->oid;
 	else
 		result = InvalidOid;
 
@@ -188,7 +189,7 @@ get_extension_name(Oid ext_oid)
 	rel = heap_open(ExtensionRelationId, AccessShareLock);
 
 	ScanKeyInit(&entry[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_extension_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(ext_oid));
 
@@ -227,7 +228,7 @@ get_extension_schema(Oid ext_oid)
 	rel = heap_open(ExtensionRelationId, AccessShareLock);
 
 	ScanKeyInit(&entry[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_extension_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(ext_oid));
 
@@ -1758,6 +1759,8 @@ InsertExtensionTuple(const char *extName, Oid extOwner,
 	memset(values, 0, sizeof(values));
 	memset(nulls, 0, sizeof(nulls));
 
+	extensionOid = GetNewOidWithIndex(rel, ExtensionOidIndexId, Anum_pg_extension_oid);
+	values[Anum_pg_extension_oid - 1] = ObjectIdGetDatum(extensionOid);
 	values[Anum_pg_extension_extname - 1] =
 		DirectFunctionCall1(namein, CStringGetDatum(extName));
 	values[Anum_pg_extension_extowner - 1] = ObjectIdGetDatum(extOwner);
@@ -1777,7 +1780,7 @@ InsertExtensionTuple(const char *extName, Oid extOwner,
 
 	tuple = heap_form_tuple(rel->rd_att, values, nulls);
 
-	extensionOid = CatalogTupleInsert(rel, tuple);
+	CatalogTupleInsert(rel, tuple);
 
 	heap_freetuple(tuple);
 	heap_close(rel, RowExclusiveLock);
@@ -1848,7 +1851,7 @@ RemoveExtensionById(Oid extId)
 	rel = heap_open(ExtensionRelationId, RowExclusiveLock);
 
 	ScanKeyInit(&entry[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_extension_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(extId));
 	scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
@@ -2376,7 +2379,7 @@ pg_extension_config_dump(PG_FUNCTION_ARGS)
 	extRel = heap_open(ExtensionRelationId, RowExclusiveLock);
 
 	ScanKeyInit(&key[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_extension_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(CurrentExtensionObject));
 
@@ -2524,7 +2527,7 @@ extension_config_remove(Oid extensionoid, Oid tableoid)
 	extRel = heap_open(ExtensionRelationId, RowExclusiveLock);
 
 	ScanKeyInit(&key[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_extension_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(extensionoid));
 
@@ -2725,7 +2728,7 @@ AlterExtensionNamespace(const char *extensionName, const char *newschema, Oid *o
 	extRel = heap_open(ExtensionRelationId, RowExclusiveLock);
 
 	ScanKeyInit(&key[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_extension_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(extensionOid));
 
@@ -2905,7 +2908,7 @@ ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
 				 errmsg("extension \"%s\" does not exist",
 						stmt->extname)));
 
-	extensionOid = HeapTupleGetOid(extTup);
+	extensionOid = ((Form_pg_extension) GETSTRUCT(extTup))->oid;
 
 	/*
 	 * Determine the existing version we are updating from
@@ -3047,7 +3050,7 @@ ApplyExtensionUpdates(Oid extensionOid,
 		extRel = heap_open(ExtensionRelationId, RowExclusiveLock);
 
 		ScanKeyInit(&key[0],
-					ObjectIdAttributeNumber,
+					Anum_pg_extension_oid,
 					BTEqualStrategyNumber, F_OIDEQ,
 					ObjectIdGetDatum(extensionOid));
 
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index e5dd9958a4c..8b2e4b5cfc2 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -17,6 +17,7 @@
 #include "access/htup_details.h"
 #include "access/reloptions.h"
 #include "access/xact.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
@@ -260,12 +261,12 @@ AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerI
 
 		/* Update owner dependency reference */
 		changeDependencyOnOwner(ForeignDataWrapperRelationId,
-								HeapTupleGetOid(tup),
+								form->oid,
 								newOwnerId);
 	}
 
 	InvokeObjectPostAlterHook(ForeignDataWrapperRelationId,
-							  HeapTupleGetOid(tup), 0);
+							  form->oid, 0);
 }
 
 /*
@@ -280,6 +281,8 @@ AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId)
 	HeapTuple	tup;
 	Relation	rel;
 	ObjectAddress address;
+	Form_pg_foreign_data_wrapper form;
+
 
 	rel = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
 
@@ -290,7 +293,8 @@ AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId)
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("foreign-data wrapper \"%s\" does not exist", name)));
 
-	fdwId = HeapTupleGetOid(tup);
+	form = (Form_pg_foreign_data_wrapper) GETSTRUCT(tup);
+	fdwId = form->oid;
 
 	AlterForeignDataWrapperOwner_internal(rel, tup, newOwnerId);
 
@@ -354,7 +358,7 @@ AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
 			Oid			srvId;
 			AclResult	aclresult;
 
-			srvId = HeapTupleGetOid(tup);
+			srvId = form->oid;
 
 			/* Must be owner */
 			if (!pg_foreign_server_ownercheck(srvId, GetUserId()))
@@ -399,12 +403,12 @@ AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
 		CatalogTupleUpdate(rel, &tup->t_self, tup);
 
 		/* Update owner dependency reference */
-		changeDependencyOnOwner(ForeignServerRelationId, HeapTupleGetOid(tup),
+		changeDependencyOnOwner(ForeignServerRelationId, form->oid,
 								newOwnerId);
 	}
 
 	InvokeObjectPostAlterHook(ForeignServerRelationId,
-							  HeapTupleGetOid(tup), 0);
+							  form->oid, 0);
 }
 
 /*
@@ -417,6 +421,7 @@ AlterForeignServerOwner(const char *name, Oid newOwnerId)
 	HeapTuple	tup;
 	Relation	rel;
 	ObjectAddress address;
+	Form_pg_foreign_server form;
 
 	rel = heap_open(ForeignServerRelationId, RowExclusiveLock);
 
@@ -427,7 +432,8 @@ AlterForeignServerOwner(const char *name, Oid newOwnerId)
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("server \"%s\" does not exist", name)));
 
-	servOid = HeapTupleGetOid(tup);
+	form = (Form_pg_foreign_server) GETSTRUCT(tup);
+	servOid = form->oid;
 
 	AlterForeignServerOwner_internal(rel, tup, newOwnerId);
 
@@ -601,6 +607,8 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 
+	fdwId = GetNewOidWithIndex(rel, ForeignDataWrapperOidIndexId, Anum_pg_foreign_data_wrapper_oid);
+	values[Anum_pg_foreign_data_wrapper_oid - 1] = ObjectIdGetDatum(fdwId);
 	values[Anum_pg_foreign_data_wrapper_fdwname - 1] =
 		DirectFunctionCall1(namein, CStringGetDatum(stmt->fdwname));
 	values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
@@ -627,7 +635,7 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
 
 	tuple = heap_form_tuple(rel->rd_att, values, nulls);
 
-	fdwId = CatalogTupleInsert(rel, tuple);
+	CatalogTupleInsert(rel, tuple);
 
 	heap_freetuple(tuple);
 
@@ -706,7 +714,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
 				 errmsg("foreign-data wrapper \"%s\" does not exist", stmt->fdwname)));
 
 	fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp);
-	fdwId = HeapTupleGetOid(tp);
+	fdwId = fdwForm->oid;
 
 	memset(repl_val, 0, sizeof(repl_val));
 	memset(repl_null, false, sizeof(repl_null));
@@ -915,6 +923,8 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 
+	srvId = GetNewOidWithIndex(rel, ForeignServerOidIndexId, Anum_pg_foreign_server_oid);
+	values[Anum_pg_foreign_server_oid - 1] = ObjectIdGetDatum(srvId);
 	values[Anum_pg_foreign_server_srvname - 1] =
 		DirectFunctionCall1(namein, CStringGetDatum(stmt->servername));
 	values[Anum_pg_foreign_server_srvowner - 1] = ObjectIdGetDatum(ownerId);
@@ -950,7 +960,7 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
 
 	tuple = heap_form_tuple(rel->rd_att, values, nulls);
 
-	srvId = CatalogTupleInsert(rel, tuple);
+	CatalogTupleInsert(rel, tuple);
 
 	heap_freetuple(tuple);
 
@@ -1003,8 +1013,8 @@ AlterForeignServer(AlterForeignServerStmt *stmt)
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("server \"%s\" does not exist", stmt->servername)));
 
-	srvId = HeapTupleGetOid(tp);
 	srvForm = (Form_pg_foreign_server) GETSTRUCT(tp);
+	srvId = srvForm->oid;
 
 	/*
 	 * Only owner or a superuser can ALTER a SERVER.
@@ -1195,6 +1205,8 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 
+	umId = GetNewOidWithIndex(rel, UserMappingOidIndexId, Anum_pg_user_mapping_oid);
+	values[Anum_pg_user_mapping_oid - 1] = ObjectIdGetDatum(umId);
 	values[Anum_pg_user_mapping_umuser - 1] = ObjectIdGetDatum(useId);
 	values[Anum_pg_user_mapping_umserver - 1] = ObjectIdGetDatum(srv->serverid);
 
@@ -1211,7 +1223,7 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
 
 	tuple = heap_form_tuple(rel->rd_att, values, nulls);
 
-	umId = CatalogTupleInsert(rel, tuple);
+	CatalogTupleInsert(rel, tuple);
 
 	heap_freetuple(tuple);
 
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 6f629a00e8a..1a4c06160c0 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -36,6 +36,7 @@
 #include "access/heapam.h"
 #include "access/htup_details.h"
 #include "access/sysattr.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
@@ -937,8 +938,8 @@ CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
 				 (PLTemplateExists(language) ?
 				  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
 
-	languageOid = HeapTupleGetOid(languageTuple);
 	languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
+	languageOid = languageStruct->oid;
 
 	if (languageStruct->lanpltrusted)
 	{
@@ -1667,6 +1668,8 @@ CreateCast(CreateCastStmt *stmt)
 						format_type_be(targettypeid))));
 
 	/* ready to go */
+	castid = GetNewOidWithIndex(relation, CastOidIndexId, Anum_pg_cast_oid);
+	values[Anum_pg_cast_oid - 1] = ObjectIdGetDatum(castid);
 	values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
 	values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
 	values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
@@ -1677,7 +1680,7 @@ CreateCast(CreateCastStmt *stmt)
 
 	tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
 
-	castid = CatalogTupleInsert(relation, tuple);
+	CatalogTupleInsert(relation, tuple);
 
 	/* make dependency entries */
 	myself.classId = CastRelationId;
@@ -1752,7 +1755,7 @@ DropCastById(Oid castOid)
 	relation = heap_open(CastRelationId, RowExclusiveLock);
 
 	ScanKeyInit(&scankey,
-				ObjectIdAttributeNumber,
+				Anum_pg_cast_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(castOid));
 	scan = systable_beginscan(relation, CastOidIndexId, true,
@@ -1924,6 +1927,8 @@ CreateTransform(CreateTransformStmt *stmt)
 							ObjectIdGetDatum(langid));
 	if (HeapTupleIsValid(tuple))
 	{
+		Form_pg_transform form = (Form_pg_transform) GETSTRUCT(tuple);
+
 		if (!stmt->replace)
 			ereport(ERROR,
 					(errcode(ERRCODE_DUPLICATE_OBJECT),
@@ -1938,14 +1943,16 @@ CreateTransform(CreateTransformStmt *stmt)
 		newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values, nulls, replaces);
 		CatalogTupleUpdate(relation, &newtuple->t_self, newtuple);
 
-		transformid = HeapTupleGetOid(tuple);
+		transformid = form->oid;
 		ReleaseSysCache(tuple);
 		is_replace = true;
 	}
 	else
 	{
+		transformid = GetNewOidWithIndex(relation, TransformOidIndexId, Anum_pg_transform_oid);
+		values[Anum_pg_transform_oid - 1] = transformid;
 		newtuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
-		transformid = CatalogTupleInsert(relation, newtuple);
+		CatalogTupleInsert(relation, newtuple);
 		is_replace = false;
 	}
 
@@ -2034,7 +2041,7 @@ DropTransformById(Oid transformOid)
 	relation = heap_open(TransformRelationId, RowExclusiveLock);
 
 	ScanKeyInit(&scankey,
-				ObjectIdAttributeNumber,
+				Anum_pg_transform_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(transformOid));
 	scan = systable_beginscan(relation, TransformOidIndexId, true,
@@ -2139,8 +2146,8 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
 				 (PLTemplateExists(language) ?
 				  errhint("Use CREATE EXTENSION to load the language into the database.") : 0)));
 
-	codeblock->langOid = HeapTupleGetOid(languageTuple);
 	languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
+	codeblock->langOid = languageStruct->oid;
 	codeblock->langIsTrusted = languageStruct->lanpltrusted;
 	codeblock->atomic = atomic;
 
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index ab3d9a0a489..b782a44c956 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -171,8 +171,8 @@ CheckIndexCompatible(Oid oldId,
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("access method \"%s\" does not exist",
 						accessMethodName)));
-	accessMethodId = HeapTupleGetOid(tuple);
 	accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
+	accessMethodId = accessMethodForm->oid;
 	amRoutine = GetIndexAmRoutine(accessMethodForm->amhandler);
 	ReleaseSysCache(tuple);
 
@@ -582,8 +582,8 @@ DefineIndex(Oid relationId,
 					 errmsg("access method \"%s\" does not exist",
 							accessMethodName)));
 	}
-	accessMethodId = HeapTupleGetOid(tuple);
 	accessMethodForm = (Form_pg_am) GETSTRUCT(tuple);
+	accessMethodId = accessMethodForm->oid;
 	amRoutine = GetIndexAmRoutine(accessMethodForm->amhandler);
 
 	if (stmt->unique && !amRoutine->amcanunique)
@@ -747,17 +747,19 @@ DefineIndex(Oid relationId,
 
 
 	/*
-	 * We disallow indexes on system columns other than OID.  They would not
-	 * necessarily get updated correctly, and they don't seem useful anyway.
+	 * We disallow indexes on system columns.  They would not necessarily get
+	 * updated correctly, and they don't seem useful anyway.
 	 */
 	for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
 	{
 		AttrNumber	attno = indexInfo->ii_IndexAttrNumbers[i];
 
-		if (attno < 0 && attno != ObjectIdAttributeNumber)
+		if (attno < 0)
+		{
 			ereport(ERROR,
 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 					 errmsg("index creation on system columns is not supported")));
+		}
 	}
 
 	/*
@@ -772,8 +774,7 @@ DefineIndex(Oid relationId,
 
 		for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++)
 		{
-			if (i != ObjectIdAttributeNumber &&
-				bms_is_member(i - FirstLowInvalidHeapAttributeNumber,
+			if (bms_is_member(i - FirstLowInvalidHeapAttributeNumber,
 							  indexattrs))
 				ereport(ERROR,
 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -1711,6 +1712,7 @@ ResolveOpClass(List *opclass, Oid attrType,
 	char	   *schemaname;
 	char	   *opcname;
 	HeapTuple	tuple;
+	Form_pg_opclass opform;
 	Oid			opClassId,
 				opInputType;
 
@@ -1795,8 +1797,9 @@ ResolveOpClass(List *opclass, Oid attrType,
 	 * Verify that the index operator class accepts this datatype.  Note we
 	 * will accept binary compatibility.
 	 */
-	opClassId = HeapTupleGetOid(tuple);
-	opInputType = ((Form_pg_opclass) GETSTRUCT(tuple))->opcintype;
+	opform = (Form_pg_opclass) GETSTRUCT(tuple);
+	opClassId = opform->oid;
+	opInputType = opform->opcintype;
 
 	if (!IsBinaryCoercible(attrType, opInputType))
 		ereport(ERROR,
@@ -1865,7 +1868,7 @@ GetDefaultOpClass(Oid type_id, Oid am_id)
 		if (opclass->opcintype == type_id)
 		{
 			nexact++;
-			result = HeapTupleGetOid(tup);
+			result = opclass->oid;
 		}
 		else if (nexact == 0 &&
 				 IsBinaryCoercible(type_id, opclass->opcintype))
@@ -1873,12 +1876,12 @@ GetDefaultOpClass(Oid type_id, Oid am_id)
 			if (IsPreferredType(tcategory, opclass->opcintype))
 			{
 				ncompatiblepreferred++;
-				result = HeapTupleGetOid(tup);
+				result = opclass->oid;
 			}
 			else if (ncompatiblepreferred == 0)
 			{
 				ncompatible++;
-				result = HeapTupleGetOid(tup);
+				result = opclass->oid;
 			}
 		}
 	}
@@ -2404,7 +2407,7 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind,
 	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
 		Form_pg_class classtuple = (Form_pg_class) GETSTRUCT(tuple);
-		Oid			relid = HeapTupleGetOid(tuple);
+		Oid			relid = classtuple->oid;
 
 		/*
 		 * Only regular tables and matviews can have indexes, so ignore any
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index e1eb7c374b8..4736eb2483c 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -184,9 +184,6 @@ ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString,
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("CONCURRENTLY and WITH NO DATA options cannot be used together")));
 
-	/* We don't allow an oid column for a materialized view. */
-	Assert(!matviewRel->rd_rel->relhasoids);
-
 	/*
 	 * Check that everything is correct for a refresh. Problems at this point
 	 * are internal errors, so elog is sufficient.
@@ -408,7 +405,7 @@ refresh_matview_datafill(DestReceiver *dest, Query *query,
 								dest, NULL, NULL, 0);
 
 	/* call ExecutorStart to prepare the plan for execution */
-	ExecutorStart(queryDesc, EXEC_FLAG_WITHOUT_OIDS);
+	ExecutorStart(queryDesc, 0);
 
 	/* run the plan */
 	ExecutorRun(queryDesc, ForwardScanDirection, 0L, true);
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index 3b5c90e3f41..2a2fdd0a0d8 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -23,6 +23,7 @@
 #include "access/nbtree.h"
 #include "access/htup_details.h"
 #include "access/sysattr.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
@@ -142,12 +143,14 @@ Oid
 get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok)
 {
 	HeapTuple	htup;
+	Form_pg_opfamily opfamform;
 	Oid			opfID;
 
 	htup = OpFamilyCacheLookup(amID, opfamilyname, missing_ok);
 	if (!HeapTupleIsValid(htup))
 		return InvalidOid;
-	opfID = HeapTupleGetOid(htup);
+	opfamform = (Form_pg_opfamily) GETSTRUCT(htup);
+	opfID = opfamform->oid;
 	ReleaseSysCache(htup);
 
 	return opfID;
@@ -221,12 +224,14 @@ Oid
 get_opclass_oid(Oid amID, List *opclassname, bool missing_ok)
 {
 	HeapTuple	htup;
+	Form_pg_opclass opcform;
 	Oid			opcID;
 
 	htup = OpClassCacheLookup(amID, opclassname, missing_ok);
 	if (!HeapTupleIsValid(htup))
 		return InvalidOid;
-	opcID = HeapTupleGetOid(htup);
+	opcform = (Form_pg_opclass) GETSTRUCT(htup);
+	opcID = opcform->oid;
 	ReleaseSysCache(htup);
 
 	return opcID;
@@ -271,6 +276,8 @@ CreateOpFamily(const char *amname, const char *opfname, Oid namespaceoid, Oid am
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 
+	opfamilyoid = GetNewOidWithIndex(rel, OpfamilyOidIndexId, Anum_pg_opfamily_oid);
+	values[Anum_pg_opfamily_oid - 1] = ObjectIdGetDatum(opfamilyoid);
 	values[Anum_pg_opfamily_opfmethod - 1] = ObjectIdGetDatum(amoid);
 	namestrcpy(&opfName, opfname);
 	values[Anum_pg_opfamily_opfname - 1] = NameGetDatum(&opfName);
@@ -279,7 +286,7 @@ CreateOpFamily(const char *amname, const char *opfname, Oid namespaceoid, Oid am
 
 	tup = heap_form_tuple(rel->rd_att, values, nulls);
 
-	opfamilyoid = CatalogTupleInsert(rel, tup);
+	CatalogTupleInsert(rel, tup);
 
 	heap_freetuple(tup);
 
@@ -338,6 +345,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
 	ListCell   *l;
 	Relation	rel;
 	HeapTuple	tup;
+	Form_pg_am	amform;
 	IndexAmRoutine *amroutine;
 	Datum		values[Natts_pg_opclass];
 	bool		nulls[Natts_pg_opclass];
@@ -364,7 +372,8 @@ DefineOpClass(CreateOpClassStmt *stmt)
 				 errmsg("access method \"%s\" does not exist",
 						stmt->amname)));
 
-	amoid = HeapTupleGetOid(tup);
+	amform = (Form_pg_am) GETSTRUCT(tup);
+	amoid = amform->oid;
 	amroutine = GetIndexAmRoutineByAmId(amoid, false);
 	ReleaseSysCache(tup);
 
@@ -429,7 +438,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
 							  ObjectIdGetDatum(namespaceoid));
 		if (HeapTupleIsValid(tup))
 		{
-			opfamilyoid = HeapTupleGetOid(tup);
+			opfamilyoid = ((Form_pg_opfamily) GETSTRUCT(tup))->oid;
 
 			/*
 			 * XXX given the superuser check above, there's no need for an
@@ -633,6 +642,8 @@ DefineOpClass(CreateOpClassStmt *stmt)
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 
+	opclassoid = GetNewOidWithIndex(rel, OpclassOidIndexId, Anum_pg_opclass_oid);
+	values[Anum_pg_opclass_oid - 1] = ObjectIdGetDatum(opclassoid);
 	values[Anum_pg_opclass_opcmethod - 1] = ObjectIdGetDatum(amoid);
 	namestrcpy(&opcName, opcname);
 	values[Anum_pg_opclass_opcname - 1] = NameGetDatum(&opcName);
@@ -645,7 +656,7 @@ DefineOpClass(CreateOpClassStmt *stmt)
 
 	tup = heap_form_tuple(rel->rd_att, values, nulls);
 
-	opclassoid = CatalogTupleInsert(rel, tup);
+	CatalogTupleInsert(rel, tup);
 
 	heap_freetuple(tup);
 
@@ -768,6 +779,7 @@ AlterOpFamily(AlterOpFamilyStmt *stmt)
 	int			maxOpNumber,	/* amstrategies value */
 				maxProcNumber;	/* amsupport value */
 	HeapTuple	tup;
+	Form_pg_am	amform;
 	IndexAmRoutine *amroutine;
 
 	/* Get necessary info about access method */
@@ -778,7 +790,8 @@ AlterOpFamily(AlterOpFamilyStmt *stmt)
 				 errmsg("access method \"%s\" does not exist",
 						stmt->amname)));
 
-	amoid = HeapTupleGetOid(tup);
+	amform = (Form_pg_am) GETSTRUCT(tup);
+	amoid = amform->oid;
 	amroutine = GetIndexAmRoutineByAmId(amoid, false);
 	ReleaseSysCache(tup);
 
@@ -1333,6 +1346,8 @@ storeOperators(List *opfamilyname, Oid amoid,
 		memset(values, 0, sizeof(values));
 		memset(nulls, false, sizeof(nulls));
 
+		entryoid = GetNewOidWithIndex(rel, AccessMethodOperatorOidIndexId, Anum_pg_amop_oid);
+		values[Anum_pg_amop_oid - 1] = ObjectIdGetDatum(entryoid);
 		values[Anum_pg_amop_amopfamily - 1] = ObjectIdGetDatum(opfamilyoid);
 		values[Anum_pg_amop_amoplefttype - 1] = ObjectIdGetDatum(op->lefttype);
 		values[Anum_pg_amop_amoprighttype - 1] = ObjectIdGetDatum(op->righttype);
@@ -1344,7 +1359,7 @@ storeOperators(List *opfamilyname, Oid amoid,
 
 		tup = heap_form_tuple(rel->rd_att, values, nulls);
 
-		entryoid = CatalogTupleInsert(rel, tup);
+		CatalogTupleInsert(rel, tup);
 
 		heap_freetuple(tup);
 
@@ -1445,6 +1460,8 @@ storeProcedures(List *opfamilyname, Oid amoid,
 		memset(values, 0, sizeof(values));
 		memset(nulls, false, sizeof(nulls));
 
+		entryoid = GetNewOidWithIndex(rel, AccessMethodProcedureOidIndexId, Anum_pg_amproc_oid);
+		values[Anum_pg_amproc_oid - 1] = ObjectIdGetDatum(entryoid);
 		values[Anum_pg_amproc_amprocfamily - 1] = ObjectIdGetDatum(opfamilyoid);
 		values[Anum_pg_amproc_amproclefttype - 1] = ObjectIdGetDatum(proc->lefttype);
 		values[Anum_pg_amproc_amprocrighttype - 1] = ObjectIdGetDatum(proc->righttype);
@@ -1453,7 +1470,7 @@ storeProcedures(List *opfamilyname, Oid amoid,
 
 		tup = heap_form_tuple(rel->rd_att, values, nulls);
 
-		entryoid = CatalogTupleInsert(rel, tup);
+		CatalogTupleInsert(rel, tup);
 
 		heap_freetuple(tup);
 
@@ -1627,7 +1644,7 @@ RemoveAmOpEntryById(Oid entryOid)
 	SysScanDesc scan;
 
 	ScanKeyInit(&skey[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_amop_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(entryOid));
 
@@ -1656,7 +1673,7 @@ RemoveAmProcEntryById(Oid entryOid)
 	SysScanDesc scan;
 
 	ScanKeyInit(&skey[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_amproc_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(entryOid));
 
diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c
index cee0ef915be..c73cfcc22a9 100644
--- a/src/backend/commands/policy.c
+++ b/src/backend/commands/policy.c
@@ -365,7 +365,7 @@ RemovePolicyById(Oid policy_id)
 	 * Find the policy to delete.
 	 */
 	ScanKeyInit(&skey[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_policy_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(policy_id));
 
@@ -457,7 +457,7 @@ RemoveRoleFromObjectPolicy(Oid roleid, Oid classid, Oid policy_id)
 	 * Find the policy to update.
 	 */
 	ScanKeyInit(&skey[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_policy_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(policy_id));
 
@@ -802,6 +802,8 @@ CreatePolicy(CreatePolicyStmt *stmt)
 				 errmsg("policy \"%s\" for table \"%s\" already exists",
 						stmt->policy_name, RelationGetRelationName(target_table))));
 
+	policy_id = GetNewOidWithIndex(pg_policy_rel, PolicyOidIndexId, Anum_pg_policy_oid);
+	values[Anum_pg_policy_oid - 1] = ObjectIdGetDatum(policy_id);
 	values[Anum_pg_policy_polrelid - 1] = ObjectIdGetDatum(table_id);
 	values[Anum_pg_policy_polname - 1] = DirectFunctionCall1(namein,
 															 CStringGetDatum(stmt->policy_name));
@@ -824,7 +826,7 @@ CreatePolicy(CreatePolicyStmt *stmt)
 	policy_tuple = heap_form_tuple(RelationGetDescr(pg_policy_rel), values,
 								   isnull);
 
-	policy_id = CatalogTupleInsert(pg_policy_rel, policy_tuple);
+	CatalogTupleInsert(pg_policy_rel, policy_tuple);
 
 	/* Record Dependencies */
 	target.classId = RelationRelationId;
@@ -1026,7 +1028,7 @@ AlterPolicy(AlterPolicyStmt *stmt)
 				(errcode(ERRCODE_SYNTAX_ERROR),
 				 errmsg("only WITH CHECK expression allowed for INSERT")));
 
-	policy_id = HeapTupleGetOid(policy_tuple);
+	policy_id = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
 
 	if (role_ids != NULL)
 	{
@@ -1275,7 +1277,7 @@ rename_policy(RenameStmt *stmt)
 				 errmsg("policy \"%s\" for table \"%s\" does not exist",
 						stmt->subname, RelationGetRelationName(target_table))));
 
-	opoloid = HeapTupleGetOid(policy_tuple);
+	opoloid = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
 
 	policy_tuple = heap_copytuple(policy_tuple);
 
@@ -1284,8 +1286,7 @@ rename_policy(RenameStmt *stmt)
 
 	CatalogTupleUpdate(pg_policy_rel, &policy_tuple->t_self, policy_tuple);
 
-	InvokeObjectPostAlterHook(PolicyRelationId,
-							  HeapTupleGetOid(policy_tuple), 0);
+	InvokeObjectPostAlterHook(PolicyRelationId, opoloid, 0);
 
 	ObjectAddressSet(address, PolicyRelationId, opoloid);
 
@@ -1350,7 +1351,7 @@ get_relation_policy_oid(Oid relid, const char *policy_name, bool missing_ok)
 		policy_oid = InvalidOid;
 	}
 	else
-		policy_oid = HeapTupleGetOid(policy_tuple);
+		policy_oid = ((Form_pg_policy) GETSTRUCT(policy_tuple))->oid;
 
 	/* Clean up. */
 	systable_endscan(sscan);
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index b945b1556a8..6036b735e9f 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -734,7 +734,7 @@ pg_prepared_statement(PG_FUNCTION_ARGS)
 	 * build tupdesc for result tuples. This must match the definition of the
 	 * pg_prepared_statements view in system_views.sql
 	 */
-	tupdesc = CreateTemplateTupleDesc(5, false);
+	tupdesc = CreateTemplateTupleDesc(5);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
 					   TEXTOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "statement",
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index c900ad9431a..c1cb2435146 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -16,6 +16,7 @@
 #include "access/genam.h"
 #include "access/heapam.h"
 #include "access/htup_details.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
@@ -329,6 +330,7 @@ create_proc_lang(const char *languageName, bool replace,
 	NameData	langname;
 	HeapTuple	oldtup;
 	HeapTuple	tup;
+	Oid			langoid;
 	bool		is_update;
 	ObjectAddress myself,
 				referenced;
@@ -356,12 +358,14 @@ create_proc_lang(const char *languageName, bool replace,
 
 	if (HeapTupleIsValid(oldtup))
 	{
+		Form_pg_language oldform = (Form_pg_language) GETSTRUCT(oldtup);
+
 		/* There is one; okay to replace it? */
 		if (!replace)
 			ereport(ERROR,
 					(errcode(ERRCODE_DUPLICATE_OBJECT),
 					 errmsg("language \"%s\" already exists", languageName)));
-		if (!pg_language_ownercheck(HeapTupleGetOid(oldtup), languageOwner))
+		if (!pg_language_ownercheck(oldform->oid, languageOwner))
 			aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_LANGUAGE,
 						   languageName);
 
@@ -376,12 +380,15 @@ create_proc_lang(const char *languageName, bool replace,
 		tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces);
 		CatalogTupleUpdate(rel, &tup->t_self, tup);
 
+		langoid = oldform->oid;
 		ReleaseSysCache(oldtup);
 		is_update = true;
 	}
 	else
 	{
 		/* Creating a new language */
+		langoid = GetNewOidWithIndex(rel, LanguageOidIndexId, Anum_pg_language_oid);
+		values[Anum_pg_language_oid - 1] = langoid;
 		tup = heap_form_tuple(tupDesc, values, nulls);
 		CatalogTupleInsert(rel, tup);
 		is_update = false;
@@ -394,7 +401,7 @@ create_proc_lang(const char *languageName, bool replace,
 	 * shared dependencies do *not* need to change, and we leave them alone.)
 	 */
 	myself.classId = LanguageRelationId;
-	myself.objectId = HeapTupleGetOid(tup);
+	myself.objectId = langoid;
 	myself.objectSubId = 0;
 
 	if (is_update)
diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c
index 6f7762a906c..38a98217698 100644
--- a/src/backend/commands/publicationcmds.c
+++ b/src/backend/commands/publicationcmds.c
@@ -189,7 +189,8 @@ CreatePublication(CreatePublicationStmt *stmt)
 							  &publish_given, &publish_insert,
 							  &publish_update, &publish_delete,
 							  &publish_truncate);
-
+	puboid = GetNewOidWithIndex(rel, PublicationObjectIndexId, Anum_pg_publication_oid);
+	values[Anum_pg_publication_oid - 1] = ObjectIdGetDatum(puboid);
 	values[Anum_pg_publication_puballtables - 1] =
 		BoolGetDatum(stmt->for_all_tables);
 	values[Anum_pg_publication_pubinsert - 1] =
@@ -204,7 +205,7 @@ CreatePublication(CreatePublicationStmt *stmt)
 	tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
 
 	/* Insert tuple into catalog. */
-	puboid = CatalogTupleInsert(rel, tup);
+	CatalogTupleInsert(rel, tup);
 	heap_freetuple(tup);
 
 	recordDependencyOnOwner(PublicationRelationId, puboid, GetUserId());
@@ -248,6 +249,7 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
 	bool		publish_delete;
 	bool		publish_truncate;
 	ObjectAddress obj;
+	Form_pg_publication pubform;
 
 	parse_publication_options(stmt->options,
 							  &publish_given, &publish_insert,
@@ -282,14 +284,16 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
 
 	CommandCounterIncrement();
 
+	pubform = (Form_pg_publication) GETSTRUCT(tup);
+
 	/* Invalidate the relcache. */
-	if (((Form_pg_publication) GETSTRUCT(tup))->puballtables)
+	if (pubform->puballtables)
 	{
 		CacheInvalidateRelcacheAll();
 	}
 	else
 	{
-		List	   *relids = GetPublicationRelations(HeapTupleGetOid(tup));
+		List	   *relids = GetPublicationRelations(pubform->oid);
 
 		/*
 		 * We don't want to send too many individual messages, at some point
@@ -310,11 +314,11 @@ AlterPublicationOptions(AlterPublicationStmt *stmt, Relation rel,
 			CacheInvalidateRelcacheAll();
 	}
 
-	ObjectAddressSet(obj, PublicationRelationId, HeapTupleGetOid(tup));
+	ObjectAddressSet(obj, PublicationRelationId, pubform->oid);
 	EventTriggerCollectSimpleCommand(obj, InvalidObjectAddress,
 									 (Node *) stmt);
 
-	InvokeObjectPostAlterHook(PublicationRelationId, HeapTupleGetOid(tup), 0);
+	InvokeObjectPostAlterHook(PublicationRelationId, pubform->oid, 0);
 }
 
 /*
@@ -324,9 +328,9 @@ static void
 AlterPublicationTables(AlterPublicationStmt *stmt, Relation rel,
 					   HeapTuple tup)
 {
-	Oid			pubid = HeapTupleGetOid(tup);
 	List	   *rels = NIL;
 	Form_pg_publication pubform = (Form_pg_publication) GETSTRUCT(tup);
+	Oid			pubid = pubform->oid;
 
 	/* Check that user is allowed to manipulate the publication tables. */
 	if (pubform->puballtables)
@@ -403,6 +407,7 @@ AlterPublication(AlterPublicationStmt *stmt)
 {
 	Relation	rel;
 	HeapTuple	tup;
+	Form_pg_publication pubform;
 
 	rel = heap_open(PublicationRelationId, RowExclusiveLock);
 
@@ -415,8 +420,10 @@ AlterPublication(AlterPublicationStmt *stmt)
 				 errmsg("publication \"%s\" does not exist",
 						stmt->pubname)));
 
+	pubform = (Form_pg_publication) GETSTRUCT(tup);
+
 	/* must be owner */
-	if (!pg_publication_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+	if (!pg_publication_ownercheck(pubform->oid, GetUserId()))
 		aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
 					   stmt->pubname);
 
@@ -662,7 +669,7 @@ AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
 		AclResult	aclresult;
 
 		/* Must be owner */
-		if (!pg_publication_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+		if (!pg_publication_ownercheck(form->oid, GetUserId()))
 			aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
 						   NameStr(form->pubname));
 
@@ -688,11 +695,11 @@ AlterPublicationOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
 
 	/* Update owner dependency reference */
 	changeDependencyOnOwner(PublicationRelationId,
-							HeapTupleGetOid(tup),
+							form->oid,
 							newOwnerId);
 
 	InvokeObjectPostAlterHook(PublicationRelationId,
-							  HeapTupleGetOid(tup), 0);
+							  form->oid, 0);
 }
 
 /*
@@ -705,6 +712,7 @@ AlterPublicationOwner(const char *name, Oid newOwnerId)
 	HeapTuple	tup;
 	Relation	rel;
 	ObjectAddress address;
+	Form_pg_publication pubform;
 
 	rel = heap_open(PublicationRelationId, RowExclusiveLock);
 
@@ -715,7 +723,8 @@ AlterPublicationOwner(const char *name, Oid newOwnerId)
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("publication \"%s\" does not exist", name)));
 
-	subid = HeapTupleGetOid(tup);
+	pubform = (Form_pg_publication) GETSTRUCT(tup);
+	subid = pubform->oid;
 
 	AlterPublicationOwner_internal(rel, tup, newOwnerId);
 
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index dc6cb46e4e7..f0ebe2d1c31 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -246,6 +246,7 @@ RenameSchema(const char *oldname, const char *newname)
 	Relation	rel;
 	AclResult	aclresult;
 	ObjectAddress address;
+	Form_pg_namespace nspform;
 
 	rel = heap_open(NamespaceRelationId, RowExclusiveLock);
 
@@ -255,7 +256,8 @@ RenameSchema(const char *oldname, const char *newname)
 				(errcode(ERRCODE_UNDEFINED_SCHEMA),
 				 errmsg("schema \"%s\" does not exist", oldname)));
 
-	nspOid = HeapTupleGetOid(tup);
+	nspform = (Form_pg_namespace) GETSTRUCT(tup);
+	nspOid = nspform->oid;
 
 	/* make sure the new name doesn't exist */
 	if (OidIsValid(get_namespace_oid(newname, true)))
@@ -264,7 +266,7 @@ RenameSchema(const char *oldname, const char *newname)
 				 errmsg("schema \"%s\" already exists", newname)));
 
 	/* must be owner */
-	if (!pg_namespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+	if (!pg_namespace_ownercheck(nspOid, GetUserId()))
 		aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SCHEMA,
 					   oldname);
 
@@ -281,10 +283,10 @@ RenameSchema(const char *oldname, const char *newname)
 				 errdetail("The prefix \"pg_\" is reserved for system schemas.")));
 
 	/* rename */
-	namestrcpy(&(((Form_pg_namespace) GETSTRUCT(tup))->nspname), newname);
+	namestrcpy(&nspform->nspname, newname);
 	CatalogTupleUpdate(rel, &tup->t_self, tup);
 
-	InvokeObjectPostAlterHook(NamespaceRelationId, HeapTupleGetOid(tup), 0);
+	InvokeObjectPostAlterHook(NamespaceRelationId, nspOid, 0);
 
 	ObjectAddressSet(address, NamespaceRelationId, nspOid);
 
@@ -324,6 +326,7 @@ AlterSchemaOwner(const char *name, Oid newOwnerId)
 	HeapTuple	tup;
 	Relation	rel;
 	ObjectAddress address;
+	Form_pg_namespace nspform;
 
 	rel = heap_open(NamespaceRelationId, RowExclusiveLock);
 
@@ -333,7 +336,8 @@ AlterSchemaOwner(const char *name, Oid newOwnerId)
 				(errcode(ERRCODE_UNDEFINED_SCHEMA),
 				 errmsg("schema \"%s\" does not exist", name)));
 
-	nspOid = HeapTupleGetOid(tup);
+	nspform = (Form_pg_namespace) GETSTRUCT(tup);
+	nspOid = nspform->oid;
 
 	AlterSchemaOwner_internal(tup, rel, newOwnerId);
 
@@ -372,7 +376,7 @@ AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
 		AclResult	aclresult;
 
 		/* Otherwise, must be owner of the existing object */
-		if (!pg_namespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+		if (!pg_namespace_ownercheck(nspForm->oid, GetUserId()))
 			aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SCHEMA,
 						   NameStr(nspForm->nspname));
 
@@ -422,10 +426,10 @@ AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
 		heap_freetuple(newtuple);
 
 		/* Update owner dependency reference */
-		changeDependencyOnOwner(NamespaceRelationId, HeapTupleGetOid(tup),
+		changeDependencyOnOwner(NamespaceRelationId, nspForm->oid,
 								newOwnerId);
 	}
 
 	InvokeObjectPostAlterHook(NamespaceRelationId,
-							  HeapTupleGetOid(tup), 0);
+							  nspForm->oid, 0);
 }
diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c
index 1ac7756f2a5..330b11c95ab 100644
--- a/src/backend/commands/seclabel.c
+++ b/src/backend/commands/seclabel.c
@@ -264,6 +264,7 @@ SetSharedSecurityLabel(const ObjectAddress *object,
 	/* Prepare to form or update a tuple, if necessary. */
 	memset(nulls, false, sizeof(nulls));
 	memset(replaces, false, sizeof(replaces));
+
 	values[Anum_pg_shseclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
 	values[Anum_pg_shseclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
 	values[Anum_pg_shseclabel_provider - 1] = CStringGetTextDatum(provider);
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 89122d4ad75..cdab7ea6923 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1789,7 +1789,7 @@ pg_sequence_parameters(PG_FUNCTION_ARGS)
 				 errmsg("permission denied for sequence %s",
 						get_rel_name(relid))));
 
-	tupdesc = CreateTemplateTupleDesc(7, false);
+	tupdesc = CreateTemplateTupleDesc(7);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "start_value",
 					   INT8OID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "minimum_value",
diff --git a/src/backend/commands/statscmds.c b/src/backend/commands/statscmds.c
index 3bb0d24cd20..7f4de7e5b23 100644
--- a/src/backend/commands/statscmds.c
+++ b/src/backend/commands/statscmds.c
@@ -15,6 +15,7 @@
 #include "postgres.h"
 
 #include "access/relscan.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
@@ -305,11 +306,16 @@ CreateStatistics(CreateStatsStmt *stmt)
 	Assert(ntypes > 0 && ntypes <= lengthof(types));
 	stxkind = construct_array(types, ntypes, CHAROID, 1, true, 'c');
 
+	statrel = heap_open(StatisticExtRelationId, RowExclusiveLock);
+
 	/*
 	 * Everything seems fine, so let's build the pg_statistic_ext tuple.
 	 */
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
+
+	statoid = GetNewOidWithIndex(rel, StatisticExtOidIndexId, Anum_pg_statistic_ext_oid);
+	values[Anum_pg_statistic_ext_oid - 1] = ObjectIdGetDatum(statoid);
 	values[Anum_pg_statistic_ext_stxrelid - 1] = ObjectIdGetDatum(relid);
 	values[Anum_pg_statistic_ext_stxname - 1] = NameGetDatum(&stxname);
 	values[Anum_pg_statistic_ext_stxnamespace - 1] = ObjectIdGetDatum(namespaceId);
@@ -322,10 +328,10 @@ CreateStatistics(CreateStatsStmt *stmt)
 	nulls[Anum_pg_statistic_ext_stxdependencies - 1] = true;
 
 	/* insert it into pg_statistic_ext */
-	statrel = heap_open(StatisticExtRelationId, RowExclusiveLock);
 	htup = heap_form_tuple(statrel->rd_att, values, nulls);
-	statoid = CatalogTupleInsert(statrel, htup);
+	CatalogTupleInsert(statrel, htup);
 	heap_freetuple(htup);
+
 	relation_close(statrel, RowExclusiveLock);
 
 	/*
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index f138e61a8d3..bc26a5149bb 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -20,6 +20,7 @@
 #include "access/htup_details.h"
 #include "access/xact.h"
 
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
@@ -379,6 +380,8 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 
+	subid = GetNewOidWithIndex(rel, SubscriptionObjectIndexId, Anum_pg_subscription_oid);
+	values[Anum_pg_subscription_oid - 1] = ObjectIdGetDatum(subid);
 	values[Anum_pg_subscription_subdbid - 1] = ObjectIdGetDatum(MyDatabaseId);
 	values[Anum_pg_subscription_subname - 1] =
 		DirectFunctionCall1(namein, CStringGetDatum(stmt->subname));
@@ -399,7 +402,7 @@ CreateSubscription(CreateSubscriptionStmt *stmt, bool isTopLevel)
 	tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
 
 	/* Insert tuple into catalog. */
-	subid = CatalogTupleInsert(rel, tup);
+	CatalogTupleInsert(rel, tup);
 	heap_freetuple(tup);
 
 	recordDependencyOnOwner(SubscriptionRelationId, subid, owner);
@@ -620,6 +623,7 @@ AlterSubscription(AlterSubscriptionStmt *stmt)
 	Oid			subid;
 	bool		update_tuple = false;
 	Subscription *sub;
+	Form_pg_subscription form;
 
 	rel = heap_open(SubscriptionRelationId, RowExclusiveLock);
 
@@ -633,12 +637,14 @@ AlterSubscription(AlterSubscriptionStmt *stmt)
 				 errmsg("subscription \"%s\" does not exist",
 						stmt->subname)));
 
+	form = (Form_pg_subscription) GETSTRUCT(tup);
+	subid = form->oid;
+
 	/* must be owner */
-	if (!pg_subscription_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+	if (!pg_subscription_ownercheck(subid, GetUserId()))
 		aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SUBSCRIPTION,
 					   stmt->subname);
 
-	subid = HeapTupleGetOid(tup);
 	sub = GetSubscription(subid, false);
 
 	/* Lock the subscription so nobody else can do anything with it. */
@@ -823,6 +829,7 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel)
 	RepOriginId originid;
 	WalReceiverConn *wrconn = NULL;
 	StringInfoData cmd;
+	Form_pg_subscription form;
 
 	/*
 	 * Lock pg_subscription with AccessExclusiveLock to ensure that the
@@ -850,7 +857,8 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel)
 		return;
 	}
 
-	subid = HeapTupleGetOid(tup);
+	form = (Form_pg_subscription) GETSTRUCT(tup);
+	subid = form->oid;
 
 	/* must be owner */
 	if (!pg_subscription_ownercheck(subid, GetUserId()))
@@ -1021,7 +1029,7 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
 	if (form->subowner == newOwnerId)
 		return;
 
-	if (!pg_subscription_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+	if (!pg_subscription_ownercheck(form->oid, GetUserId()))
 		aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_SUBSCRIPTION,
 					   NameStr(form->subname));
 
@@ -1038,11 +1046,11 @@ AlterSubscriptionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
 
 	/* Update owner dependency reference */
 	changeDependencyOnOwner(SubscriptionRelationId,
-							HeapTupleGetOid(tup),
+							form->oid,
 							newOwnerId);
 
 	InvokeObjectPostAlterHook(SubscriptionRelationId,
-							  HeapTupleGetOid(tup), 0);
+							  form->oid, 0);
 }
 
 /*
@@ -1055,6 +1063,7 @@ AlterSubscriptionOwner(const char *name, Oid newOwnerId)
 	HeapTuple	tup;
 	Relation	rel;
 	ObjectAddress address;
+	Form_pg_subscription form;
 
 	rel = heap_open(SubscriptionRelationId, RowExclusiveLock);
 
@@ -1066,7 +1075,8 @@ AlterSubscriptionOwner(const char *name, Oid newOwnerId)
 				(errcode(ERRCODE_UNDEFINED_OBJECT),
 				 errmsg("subscription \"%s\" does not exist", name)));
 
-	subid = HeapTupleGetOid(tup);
+	form = (Form_pg_subscription) GETSTRUCT(tup);
+	subid = form->oid;
 
 	AlterSubscriptionOwner_internal(rel, tup, newOwnerId);
 
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 29d8353779b..98e682c16b0 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -305,8 +305,7 @@ static void truncate_check_activity(Relation rel);
 static void RangeVarCallbackForTruncate(const RangeVar *relation,
 							Oid relId, Oid oldRelId, void *arg);
 static List *MergeAttributes(List *schema, List *supers, char relpersistence,
-				bool is_partition, List **supOids, List **supconstr,
-				int *supOidCount);
+				bool is_partition, List **supOids, List **supconstr);
 static bool MergeCheckConstraint(List *constraints, char *name, Node *expr);
 static void MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel);
 static void MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel);
@@ -363,15 +362,13 @@ static List *find_typed_table_dependencies(Oid typeOid, const char *typeName,
 static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
 				bool is_view, AlterTableCmd *cmd, LOCKMODE lockmode);
 static ObjectAddress ATExecAddColumn(List **wqueue, AlteredTableInfo *tab,
-				Relation rel, ColumnDef *colDef, bool isOid,
+				Relation rel, ColumnDef *colDef,
 				bool recurse, bool recursing,
 				bool if_not_exists, LOCKMODE lockmode);
 static bool check_for_column_name_collision(Relation rel, const char *colname,
 								bool if_not_exists);
 static void add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid);
 static void add_column_collation_dependency(Oid relid, int32 attnum, Oid collid);
-static void ATPrepAddOids(List **wqueue, Relation rel, bool recurse,
-			  AlterTableCmd *cmd, LOCKMODE lockmode);
 static void ATPrepDropNotNull(Relation rel, bool recurse, bool recursing);
 static ObjectAddress ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode);
 static void ATPrepSetNotNull(Relation rel, bool recurse, bool recursing);
@@ -530,8 +527,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 	TupleDesc	descriptor;
 	List	   *inheritOids;
 	List	   *old_constraints;
-	bool		localHasOids;
-	int			parentOidCount;
 	List	   *rawDefaults;
 	List	   *cookedDefaults;
 	Datum		reloptions;
@@ -653,7 +648,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 		MergeAttributes(stmt->tableElts, stmt->inhRelations,
 						stmt->relation->relpersistence,
 						stmt->partbound != NULL,
-						&inheritOids, &old_constraints, &parentOidCount);
+						&inheritOids, &old_constraints);
 
 	/*
 	 * Create a tuple descriptor from the relation schema.  Note that this
@@ -662,29 +657,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 	 */
 	descriptor = BuildDescForRelation(stmt->tableElts);
 
-	/*
-	 * Notice that we allow OIDs here only for plain tables and partitioned
-	 * tables, even though some other relkinds can support them.  This is
-	 * necessary because the default_with_oids GUC must apply only to plain
-	 * tables and not any other relkind; doing otherwise would break existing
-	 * pg_dump files.  We could allow explicit "WITH OIDS" while not allowing
-	 * default_with_oids to affect other relkinds, but it would complicate
-	 * interpretOidsOption().
-	 */
-	localHasOids = interpretOidsOption(stmt->options,
-									   (relkind == RELKIND_RELATION ||
-										relkind == RELKIND_PARTITIONED_TABLE));
-	descriptor->tdhasoid = (localHasOids || parentOidCount > 0);
-
-	/*
-	 * If a partitioned table doesn't have the system OID column, then none of
-	 * its partitions should have it.
-	 */
-	if (stmt->partbound && parentOidCount == 0 && localHasOids)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot create table with OIDs as partition of table without OIDs")));
-
 	/*
 	 * Find columns with default values and prepare for insertion of the
 	 * defaults.  Pre-cooked (that is, inherited) defaults go into a list of
@@ -763,8 +735,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 										  stmt->relation->relpersistence,
 										  false,
 										  false,
-										  localHasOids,
-										  parentOidCount,
 										  stmt->oncommit,
 										  reloptions,
 										  true,
@@ -1815,7 +1785,6 @@ storage_name(char c)
  * 'supOids' receives a list of the OIDs of the parent relations.
  * 'supconstr' receives a list of constraints belonging to the parents,
  *		updated as necessary to be valid for the child.
- * 'supOidCount' is set to the number of parents that have OID columns.
  *
  * Return value:
  * Completed schema list.
@@ -1861,14 +1830,12 @@ storage_name(char c)
  */
 static List *
 MergeAttributes(List *schema, List *supers, char relpersistence,
-				bool is_partition, List **supOids, List **supconstr,
-				int *supOidCount)
+				bool is_partition, List **supOids, List **supconstr)
 {
 	ListCell   *entry;
 	List	   *inhSchema = NIL;
 	List	   *parentOids = NIL;
 	List	   *constraints = NIL;
-	int			parentsWithOids = 0;
 	bool		have_bogus_defaults = false;
 	int			child_attno;
 	static Node bogus_marker = {0}; /* marks conflicting defaults */
@@ -2066,9 +2033,6 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
 
 		parentOids = lappend_oid(parentOids, RelationGetRelid(relation));
 
-		if (relation->rd_rel->relhasoids)
-			parentsWithOids++;
-
 		tupleDesc = RelationGetDescr(relation);
 		constr = tupleDesc->constr;
 
@@ -2496,7 +2460,6 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
 
 	*supOids = parentOids;
 	*supconstr = constraints;
-	*supOidCount = parentsWithOids;
 	return schema;
 }
 
@@ -3415,7 +3378,6 @@ AlterTableGetLockLevel(List *cmds)
 								 * to SELECT */
 			case AT_SetTableSpace:	/* must rewrite heap */
 			case AT_AlterColumnType:	/* must rewrite heap */
-			case AT_AddOids:	/* must rewrite heap */
 				cmd_lockmode = AccessExclusiveLock;
 				break;
 
@@ -3444,7 +3406,6 @@ AlterTableGetLockLevel(List *cmds)
 				 */
 			case AT_DropColumn: /* change visible to SELECT */
 			case AT_AddColumnToView:	/* CREATE VIEW */
-			case AT_DropOids:	/* calls AT_DropColumn */
 			case AT_EnableAlwaysRule:	/* may change SELECT rules */
 			case AT_EnableReplicaRule:	/* may change SELECT rules */
 			case AT_EnableRule: /* may change SELECT rules */
@@ -3853,27 +3814,6 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
 			}
 			pass = AT_PASS_MISC;
 			break;
-		case AT_AddOids:		/* SET WITH OIDS */
-			ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
-			if (!rel->rd_rel->relhasoids || recursing)
-				ATPrepAddOids(wqueue, rel, recurse, cmd, lockmode);
-			/* Recursion occurs during execution phase */
-			pass = AT_PASS_ADD_COL;
-			break;
-		case AT_DropOids:		/* SET WITHOUT OIDS */
-			ATSimplePermissions(rel, ATT_TABLE | ATT_FOREIGN_TABLE);
-			/* Performs own recursion */
-			if (rel->rd_rel->relhasoids)
-			{
-				AlterTableCmd *dropCmd = makeNode(AlterTableCmd);
-
-				dropCmd->subtype = AT_DropColumn;
-				dropCmd->name = pstrdup("oid");
-				dropCmd->behavior = cmd->behavior;
-				ATPrepCmd(wqueue, rel, dropCmd, recurse, false, lockmode);
-			}
-			pass = AT_PASS_DROP;
-			break;
 		case AT_SetTableSpace:	/* SET TABLESPACE */
 			ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_INDEX);
 			/* This command never recurses */
@@ -4058,12 +3998,12 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
 		case AT_AddColumn:		/* ADD COLUMN */
 		case AT_AddColumnToView:	/* add column via CREATE OR REPLACE VIEW */
 			address = ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
-									  false, false, false,
+									  false, false,
 									  false, lockmode);
 			break;
 		case AT_AddColumnRecurse:
 			address = ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
-									  false, true, false,
+									  true, false,
 									  cmd->missing_ok, lockmode);
 			break;
 		case AT_ColumnDefault:	/* ALTER COLUMN DEFAULT */
@@ -4187,29 +4127,6 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
 		case AT_SetLogged:		/* SET LOGGED */
 		case AT_SetUnLogged:	/* SET UNLOGGED */
 			break;
-		case AT_AddOids:		/* SET WITH OIDS */
-			/* Use the ADD COLUMN code, unless prep decided to do nothing */
-			if (cmd->def != NULL)
-				address =
-					ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
-									true, false, false,
-									cmd->missing_ok, lockmode);
-			break;
-		case AT_AddOidsRecurse: /* SET WITH OIDS */
-			/* Use the ADD COLUMN code, unless prep decided to do nothing */
-			if (cmd->def != NULL)
-				address =
-					ATExecAddColumn(wqueue, tab, rel, (ColumnDef *) cmd->def,
-									true, true, false,
-									cmd->missing_ok, lockmode);
-			break;
-		case AT_DropOids:		/* SET WITHOUT OIDS */
-
-			/*
-			 * Nothing to do here; we'll have generated a DropColumn
-			 * subcommand to do the real work
-			 */
-			break;
 		case AT_SetTableSpace:	/* SET TABLESPACE */
 
 			/*
@@ -4761,12 +4678,8 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
 		{
 			if (tab->rewrite > 0)
 			{
-				Oid			tupOid = InvalidOid;
-
 				/* Extract data from old tuple */
 				heap_deform_tuple(tuple, oldTupDesc, values, isnull);
-				if (oldTupDesc->tdhasoid)
-					tupOid = HeapTupleGetOid(tuple);
 
 				/* Set dropped attributes to null in new tuple */
 				foreach(lc, dropped_attrs)
@@ -4794,10 +4707,6 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
 				 */
 				tuple = heap_form_tuple(newTupDesc, values, isnull);
 
-				/* Preserve OID, if any */
-				if (newTupDesc->tdhasoid)
-					HeapTupleSetOid(tuple, tupOid);
-
 				/*
 				 * Constraints might reference the tableoid column, so
 				 * initialize t_tableOid before evaluating them.
@@ -5280,6 +5189,8 @@ find_typed_table_dependencies(Oid typeOid, const char *typeName, DropBehavior be
 
 	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
+		Form_pg_class classform = (Form_pg_class) GETSTRUCT(tuple);
+
 		if (behavior == DROP_RESTRICT)
 			ereport(ERROR,
 					(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
@@ -5287,7 +5198,7 @@ find_typed_table_dependencies(Oid typeOid, const char *typeName, DropBehavior be
 							typeName),
 					 errhint("Use ALTER ... CASCADE to alter the typed tables too.")));
 		else
-			result = lappend_oid(result, HeapTupleGetOid(tuple));
+			result = lappend_oid(result, classform->oid);
 	}
 
 	heap_endscan(scan);
@@ -5332,7 +5243,7 @@ check_of_type(HeapTuple typetuple)
 		ereport(ERROR,
 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 				 errmsg("type %s is not a composite type",
-						format_type_be(HeapTupleGetOid(typetuple)))));
+						format_type_be(typ->oid))));
 }
 
 
@@ -5372,7 +5283,7 @@ ATPrepAddColumn(List **wqueue, Relation rel, bool recurse, bool recursing,
  */
 static ObjectAddress
 ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
-				ColumnDef *colDef, bool isOid,
+				ColumnDef *colDef,
 				bool recurse, bool recursing,
 				bool if_not_exists, LOCKMODE lockmode)
 {
@@ -5442,13 +5353,6 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 								   get_collation_name(ccollid),
 								   get_collation_name(childatt->attcollation))));
 
-			/* If it's OID, child column must actually be OID */
-			if (isOid && childatt->attnum != ObjectIdAttributeNumber)
-				ereport(ERROR,
-						(errcode(ERRCODE_DATATYPE_MISMATCH),
-						 errmsg("child table \"%s\" has a conflicting \"%s\" column",
-								RelationGetRelationName(rel), colDef->colname)));
-
 			/* Bump the existing child att's inhcount */
 			childatt->attinhcount++;
 			CatalogTupleUpdate(attrdesc, &tuple->t_self, tuple);
@@ -5493,21 +5397,16 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	}
 
 	/* Determine the new attribute's number */
-	if (isOid)
-		newattnum = ObjectIdAttributeNumber;
-	else
-	{
-		newattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts + 1;
-		if (newattnum > MaxHeapAttributeNumber)
-			ereport(ERROR,
-					(errcode(ERRCODE_TOO_MANY_COLUMNS),
-					 errmsg("tables can have at most %d columns",
-							MaxHeapAttributeNumber)));
-	}
+	newattnum = ((Form_pg_class) GETSTRUCT(reltup))->relnatts + 1;
+	if (newattnum > MaxHeapAttributeNumber)
+		ereport(ERROR,
+				(errcode(ERRCODE_TOO_MANY_COLUMNS),
+				 errmsg("tables can have at most %d columns",
+						MaxHeapAttributeNumber)));
 
 	typeTuple = typenameType(NULL, colDef->typeName, &typmod);
 	tform = (Form_pg_type) GETSTRUCT(typeTuple);
-	typeOid = HeapTupleGetOid(typeTuple);
+	typeOid = tform->oid;
 
 	aclresult = pg_type_aclcheck(typeOid, GetUserId(), ACL_USAGE);
 	if (aclresult != ACLCHECK_OK)
@@ -5551,10 +5450,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 	/*
 	 * Update pg_class tuple as appropriate
 	 */
-	if (isOid)
-		((Form_pg_class) GETSTRUCT(reltup))->relhasoids = true;
-	else
-		((Form_pg_class) GETSTRUCT(reltup))->relnatts = newattnum;
+	((Form_pg_class) GETSTRUCT(reltup))->relnatts = newattnum;
 
 	CatalogTupleUpdate(pgclass, &reltup->t_self, reltup);
 
@@ -5702,13 +5598,6 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 		}
 	}
 
-	/*
-	 * If we are adding an OID column, we have to tell Phase 3 to rewrite the
-	 * table to fix that.
-	 */
-	if (isOid)
-		tab->rewrite |= AT_REWRITE_ALTER_OID;
-
 	/*
 	 * Add needed dependency entries for the new column.
 	 */
@@ -5754,7 +5643,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 
 		/* Recurse to child; return value is ignored */
 		ATExecAddColumn(wqueue, childtab, childrel,
-						colDef, isOid, recurse, true,
+						colDef, recurse, true,
 						if_not_exists, lockmode);
 
 		heap_close(childrel, NoLock);
@@ -5858,35 +5747,6 @@ add_column_collation_dependency(Oid relid, int32 attnum, Oid collid)
 	}
 }
 
-/*
- * ALTER TABLE SET WITH OIDS
- *
- * Basically this is an ADD COLUMN for the special OID column.  We have
- * to cons up a ColumnDef node because the ADD COLUMN code needs one.
- */
-static void
-ATPrepAddOids(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd, LOCKMODE lockmode)
-{
-	/* If we're recursing to a child table, the ColumnDef is already set up */
-	if (cmd->def == NULL)
-	{
-		ColumnDef  *cdef = makeNode(ColumnDef);
-
-		cdef->colname = pstrdup("oid");
-		cdef->typeName = makeTypeNameFromOid(OIDOID, -1);
-		cdef->inhcount = 0;
-		cdef->is_local = true;
-		cdef->is_not_null = true;
-		cdef->storage = 0;
-		cdef->location = -1;
-		cmd->def = (Node *) cdef;
-	}
-	ATPrepAddColumn(wqueue, rel, recurse, false, false, cmd, lockmode);
-
-	if (recurse)
-		cmd->subtype = AT_AddOidsRecurse;
-}
-
 /*
  * ALTER TABLE ALTER COLUMN DROP NOT NULL
  *
@@ -6787,8 +6647,8 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
 
 	attnum = targetatt->attnum;
 
-	/* Can't drop a system attribute, except OID */
-	if (attnum <= 0 && attnum != ObjectIdAttributeNumber)
+	/* Can't drop a system attribute */
+	if (attnum <= 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 				 errmsg("cannot drop system column \"%s\"",
@@ -6918,39 +6778,6 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
 
 	performDeletion(&object, behavior, 0);
 
-	/*
-	 * If we dropped the OID column, must adjust pg_class.relhasoids and tell
-	 * Phase 3 to physically get rid of the column.  We formerly left the
-	 * column in place physically, but this caused subtle problems.  See
-	 * http://archives.postgresql.org/pgsql-hackers/2009-02/msg00363.php
-	 */
-	if (attnum == ObjectIdAttributeNumber)
-	{
-		Relation	class_rel;
-		Form_pg_class tuple_class;
-		AlteredTableInfo *tab;
-
-		class_rel = heap_open(RelationRelationId, RowExclusiveLock);
-
-		tuple = SearchSysCacheCopy1(RELOID,
-									ObjectIdGetDatum(RelationGetRelid(rel)));
-		if (!HeapTupleIsValid(tuple))
-			elog(ERROR, "cache lookup failed for relation %u",
-				 RelationGetRelid(rel));
-		tuple_class = (Form_pg_class) GETSTRUCT(tuple);
-
-		tuple_class->relhasoids = false;
-		CatalogTupleUpdate(class_rel, &tuple->t_self, tuple);
-
-		heap_close(class_rel, RowExclusiveLock);
-
-		/* Find or create work queue entry for this table */
-		tab = ATGetQueueEntry(wqueue, rel);
-
-		/* Tell Phase 3 to physically remove the OID column */
-		tab->rewrite |= AT_REWRITE_ALTER_OID;
-	}
-
 	return object;
 }
 
@@ -7863,7 +7690,7 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
 		CatalogTupleUpdate(conrel, &copyTuple->t_self, copyTuple);
 
 		InvokeObjectPostAlterHook(ConstraintRelationId,
-								  HeapTupleGetOid(contuple), 0);
+								  currcon->oid, 0);
 
 		heap_freetuple(copyTuple);
 
@@ -7876,7 +7703,7 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
 		ScanKeyInit(&tgkey,
 					Anum_pg_trigger_tgconstraint,
 					BTEqualStrategyNumber, F_OIDEQ,
-					ObjectIdGetDatum(HeapTupleGetOid(contuple)));
+					ObjectIdGetDatum(currcon->oid));
 
 		tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
 									NULL, 1, &tgkey);
@@ -7915,8 +7742,7 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
 			copy_tg->tginitdeferred = cmdcon->initdeferred;
 			CatalogTupleUpdate(tgrel, &copyTuple->t_self, copyTuple);
 
-			InvokeObjectPostAlterHook(TriggerRelationId,
-									  HeapTupleGetOid(tgtuple), 0);
+			InvokeObjectPostAlterHook(TriggerRelationId, currcon->oid, 0);
 
 			heap_freetuple(copyTuple);
 		}
@@ -7937,8 +7763,7 @@ ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
 			CacheInvalidateRelcacheByRelid(lfirst_oid(lc));
 		}
 
-		ObjectAddressSet(address, ConstraintRelationId,
-						 HeapTupleGetOid(contuple));
+		ObjectAddressSet(address, ConstraintRelationId, currcon->oid);
 	}
 	else
 		address = InvalidObjectAddress;
@@ -8028,7 +7853,7 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
 
 			validateForeignKeyConstraint(constrName, rel, refrel,
 										 con->conindid,
-										 HeapTupleGetOid(tuple));
+										 con->oid);
 			heap_close(refrel, NoLock);
 
 			/*
@@ -8101,13 +7926,11 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
 		copy_con->convalidated = true;
 		CatalogTupleUpdate(conrel, &copyTuple->t_self, copyTuple);
 
-		InvokeObjectPostAlterHook(ConstraintRelationId,
-								  HeapTupleGetOid(tuple), 0);
+		InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0);
 
 		heap_freetuple(copyTuple);
 
-		ObjectAddressSet(address, ConstraintRelationId,
-						 HeapTupleGetOid(tuple));
+		ObjectAddressSet(address, ConstraintRelationId, con->oid);
 	}
 	else
 		address = InvalidObjectAddress; /* already validated */
@@ -8505,7 +8328,7 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup)
 						  &isnull);
 	if (isnull)
 		elog(ERROR, "null conbin for constraint %u",
-			 HeapTupleGetOid(constrtup));
+			 constrForm->oid);
 	conbin = TextDatumGetCString(val);
 	origexpr = (Expr *) stringToNode(conbin);
 	exprstate = ExecPrepareExpr(origexpr, estate);
@@ -8929,7 +8752,7 @@ ATExecDropConstraint(Relation rel, const char *constrName,
 		 * Perform the actual constraint deletion
 		 */
 		conobj.classId = ConstraintRelationId;
-		conobj.objectId = HeapTupleGetOid(tuple);
+		conobj.objectId = con->oid;
 		conobj.objectSubId = 0;
 
 		performDeletion(&conobj, behavior, 0);
@@ -9404,7 +9227,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
 	/* Look up the target type (should not fail, since prep found it) */
 	typeTuple = typenameType(NULL, typeName, &targettypmod);
 	tform = (Form_pg_type) GETSTRUCT(typeTuple);
-	targettype = HeapTupleGetOid(typeTuple);
+	targettype = tform->oid;
 	/* And the collation */
 	targetcollid = GetColumnDefCollation(NULL, def, targettype);
 
@@ -11155,10 +10978,8 @@ AlterTableMoveAll(AlterTableMoveAllStmt *stmt)
 	scan = heap_beginscan_catalog(rel, 1, key);
 	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
-		Oid			relOid = HeapTupleGetOid(tuple);
-		Form_pg_class relForm;
-
-		relForm = (Form_pg_class) GETSTRUCT(tuple);
+		Form_pg_class relForm = (Form_pg_class) GETSTRUCT(tuple);
+		Oid			relOid = relForm->oid;
 
 		/*
 		 * Do not move objects in pg_catalog as part of this, if an admin
@@ -11462,14 +11283,6 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
 						   parent->relname,
 						   RelationGetRelationName(child_rel))));
 
-	/* If parent has OIDs then child must have OIDs */
-	if (parent_rel->rd_rel->relhasoids && !child_rel->rd_rel->relhasoids)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("table \"%s\" without OIDs cannot inherit from table \"%s\" with OIDs",
-						RelationGetRelationName(child_rel),
-						RelationGetRelationName(parent_rel))));
-
 	/*
 	 * If child_rel has row-level triggers with transition tables, we
 	 * currently don't allow it to become an inheritance child.  See also
@@ -11582,7 +11395,7 @@ decompile_conbin(HeapTuple contup, TupleDesc tupdesc)
 	con = (Form_pg_constraint) GETSTRUCT(contup);
 	attr = heap_getattr(contup, Anum_pg_constraint_conbin, tupdesc, &isnull);
 	if (isnull)
-		elog(ERROR, "null conbin for constraint %u", HeapTupleGetOid(contup));
+		elog(ERROR, "null conbin for constraint %u", con->oid);
 
 	expr = DirectFunctionCall2(pg_get_expr, attr,
 							   ObjectIdGetDatum(con->conrelid));
@@ -11716,45 +11529,6 @@ MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel)
 		}
 	}
 
-	/*
-	 * If the parent has an OID column, so must the child, and we'd better
-	 * update the child's attinhcount and attislocal the same as for normal
-	 * columns.  We needn't check data type or not-nullness though.
-	 */
-	if (tupleDesc->tdhasoid)
-	{
-		/*
-		 * Here we match by column number not name; the match *must* be the
-		 * system column, not some random column named "oid".
-		 */
-		tuple = SearchSysCacheCopy2(ATTNUM,
-									ObjectIdGetDatum(RelationGetRelid(child_rel)),
-									Int16GetDatum(ObjectIdAttributeNumber));
-		if (HeapTupleIsValid(tuple))
-		{
-			Form_pg_attribute childatt = (Form_pg_attribute) GETSTRUCT(tuple);
-
-			/* See comments above; these changes should be the same */
-			childatt->attinhcount++;
-
-			if (child_is_partition)
-			{
-				Assert(childatt->attinhcount == 1);
-				childatt->attislocal = false;
-			}
-
-			CatalogTupleUpdate(attrrel, &tuple->t_self, tuple);
-			heap_freetuple(tuple);
-		}
-		else
-		{
-			ereport(ERROR,
-					(errcode(ERRCODE_DATATYPE_MISMATCH),
-					 errmsg("child table is missing column \"%s\"",
-							"oid")));
-		}
-	}
-
 	heap_close(attrrel, RowExclusiveLock);
 }
 
@@ -12184,6 +11958,7 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode)
 {
 	Oid			relid = RelationGetRelid(rel);
 	Type		typetuple;
+	Form_pg_type typeform;
 	Oid			typeid;
 	Relation	inheritsRelation,
 				relationRelation;
@@ -12200,7 +11975,8 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode)
 	/* Validate the type. */
 	typetuple = typenameType(NULL, ofTypename, NULL);
 	check_of_type(typetuple);
-	typeid = HeapTupleGetOid(typetuple);
+	typeform = (Form_pg_type) GETSTRUCT(typetuple);
+	typeid = typeform->oid;
 
 	/* Fail if the table has any inheritance parents. */
 	inheritsRelation = heap_open(InheritsRelationId, AccessShareLock);
@@ -12220,7 +11996,6 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode)
 	/*
 	 * Check the tuple descriptors for compatibility.  Unlike inheritance, we
 	 * require that the order also match.  However, attnotnull need not match.
-	 * Also unlike inheritance, we do not require matching relhasoids.
 	 */
 	typeTupleDesc = lookup_rowtype_tupdesc(typeid, -1);
 	tableTupleDesc = RelationGetDescr(rel);
@@ -12545,10 +12320,6 @@ ATExecReplicaIdentity(Relation rel, ReplicaIdentityStmt *stmt, LOCKMODE lockmode
 		int16		attno = indexRel->rd_index->indkey.values[key];
 		Form_pg_attribute attr;
 
-		/* Allow OID column to be indexed; it's certainly not nullable */
-		if (attno == ObjectIdAttributeNumber)
-			continue;
-
 		/*
 		 * Reject any other system columns.  (Going forward, we'll disallow
 		 * indexes containing such columns in the first place, but they might
@@ -14183,22 +13954,6 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd)
 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 				 errmsg("cannot attach temporary relation of another session as partition")));
 
-	/* If parent has OIDs then child must have OIDs */
-	if (rel->rd_rel->relhasoids && !attachrel->rd_rel->relhasoids)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot attach table \"%s\" without OIDs as partition of"
-						" table \"%s\" with OIDs", RelationGetRelationName(attachrel),
-						RelationGetRelationName(rel))));
-
-	/* OTOH, if parent doesn't have them, do not allow in attachrel either */
-	if (attachrel->rd_rel->relhasoids && !rel->rd_rel->relhasoids)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("cannot attach table \"%s\" with OIDs as partition of table"
-						" \"%s\" without OIDs", RelationGetRelationName(attachrel),
-						RelationGetRelationName(rel))));
-
 	/* Check if there are any columns in attachrel that aren't in the parent */
 	tupleDesc = RelationGetDescr(attachrel);
 	natts = tupleDesc->natts;
@@ -14619,7 +14374,7 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
 
 		CreateTrigger(trigStmt, NULL, RelationGetRelid(partition),
 					  trigForm->tgconstrrelid, InvalidOid, InvalidOid,
-					  trigForm->tgfoid, HeapTupleGetOid(tuple), qual,
+					  trigForm->tgfoid, trigForm->oid, qual,
 					  false, true);
 
 		MemoryContextReset(perTupCxt);
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index f7e9160a4f6..bc37112f51e 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -327,6 +327,8 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
 
 	MemSet(nulls, false, sizeof(nulls));
 
+	tablespaceoid = GetNewOidWithIndex(rel, TablespaceOidIndexId, Anum_pg_tablespace_oid);
+	values[Anum_pg_tablespace_oid - 1] = ObjectIdGetDatum(tablespaceoid);
 	values[Anum_pg_tablespace_spcname - 1] =
 		DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename));
 	values[Anum_pg_tablespace_spcowner - 1] =
@@ -345,7 +347,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
 
 	tuple = heap_form_tuple(rel->rd_att, values, nulls);
 
-	tablespaceoid = CatalogTupleInsert(rel, tuple);
+	CatalogTupleInsert(rel, tuple);
 
 	heap_freetuple(tuple);
 
@@ -406,6 +408,7 @@ DropTableSpace(DropTableSpaceStmt *stmt)
 	HeapScanDesc scandesc;
 	Relation	rel;
 	HeapTuple	tuple;
+	Form_pg_tablespace spcform;
 	ScanKeyData entry[1];
 	Oid			tablespaceoid;
 
@@ -442,7 +445,8 @@ DropTableSpace(DropTableSpaceStmt *stmt)
 		return;
 	}
 
-	tablespaceoid = HeapTupleGetOid(tuple);
+	spcform = (Form_pg_tablespace) GETSTRUCT(tuple);
+	tablespaceoid = spcform->oid;
 
 	/* Must be tablespace owner */
 	if (!pg_tablespace_ownercheck(tablespaceoid, GetUserId()))
@@ -935,14 +939,14 @@ RenameTableSpace(const char *oldname, const char *newname)
 				 errmsg("tablespace \"%s\" does not exist",
 						oldname)));
 
-	tspId = HeapTupleGetOid(tup);
 	newtuple = heap_copytuple(tup);
 	newform = (Form_pg_tablespace) GETSTRUCT(newtuple);
+	tspId = newform->oid;
 
 	heap_endscan(scan);
 
 	/* Must be owner */
-	if (!pg_tablespace_ownercheck(HeapTupleGetOid(newtuple), GetUserId()))
+	if (!pg_tablespace_ownercheck(tspId, GetUserId()))
 		aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_TABLESPACE, oldname);
 
 	/* Validate new name */
@@ -1015,10 +1019,10 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)
 				 errmsg("tablespace \"%s\" does not exist",
 						stmt->tablespacename)));
 
-	tablespaceoid = HeapTupleGetOid(tup);
+	tablespaceoid = ((Form_pg_tablespace) GETSTRUCT(tup))->oid;
 
 	/* Must be owner of the existing object */
-	if (!pg_tablespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+	if (!pg_tablespace_ownercheck(tablespaceoid, GetUserId()))
 		aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLESPACE,
 					   stmt->tablespacename);
 
@@ -1044,7 +1048,7 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)
 	/* Update system catalog. */
 	CatalogTupleUpdate(rel, &newtuple->t_self, newtuple);
 
-	InvokeObjectPostAlterHook(TableSpaceRelationId, HeapTupleGetOid(tup), 0);
+	InvokeObjectPostAlterHook(TableSpaceRelationId, tablespaceoid, 0);
 
 	heap_freetuple(newtuple);
 
@@ -1403,7 +1407,7 @@ get_tablespace_oid(const char *tablespacename, bool missing_ok)
 
 	/* We assume that there can be at most one matching tuple */
 	if (HeapTupleIsValid(tuple))
-		result = HeapTupleGetOid(tuple);
+		result = ((Form_pg_tablespace) GETSTRUCT(tuple))->oid;
 	else
 		result = InvalidOid;
 
@@ -1441,7 +1445,7 @@ get_tablespace_name(Oid spc_oid)
 	rel = heap_open(TableSpaceRelationId, AccessShareLock);
 
 	ScanKeyInit(&entry[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_tablespace_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(spc_oid));
 	scandesc = heap_beginscan_catalog(rel, 1, entry);
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 36778b6f4d5..90dcd553d72 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -823,6 +823,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 	 */
 	memset(nulls, false, sizeof(nulls));
 
+	values[Anum_pg_trigger_oid - 1] = ObjectIdGetDatum(trigoid);
 	values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
 	values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein,
 															 CStringGetDatum(trigname));
@@ -939,9 +940,6 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 
 	tuple = heap_form_tuple(tgrel->rd_att, values, nulls);
 
-	/* force tuple to have the desired OID */
-	HeapTupleSetOid(tuple, trigoid);
-
 	/*
 	 * Insert tuple into pg_trigger.
 	 */
@@ -1493,7 +1491,7 @@ RemoveTriggerById(Oid trigOid)
 	 * Find the trigger to delete.
 	 */
 	ScanKeyInit(&skey[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_trigger_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(trigOid));
 
@@ -1594,7 +1592,7 @@ get_trigger_oid(Oid relid, const char *trigname, bool missing_ok)
 	}
 	else
 	{
-		oid = HeapTupleGetOid(tup);
+		oid = ((Form_pg_trigger) GETSTRUCT(tup))->oid;
 	}
 
 	systable_endscan(tgscan);
@@ -1721,20 +1719,22 @@ renametrig(RenameStmt *stmt)
 								NULL, 2, key);
 	if (HeapTupleIsValid(tuple = systable_getnext(tgscan)))
 	{
-		tgoid = HeapTupleGetOid(tuple);
+		Form_pg_trigger trigform = (Form_pg_trigger) GETSTRUCT(tuple);
+
+		tgoid = trigform->oid;
 
 		/*
 		 * Update pg_trigger tuple with new tgname.
 		 */
 		tuple = heap_copytuple(tuple);	/* need a modifiable copy */
 
-		namestrcpy(&((Form_pg_trigger) GETSTRUCT(tuple))->tgname,
+		namestrcpy(&trigform->tgname,
 				   stmt->newname);
 
 		CatalogTupleUpdate(tgrel, &tuple->t_self, tuple);
 
 		InvokeObjectPostAlterHook(TriggerRelationId,
-								  HeapTupleGetOid(tuple), 0);
+								  tgoid, 0);
 
 		/*
 		 * Invalidate relation's relcache entry so that other backends (and
@@ -1873,7 +1873,7 @@ EnableDisableTrigger(Relation rel, const char *tgname,
 		}
 
 		InvokeObjectPostAlterHook(TriggerRelationId,
-								  HeapTupleGetOid(tuple), 0);
+								  oldtrig->oid, 0);
 	}
 
 	systable_endscan(tgscan);
@@ -1957,7 +1957,7 @@ RelationBuildTriggers(Relation relation)
 		}
 		build = &(triggers[numtrigs]);
 
-		build->tgoid = HeapTupleGetOid(htup);
+		build->tgoid = pg_trigger->oid;
 		build->tgname = DatumGetCString(DirectFunctionCall1(nameout,
 															NameGetDatum(&pg_trigger->tgname)));
 		build->tgfoid = pg_trigger->tgfoid;
@@ -5444,8 +5444,7 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt)
 					Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tup);
 
 					if (con->condeferrable)
-						conoidlist = lappend_oid(conoidlist,
-												 HeapTupleGetOid(tup));
+						conoidlist = lappend_oid(conoidlist, con->oid);
 					else if (stmt->deferred)
 						ereport(ERROR,
 								(errcode(ERRCODE_WRONG_OBJECT_TYPE),
@@ -5497,7 +5496,11 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt)
 			scan = systable_beginscan(conrel, ConstraintParentIndexId, true, NULL, 1, &key);
 
 			while (HeapTupleIsValid(tuple = systable_getnext(scan)))
-				conoidlist = lappend_oid(conoidlist, HeapTupleGetOid(tuple));
+			{
+				Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
+
+				conoidlist = lappend_oid(conoidlist, con->oid);
+			}
 
 			systable_endscan(scan);
 		}
@@ -5539,8 +5542,7 @@ AfterTriggerSetState(ConstraintsSetStmt *stmt)
 				 * actions.
 				 */
 				if (pg_trigger->tgdeferrable)
-					tgoidlist = lappend_oid(tgoidlist,
-											HeapTupleGetOid(htup));
+					tgoidlist = lappend_oid(tgoidlist, pg_trigger->oid);
 
 				found = true;
 			}
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 3a843512d13..1403d9ac2e3 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -21,6 +21,7 @@
 #include "access/heapam.h"
 #include "access/htup_details.h"
 #include "access/xact.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/objectaccess.h"
@@ -132,7 +133,7 @@ makeParserDependencies(HeapTuple tuple)
 				referenced;
 
 	myself.classId = TSParserRelationId;
-	myself.objectId = HeapTupleGetOid(tuple);
+	myself.objectId = prs->oid;
 	myself.objectSubId = 0;
 
 	/* dependency on namespace */
@@ -191,6 +192,8 @@ DefineTSParser(List *names, List *parameters)
 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 				 errmsg("must be superuser to create text search parsers")));
 
+	prsRel = heap_open(TSParserRelationId, RowExclusiveLock);
+
 	/* Convert list of names to a name and namespace */
 	namespaceoid = QualifiedNameGetCreationNamespace(names, &prsname);
 
@@ -198,6 +201,8 @@ DefineTSParser(List *names, List *parameters)
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 
+	prsOid = GetNewOidWithIndex(prsRel, TSParserOidIndexId, Anum_pg_ts_parser_oid);
+	values[Anum_pg_ts_parser_oid - 1] = ObjectIdGetDatum(prsOid);
 	namestrcpy(&pname, prsname);
 	values[Anum_pg_ts_parser_prsname - 1] = NameGetDatum(&pname);
 	values[Anum_pg_ts_parser_prsnamespace - 1] = ObjectIdGetDatum(namespaceoid);
@@ -267,11 +272,9 @@ DefineTSParser(List *names, List *parameters)
 	/*
 	 * Looks good, insert
 	 */
-	prsRel = heap_open(TSParserRelationId, RowExclusiveLock);
-
 	tup = heap_form_tuple(prsRel->rd_att, values, nulls);
 
-	prsOid = CatalogTupleInsert(prsRel, tup);
+	CatalogTupleInsert(prsRel, tup);
 
 	address = makeParserDependencies(tup);
 
@@ -323,7 +326,7 @@ makeDictionaryDependencies(HeapTuple tuple)
 				referenced;
 
 	myself.classId = TSDictionaryRelationId;
-	myself.objectId = HeapTupleGetOid(tuple);
+	myself.objectId = dict->oid;
 	myself.objectSubId = 0;
 
 	/* dependency on namespace */
@@ -459,12 +462,17 @@ DefineTSDictionary(List *names, List *parameters)
 
 	verify_dictoptions(templId, dictoptions);
 
+
+	dictRel = heap_open(TSDictionaryRelationId, RowExclusiveLock);
+
 	/*
 	 * Looks good, insert
 	 */
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 
+	dictOid = GetNewOidWithIndex(dictRel, TSDictionaryOidIndexId, Anum_pg_ts_dict_oid);
+	values[Anum_pg_ts_dict_oid - 1] = ObjectIdGetDatum(dictOid);
 	namestrcpy(&dname, dictname);
 	values[Anum_pg_ts_dict_dictname - 1] = NameGetDatum(&dname);
 	values[Anum_pg_ts_dict_dictnamespace - 1] = ObjectIdGetDatum(namespaceoid);
@@ -476,11 +484,9 @@ DefineTSDictionary(List *names, List *parameters)
 	else
 		nulls[Anum_pg_ts_dict_dictinitoption - 1] = true;
 
-	dictRel = heap_open(TSDictionaryRelationId, RowExclusiveLock);
-
 	tup = heap_form_tuple(dictRel->rd_att, values, nulls);
 
-	dictOid = CatalogTupleInsert(dictRel, tup);
+	CatalogTupleInsert(dictRel, tup);
 
 	address = makeDictionaryDependencies(tup);
 
@@ -694,7 +700,7 @@ makeTSTemplateDependencies(HeapTuple tuple)
 				referenced;
 
 	myself.classId = TSTemplateRelationId;
-	myself.objectId = HeapTupleGetOid(tuple);
+	myself.objectId = tmpl->oid;
 	myself.objectSubId = 0;
 
 	/* dependency on namespace */
@@ -748,12 +754,16 @@ DefineTSTemplate(List *names, List *parameters)
 	/* Convert list of names to a name and namespace */
 	namespaceoid = QualifiedNameGetCreationNamespace(names, &tmplname);
 
+	tmplRel = heap_open(TSTemplateRelationId, RowExclusiveLock);
+
 	for (i = 0; i < Natts_pg_ts_template; i++)
 	{
 		nulls[i] = false;
 		values[i] = ObjectIdGetDatum(InvalidOid);
 	}
 
+	tmplOid = GetNewOidWithIndex(tmplRel, TSTemplateOidIndexId, Anum_pg_ts_dict_oid);
+	values[Anum_pg_ts_template_oid - 1] = ObjectIdGetDatum(tmplOid);
 	namestrcpy(&dname, tmplname);
 	values[Anum_pg_ts_template_tmplname - 1] = NameGetDatum(&dname);
 	values[Anum_pg_ts_template_tmplnamespace - 1] = ObjectIdGetDatum(namespaceoid);
@@ -795,12 +805,9 @@ DefineTSTemplate(List *names, List *parameters)
 	/*
 	 * Looks good, insert
 	 */
-
-	tmplRel = heap_open(TSTemplateRelationId, RowExclusiveLock);
-
 	tup = heap_form_tuple(tmplRel->rd_att, values, nulls);
 
-	tmplOid = CatalogTupleInsert(tmplRel, tup);
+	CatalogTupleInsert(tmplRel, tup);
 
 	address = makeTSTemplateDependencies(tup);
 
@@ -879,7 +886,7 @@ makeConfigurationDependencies(HeapTuple tuple, bool removeOld,
 				referenced;
 
 	myself.classId = TSConfigRelationId;
-	myself.objectId = HeapTupleGetOid(tuple);
+	myself.objectId = cfg->oid;
 	myself.objectSubId = 0;
 
 	/* for ALTER case, first flush old dependencies, except extension deps */
@@ -1042,23 +1049,25 @@ DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied)
 				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 				 errmsg("text search parser is required")));
 
+	cfgRel = heap_open(TSConfigRelationId, RowExclusiveLock);
+
 	/*
 	 * Looks good, build tuple and insert
 	 */
 	memset(values, 0, sizeof(values));
 	memset(nulls, false, sizeof(nulls));
 
+	cfgOid = GetNewOidWithIndex(cfgRel, TSConfigOidIndexId, Anum_pg_ts_config_oid);
+	values[Anum_pg_ts_config_oid - 1] = ObjectIdGetDatum(cfgOid);
 	namestrcpy(&cname, cfgname);
 	values[Anum_pg_ts_config_cfgname - 1] = NameGetDatum(&cname);
 	values[Anum_pg_ts_config_cfgnamespace - 1] = ObjectIdGetDatum(namespaceoid);
 	values[Anum_pg_ts_config_cfgowner - 1] = ObjectIdGetDatum(GetUserId());
 	values[Anum_pg_ts_config_cfgparser - 1] = ObjectIdGetDatum(prsOid);
 
-	cfgRel = heap_open(TSConfigRelationId, RowExclusiveLock);
-
 	tup = heap_form_tuple(cfgRel->rd_att, values, nulls);
 
-	cfgOid = CatalogTupleInsert(cfgRel, tup);
+	CatalogTupleInsert(cfgRel, tup);
 
 	if (OidIsValid(sourceOid))
 	{
@@ -1185,10 +1194,10 @@ AlterTSConfiguration(AlterTSConfigurationStmt *stmt)
 				 errmsg("text search configuration \"%s\" does not exist",
 						NameListToString(stmt->cfgname))));
 
-	cfgId = HeapTupleGetOid(tup);
+	cfgId = ((Form_pg_ts_config) GETSTRUCT(tup))->oid;
 
 	/* must be owner */
-	if (!pg_ts_config_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+	if (!pg_ts_config_ownercheck(cfgId, GetUserId()))
 		aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TSCONFIGURATION,
 					   NameListToString(stmt->cfgname));
 
@@ -1203,8 +1212,7 @@ AlterTSConfiguration(AlterTSConfigurationStmt *stmt)
 	/* Update dependencies */
 	makeConfigurationDependencies(tup, true, relMap);
 
-	InvokeObjectPostAlterHook(TSConfigRelationId,
-							  HeapTupleGetOid(tup), 0);
+	InvokeObjectPostAlterHook(TSConfigRelationId, cfgId, 0);
 
 	ObjectAddressSet(address, TSConfigRelationId, cfgId);
 
@@ -1277,7 +1285,8 @@ static void
 MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
 						 HeapTuple tup, Relation relMap)
 {
-	Oid			cfgId = HeapTupleGetOid(tup);
+	Form_pg_ts_config tsform;
+	Oid			cfgId;
 	ScanKeyData skey[2];
 	SysScanDesc scan;
 	HeapTuple	maptup;
@@ -1290,7 +1299,9 @@ MakeConfigurationMapping(AlterTSConfigurationStmt *stmt,
 	int			ndict;
 	ListCell   *c;
 
-	prsId = ((Form_pg_ts_config) GETSTRUCT(tup))->cfgparser;
+	tsform = (Form_pg_ts_config) GETSTRUCT(tup);
+	cfgId = tsform->oid;
+	prsId = tsform->cfgparser;
 
 	tokens = getTokenTypes(prsId, stmt->tokentype);
 	ntoken = list_length(stmt->tokentype);
@@ -1438,7 +1449,8 @@ static void
 DropConfigurationMapping(AlterTSConfigurationStmt *stmt,
 						 HeapTuple tup, Relation relMap)
 {
-	Oid			cfgId = HeapTupleGetOid(tup);
+	Form_pg_ts_config tsform;
+	Oid			cfgId;
 	ScanKeyData skey[2];
 	SysScanDesc scan;
 	HeapTuple	maptup;
@@ -1447,7 +1459,9 @@ DropConfigurationMapping(AlterTSConfigurationStmt *stmt,
 	int		   *tokens;
 	ListCell   *c;
 
-	prsId = ((Form_pg_ts_config) GETSTRUCT(tup))->cfgparser;
+	tsform = (Form_pg_ts_config) GETSTRUCT(tup);
+	cfgId = tsform->oid;
+	prsId = tsform->cfgparser;
 
 	tokens = getTokenTypes(prsId, stmt->tokentype);
 
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index b018585aef8..8b994c79359 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -792,7 +792,7 @@ DefineDomain(CreateDomainStmt *stmt)
 	 */
 	typeTup = typenameType(NULL, stmt->typeName, &basetypeMod);
 	baseType = (Form_pg_type) GETSTRUCT(typeTup);
-	basetypeoid = HeapTupleGetOid(typeTup);
+	basetypeoid = baseType->oid;
 
 	/*
 	 * Base type must be a plain base type, a composite type, another domain,
@@ -1351,11 +1351,11 @@ checkEnumOwner(HeapTuple tup)
 		ereport(ERROR,
 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 				 errmsg("%s is not an enum",
-						format_type_be(HeapTupleGetOid(tup)))));
+						format_type_be(typTup->oid))));
 
 	/* Permission check: must own type */
-	if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId()))
-		aclcheck_error_type(ACLCHECK_NOT_OWNER, HeapTupleGetOid(tup));
+	if (!pg_type_ownercheck(typTup->oid, GetUserId()))
+		aclcheck_error_type(ACLCHECK_NOT_OWNER, typTup->oid);
 }
 
 
@@ -2502,7 +2502,7 @@ AlterDomainDropConstraint(List *names, const char *constrName,
 		ObjectAddress conobj;
 
 		conobj.classId = ConstraintRelationId;
-		conobj.objectId = HeapTupleGetOid(contup);
+		conobj.objectId = ((Form_pg_constraint) GETSTRUCT(contup))->oid;
 		conobj.objectSubId = 0;
 
 		performDeletion(&conobj, behavior, 0);
@@ -2720,7 +2720,7 @@ AlterDomainValidateConstraint(List *names, const char *constrName)
 						  &isnull);
 	if (isnull)
 		elog(ERROR, "null conbin for constraint %u",
-			 HeapTupleGetOid(tuple));
+			 con->oid);
 	conbin = TextDatumGetCString(val);
 
 	validateDomainConstraint(domainoid, conbin);
@@ -2733,8 +2733,7 @@ AlterDomainValidateConstraint(List *names, const char *constrName)
 	copy_con->convalidated = true;
 	CatalogTupleUpdate(conrel, &copyTuple->t_self, copyTuple);
 
-	InvokeObjectPostAlterHook(ConstraintRelationId,
-							  HeapTupleGetOid(copyTuple), 0);
+	InvokeObjectPostAlterHook(ConstraintRelationId, con->oid, 0);
 
 	ObjectAddressSet(address, TypeRelationId, domainoid);
 
@@ -3047,11 +3046,11 @@ checkDomainOwner(HeapTuple tup)
 		ereport(ERROR,
 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 				 errmsg("%s is not a domain",
-						format_type_be(HeapTupleGetOid(tup)))));
+						format_type_be(typTup->oid))));
 
 	/* Permission check: must own type */
-	if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId()))
-		aclcheck_error_type(ACLCHECK_NOT_OWNER, HeapTupleGetOid(tup));
+	if (!pg_type_ownercheck(typTup->oid, GetUserId()))
+		aclcheck_error_type(ACLCHECK_NOT_OWNER, typTup->oid);
 }
 
 /*
@@ -3370,8 +3369,8 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype)
 		if (!superuser())
 		{
 			/* Otherwise, must be owner of the existing object */
-			if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId()))
-				aclcheck_error_type(ACLCHECK_NOT_OWNER, HeapTupleGetOid(tup));
+			if (!pg_type_ownercheck(typTup->oid, GetUserId()))
+				aclcheck_error_type(ACLCHECK_NOT_OWNER, typTup->oid);
 
 			/* Must be able to become new owner */
 			check_is_member_of_role(GetUserId(), newOwnerId);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index 71c5caa41b9..c43afa24410 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -423,8 +423,6 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
 
 	new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls);
 
-	tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls);
-
 	/*
 	 * pg_largeobject_metadata contains pg_authid.oid's, so we use the
 	 * binary-upgrade override.
@@ -436,14 +434,22 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 					 errmsg("pg_authid OID value not set when in binary upgrade mode")));
 
-		HeapTupleSetOid(tuple, binary_upgrade_next_pg_authid_oid);
+		roleid = binary_upgrade_next_pg_authid_oid;
 		binary_upgrade_next_pg_authid_oid = InvalidOid;
 	}
+	else
+	{
+		roleid = GetNewOidWithIndex(pg_authid_rel, AuthIdOidIndexId, Anum_pg_authid_oid);
+	}
+
+	new_record[Anum_pg_authid_oid - 1] = ObjectIdGetDatum(roleid);
+
+	tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls);
 
 	/*
 	 * Insert new record in the pg_authid table
 	 */
-	roleid = CatalogTupleInsert(pg_authid_rel, tuple);
+	CatalogTupleInsert(pg_authid_rel, tuple);
 
 	/*
 	 * Advance command counter so we can see new record; else tests in
@@ -459,8 +465,9 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
 	{
 		RoleSpec   *oldrole = lfirst(item);
 		HeapTuple	oldroletup = get_rolespec_tuple(oldrole);
-		Oid			oldroleid = HeapTupleGetOid(oldroletup);
-		char	   *oldrolename = NameStr(((Form_pg_authid) GETSTRUCT(oldroletup))->rolname);
+		Form_pg_authid oldroleform = (Form_pg_authid) GETSTRUCT(oldroletup);
+		Oid			oldroleid = oldroleform->oid;
+		char	   *oldrolename = NameStr(oldroleform->rolname);
 
 		AddRoleMems(oldrolename, oldroleid,
 					list_make1(makeString(stmt->role)),
@@ -679,7 +686,7 @@ AlterRole(AlterRoleStmt *stmt)
 	tuple = get_rolespec_tuple(stmt->role);
 	authform = (Form_pg_authid) GETSTRUCT(tuple);
 	rolename = pstrdup(NameStr(authform->rolname));
-	roleid = HeapTupleGetOid(tuple);
+	roleid = authform->oid;
 
 	/*
 	 * To mess with a superuser you gotta be superuser; else you need
@@ -886,6 +893,7 @@ Oid
 AlterRoleSet(AlterRoleSetStmt *stmt)
 {
 	HeapTuple	roletuple;
+	Form_pg_authid roleform;
 	Oid			databaseid = InvalidOid;
 	Oid			roleid = InvalidOid;
 
@@ -895,19 +903,20 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
 							"Cannot alter reserved roles.");
 
 		roletuple = get_rolespec_tuple(stmt->role);
-		roleid = HeapTupleGetOid(roletuple);
+		roleform = (Form_pg_authid) GETSTRUCT(roletuple);
+		roleid = roleform->oid;
 
 		/*
 		 * Obtain a lock on the role and make sure it didn't go away in the
 		 * meantime.
 		 */
-		shdepLockAndCheckObject(AuthIdRelationId, HeapTupleGetOid(roletuple));
+		shdepLockAndCheckObject(AuthIdRelationId, roleid);
 
 		/*
 		 * To mess with a superuser you gotta be superuser; else you need
 		 * createrole, or just want to change your own settings
 		 */
-		if (((Form_pg_authid) GETSTRUCT(roletuple))->rolsuper)
+		if (roleform->rolsuper)
 		{
 			if (!superuser())
 				ereport(ERROR,
@@ -916,8 +925,7 @@ AlterRoleSet(AlterRoleSetStmt *stmt)
 		}
 		else
 		{
-			if (!have_createrole_privilege() &&
-				HeapTupleGetOid(roletuple) != GetUserId())
+			if (!have_createrole_privilege() && roleid != GetUserId())
 				ereport(ERROR,
 						(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
 						 errmsg("permission denied")));
@@ -987,6 +995,7 @@ DropRole(DropRoleStmt *stmt)
 		char	   *role;
 		HeapTuple	tuple,
 					tmp_tuple;
+		Form_pg_authid roleform;
 		ScanKeyData scankey;
 		char	   *detail;
 		char	   *detail_log;
@@ -1018,7 +1027,8 @@ DropRole(DropRoleStmt *stmt)
 			continue;
 		}
 
-		roleid = HeapTupleGetOid(tuple);
+		roleform = (Form_pg_authid) GETSTRUCT(tuple);
+		roleid = roleform->oid;
 
 		if (roleid == GetUserId())
 			ereport(ERROR,
@@ -1038,7 +1048,7 @@ DropRole(DropRoleStmt *stmt)
 		 * roles but not superuser roles.  This is mainly to avoid the
 		 * scenario where you accidentally drop the last superuser.
 		 */
-		if (((Form_pg_authid) GETSTRUCT(tuple))->rolsuper &&
+		if (roleform->rolsuper &&
 			!superuser())
 			ereport(ERROR,
 					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@@ -1173,8 +1183,8 @@ RenameRole(const char *oldname, const char *newname)
 	 * effective userid, though.
 	 */
 
-	roleid = HeapTupleGetOid(oldtuple);
 	authform = (Form_pg_authid) GETSTRUCT(oldtuple);
+	roleid = authform->oid;
 
 	if (roleid == GetSessionUserId())
 		ereport(ERROR,
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index f1665097346..6019afb87ae 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -627,7 +627,7 @@ get_all_vacuum_rels(int options)
 	{
 		Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
 		MemoryContext oldcontext;
-		Oid			relid = HeapTupleGetOid(tuple);
+		Oid			relid = classForm->oid;
 
 		/* check permissions of relation */
 		if (!vacuum_is_relation_owner(relid, classForm, options))
@@ -1312,13 +1312,13 @@ vac_truncate_clog(TransactionId frozenXID,
 		else if (TransactionIdPrecedes(datfrozenxid, frozenXID))
 		{
 			frozenXID = datfrozenxid;
-			oldestxid_datoid = HeapTupleGetOid(tuple);
+			oldestxid_datoid = dbform->oid;
 		}
 
 		if (MultiXactIdPrecedes(datminmxid, minMulti))
 		{
 			minMulti = datminmxid;
-			minmulti_datoid = HeapTupleGetOid(tuple);
+			minmulti_datoid = dbform->oid;
 		}
 	}
 
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index 8996d366e91..8134c52253e 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -1053,12 +1053,6 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
 					all_visible = false;
 					break;
 				case HEAPTUPLE_LIVE:
-					/* Tuple is good --- but let's do some validity checks */
-					if (onerel->rd_rel->relhasoids &&
-						!OidIsValid(HeapTupleGetOid(&tuple)))
-						elog(WARNING, "relation \"%s\" TID %u/%u: OID is invalid",
-							 relname, blkno, offnum);
-
 					/*
 					 * Count it as live.  Not only is this natural, but it's
 					 * also what acquire_sample_rows() does.
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 9a754dae3fd..5cc09ff9049 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -797,6 +797,7 @@ bool
 check_session_authorization(char **newval, void **extra, GucSource source)
 {
 	HeapTuple	roleTup;
+	Form_pg_authid roleform;
 	Oid			roleid;
 	bool		is_superuser;
 	role_auth_extra *myextra;
@@ -823,8 +824,9 @@ check_session_authorization(char **newval, void **extra, GucSource source)
 		return false;
 	}
 
-	roleid = HeapTupleGetOid(roleTup);
-	is_superuser = ((Form_pg_authid) GETSTRUCT(roleTup))->rolsuper;
+	roleform = (Form_pg_authid) GETSTRUCT(roleTup);
+	roleid = roleform->oid;
+	is_superuser = roleform->rolsuper;
 
 	ReleaseSysCache(roleTup);
 
@@ -868,6 +870,7 @@ check_role(char **newval, void **extra, GucSource source)
 	Oid			roleid;
 	bool		is_superuser;
 	role_auth_extra *myextra;
+	Form_pg_authid roleform;
 
 	if (strcmp(*newval, "none") == 0)
 	{
@@ -895,8 +898,9 @@ check_role(char **newval, void **extra, GucSource source)
 			return false;
 		}
 
-		roleid = HeapTupleGetOid(roleTup);
-		is_superuser = ((Form_pg_authid) GETSTRUCT(roleTup))->rolsuper;
+		roleform = (Form_pg_authid) GETSTRUCT(roleTup);
+		roleid = roleform->oid;
+		is_superuser = roleform->rolsuper;
 
 		ReleaseSysCache(roleTup);
 
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index ffb71c0ea7c..611461d0578 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -279,7 +279,6 @@ checkViewTupleDesc(TupleDesc newdesc, TupleDesc olddesc)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
 				 errmsg("cannot drop columns from view")));
-	/* we can ignore tdhasoid */
 
 	for (i = 0; i < olddesc->natts; i++)
 	{
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index e284fd71d75..f20fe7cd464 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -2421,7 +2421,6 @@ ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state)
 			{
 				scratch->d.wholerow.junkFilter =
 					ExecInitJunkFilter(subplan->plan->targetlist,
-									   ExecGetResultType(subplan)->tdhasoid,
 									   ExecInitExtraTupleSlot(parent->state, NULL));
 			}
 		}
diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c
index 57d74e57c1a..00dcc3cb6b1 100644
--- a/src/backend/executor/execJunk.c
+++ b/src/backend/executor/execJunk.c
@@ -53,12 +53,11 @@
  * Initialize the Junk filter.
  *
  * The source targetlist is passed in.  The output tuple descriptor is
- * built from the non-junk tlist entries, plus the passed specification
- * of whether to include room for an OID or not.
+ * built from the non-junk tlist entries.
  * An optional resultSlot can be passed as well.
  */
 JunkFilter *
-ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
+ExecInitJunkFilter(List *targetList, TupleTableSlot *slot)
 {
 	JunkFilter *junkfilter;
 	TupleDesc	cleanTupType;
@@ -70,7 +69,7 @@ ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
 	/*
 	 * Compute the tuple descriptor for the cleaned tuple.
 	 */
-	cleanTupType = ExecCleanTypeFromTL(targetList, hasoid);
+	cleanTupType = ExecCleanTypeFromTL(targetList);
 
 	/*
 	 * Use the given slot, or make a new slot if we weren't given one.
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 5443cbf67db..eb1088e4264 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -344,7 +344,6 @@ standard_ExecutorRun(QueryDesc *queryDesc,
 	 * startup tuple receiver, if we will be emitting tuples
 	 */
 	estate->es_processed = 0;
-	estate->es_lastoid = InvalidOid;
 
 	sendTuples = (operation == CMD_SELECT ||
 				  queryDesc->plannedstmt->hasReturning);
@@ -1090,7 +1089,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
 			JunkFilter *j;
 
 			j = ExecInitJunkFilter(planstate->plan->targetlist,
-								   tupType->tdhasoid,
 								   ExecInitExtraTupleSlot(estate, NULL));
 			estate->es_junkFilter = j;
 
@@ -1497,68 +1495,6 @@ ExecCleanUpTriggerState(EState *estate)
 	}
 }
 
-/*
- *		ExecContextForcesOids
- *
- * This is pretty grotty: when doing INSERT, UPDATE, or CREATE TABLE AS,
- * we need to ensure that result tuples have space for an OID iff they are
- * going to be stored into a relation that has OIDs.  In other contexts
- * we are free to choose whether to leave space for OIDs in result tuples
- * (we generally don't want to, but we do if a physical-tlist optimization
- * is possible).  This routine checks the plan context and returns true if the
- * choice is forced, false if the choice is not forced.  In the true case,
- * *hasoids is set to the required value.
- *
- * One reason this is ugly is that all plan nodes in the plan tree will emit
- * tuples with space for an OID, though we really only need the topmost node
- * to do so.  However, node types like Sort don't project new tuples but just
- * return their inputs, and in those cases the requirement propagates down
- * to the input node.  Eventually we might make this code smart enough to
- * recognize how far down the requirement really goes, but for now we just
- * make all plan nodes do the same thing if the top level forces the choice.
- *
- * We assume that if we are generating tuples for INSERT or UPDATE,
- * estate->es_result_relation_info is already set up to describe the target
- * relation.  Note that in an UPDATE that spans an inheritance tree, some of
- * the target relations may have OIDs and some not.  We have to make the
- * decisions on a per-relation basis as we initialize each of the subplans of
- * the ModifyTable node, so ModifyTable has to set es_result_relation_info
- * while initializing each subplan.
- *
- * CREATE TABLE AS is even uglier, because we don't have the target relation's
- * descriptor available when this code runs; we have to look aside at the
- * flags passed to ExecutorStart().
- */
-bool
-ExecContextForcesOids(PlanState *planstate, bool *hasoids)
-{
-	ResultRelInfo *ri = planstate->state->es_result_relation_info;
-
-	if (ri != NULL)
-	{
-		Relation	rel = ri->ri_RelationDesc;
-
-		if (rel != NULL)
-		{
-			*hasoids = rel->rd_rel->relhasoids;
-			return true;
-		}
-	}
-
-	if (planstate->state->es_top_eflags & EXEC_FLAG_WITH_OIDS)
-	{
-		*hasoids = true;
-		return true;
-	}
-	if (planstate->state->es_top_eflags & EXEC_FLAG_WITHOUT_OIDS)
-	{
-		*hasoids = false;
-		return true;
-	}
-
-	return false;
-}
-
 /* ----------------------------------------------------------------
  *		ExecPostprocessPlan
  *
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index ec7a5267c34..4f547ba1b4b 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -661,7 +661,7 @@ ExecInitPartitionInfo(ModifyTableState *mtstate,
 				 * partition that's tupdesc-equal to the partitioned table;
 				 * partitions of different tupdescs must generate their own.
 				 */
-				tupDesc = ExecTypeFromTL(onconflset, partrelDesc->tdhasoid);
+				tupDesc = ExecTypeFromTL(onconflset);
 				ExecSetSlotDescriptor(mtstate->mt_conflproj, tupDesc);
 				leaf_part_rri->ri_onConflict->oc_ProjInfo =
 					ExecBuildProjectionInfo(onconflset, econtext,
diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c
index b97b8d797ec..ce1c5835a28 100644
--- a/src/backend/executor/execSRF.c
+++ b/src/backend/executor/execSRF.c
@@ -260,7 +260,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
 				rsinfo.setResult = tupstore;
 				if (!returnsTuple)
 				{
-					tupdesc = CreateTemplateTupleDesc(1, false);
+					tupdesc = CreateTemplateTupleDesc(1);
 					TupleDescInitEntry(tupdesc,
 									   (AttrNumber) 1,
 									   "column",
@@ -746,7 +746,7 @@ init_sexpr(Oid foid, Oid input_collation, Expr *node,
 		else if (functypclass == TYPEFUNC_SCALAR)
 		{
 			/* Base data type, i.e. scalar */
-			tupdesc = CreateTemplateTupleDesc(1, false);
+			tupdesc = CreateTemplateTupleDesc(1);
 			TupleDescInitEntry(tupdesc,
 							   (AttrNumber) 1,
 							   NULL,
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 716c04939cd..3987c3badf0 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -65,7 +65,7 @@
 
 
 static TupleDesc ExecTypeFromTLInternal(List *targetList,
-					   bool hasoid, bool skipjunk);
+					   bool skipjunk);
 
 
 /* ----------------------------------------------------------------
@@ -899,20 +899,7 @@ ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
 void
 ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
 {
-	bool		hasoid;
-	TupleDesc	tupDesc;
-
-	if (ExecContextForcesOids(planstate, &hasoid))
-	{
-		/* context forces OID choice; hasoid is now set correctly */
-	}
-	else
-	{
-		/* given free choice, don't leave space for OIDs in result tuples */
-		hasoid = false;
-	}
-
-	tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
+	TupleDesc	tupDesc = ExecTypeFromTL(planstate->plan->targetlist);
 
 	planstate->ps_ResultTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable, tupDesc);
 }
@@ -972,9 +959,9 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
  * ----------------------------------------------------------------
  */
 TupleDesc
-ExecTypeFromTL(List *targetList, bool hasoid)
+ExecTypeFromTL(List *targetList)
 {
-	return ExecTypeFromTLInternal(targetList, hasoid, false);
+	return ExecTypeFromTLInternal(targetList, false);
 }
 
 /* ----------------------------------------------------------------
@@ -984,13 +971,13 @@ ExecTypeFromTL(List *targetList, bool hasoid)
  * ----------------------------------------------------------------
  */
 TupleDesc
-ExecCleanTypeFromTL(List *targetList, bool hasoid)
+ExecCleanTypeFromTL(List *targetList)
 {
-	return ExecTypeFromTLInternal(targetList, hasoid, true);
+	return ExecTypeFromTLInternal(targetList, true);
 }
 
 static TupleDesc
-ExecTypeFromTLInternal(List *targetList, bool hasoid, bool skipjunk)
+ExecTypeFromTLInternal(List *targetList, bool skipjunk)
 {
 	TupleDesc	typeInfo;
 	ListCell   *l;
@@ -1001,7 +988,7 @@ ExecTypeFromTLInternal(List *targetList, bool hasoid, bool skipjunk)
 		len = ExecCleanTargetListLength(targetList);
 	else
 		len = ExecTargetListLength(targetList);
-	typeInfo = CreateTemplateTupleDesc(len, hasoid);
+	typeInfo = CreateTemplateTupleDesc(len);
 
 	foreach(l, targetList)
 	{
@@ -1037,7 +1024,7 @@ ExecTypeFromExprList(List *exprList)
 	ListCell   *lc;
 	int			cur_resno = 1;
 
-	typeInfo = CreateTemplateTupleDesc(list_length(exprList), false);
+	typeInfo = CreateTemplateTupleDesc(list_length(exprList));
 
 	foreach(lc, exprList)
 	{
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 5b3eaec80bc..a5caabe5b1a 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -138,7 +138,6 @@ CreateExecutorState(void)
 	estate->es_rowMarks = NIL;
 
 	estate->es_processed = 0;
-	estate->es_lastoid = InvalidOid;
 
 	estate->es_top_eflags = 0;
 	estate->es_instrument = 0;
@@ -498,7 +497,6 @@ tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc
 {
 	int			numattrs = tupdesc->natts;
 	int			attrno;
-	bool		hasoid;
 	ListCell   *tlist_item = list_head(tlist);
 
 	/* Check the tlist attributes */
@@ -543,14 +541,6 @@ tlist_matches_tupdesc(PlanState *ps, List *tlist, Index varno, TupleDesc tupdesc
 	if (tlist_item)
 		return false;			/* tlist too long */
 
-	/*
-	 * If the plan context requires a particular hasoid setting, then that has
-	 * to match, too.
-	 */
-	if (ExecContextForcesOids(ps, &hasoid) &&
-		hasoid != tupdesc->tdhasoid)
-		return false;
-
 	return true;
 }
 
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 23545896d4d..9f898513edc 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -1717,7 +1717,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
 
 		/* Set up junk filter if needed */
 		if (junkFilter)
-			*junkFilter = ExecInitJunkFilter(tlist, false, NULL);
+			*junkFilter = ExecInitJunkFilter(tlist, NULL);
 	}
 	else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID)
 	{
@@ -1770,7 +1770,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
 				}
 				/* Set up junk filter if needed */
 				if (junkFilter)
-					*junkFilter = ExecInitJunkFilter(tlist, false, NULL);
+					*junkFilter = ExecInitJunkFilter(tlist, NULL);
 				return false;	/* NOT returning whole tuple */
 			}
 		}
@@ -1786,7 +1786,7 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
 			 * what the caller expects will happen at runtime.
 			 */
 			if (junkFilter)
-				*junkFilter = ExecInitJunkFilter(tlist, false, NULL);
+				*junkFilter = ExecInitJunkFilter(tlist, NULL);
 			return true;
 		}
 		Assert(tupdesc);
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 98d8483b720..1d7baf3a927 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1396,7 +1396,7 @@ find_hash_columns(AggState *aggstate)
 				Max(varNumber + 1, perhash->largestGrpColIdx);
 		}
 
-		hashDesc = ExecTypeFromTL(hashTlist, false);
+		hashDesc = ExecTypeFromTL(hashTlist);
 
 		execTuplesHashPrepare(perhash->numCols,
 							  perhash->aggnode->grpOperators,
@@ -3060,7 +3060,7 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
 	 */
 	if (numSortCols > 0 || aggref->aggfilter)
 	{
-		pertrans->sortdesc = ExecTypeFromTL(aggref->args, false);
+		pertrans->sortdesc = ExecTypeFromTL(aggref->args);
 		pertrans->sortslot =
 			ExecInitExtraTupleSlot(estate, pertrans->sortdesc);
 	}
diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c
index b816e0b31db..0e0c6b34de2 100644
--- a/src/backend/executor/nodeCustom.c
+++ b/src/backend/executor/nodeCustom.c
@@ -72,7 +72,7 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
 	{
 		TupleDesc	scan_tupdesc;
 
-		scan_tupdesc = ExecTypeFromTL(cscan->custom_scan_tlist, false);
+		scan_tupdesc = ExecTypeFromTL(cscan->custom_scan_tlist);
 		ExecInitScanTupleSlot(estate, &css->ss, scan_tupdesc);
 		/* Node's targetlist will contain Vars with varno = INDEX_VAR */
 		tlistvarno = INDEX_VAR;
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index a2a28b7ec26..abea32bf566 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -179,7 +179,7 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
 	{
 		TupleDesc	scan_tupdesc;
 
-		scan_tupdesc = ExecTypeFromTL(node->fdw_scan_tlist, false);
+		scan_tupdesc = ExecTypeFromTL(node->fdw_scan_tlist);
 		ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc);
 		/* Node's targetlist will contain Vars with varno = INDEX_VAR */
 		tlistvarno = INDEX_VAR;
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index fb7c9f67875..2464598877c 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -383,7 +383,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 		else if (functypclass == TYPEFUNC_SCALAR)
 		{
 			/* Base data type, i.e. scalar */
-			tupdesc = CreateTemplateTupleDesc(1, false);
+			tupdesc = CreateTemplateTupleDesc(1);
 			TupleDescInitEntry(tupdesc,
 							   (AttrNumber) 1,
 							   NULL,	/* don't care about the name here */
@@ -453,7 +453,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 		if (node->funcordinality)
 			natts++;
 
-		scan_tupdesc = CreateTemplateTupleDesc(natts, false);
+		scan_tupdesc = CreateTemplateTupleDesc(natts);
 
 		for (i = 0; i < nfuncs; i++)
 		{
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index 4b6d531810c..9d94ac143fb 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -532,7 +532,7 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
 	 * types of the original datums.  (It's the AM's responsibility to return
 	 * suitable data anyway.)
 	 */
-	tupDesc = ExecTypeFromTL(node->indextlist, false);
+	tupDesc = ExecTypeFromTL(node->indextlist);
 	ExecInitScanTupleSlot(estate, &indexstate->ss, tupDesc);
 
 	/*
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index bf0d5e8edb5..909e4533faf 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -39,6 +39,8 @@
 
 #include "access/htup_details.h"
 #include "access/xact.h"
+#include "catalog/catalog.h"
+#include "catalog/objectaddress.h"
 #include "commands/trigger.h"
 #include "executor/execPartition.h"
 #include "executor/executor.h"
@@ -269,7 +271,6 @@ ExecInsert(ModifyTableState *mtstate,
 	HeapTuple	tuple;
 	ResultRelInfo *resultRelInfo;
 	Relation	resultRelationDesc;
-	Oid			newId;
 	List	   *recheckIndexes = NIL;
 	TupleTableSlot *result = NULL;
 	TransitionCaptureState *ar_insert_trig_tcs;
@@ -288,21 +289,6 @@ ExecInsert(ModifyTableState *mtstate,
 	resultRelInfo = estate->es_result_relation_info;
 	resultRelationDesc = resultRelInfo->ri_RelationDesc;
 
-	/*
-	 * If the result relation has OIDs, force the tuple's OID to zero so that
-	 * heap_insert will assign a fresh OID.  Usually the OID already will be
-	 * zero at this point, but there are corner cases where the plan tree can
-	 * return a tuple extracted literally from some table with the same
-	 * rowtype.
-	 *
-	 * XXX if we ever wanted to allow users to assign their own OIDs to new
-	 * rows, this'd be the place to do it.  For the moment, we make a point of
-	 * doing this before calling triggers, so that a user-supplied trigger
-	 * could hack the OID if desired.
-	 */
-	if (resultRelationDesc->rd_rel->relhasoids)
-		HeapTupleSetOid(tuple, InvalidOid);
-
 	/*
 	 * BEFORE ROW INSERT Triggers.
 	 *
@@ -335,8 +321,6 @@ ExecInsert(ModifyTableState *mtstate,
 
 		/* trigger might have changed tuple */
 		tuple = ExecMaterializeSlot(slot);
-
-		newId = InvalidOid;
 	}
 	else if (resultRelInfo->ri_FdwRoutine)
 	{
@@ -359,8 +343,6 @@ ExecInsert(ModifyTableState *mtstate,
 		 * tableoid column, so initialize t_tableOid before evaluating them.
 		 */
 		tuple->t_tableOid = RelationGetRelid(resultRelationDesc);
-
-		newId = InvalidOid;
 	}
 	else
 	{
@@ -395,7 +377,31 @@ ExecInsert(ModifyTableState *mtstate,
 		 * Check the constraints of the tuple.
 		 */
 		if (resultRelationDesc->rd_att->constr)
+		{
+			/* XXX: assign oids for manual catalog insertions */
+			if (IsSystemRelation(resultRelationDesc) && is_objectclass_supported(RelationGetRelid(resultRelationDesc)))
+			{
+				Oid oidIndex = get_object_oid_index(RelationGetRelid(resultRelationDesc));
+				if (oidIndex != InvalidOid)
+				{
+					AttrNumber oidAttr = get_object_attnum_oid(RelationGetRelid(resultRelationDesc));
+					Datum *values = palloc0(sizeof(Datum) * resultRelationDesc->rd_att->natts);
+					bool *isnull = palloc0(sizeof(bool) * resultRelationDesc->rd_att->natts);
+					bool *replaces = palloc0(sizeof(bool) * resultRelationDesc->rd_att->natts);
+					Oid newoid;
+
+					newoid = GetNewOidWithIndex(resultRelationDesc, oidIndex, oidAttr);
+
+					values[oidAttr - 1] = newoid;
+					replaces[oidAttr - 1] = true;
+					tuple = heap_modify_tuple(tuple, RelationGetDescr(resultRelationDesc),
+											  values, isnull, replaces);
+					ExecStoreHeapTuple(tuple, slot, true);
+				}
+			}
+
 			ExecConstraints(resultRelInfo, slot, estate);
+		}
 
 		/*
 		 * Also check the tuple against the partition constraint, if there is
@@ -480,10 +486,10 @@ ExecInsert(ModifyTableState *mtstate,
 			HeapTupleHeaderSetSpeculativeToken(tuple->t_data, specToken);
 
 			/* insert the tuple, with the speculative token */
-			newId = heap_insert(resultRelationDesc, tuple,
-								estate->es_output_cid,
-								HEAP_INSERT_SPECULATIVE,
-								NULL);
+			heap_insert(resultRelationDesc, tuple,
+						estate->es_output_cid,
+						HEAP_INSERT_SPECULATIVE,
+						NULL);
 
 			/* insert index entries for tuple */
 			recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self),
@@ -526,9 +532,9 @@ ExecInsert(ModifyTableState *mtstate,
 			 * Note: heap_insert returns the tid (location) of the new tuple
 			 * in the t_self field.
 			 */
-			newId = heap_insert(resultRelationDesc, tuple,
-								estate->es_output_cid,
-								0, NULL);
+			heap_insert(resultRelationDesc, tuple,
+						estate->es_output_cid,
+						0, NULL);
 
 			/* insert index entries for tuple */
 			if (resultRelInfo->ri_NumIndices > 0)
@@ -541,7 +547,6 @@ ExecInsert(ModifyTableState *mtstate,
 	if (canSetTag)
 	{
 		(estate->es_processed)++;
-		estate->es_lastoid = newId;
 		setLastTid(&(tuple->t_self));
 	}
 
@@ -2489,8 +2494,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 		 * the tupdesc in the parent's state: it can be reused by partitions
 		 * with an identical descriptor to the parent.
 		 */
-		tupDesc = ExecTypeFromTL((List *) node->onConflictSet,
-								 relationDesc->tdhasoid);
+		tupDesc = ExecTypeFromTL((List *) node->onConflictSet);
 		mtstate->mt_conflproj =
 			ExecInitExtraTupleSlot(mtstate->ps.state,
 								   mtstate->mt_partition_tuple_routing ?
@@ -2604,7 +2608,6 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 										subplan->targetlist);
 
 				j = ExecInitJunkFilter(subplan->targetlist,
-									   resultRelInfo->ri_RelationDesc->rd_att->tdhasoid,
 									   ExecInitExtraTupleSlot(estate, NULL));
 
 				if (operation == CMD_UPDATE || operation == CMD_DELETE)
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 63de981034d..e4b9cd80bc3 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -967,7 +967,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
 		 * (hack alert!).  The righthand expressions will be evaluated in our
 		 * own innerecontext.
 		 */
-		tupDescLeft = ExecTypeFromTL(lefttlist, false);
+		tupDescLeft = ExecTypeFromTL(lefttlist);
 		slot = ExecInitExtraTupleSlot(estate, tupDescLeft);
 		sstate->projLeft = ExecBuildProjectionInfo(lefttlist,
 												   NULL,
@@ -975,7 +975,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
 												   parent,
 												   NULL);
 
-		sstate->descRight = tupDescRight = ExecTypeFromTL(righttlist, false);
+		sstate->descRight = tupDescRight = ExecTypeFromTL(righttlist);
 		slot = ExecInitExtraTupleSlot(estate, tupDescRight);
 		sstate->projRight = ExecBuildProjectionInfo(righttlist,
 													sstate->innerecontext,
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 11ca800e4cd..a4d42e96912 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -128,7 +128,6 @@ SPI_connect_ext(int options)
 
 	_SPI_current = &(_SPI_stack[_SPI_connected]);
 	_SPI_current->processed = 0;
-	_SPI_current->lastoid = InvalidOid;
 	_SPI_current->tuptable = NULL;
 	_SPI_current->execSubid = InvalidSubTransactionId;
 	slist_init(&_SPI_current->tuptables);
@@ -139,7 +138,6 @@ SPI_connect_ext(int options)
 	_SPI_current->atomic = (options & SPI_OPT_NONATOMIC ? false : true);
 	_SPI_current->internal_xact = false;
 	_SPI_current->outer_processed = SPI_processed;
-	_SPI_current->outer_lastoid = SPI_lastoid;
 	_SPI_current->outer_tuptable = SPI_tuptable;
 	_SPI_current->outer_result = SPI_result;
 
@@ -169,7 +167,6 @@ SPI_connect_ext(int options)
 	 * depend on state of an outer caller.
 	 */
 	SPI_processed = 0;
-	SPI_lastoid = InvalidOid;
 	SPI_tuptable = NULL;
 	SPI_result = 0;
 
@@ -199,7 +196,6 @@ SPI_finish(void)
 	 * pointing at a just-deleted tuptable
 	 */
 	SPI_processed = _SPI_current->outer_processed;
-	SPI_lastoid = _SPI_current->outer_lastoid;
 	SPI_tuptable = _SPI_current->outer_tuptable;
 	SPI_result = _SPI_current->outer_result;
 
@@ -363,7 +359,6 @@ AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid)
 		 * be already gone.
 		 */
 		SPI_processed = connection->outer_processed;
-		SPI_lastoid = connection->outer_lastoid;
 		SPI_tuptable = connection->outer_tuptable;
 		SPI_result = connection->outer_result;
 
@@ -865,8 +860,6 @@ SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum,
 		mtuple->t_data->t_ctid = tuple->t_data->t_ctid;
 		mtuple->t_self = tuple->t_self;
 		mtuple->t_tableOid = tuple->t_tableOid;
-		if (rel->rd_att->tdhasoid)
-			HeapTupleSetOid(mtuple, HeapTupleGetOid(tuple));
 	}
 	else
 	{
@@ -897,7 +890,7 @@ SPI_fnumber(TupleDesc tupdesc, const char *fname)
 			return res + 1;
 	}
 
-	sysatt = SystemAttributeByName(fname, true /* "oid" will be accepted */ );
+	sysatt = SystemAttributeByName(fname);
 	if (sysatt != NULL)
 		return sysatt->attnum;
 
@@ -922,7 +915,7 @@ SPI_fname(TupleDesc tupdesc, int fnumber)
 	if (fnumber > 0)
 		att = TupleDescAttr(tupdesc, fnumber - 1);
 	else
-		att = SystemAttributeDefinition(fnumber, true);
+		att = SystemAttributeDefinition(fnumber);
 
 	return pstrdup(NameStr(att->attname));
 }
@@ -952,7 +945,7 @@ SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
 	if (fnumber > 0)
 		typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
 	else
-		typoid = (SystemAttributeDefinition(fnumber, true))->atttypid;
+		typoid = (SystemAttributeDefinition(fnumber))->atttypid;
 
 	getTypeOutputInfo(typoid, &foutoid, &typisvarlena);
 
@@ -994,7 +987,7 @@ SPI_gettype(TupleDesc tupdesc, int fnumber)
 	if (fnumber > 0)
 		typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
 	else
-		typoid = (SystemAttributeDefinition(fnumber, true))->atttypid;
+		typoid = (SystemAttributeDefinition(fnumber))->atttypid;
 
 	typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid));
 
@@ -1030,7 +1023,7 @@ SPI_gettypeid(TupleDesc tupdesc, int fnumber)
 	if (fnumber > 0)
 		return TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
 	else
-		return (SystemAttributeDefinition(fnumber, true))->atttypid;
+		return (SystemAttributeDefinition(fnumber))->atttypid;
 }
 
 char *
@@ -2170,7 +2163,6 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
 			DestReceiver *dest;
 
 			_SPI_current->processed = 0;
-			_SPI_current->lastoid = InvalidOid;
 			_SPI_current->tuptable = NULL;
 
 			if (stmt->utilityStmt)
@@ -2311,7 +2303,6 @@ _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI,
 			if (canSetTag)
 			{
 				my_processed = _SPI_current->processed;
-				my_lastoid = _SPI_current->lastoid;
 				SPI_freetuptable(my_tuptable);
 				my_tuptable = _SPI_current->tuptable;
 				my_res = res;
@@ -2471,7 +2462,6 @@ _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount)
 	ExecutorRun(queryDesc, ForwardScanDirection, tcount, true);
 
 	_SPI_current->processed = queryDesc->estate->es_processed;
-	_SPI_current->lastoid = queryDesc->estate->es_lastoid;
 
 	if ((res == SPI_OK_SELECT || queryDesc->plannedstmt->hasReturning) &&
 		queryDesc->dest->mydest == DestSPI)
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c
index eac78a5d315..d8cf865d33a 100644
--- a/src/backend/foreign/foreign.c
+++ b/src/backend/foreign/foreign.c
@@ -189,7 +189,7 @@ GetUserMapping(Oid userid, Oid serverid)
 						MappingUserName(userid))));
 
 	um = (UserMapping *) palloc(sizeof(UserMapping));
-	um->umid = HeapTupleGetOid(tp);
+	um->umid = ((Form_pg_user_mapping) GETSTRUCT(tp))->oid;
 	um->userid = userid;
 	um->serverid = serverid;
 
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 8369e3ad62d..e820bcff7fb 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -1695,8 +1695,7 @@ build_index_tlist(PlannerInfo *root, IndexOptInfo *index,
 			Form_pg_attribute att_tup;
 
 			if (indexkey < 0)
-				att_tup = SystemAttributeDefinition(indexkey,
-													heapRelation->rd_rel->relhasoids);
+				att_tup = SystemAttributeDefinition(indexkey);
 			else
 				att_tup = TupleDescAttr(heapRelation->rd_att, indexkey - 1);
 
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index d41eecd5bd5..08afa85969b 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -440,7 +440,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <boolean> opt_instead
 %type <boolean> opt_unique opt_concurrently opt_verbose opt_full
 %type <boolean> opt_freeze opt_analyze opt_default opt_recheck
-%type <defelt>	opt_binary opt_oids copy_delimiter
+%type <defelt>	opt_binary copy_delimiter
 
 %type <boolean> copy_from opt_program
 
@@ -2311,20 +2311,6 @@ alter_table_cmd:
 					n->missing_ok = false;
 					$$ = (Node *)n;
 				}
-			/* ALTER TABLE <name> SET WITH OIDS  */
-			| SET WITH OIDS
-				{
-					AlterTableCmd *n = makeNode(AlterTableCmd);
-					n->subtype = AT_AddOids;
-					$$ = (Node *)n;
-				}
-			/* ALTER TABLE <name> SET WITHOUT OIDS  */
-			| SET WITHOUT OIDS
-				{
-					AlterTableCmd *n = makeNode(AlterTableCmd);
-					n->subtype = AT_DropOids;
-					$$ = (Node *)n;
-				}
 			/* ALTER TABLE <name> CLUSTER ON <indexname> */
 			| CLUSTER ON name
 				{
@@ -2961,23 +2947,23 @@ ClosePortalStmt:
  *				syntax had a hard-wired, space-separated set of options.
  *
  *				Really old syntax, from versions 7.2 and prior:
- *				COPY [ BINARY ] table [ WITH OIDS ] FROM/TO file
+ *				COPY [ BINARY ] table FROM/TO file
  *					[ [ USING ] DELIMITERS 'delimiter' ] ]
  *					[ WITH NULL AS 'null string' ]
  *				This option placement is not supported with COPY (query...).
  *
  *****************************************************************************/
 
-CopyStmt:	COPY opt_binary qualified_name opt_column_list opt_oids
+CopyStmt:	COPY opt_binary qualified_name opt_column_list
 			copy_from opt_program copy_file_name copy_delimiter opt_with copy_options
 				{
 					CopyStmt *n = makeNode(CopyStmt);
 					n->relation = $3;
 					n->query = NULL;
 					n->attlist = $4;
-					n->is_from = $6;
-					n->is_program = $7;
-					n->filename = $8;
+					n->is_from = $5;
+					n->is_program = $6;
+					n->filename = $7;
 
 					if (n->is_program && n->filename == NULL)
 						ereport(ERROR,
@@ -2989,12 +2975,10 @@ CopyStmt:	COPY opt_binary qualified_name opt_column_list opt_oids
 					/* Concatenate user-supplied flags */
 					if ($2)
 						n->options = lappend(n->options, $2);
-					if ($5)
-						n->options = lappend(n->options, $5);
-					if ($9)
-						n->options = lappend(n->options, $9);
-					if ($11)
-						n->options = list_concat(n->options, $11);
+					if ($8)
+						n->options = lappend(n->options, $8);
+					if ($10)
+						n->options = list_concat(n->options, $10);
 					$$ = (Node *)n;
 				}
 			| COPY '(' PreparableStmt ')' TO opt_program copy_file_name opt_with copy_options
@@ -3118,14 +3102,6 @@ opt_binary:
 			| /*EMPTY*/								{ $$ = NULL; }
 		;
 
-opt_oids:
-			WITH OIDS
-				{
-					$$ = makeDefElem("oids", (Node *)makeInteger(true), @1);
-				}
-			| /*EMPTY*/								{ $$ = NULL; }
-		;
-
 copy_delimiter:
 			opt_using DELIMITERS Sconst
 				{
@@ -3948,7 +3924,6 @@ part_elem: ColId opt_collate opt_class
 /* WITH (options) is preferred, WITH OIDS and WITHOUT OIDS are legacy forms */
 OptWith:
 			WITH reloptions				{ $$ = $2; }
-			| WITH OIDS					{ $$ = list_make1(makeDefElem("oids", (Node *) makeInteger(true), @1)); }
 			| WITHOUT OIDS				{ $$ = list_make1(makeDefElem("oids", (Node *) makeInteger(false), @1)); }
 			| /*EMPTY*/					{ $$ = NIL; }
 		;
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index d6b93f55dfd..a30dca7a88f 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -248,46 +248,6 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
 	return rtindex;
 }
 
-/*
- * Given a relation-options list (of DefElems), return true iff the specified
- * table/result set should be created with OIDs. This needs to be done after
- * parsing the query string because the return value can depend upon the
- * default_with_oids GUC var.
- *
- * In some situations, we want to reject an OIDS option even if it's present.
- * That's (rather messily) handled here rather than reloptions.c, because that
- * code explicitly punts checking for oids to here.
- */
-bool
-interpretOidsOption(List *defList, bool allowOids)
-{
-	ListCell   *cell;
-
-	/* Scan list to see if OIDS was included */
-	foreach(cell, defList)
-	{
-		DefElem    *def = (DefElem *) lfirst(cell);
-
-		if (def->defnamespace == NULL &&
-			strcmp(def->defname, "oids") == 0)
-		{
-			if (!allowOids)
-				ereport(ERROR,
-						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-						 errmsg("unrecognized parameter \"%s\"",
-								def->defname)));
-			return defGetBoolean(def);
-		}
-	}
-
-	/* Force no-OIDS result if caller disallows OIDS. */
-	if (!allowOids)
-		return false;
-
-	/* OIDS option was not specified, so use default. */
-	return default_with_oids;
-}
-
 /*
  * Extract all not-in-common columns from column lists of a source table
  */
diff --git a/src/backend/parser/parse_oper.c b/src/backend/parser/parse_oper.c
index b279e1236ad..2f780b9941d 100644
--- a/src/backend/parser/parse_oper.c
+++ b/src/backend/parser/parse_oper.c
@@ -244,7 +244,7 @@ get_sort_group_operators(Oid argtype,
 Oid
 oprid(Operator op)
 {
-	return HeapTupleGetOid(op);
+	return ((Form_pg_operator) GETSTRUCT(op))->oid;
 }
 
 /* given operator tuple, return the underlying function's OID */
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 60b8de0f95d..fa18fa04254 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -1504,7 +1504,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
 		else if (functypclass == TYPEFUNC_SCALAR)
 		{
 			/* Base data type, i.e. scalar */
-			tupdesc = CreateTemplateTupleDesc(1, false);
+			tupdesc = CreateTemplateTupleDesc(1);
 			TupleDescInitEntry(tupdesc,
 							   (AttrNumber) 1,
 							   chooseScalarFunctionAlias(funcexpr, funcname,
@@ -1521,7 +1521,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
 			 * Use the column definition list to construct a tupdesc and fill
 			 * in the RangeTblFunction's lists.
 			 */
-			tupdesc = CreateTemplateTupleDesc(list_length(coldeflist), false);
+			tupdesc = CreateTemplateTupleDesc(list_length(coldeflist));
 			i = 1;
 			foreach(col, coldeflist)
 			{
@@ -1595,7 +1595,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
 			totalatts++;
 
 		/* Merge the tuple descs of each function into a composite one */
-		tupdesc = CreateTemplateTupleDesc(totalatts, false);
+		tupdesc = CreateTemplateTupleDesc(totalatts);
 		natts = 0;
 		for (i = 0; i < nfuncs; i++)
 		{
@@ -3089,10 +3089,7 @@ attnameAttNum(Relation rd, const char *attname, bool sysColOK)
 	if (sysColOK)
 	{
 		if ((i = specialAttNum(attname)) != InvalidAttrNumber)
-		{
-			if (i != ObjectIdAttributeNumber || rd->rd_rel->relhasoids)
-				return i;
-		}
+			return i;
 	}
 
 	/* on failure */
@@ -3106,15 +3103,14 @@ attnameAttNum(Relation rd, const char *attname, bool sysColOK)
  *
  * Note: this only discovers whether the name could be a system attribute.
  * Caller needs to verify that it really is an attribute of the rel,
- * at least in the case of "oid", which is now optional.
+ * at least in the case of "oid", which is now optional. XXX?
  */
 static int
 specialAttNum(const char *attname)
 {
 	Form_pg_attribute sysatt;
 
-	sysatt = SystemAttributeByName(attname,
-								   true /* "oid" will be accepted */ );
+	sysatt = SystemAttributeByName(attname);
 	if (sysatt != NULL)
 		return sysatt->attnum;
 	return InvalidAttrNumber;
@@ -3135,7 +3131,7 @@ attnumAttName(Relation rd, int attid)
 	{
 		Form_pg_attribute sysatt;
 
-		sysatt = SystemAttributeDefinition(attid, rd->rd_rel->relhasoids);
+		sysatt = SystemAttributeDefinition(attid);
 		return &sysatt->attname;
 	}
 	if (attid > rd->rd_att->natts)
@@ -3157,7 +3153,7 @@ attnumTypeId(Relation rd, int attid)
 	{
 		Form_pg_attribute sysatt;
 
-		sysatt = SystemAttributeDefinition(attid, rd->rd_rel->relhasoids);
+		sysatt = SystemAttributeDefinition(attid);
 		return sysatt->atttypid;
 	}
 	if (attid > rd->rd_att->natts)
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 4932e58022b..0aae9d90bf0 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -1497,7 +1497,7 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
 		expandRTE(rte, var->varno, 0, var->location, false,
 				  &names, &vars);
 
-		tupleDesc = CreateTemplateTupleDesc(list_length(vars), false);
+		tupleDesc = CreateTemplateTupleDesc(list_length(vars));
 		i = 1;
 		forboth(lname, names, lvar, vars)
 		{
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index d959b6122a5..e767018df7d 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -230,7 +230,7 @@ LookupTypeNameOid(ParseState *pstate, const TypeName *typeName, bool missing_ok)
 		return InvalidOid;
 	}
 
-	typoid = HeapTupleGetOid(tup);
+	typoid = ((Form_pg_type) GETSTRUCT(tup))->oid;
 	ReleaseSysCache(tup);
 
 	return typoid;
@@ -277,7 +277,7 @@ typenameTypeId(ParseState *pstate, const TypeName *typeName)
 	Type		tup;
 
 	tup = typenameType(pstate, typeName, NULL);
-	typoid = HeapTupleGetOid(tup);
+	typoid = ((Form_pg_type) GETSTRUCT(tup))->oid;
 	ReleaseSysCache(tup);
 
 	return typoid;
@@ -296,7 +296,7 @@ typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName,
 	Type		tup;
 
 	tup = typenameType(pstate, typeName, typmod_p);
-	*typeid_p = HeapTupleGetOid(tup);
+	*typeid_p = ((Form_pg_type) GETSTRUCT(tup))->oid;
 	ReleaseSysCache(tup);
 }
 
@@ -570,9 +570,13 @@ typeidType(Oid id)
 Oid
 typeTypeId(Type tp)
 {
+	Form_pg_type typ;
+
 	if (tp == NULL)				/* probably useless */
 		elog(ERROR, "typeTypeId() called with NULL type struct");
-	return HeapTupleGetOid(tp);
+
+	typ = (Form_pg_type) GETSTRUCT(tp);
+	return typ->oid;
 }
 
 /* given type (as type struct), return the length of type */
@@ -832,13 +836,15 @@ parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok
 	}
 	else
 	{
-		if (!((Form_pg_type) GETSTRUCT(tup))->typisdefined)
+		Form_pg_type typ = (Form_pg_type) GETSTRUCT(tup);
+
+		if (!typ->typisdefined)
 			ereport(ERROR,
 					(errcode(ERRCODE_UNDEFINED_OBJECT),
 					 errmsg("type \"%s\" is only a shell",
 							TypeNameToString(typeName)),
 					 parser_errposition(NULL, typeName->location)));
-		*typeid_p = HeapTupleGetOid(tup);
+		*typeid_p = typ->oid;
 		ReleaseSysCache(tup);
 	}
 }
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index f5c1e2a0d73..479bcdefb39 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -80,7 +80,6 @@ typedef struct
 	List	   *inhRelations;	/* relations to inherit from */
 	bool		isforeign;		/* true if CREATE/ALTER FOREIGN TABLE */
 	bool		isalter;		/* true if altering existing table */
-	bool		hasoids;		/* does relation have an OID column? */
 	List	   *columns;		/* ColumnDef items */
 	List	   *ckconstraints;	/* CHECK constraints */
 	List	   *fkconstraints;	/* FOREIGN KEY constraints */
@@ -168,7 +167,6 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
 	Oid			namespaceid;
 	Oid			existing_relid;
 	ParseCallbackState pcbstate;
-	bool		like_found = false;
 	bool		is_foreign_table = IsA(stmt, CreateForeignTableStmt);
 
 	/*
@@ -247,18 +245,6 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
 	cxt.partbound = stmt->partbound;
 	cxt.ofType = (stmt->ofTypename != NULL);
 
-	/*
-	 * Notice that we allow OIDs here only for plain tables, even though
-	 * foreign tables also support them.  This is necessary because the
-	 * default_with_oids GUC must apply only to plain tables and not any other
-	 * relkind; doing otherwise would break existing pg_dump files.  We could
-	 * allow explicit "WITH OIDS" while not allowing default_with_oids to
-	 * affect other relkinds, but it would complicate interpretOidsOption(),
-	 * and right now there's no WITH OIDS option in CREATE FOREIGN TABLE
-	 * anyway.
-	 */
-	cxt.hasoids = interpretOidsOption(stmt->options, !cxt.isforeign);
-
 	Assert(!stmt->ofTypename || !stmt->inhRelations);	/* grammar enforces */
 
 	if (stmt->ofTypename)
@@ -291,7 +277,6 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
 				break;
 
 			case T_TableLikeClause:
-				like_found = true;
 				transformTableLikeClause(&cxt, (TableLikeClause *) element);
 				break;
 
@@ -302,20 +287,6 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
 		}
 	}
 
-	/*
-	 * If we had any LIKE tables, they may require creation of an OID column
-	 * even though the command's own WITH clause didn't ask for one (or,
-	 * perhaps, even specifically rejected having one).  Insert a WITH option
-	 * to ensure that happens.  We prepend to the list because the first oid
-	 * option will be honored, and we want to override anything already there.
-	 * (But note that DefineRelation will override this again to add an OID
-	 * column if one appears in an inheritance parent table.)
-	 */
-	if (like_found && cxt.hasoids)
-		stmt->options = lcons(makeDefElem("oids",
-										  (Node *) makeInteger(true), -1),
-							  stmt->options);
-
 	/*
 	 * transformIndexConstraints wants cxt.alist to contain only index
 	 * statements, so transfer anything we already have into save_alist.
@@ -692,7 +663,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
 								 errmsg("identity columns are not supported on partitions")));
 
 					ctype = typenameType(cxt->pstate, column->typeName, NULL);
-					typeOid = HeapTupleGetOid(ctype);
+					typeOid = ((Form_pg_type) GETSTRUCT(ctype))->oid;
 					ReleaseSysCache(ctype);
 
 					if (saw_identity)
@@ -1080,9 +1051,6 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
 		}
 	}
 
-	/* We use oids if at least one LIKE'ed table has oids. */
-	cxt->hasoids |= relation->rd_rel->relhasoids;
-
 	/*
 	 * Copy CHECK constraints if requested, being careful to adjust attribute
 	 * numbers so they match the child.
@@ -1246,7 +1214,7 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
 
 	tuple = typenameType(NULL, ofTypename, NULL);
 	check_of_type(tuple);
-	ofTypeId = HeapTupleGetOid(tuple);
+	ofTypeId = ((Form_pg_type) GETSTRUCT(tuple))->oid;
 	ofTypename->typeOid = ofTypeId; /* cached for later */
 
 	tupdesc = lookup_rowtype_tupdesc(ofTypeId, -1);
@@ -2080,8 +2048,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
 				attform = TupleDescAttr(heap_rel->rd_att, attnum - 1);
 			}
 			else
-				attform = SystemAttributeDefinition(attnum,
-													heap_rel->rd_rel->relhasoids);
+				attform = SystemAttributeDefinition(attnum);
 			attname = pstrdup(NameStr(attform->attname));
 
 			if (i < index_form->indnkeyatts)
@@ -2171,7 +2138,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
 				if (constraint->contype == CONSTR_PRIMARY)
 					column->is_not_null = true;
 			}
-			else if (SystemAttributeByName(key, cxt->hasoids) != NULL)
+			else if (SystemAttributeByName(key) != NULL)
 			{
 				/*
 				 * column will be a system column in the new table, so accept
@@ -2294,7 +2261,7 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
 
 		if (!found)
 		{
-			if (SystemAttributeByName(key, cxt->hasoids) != NULL)
+			if (SystemAttributeByName(key) != NULL)
 			{
 				/*
 				 * column will be a system column in the new table, so accept
@@ -2959,7 +2926,6 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
 	cxt.rel = rel;
 	cxt.inhRelations = NIL;
 	cxt.isalter = true;
-	cxt.hasoids = false;		/* need not be right */
 	cxt.columns = NIL;
 	cxt.ckconstraints = NIL;
 	cxt.fkconstraints = NIL;
@@ -3392,7 +3358,7 @@ transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
 			ereport(ERROR,
 					(errcode(ERRCODE_DATATYPE_MISMATCH),
 					 errmsg("collations are not supported by type %s",
-							format_type_be(HeapTupleGetOid(ctype))),
+							format_type_be(typtup->oid)),
 					 parser_errposition(cxt->pstate,
 										column->collClause->location)));
 	}
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 978089575b8..31e98db9d69 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -1910,7 +1910,7 @@ get_database_list(void)
 
 		avdb = (avw_dbase *) palloc(sizeof(avw_dbase));
 
-		avdb->adw_datid = HeapTupleGetOid(tup);
+		avdb->adw_datid = pgdatabase->oid;
 		avdb->adw_name = pstrdup(NameStr(pgdatabase->datname));
 		avdb->adw_frozenxid = pgdatabase->datfrozenxid;
 		avdb->adw_minmulti = pgdatabase->datminmxid;
@@ -2072,7 +2072,7 @@ do_autovacuum(void)
 			classForm->relkind != RELKIND_MATVIEW)
 			continue;
 
-		relid = HeapTupleGetOid(tuple);
+		relid = classForm->oid;
 
 		/*
 		 * Check if it is a temp table (presumably, of some other backend's).
@@ -2166,7 +2166,7 @@ do_autovacuum(void)
 		if (classForm->relpersistence == RELPERSISTENCE_TEMP)
 			continue;
 
-		relid = HeapTupleGetOid(tuple);
+		relid = classForm->oid;
 
 		/*
 		 * fetch reloptions -- if this toast table does not have them, try the
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 8a5b2b3b420..14599137ae1 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -1209,6 +1209,7 @@ pgstat_collect_oids(Oid catalogid)
 	HeapScanDesc scan;
 	HeapTuple	tup;
 	Snapshot	snapshot;
+	AttrNumber	anum_oid = get_object_attnum_oid(catalogid);
 
 	memset(&hash_ctl, 0, sizeof(hash_ctl));
 	hash_ctl.keysize = sizeof(Oid);
@@ -1224,7 +1225,11 @@ pgstat_collect_oids(Oid catalogid)
 	scan = heap_beginscan(rel, snapshot, 0, NULL);
 	while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
-		Oid			thisoid = HeapTupleGetOid(tup);
+		Oid			thisoid;
+		bool		isnull;
+
+		thisoid = heap_getattr(tup, anum_oid, RelationGetDescr(rel), &isnull);
+		Assert(!isnull);
 
 		CHECK_FOR_INTERRUPTS();
 
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 1e1695ef4f4..e2b54265d78 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -868,7 +868,7 @@ libpqrcv_processTuples(PGresult *pgres, WalRcvExecResult *walres,
 	walres->tuplestore = tuplestore_begin_heap(true, false, work_mem);
 
 	/* Create tuple descriptor corresponding to expected result. */
-	walres->tupledesc = CreateTemplateTupleDesc(nRetTypes, false);
+	walres->tupledesc = CreateTemplateTupleDesc(nRetTypes);
 	for (coln = 0; coln < nRetTypes; coln++)
 		TupleDescInitEntry(walres->tupledesc, (AttrNumber) coln + 1,
 						   PQfname(pgres, coln), retTypes[coln], -1, 0);
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index ada16adb67b..ce089ac07ca 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -153,7 +153,7 @@ get_subscription_list(void)
 		oldcxt = MemoryContextSwitchTo(resultcxt);
 
 		sub = (Subscription *) palloc0(sizeof(Subscription));
-		sub->oid = HeapTupleGetOid(tup);
+		sub->oid = subform->oid;
 		sub->dbid = subform->subdbid;
 		sub->owner = subform->subowner;
 		sub->enabled = subform->subenabled;
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 370429d746c..426c5acfd16 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -390,7 +390,7 @@ IdentifySystem(void)
 	MemSet(nulls, false, sizeof(nulls));
 
 	/* need a tuple descriptor representing four columns */
-	tupdesc = CreateTemplateTupleDesc(4, false);
+	tupdesc = CreateTemplateTupleDesc(4);
 	TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, "systemid",
 							  TEXTOID, -1, 0);
 	TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "timeline",
@@ -726,7 +726,7 @@ StartReplication(StartReplicationCmd *cmd)
 		 * like a surprising data type for this, but in theory int4 would not
 		 * be wide enough for this, as TimeLineID is unsigned.
 		 */
-		tupdesc = CreateTemplateTupleDesc(2, false);
+		tupdesc = CreateTemplateTupleDesc(2);
 		TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, "next_tli",
 								  INT8OID, -1, 0);
 		TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "next_tli_startpos",
@@ -994,7 +994,7 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
 	 * - fourth field: output plugin
 	 *----------
 	 */
-	tupdesc = CreateTemplateTupleDesc(4, false);
+	tupdesc = CreateTemplateTupleDesc(4);
 	TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, "slot_name",
 							  TEXTOID, -1, 0);
 	TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "consistent_point",
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index d81a2ea342b..4c6cd978e81 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -128,14 +128,18 @@ InsertRule(const char *rulname,
 
 		ReleaseSysCache(oldtup);
 
-		rewriteObjectId = HeapTupleGetOid(tup);
+		rewriteObjectId = ((Form_pg_rewrite) GETSTRUCT(tup))->oid;
 		is_update = true;
 	}
 	else
 	{
+		rewriteObjectId = GetNewOidWithIndex(pg_rewrite_desc, RewriteOidIndexId, Anum_pg_rewrite_oid);
+
+		values[Anum_pg_rewrite_oid - 1] = ObjectIdGetDatum(rewriteObjectId);
+
 		tup = heap_form_tuple(pg_rewrite_desc->rd_att, values, nulls);
 
-		rewriteObjectId = CatalogTupleInsert(pg_rewrite_desc, tup);
+		CatalogTupleInsert(pg_rewrite_desc, tup);
 	}
 
 
@@ -617,7 +621,6 @@ DefineQueryRewrite(const char *rulename,
 		classForm->reltoastrelid = InvalidOid;
 		classForm->relhasindex = false;
 		classForm->relkind = RELKIND_VIEW;
-		classForm->relhasoids = false;
 		classForm->relfrozenxid = InvalidTransactionId;
 		classForm->relminmxid = InvalidMultiXactId;
 		classForm->relreplident = REPLICA_IDENTITY_NOTHING;
@@ -842,6 +845,7 @@ EnableDisableRule(Relation rel, const char *rulename,
 	Oid			owningRel = RelationGetRelid(rel);
 	Oid			eventRelationOid;
 	HeapTuple	ruletup;
+	Form_pg_rewrite ruleform;
 	bool		changed = false;
 
 	/*
@@ -857,10 +861,12 @@ EnableDisableRule(Relation rel, const char *rulename,
 				 errmsg("rule \"%s\" for relation \"%s\" does not exist",
 						rulename, get_rel_name(owningRel))));
 
+	ruleform = (Form_pg_rewrite) GETSTRUCT(ruletup);
+
 	/*
 	 * Verify that the user has appropriate permissions.
 	 */
-	eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(ruletup))->ev_class;
+	eventRelationOid = ruleform->ev_class;
 	Assert(eventRelationOid == owningRel);
 	if (!pg_class_ownercheck(eventRelationOid, GetUserId()))
 		aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(get_rel_relkind(eventRelationOid)),
@@ -869,18 +875,16 @@ EnableDisableRule(Relation rel, const char *rulename,
 	/*
 	 * Change ev_enabled if it is different from the desired new state.
 	 */
-	if (DatumGetChar(((Form_pg_rewrite) GETSTRUCT(ruletup))->ev_enabled) !=
+	if (DatumGetChar(ruleform->ev_enabled) !=
 		fires_when)
 	{
-		((Form_pg_rewrite) GETSTRUCT(ruletup))->ev_enabled =
-			CharGetDatum(fires_when);
+		ruleform->ev_enabled = CharGetDatum(fires_when);
 		CatalogTupleUpdate(pg_rewrite_desc, &ruletup->t_self, ruletup);
 
 		changed = true;
 	}
 
-	InvokeObjectPostAlterHook(RewriteRelationId,
-							  HeapTupleGetOid(ruletup), 0);
+	InvokeObjectPostAlterHook(RewriteRelationId, ruleform->oid, 0);
 
 	heap_freetuple(ruletup);
 	heap_close(pg_rewrite_desc, RowExclusiveLock);
@@ -971,7 +975,7 @@ RenameRewriteRule(RangeVar *relation, const char *oldName,
 				 errmsg("rule \"%s\" for relation \"%s\" does not exist",
 						oldName, RelationGetRelationName(targetrel))));
 	ruleform = (Form_pg_rewrite) GETSTRUCT(ruletup);
-	ruleOid = HeapTupleGetOid(ruletup);
+	ruleOid = ruleform->oid;
 
 	/* rule with the new name should not already exist */
 	if (IsDefinedRewriteRule(relid, newName))
diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c
index 07de85b8a31..73e67083fbf 100644
--- a/src/backend/rewrite/rewriteRemove.c
+++ b/src/backend/rewrite/rewriteRemove.c
@@ -53,7 +53,7 @@ RemoveRewriteRuleById(Oid ruleOid)
 	 * Find the tuple for the target rule.
 	 */
 	ScanKeyInit(&skey[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_rewrite_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(ruleOid));
 
diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c
index ab291a43e2c..c87fe4a4d93 100644
--- a/src/backend/rewrite/rewriteSupport.c
+++ b/src/backend/rewrite/rewriteSupport.c
@@ -94,6 +94,7 @@ Oid
 get_rewrite_oid(Oid relid, const char *rulename, bool missing_ok)
 {
 	HeapTuple	tuple;
+	Form_pg_rewrite ruleform;
 	Oid			ruleoid;
 
 	/* Find the rule's pg_rewrite tuple, get its OID */
@@ -109,8 +110,9 @@ get_rewrite_oid(Oid relid, const char *rulename, bool missing_ok)
 				 errmsg("rule \"%s\" for relation \"%s\" does not exist",
 						rulename, get_rel_name(relid))));
 	}
-	Assert(relid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class);
-	ruleoid = HeapTupleGetOid(tuple);
+	ruleform = (Form_pg_rewrite) GETSTRUCT(tuple);
+	Assert(relid == ruleform->ev_class);
+	ruleoid = ruleform->oid;
 	ReleaseSysCache(tuple);
 	return ruleoid;
 }
diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c
index 2df5f7dc3a5..5dcee95250a 100644
--- a/src/backend/statistics/extended_stats.c
+++ b/src/backend/statistics/extended_stats.c
@@ -196,8 +196,8 @@ fetch_statentries_for_relation(Relation pg_statext, Oid relid)
 		Form_pg_statistic_ext staForm;
 
 		entry = palloc0(sizeof(StatExtEntry));
-		entry->statOid = HeapTupleGetOid(htup);
 		staForm = (Form_pg_statistic_ext) GETSTRUCT(htup);
+		entry->statOid = staForm->oid;
 		entry->schema = get_namespace_name(staForm->stxnamespace);
 		entry->name = pstrdup(NameStr(staForm->stxname));
 		for (i = 0; i < staForm->stxkeys.dim1; i++)
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index 7eac0724bb2..af22b6ba6dc 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -137,7 +137,7 @@ myLargeObjectExists(Oid loid, Snapshot snapshot)
 	bool		retval = false;
 
 	ScanKeyInit(&skey[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_largeobject_metadata_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(loid));
 
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 66cc5c35c68..ae6dd415def 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -175,10 +175,8 @@ ProcessQuery(PlannedStmt *plan,
 						 queryDesc->estate->es_processed);
 				break;
 			case CMD_INSERT:
-				if (queryDesc->estate->es_processed == 1)
-					lastOid = queryDesc->estate->es_lastoid;
-				else
-					lastOid = InvalidOid;
+				/* lastoid doesn't exist anymore */
+				lastOid = InvalidOid;
 				snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
 						 "INSERT %u " UINT64_FORMAT,
 						 lastOid, queryDesc->estate->es_processed);
@@ -551,8 +549,7 @@ PortalStart(Portal portal, ParamListInfo params,
 
 					pstmt = PortalGetPrimaryStmt(portal);
 					portal->tupDesc =
-						ExecCleanTypeFromTL(pstmt->planTree->targetlist,
-											false);
+						ExecCleanTypeFromTL(pstmt->planTree->targetlist);
 				}
 
 				/*
diff --git a/src/backend/tsearch/wparser.c b/src/backend/tsearch/wparser.c
index 649245b2922..e8b612d4310 100644
--- a/src/backend/tsearch/wparser.c
+++ b/src/backend/tsearch/wparser.c
@@ -66,7 +66,7 @@ tt_setup_firstcall(FuncCallContext *funcctx, Oid prsid)
 															 (Datum) 0));
 	funcctx->user_fctx = (void *) st;
 
-	tupdesc = CreateTemplateTupleDesc(3, false);
+	tupdesc = CreateTemplateTupleDesc(3);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tokid",
 					   INT4OID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "alias",
@@ -212,7 +212,7 @@ prs_setup_firstcall(FuncCallContext *funcctx, Oid prsid, text *txt)
 	st->cur = 0;
 
 	funcctx->user_fctx = (void *) st;
-	tupdesc = CreateTemplateTupleDesc(2, false);
+	tupdesc = CreateTemplateTupleDesc(2);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "tokid",
 					   INT4OID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "token",
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index d5285e25999..09109eee139 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -1763,7 +1763,7 @@ aclexplode(PG_FUNCTION_ARGS)
 		 * build tupdesc for result tuples (matches out parameters in pg_proc
 		 * entry)
 		 */
-		tupdesc = CreateTemplateTupleDesc(4, false);
+		tupdesc = CreateTemplateTupleDesc(4);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "grantor",
 						   OIDOID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "grantee",
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index 46159de7958..232b45fc853 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -4674,7 +4674,7 @@ pg_timezone_abbrevs(PG_FUNCTION_ARGS)
 		 * build tupdesc for result tuples. This must match this function's
 		 * pg_proc entry!
 		 */
-		tupdesc = CreateTemplateTupleDesc(3, false);
+		tupdesc = CreateTemplateTupleDesc(3);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "abbrev",
 						   TEXTOID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "utc_offset",
@@ -4801,7 +4801,7 @@ pg_timezone_names(PG_FUNCTION_ARGS)
 		 * build tupdesc for result tuples. This must match this function's
 		 * pg_proc entry!
 		 */
-		tupdesc = CreateTemplateTupleDesc(4, false);
+		tupdesc = CreateTemplateTupleDesc(4);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
 						   TEXTOID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "abbrev",
diff --git a/src/backend/utils/adt/enum.c b/src/backend/utils/adt/enum.c
index 562cd5c555d..043ff2b50ab 100644
--- a/src/backend/utils/adt/enum.c
+++ b/src/backend/utils/adt/enum.c
@@ -63,7 +63,7 @@ enum_in(PG_FUNCTION_ARGS)
 	 * This comes from pg_enum.oid and stores system oids in user tables. This
 	 * oid must be preserved by binary upgrades.
 	 */
-	enumoid = HeapTupleGetOid(tup);
+	enumoid = ((Form_pg_enum) GETSTRUCT(tup))->oid;
 
 	ReleaseSysCache(tup);
 
@@ -124,7 +124,7 @@ enum_recv(PG_FUNCTION_ARGS)
 						format_type_be(enumtypoid),
 						name)));
 
-	enumoid = HeapTupleGetOid(tup);
+	enumoid = ((Form_pg_enum) GETSTRUCT(tup))->oid;
 
 	ReleaseSysCache(tup);
 
@@ -331,7 +331,7 @@ enum_endpoint(Oid enumtypoid, ScanDirection direction)
 
 	enum_tuple = systable_getnext_ordered(enum_scan, direction);
 	if (HeapTupleIsValid(enum_tuple))
-		minmax = HeapTupleGetOid(enum_tuple);
+		minmax = ((Form_pg_enum) GETSTRUCT(enum_tuple))->oid;
 	else
 		minmax = InvalidOid;
 
@@ -487,7 +487,7 @@ enum_range_internal(Oid enumtypoid, Oid lower, Oid upper)
 
 	while (HeapTupleIsValid(enum_tuple = systable_getnext_ordered(enum_scan, ForwardScanDirection)))
 	{
-		Oid			enum_oid = HeapTupleGetOid(enum_tuple);
+		Oid			enum_oid = ((Form_pg_enum) GETSTRUCT(enum_tuple))->oid;
 
 		if (!left_found && lower == enum_oid)
 			left_found = true;
diff --git a/src/backend/utils/adt/expandedrecord.c b/src/backend/utils/adt/expandedrecord.c
index b1b6883c19f..0e517465ed5 100644
--- a/src/backend/utils/adt/expandedrecord.c
+++ b/src/backend/utils/adt/expandedrecord.c
@@ -741,9 +741,6 @@ ER_get_flat_size(ExpandedObjectHeader *eohptr)
 	if (hasnull)
 		len += BITMAPLEN(tupdesc->natts);
 
-	if (tupdesc->tdhasoid)
-		len += sizeof(Oid);
-
 	hoff = len = MAXALIGN(len); /* align user data safely */
 
 	data_len = heap_compute_data_size(tupdesc, erh->dvalues, erh->dnulls);
@@ -804,9 +801,6 @@ ER_flatten_into(ExpandedObjectHeader *eohptr,
 	HeapTupleHeaderSetNatts(tuphdr, tupdesc->natts);
 	tuphdr->t_hoff = erh->hoff;
 
-	if (tupdesc->tdhasoid)		/* else leave infomask = 0 */
-		tuphdr->t_infomask = HEAP_HASOID;
-
 	/* And fill the data area from dvalues/dnulls */
 	heap_fill_tuple(tupdesc,
 					erh->dvalues,
@@ -1044,7 +1038,7 @@ expanded_record_lookup_field(ExpandedRecordHeader *erh, const char *fieldname,
 	}
 
 	/* How about system attributes? */
-	attr = SystemAttributeByName(fieldname, tupdesc->tdhasoid);
+	attr = SystemAttributeByName(fieldname);
 	if (attr != NULL)
 	{
 		finfo->fnumber = attr->attnum;
diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index a97cbea2483..3fa3430d1d4 100644
--- a/src/backend/utils/adt/genfile.c
+++ b/src/backend/utils/adt/genfile.c
@@ -386,7 +386,7 @@ pg_stat_file(PG_FUNCTION_ARGS)
 	 * This record type had better match the output parameters declared for me
 	 * in pg_proc.h.
 	 */
-	tupdesc = CreateTemplateTupleDesc(6, false);
+	tupdesc = CreateTemplateTupleDesc(6);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1,
 					   "size", INT8OID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2,
@@ -536,7 +536,7 @@ pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir)
 
 		fctx = palloc(sizeof(directory_fctx));
 
-		tupdesc = CreateTemplateTupleDesc(3, false);
+		tupdesc = CreateTemplateTupleDesc(3);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
 						   TEXTOID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "size",
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index 66c09a1f316..525decb6f1b 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -101,7 +101,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
 
 		/* build tupdesc for result tuples */
 		/* this had better match function's declaration in pg_proc.h */
-		tupdesc = CreateTemplateTupleDesc(NUM_LOCK_STATUS_COLUMNS, false);
+		tupdesc = CreateTemplateTupleDesc(NUM_LOCK_STATUS_COLUMNS);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "locktype",
 						   TEXTOID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database",
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index b24dece23f8..aeeff67ba86 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -596,7 +596,7 @@ pg_get_keywords(PG_FUNCTION_ARGS)
 		funcctx = SRF_FIRSTCALL_INIT();
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-		tupdesc = CreateTemplateTupleDesc(3, false);
+		tupdesc = CreateTemplateTupleDesc(3);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "word",
 						   TEXTOID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catcode",
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c
index be9422dcfb6..fcebfa218ec 100644
--- a/src/backend/utils/adt/orderedsetaggs.c
+++ b/src/backend/utils/adt/orderedsetaggs.c
@@ -215,7 +215,7 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
 			 * Get a tupledesc corresponding to the aggregated inputs
 			 * (including sort expressions) of the agg.
 			 */
-			qstate->tupdesc = ExecTypeFromTL(aggref->args, false);
+			qstate->tupdesc = ExecTypeFromTL(aggref->args);
 
 			/* If we need a flag column, hack the tupledesc to include that */
 			if (ishypothetical)
@@ -223,7 +223,7 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
 				TupleDesc	newdesc;
 				int			natts = qstate->tupdesc->natts;
 
-				newdesc = CreateTemplateTupleDesc(natts + 1, false);
+				newdesc = CreateTemplateTupleDesc(natts + 1);
 				for (i = 1; i <= natts; i++)
 					TupleDescCopyEntry(newdesc, i, qstate->tupdesc, i);
 
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index e95e3471846..f955f1912a4 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -1829,7 +1829,7 @@ pg_stat_get_archiver(PG_FUNCTION_ARGS)
 	MemSet(nulls, 0, sizeof(nulls));
 
 	/* Initialise attributes information in the tuple descriptor */
-	tupdesc = CreateTemplateTupleDesc(7, false);
+	tupdesc = CreateTemplateTupleDesc(7);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "archived_count",
 					   INT8OID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "last_archived_wal",
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index eecd64e4b57..17780de6847 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -843,7 +843,7 @@ pg_get_triggerdef_worker(Oid trigid, bool pretty)
 	tgrel = heap_open(TriggerRelationId, AccessShareLock);
 
 	ScanKeyInit(&skey[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_trigger_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(trigid));
 
@@ -1879,7 +1879,7 @@ pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
 	Relation	relation = heap_open(ConstraintRelationId, AccessShareLock);
 
 	ScanKeyInit(&scankey[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_constraint_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(constraintId));
 
@@ -2926,11 +2926,10 @@ print_function_arguments(StringInfo buf, HeapTuple proctup,
 		HeapTuple	aggtup;
 		Form_pg_aggregate agg;
 
-		aggtup = SearchSysCache1(AGGFNOID,
-								 ObjectIdGetDatum(HeapTupleGetOid(proctup)));
+		aggtup = SearchSysCache1(AGGFNOID, proc->oid);
 		if (!HeapTupleIsValid(aggtup))
 			elog(ERROR, "cache lookup failed for aggregate %u",
-				 HeapTupleGetOid(proctup));
+				 proc->oid);
 		agg = (Form_pg_aggregate) GETSTRUCT(aggtup);
 		if (AGGKIND_IS_ORDERED_SET(agg->aggkind))
 			insertorderbyat = agg->aggnumdirectargs;
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index b8c0e034ca1..c83b4c4c2a7 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -5233,7 +5233,6 @@ get_variable_numdistinct(VariableStatData *vardata, bool *isdefault)
 		{
 			switch (((Var *) vardata->var)->varattno)
 			{
-				case ObjectIdAttributeNumber:
 				case SelfItemPointerAttributeNumber:
 					stadistinct = -1.0; /* unique (and all non null) */
 					break;
diff --git a/src/backend/utils/adt/trigfuncs.c b/src/backend/utils/adt/trigfuncs.c
index 04605021d79..93ac936420d 100644
--- a/src/backend/utils/adt/trigfuncs.c
+++ b/src/backend/utils/adt/trigfuncs.c
@@ -66,17 +66,6 @@ suppress_redundant_updates_trigger(PG_FUNCTION_ARGS)
 	newheader = newtuple->t_data;
 	oldheader = oldtuple->t_data;
 
-	/*
-	 * We are called before the OID, if any, has been transcribed from the old
-	 * tuple to the new (in heap_update).  To avoid a bogus compare failure,
-	 * copy the OID now.  But check that someone didn't already put another
-	 * OID value into newtuple.  (That's not actually possible at present, but
-	 * maybe someday.)
-	 */
-	if (trigdata->tg_relation->rd_rel->relhasoids &&
-		!OidIsValid(HeapTupleHeaderGetOid(newheader)))
-		HeapTupleHeaderSetOid(newheader, HeapTupleHeaderGetOid(oldheader));
-
 	/* if the tuple payload is the same ... */
 	if (newtuple->t_len == oldtuple->t_len &&
 		newheader->t_hoff == oldheader->t_hoff &&
diff --git a/src/backend/utils/adt/tsvector_op.c b/src/backend/utils/adt/tsvector_op.c
index 258fe47a245..3c55166a14e 100644
--- a/src/backend/utils/adt/tsvector_op.c
+++ b/src/backend/utils/adt/tsvector_op.c
@@ -646,7 +646,7 @@ tsvector_unnest(PG_FUNCTION_ARGS)
 		funcctx = SRF_FIRSTCALL_INIT();
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-		tupdesc = CreateTemplateTupleDesc(3, false);
+		tupdesc = CreateTemplateTupleDesc(3);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "lexeme",
 						   TEXTOID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "positions",
@@ -2187,7 +2187,7 @@ ts_setup_firstcall(FunctionCallInfo fcinfo, FuncCallContext *funcctx,
 		}
 	Assert(stat->stackpos <= stat->maxdepth);
 
-	tupdesc = CreateTemplateTupleDesc(3, false);
+	tupdesc = CreateTemplateTupleDesc(3);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "word",
 					   TEXTOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "ndoc",
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 5ddbf6eab10..b31fd5acea7 100644
--- a/src/backend/utils/cache/catcache.c
+++ b/src/backend/utils/cache/catcache.c
@@ -338,39 +338,31 @@ CatalogCacheComputeTupleHashValue(CatCache *cache, int nkeys, HeapTuple tuple)
 	switch (nkeys)
 	{
 		case 4:
-			v4 = (cc_keyno[3] == ObjectIdAttributeNumber)
-				? ObjectIdGetDatum(HeapTupleGetOid(tuple))
-				: fastgetattr(tuple,
-							  cc_keyno[3],
-							  cc_tupdesc,
-							  &isNull);
+			v4 = fastgetattr(tuple,
+							 cc_keyno[3],
+							 cc_tupdesc,
+							 &isNull);
 			Assert(!isNull);
 			/* FALLTHROUGH */
 		case 3:
-			v3 = (cc_keyno[2] == ObjectIdAttributeNumber)
-				? ObjectIdGetDatum(HeapTupleGetOid(tuple))
-				: fastgetattr(tuple,
-							  cc_keyno[2],
-							  cc_tupdesc,
-							  &isNull);
+			v3 = fastgetattr(tuple,
+							 cc_keyno[2],
+							 cc_tupdesc,
+							 &isNull);
 			Assert(!isNull);
 			/* FALLTHROUGH */
 		case 2:
-			v2 = (cc_keyno[1] == ObjectIdAttributeNumber)
-				? ObjectIdGetDatum(HeapTupleGetOid(tuple))
-				: fastgetattr(tuple,
-							  cc_keyno[1],
-							  cc_tupdesc,
-							  &isNull);
+			v2 = fastgetattr(tuple,
+							 cc_keyno[1],
+							 cc_tupdesc,
+							 &isNull);
 			Assert(!isNull);
 			/* FALLTHROUGH */
 		case 1:
-			v1 = (cc_keyno[0] == ObjectIdAttributeNumber)
-				? ObjectIdGetDatum(HeapTupleGetOid(tuple))
-				: fastgetattr(tuple,
-							  cc_keyno[0],
-							  cc_tupdesc,
-							  &isNull);
+			v1 = fastgetattr(tuple,
+							 cc_keyno[0],
+							 cc_tupdesc,
+							 &isNull);
 			Assert(!isNull);
 			break;
 		default:
@@ -998,8 +990,8 @@ CatalogCacheInitializeCache(CatCache *cache)
 		}
 		else
 		{
-			if (cache->cc_keyno[i] != ObjectIdAttributeNumber)
-				elog(FATAL, "only sys attr supported in caches is OID");
+			if (cache->cc_keyno[i] < 0)
+				elog(FATAL, "sys attributes are not supported in caches");
 			keytype = OIDOID;
 		}
 
@@ -1935,9 +1927,7 @@ CatCacheFreeKeys(TupleDesc tupdesc, int nkeys, int *attnos, Datum *keys)
 		int			attnum = attnos[i];
 		Form_pg_attribute att;
 
-		/* only valid system attribute is the oid, which is by value */
-		if (attnum == ObjectIdAttributeNumber)
-			continue;
+		/* system attribute are not supported in caches */
 		Assert(attnum > 0);
 
 		att = TupleDescAttr(tupdesc, attnum - 1);
@@ -1966,33 +1956,25 @@ CatCacheCopyKeys(TupleDesc tupdesc, int nkeys, int *attnos,
 	for (i = 0; i < nkeys; i++)
 	{
 		int			attnum = attnos[i];
+		Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
+		Datum		src = srckeys[i];
+		NameData	srcname;
 
-		if (attnum == ObjectIdAttributeNumber)
+		/*
+		 * Must be careful in case the caller passed a C string where a
+		 * NAME is wanted: convert the given argument to a correctly
+		 * padded NAME.  Otherwise the memcpy() done by datumCopy() could
+		 * fall off the end of memory.
+		 */
+		if (att->atttypid == NAMEOID)
 		{
-			dstkeys[i] = srckeys[i];
+			namestrcpy(&srcname, DatumGetCString(src));
+			src = NameGetDatum(&srcname);
 		}
-		else
-		{
-			Form_pg_attribute att = TupleDescAttr(tupdesc, attnum - 1);
-			Datum		src = srckeys[i];
-			NameData	srcname;
 
-			/*
-			 * Must be careful in case the caller passed a C string where a
-			 * NAME is wanted: convert the given argument to a correctly
-			 * padded NAME.  Otherwise the memcpy() done by datumCopy() could
-			 * fall off the end of memory.
-			 */
-			if (att->atttypid == NAMEOID)
-			{
-				namestrcpy(&srcname, DatumGetCString(src));
-				src = NameGetDatum(&srcname);
-			}
-
-			dstkeys[i] = datumCopy(src,
-								   att->attbyval,
-								   att->attlen);
-		}
+		dstkeys[i] = datumCopy(src,
+							   att->attbyval,
+							   att->attlen);
 	}
 
 }
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index f3ded4def90..51574937959 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -1166,7 +1166,7 @@ CacheInvalidateHeapTuple(Relation relation,
 	{
 		Form_pg_class classtup = (Form_pg_class) GETSTRUCT(tuple);
 
-		relationId = HeapTupleGetOid(tuple);
+		relationId = classtup->oid;
 		if (classtup->relisshared)
 			databaseId = InvalidOid;
 		else
@@ -1292,7 +1292,7 @@ CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
 
 	PrepareInvalidationState();
 
-	relationId = HeapTupleGetOid(classTuple);
+	relationId = classtup->oid;
 	if (classtup->relisshared)
 		databaseId = InvalidOid;
 	else
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 12b2532d957..7147c198f0b 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -2115,7 +2115,7 @@ getTypeIOParam(HeapTuple typeTuple)
 	if (OidIsValid(typeStruct->typelem))
 		return typeStruct->typelem;
 	else
-		return HeapTupleGetOid(typeTuple);
+		return typeStruct->oid;
 }
 
 /*
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 7271b5880b8..210e0e4bcc4 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -1688,12 +1688,12 @@ PlanCacheComputeResultDesc(List *stmt_list)
 		case PORTAL_ONE_SELECT:
 		case PORTAL_ONE_MOD_WITH:
 			query = linitial_node(Query, stmt_list);
-			return ExecCleanTypeFromTL(query->targetList, false);
+			return ExecCleanTypeFromTL(query->targetList);
 
 		case PORTAL_ONE_RETURNING:
 			query = QueryListGetPrimaryStmt(stmt_list);
 			Assert(query->returningList);
-			return ExecCleanTypeFromTL(query->returningList, false);
+			return ExecCleanTypeFromTL(query->returningList);
 
 		case PORTAL_UTIL_SELECT:
 			query = linitial_node(Query, stmt_list);
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index a4fc0011031..93e7d1994be 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -261,8 +261,7 @@ static void write_relcache_init_file(bool shared);
 static void write_item(const void *data, Size len, FILE *fp);
 
 static void formrdesc(const char *relationName, Oid relationReltype,
-		  bool isshared, bool hasoids,
-		  int natts, const FormData_pg_attribute *attrs);
+		  bool isshared, int natts, const FormData_pg_attribute *attrs);
 
 static HeapTuple ScanPgRelation(Oid targetRelId, bool indexOK, bool force_non_historic);
 static Relation AllocateRelationDesc(Form_pg_class relp);
@@ -328,7 +327,7 @@ ScanPgRelation(Oid targetRelId, bool indexOK, bool force_non_historic)
 	 * form a scan key
 	 */
 	ScanKeyInit(&key[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_class_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(targetRelId));
 
@@ -414,8 +413,7 @@ AllocateRelationDesc(Form_pg_class relp)
 	relation->rd_rel = relationForm;
 
 	/* and allocate attribute tuple form storage */
-	relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts,
-											   relationForm->relhasoids);
+	relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts);
 	/* which we mark as a reference-counted tupdesc */
 	relation->rd_att->tdrefcount = 1;
 
@@ -505,7 +503,6 @@ RelationBuildTupleDesc(Relation relation)
 	/* copy some fields from pg_class row to rd_att */
 	relation->rd_att->tdtypeid = relation->rd_rel->reltype;
 	relation->rd_att->tdtypmod = -1;	/* unnecessary, but... */
-	relation->rd_att->tdhasoid = relation->rd_rel->relhasoids;
 
 	constr = (TupleConstr *) MemoryContextAlloc(CacheMemoryContext,
 												sizeof(TupleConstr));
@@ -789,7 +786,7 @@ RelationBuildRuleLock(Relation relation)
 		rule = (RewriteRule *) MemoryContextAlloc(rulescxt,
 												  sizeof(RewriteRule));
 
-		rule->ruleId = HeapTupleGetOid(rewrite_tuple);
+		rule->ruleId = rewrite_form->oid;
 
 		rule->event = rewrite_form->ev_type - '0';
 		rule->enabled = rewrite_form->ev_enabled;
@@ -1090,8 +1087,8 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
 	/*
 	 * get information from the pg_class_tuple
 	 */
-	relid = HeapTupleGetOid(pg_class_tuple);
 	relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
+	relid = relp->oid;
 	Assert(relid == targetRelId);
 
 	/*
@@ -1641,7 +1638,7 @@ LookupOpclassInfo(Oid operatorClassOid,
 	 * work while bootstrapping.
 	 */
 	ScanKeyInit(&skey[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_opclass_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(operatorClassOid));
 	rel = heap_open(OperatorClassRelationId, AccessShareLock);
@@ -1725,7 +1722,7 @@ LookupOpclassInfo(Oid operatorClassOid,
  */
 static void
 formrdesc(const char *relationName, Oid relationReltype,
-		  bool isshared, bool hasoids,
+		  bool isshared,
 		  int natts, const FormData_pg_attribute *attrs)
 {
 	Relation	relation;
@@ -1789,7 +1786,6 @@ formrdesc(const char *relationName, Oid relationReltype,
 	relation->rd_rel->reltuples = 0;
 	relation->rd_rel->relallvisible = 0;
 	relation->rd_rel->relkind = RELKIND_RELATION;
-	relation->rd_rel->relhasoids = hasoids;
 	relation->rd_rel->relnatts = (int16) natts;
 
 	/*
@@ -1799,7 +1795,7 @@ formrdesc(const char *relationName, Oid relationReltype,
 	 * because it will never be replaced.  The data comes from
 	 * src/include/catalog/ headers via genbki.pl.
 	 */
-	relation->rd_att = CreateTemplateTupleDesc(natts, hasoids);
+	relation->rd_att = CreateTemplateTupleDesc(natts);
 	relation->rd_att->tdrefcount = 1;	/* mark as refcounted */
 
 	relation->rd_att->tdtypeid = relationReltype;
@@ -2964,7 +2960,9 @@ AtEOXact_cleanup(Relation relation, bool isCommit)
 	{
 		list_free(relation->rd_indexlist);
 		relation->rd_indexlist = NIL;
+#if 0
 		relation->rd_oidindex = InvalidOid;
+#endif
 		relation->rd_pkindex = InvalidOid;
 		relation->rd_replidindex = InvalidOid;
 		relation->rd_indexvalid = 0;
@@ -3077,7 +3075,9 @@ AtEOSubXact_cleanup(Relation relation, bool isCommit,
 	{
 		list_free(relation->rd_indexlist);
 		relation->rd_indexlist = NIL;
+#if 0
 		relation->rd_oidindex = InvalidOid;
+#endif
 		relation->rd_pkindex = InvalidOid;
 		relation->rd_replidindex = InvalidOid;
 		relation->rd_indexvalid = 0;
@@ -3208,7 +3208,6 @@ RelationBuildLocalRelation(const char *relname,
 	rel->rd_rel->relnamespace = relnamespace;
 
 	rel->rd_rel->relkind = relkind;
-	rel->rd_rel->relhasoids = rel->rd_att->tdhasoid;
 	rel->rd_rel->relnatts = natts;
 	rel->rd_rel->reltype = InvalidOid;
 	/* needed when bootstrapping: */
@@ -3507,15 +3506,15 @@ RelationCacheInitializePhase2(void)
 	 */
 	if (!load_relcache_init_file(true))
 	{
-		formrdesc("pg_database", DatabaseRelation_Rowtype_Id, true,
+		formrdesc("pg_database", DatabaseRelation_Rowtype_Id,
 				  true, Natts_pg_database, Desc_pg_database);
-		formrdesc("pg_authid", AuthIdRelation_Rowtype_Id, true,
+		formrdesc("pg_authid", AuthIdRelation_Rowtype_Id,
 				  true, Natts_pg_authid, Desc_pg_authid);
-		formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id, true,
-				  false, Natts_pg_auth_members, Desc_pg_auth_members);
-		formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id, true,
-				  false, Natts_pg_shseclabel, Desc_pg_shseclabel);
-		formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id, true,
+		formrdesc("pg_auth_members", AuthMemRelation_Rowtype_Id,
+				  true, Natts_pg_auth_members, Desc_pg_auth_members);
+		formrdesc("pg_shseclabel", SharedSecLabelRelation_Rowtype_Id,
+				  true, Natts_pg_shseclabel, Desc_pg_shseclabel);
+		formrdesc("pg_subscription", SubscriptionRelation_Rowtype_Id,
 				  true, Natts_pg_subscription, Desc_pg_subscription);
 
 #define NUM_CRITICAL_SHARED_RELS	5	/* fix if you change list above */
@@ -3566,14 +3565,14 @@ RelationCacheInitializePhase3(void)
 	{
 		needNewCacheFile = true;
 
-		formrdesc("pg_class", RelationRelation_Rowtype_Id, false,
-				  true, Natts_pg_class, Desc_pg_class);
-		formrdesc("pg_attribute", AttributeRelation_Rowtype_Id, false,
+		formrdesc("pg_class", RelationRelation_Rowtype_Id,
+				  false, Natts_pg_class, Desc_pg_class);
+		formrdesc("pg_attribute", AttributeRelation_Rowtype_Id,
 				  false, Natts_pg_attribute, Desc_pg_attribute);
-		formrdesc("pg_proc", ProcedureRelation_Rowtype_Id, false,
-				  true, Natts_pg_proc, Desc_pg_proc);
-		formrdesc("pg_type", TypeRelation_Rowtype_Id, false,
-				  true, Natts_pg_type, Desc_pg_type);
+		formrdesc("pg_proc", ProcedureRelation_Rowtype_Id,
+				  false, Natts_pg_proc, Desc_pg_proc);
+		formrdesc("pg_type", TypeRelation_Rowtype_Id,
+				  false, Natts_pg_type, Desc_pg_type);
 
 #define NUM_CRITICAL_LOCAL_RELS 4	/* fix if you change list above */
 	}
@@ -3725,7 +3724,6 @@ RelationCacheInitializePhase3(void)
 			 */
 			Assert(relation->rd_att->tdtypeid == relp->reltype);
 			Assert(relation->rd_att->tdtypmod == -1);
-			Assert(relation->rd_att->tdhasoid == relp->relhasoids);
 
 			ReleaseSysCache(htup);
 
@@ -3868,8 +3866,7 @@ load_critical_index(Oid indexoid, Oid heapoid)
  * extracting fields.
  */
 static TupleDesc
-BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs,
-						 bool hasoids)
+BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs)
 {
 	TupleDesc	result;
 	MemoryContext oldcxt;
@@ -3877,7 +3874,7 @@ BuildHardcodedDescriptor(int natts, const FormData_pg_attribute *attrs,
 
 	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 
-	result = CreateTemplateTupleDesc(natts, hasoids);
+	result = CreateTemplateTupleDesc(natts);
 	result->tdtypeid = RECORDOID;	/* not right, but we don't care */
 	result->tdtypmod = -1;
 
@@ -3906,8 +3903,7 @@ GetPgClassDescriptor(void)
 	/* Already done? */
 	if (pgclassdesc == NULL)
 		pgclassdesc = BuildHardcodedDescriptor(Natts_pg_class,
-											   Desc_pg_class,
-											   true);
+											   Desc_pg_class);
 
 	return pgclassdesc;
 }
@@ -3920,8 +3916,7 @@ GetPgIndexDescriptor(void)
 	/* Already done? */
 	if (pgindexdesc == NULL)
 		pgindexdesc = BuildHardcodedDescriptor(Natts_pg_index,
-											   Desc_pg_index,
-											   false);
+											   Desc_pg_index);
 
 	return pgindexdesc;
 }
@@ -4266,7 +4261,9 @@ RelationGetIndexList(Relation relation)
 	List	   *result;
 	List	   *oldlist;
 	char		replident = relation->rd_rel->relreplident;
+#if 0
 	Oid			oidIndex = InvalidOid;
+#endif
 	Oid			pkeyIndex = InvalidOid;
 	Oid			candidateIndex = InvalidOid;
 	MemoryContext oldcxt;
@@ -4282,7 +4279,9 @@ RelationGetIndexList(Relation relation)
 	 * if we get some sort of error partway through.
 	 */
 	result = NIL;
+#if 0
 	oidIndex = InvalidOid;
+#endif
 
 	/* Prepare to scan pg_index for entries having indrelid = this rel. */
 	ScanKeyInit(&skey,
@@ -4297,9 +4296,11 @@ RelationGetIndexList(Relation relation)
 	while (HeapTupleIsValid(htup = systable_getnext(indscan)))
 	{
 		Form_pg_index index = (Form_pg_index) GETSTRUCT(htup);
+#if 0
 		Datum		indclassDatum;
 		oidvector  *indclass;
 		bool		isnull;
+#endif
 
 		/*
 		 * Ignore any indexes that are currently being dropped.  This will
@@ -4313,6 +4314,7 @@ RelationGetIndexList(Relation relation)
 		/* Add index's OID to result list in the proper order */
 		result = insert_ordered_oid(result, index->indexrelid);
 
+#if 0
 		/*
 		 * indclass cannot be referenced directly through the C struct,
 		 * because it comes after the variable-width indkey field.  Must
@@ -4324,6 +4326,7 @@ RelationGetIndexList(Relation relation)
 									 &isnull);
 		Assert(!isnull);
 		indclass = (oidvector *) DatumGetPointer(indclassDatum);
+#endif
 
 		/*
 		 * Invalid, non-unique, non-immediate or predicate indexes aren't
@@ -4335,11 +4338,13 @@ RelationGetIndexList(Relation relation)
 			!heap_attisnull(htup, Anum_pg_index_indpred, NULL))
 			continue;
 
+#if 0
 		/* Check to see if is a usable btree index on OID */
 		if (index->indnatts == 1 &&
 			index->indkey.values[0] == ObjectIdAttributeNumber &&
 			indclass->values[0] == OID_BTREE_OPS_OID)
 			oidIndex = index->indexrelid;
+#endif
 
 		/* remember primary key index if any */
 		if (index->indisprimary)
@@ -4358,7 +4363,9 @@ RelationGetIndexList(Relation relation)
 	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 	oldlist = relation->rd_indexlist;
 	relation->rd_indexlist = list_copy(result);
+#if 0
 	relation->rd_oidindex = oidIndex;
+#endif
 	relation->rd_pkindex = pkeyIndex;
 	if (replident == REPLICA_IDENTITY_DEFAULT && OidIsValid(pkeyIndex))
 		relation->rd_replidindex = pkeyIndex;
@@ -4433,7 +4440,11 @@ RelationGetStatExtList(Relation relation)
 								 NULL, 1, &skey);
 
 	while (HeapTupleIsValid(htup = systable_getnext(indscan)))
-		result = insert_ordered_oid(result, HeapTupleGetOid(htup));
+	{
+		Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
+
+		result = insert_ordered_oid(result, oid);
+	}
 
 	systable_endscan(indscan);
 
@@ -4520,7 +4531,9 @@ RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex)
 	/* Okay to replace old list */
 	list_free(relation->rd_indexlist);
 	relation->rd_indexlist = indexIds;
+#if 0
 	relation->rd_oidindex = oidIndex;
+#endif
 
 	/*
 	 * For the moment, assume the target rel hasn't got a pk or replica index.
@@ -4533,34 +4546,6 @@ RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex)
 	EOXactListAdd(relation);
 }
 
-/*
- * RelationGetOidIndex -- get the pg_class OID of the relation's OID index
- *
- * Returns InvalidOid if there is no such index.
- */
-Oid
-RelationGetOidIndex(Relation relation)
-{
-	List	   *ilist;
-
-	/*
-	 * If relation doesn't have OIDs at all, caller is probably confused. (We
-	 * could just silently return InvalidOid, but it seems better to throw an
-	 * assertion.)
-	 */
-	Assert(relation->rd_rel->relhasoids);
-
-	if (relation->rd_indexvalid == 0)
-	{
-		/* RelationGetIndexList does the heavy lifting. */
-		ilist = RelationGetIndexList(relation);
-		list_free(ilist);
-		Assert(relation->rd_indexvalid != 0);
-	}
-
-	return relation->rd_oidindex;
-}
-
 /*
  * RelationGetPrimaryKeyIndex -- get OID of the relation's primary key index
  *
@@ -5467,8 +5452,7 @@ load_relcache_init_file(bool shared)
 		rel->rd_rel = relform;
 
 		/* initialize attribute tuple forms */
-		rel->rd_att = CreateTemplateTupleDesc(relform->relnatts,
-											  relform->relhasoids);
+		rel->rd_att = CreateTemplateTupleDesc(relform->relnatts);
 		rel->rd_att->tdrefcount = 1;	/* mark as refcounted */
 
 		rel->rd_att->tdtypeid = relform->reltype;
@@ -5672,7 +5656,9 @@ load_relcache_init_file(bool shared)
 		rel->rd_fkeylist = NIL;
 		rel->rd_fkeyvalid = false;
 		rel->rd_indexlist = NIL;
+#if 0
 		rel->rd_oidindex = InvalidOid;
+#endif
 		rel->rd_pkindex = InvalidOid;
 		rel->rd_replidindex = InvalidOid;
 		rel->rd_indexattr = NULL;
diff --git a/src/backend/utils/cache/relfilenodemap.c b/src/backend/utils/cache/relfilenodemap.c
index 6f6bba79c34..84b3eb03a9f 100644
--- a/src/backend/utils/cache/relfilenodemap.c
+++ b/src/backend/utils/cache/relfilenodemap.c
@@ -212,29 +212,17 @@ RelidByRelfilenode(Oid reltablespace, Oid relfilenode)
 
 		while (HeapTupleIsValid(ntp = systable_getnext(scandesc)))
 		{
+			Form_pg_class classform = (Form_pg_class) GETSTRUCT(ntp);
+
 			if (found)
 				elog(ERROR,
 					 "unexpected duplicate for tablespace %u, relfilenode %u",
 					 reltablespace, relfilenode);
 			found = true;
 
-#ifdef USE_ASSERT_CHECKING
-			{
-				bool		isnull;
-				Oid			check;
-
-				check = fastgetattr(ntp, Anum_pg_class_reltablespace,
-									RelationGetDescr(relation),
-									&isnull);
-				Assert(!isnull && check == reltablespace);
-
-				check = fastgetattr(ntp, Anum_pg_class_relfilenode,
-									RelationGetDescr(relation),
-									&isnull);
-				Assert(!isnull && check == relfilenode);
-			}
-#endif
-			relid = HeapTupleGetOid(ntp);
+			Assert(classform->reltablespace == reltablespace);
+			Assert(classform->relfilenode == relfilenode);
+			relid = classform->oid;
 		}
 
 		systable_endscan(scandesc);
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 2b381782a32..237e7818024 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -147,7 +147,7 @@ static const struct cachedesc cacheinfo[] = {
 		AmOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_am_oid,
 			0,
 			0,
 			0
@@ -246,7 +246,7 @@ static const struct cachedesc cacheinfo[] = {
 		AuthIdOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_authid_oid,
 			0,
 			0,
 			0
@@ -280,7 +280,7 @@ static const struct cachedesc cacheinfo[] = {
 		OpclassOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_opclass_oid,
 			0,
 			0,
 			0
@@ -302,7 +302,7 @@ static const struct cachedesc cacheinfo[] = {
 		CollationOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_collation_oid,
 			0,
 			0,
 			0
@@ -316,7 +316,7 @@ static const struct cachedesc cacheinfo[] = {
 			Anum_pg_conversion_connamespace,
 			Anum_pg_conversion_conforencoding,
 			Anum_pg_conversion_contoencoding,
-			ObjectIdAttributeNumber,
+			Anum_pg_conversion_oid
 		},
 		8
 	},
@@ -335,7 +335,7 @@ static const struct cachedesc cacheinfo[] = {
 		ConstraintOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_constraint_oid,
 			0,
 			0,
 			0
@@ -346,7 +346,7 @@ static const struct cachedesc cacheinfo[] = {
 		ConversionOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_conversion_oid,
 			0,
 			0,
 			0
@@ -357,7 +357,7 @@ static const struct cachedesc cacheinfo[] = {
 		DatabaseOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_database_oid,
 			0,
 			0,
 			0
@@ -379,7 +379,7 @@ static const struct cachedesc cacheinfo[] = {
 		EnumOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_enum_oid,
 			0,
 			0,
 			0
@@ -412,7 +412,7 @@ static const struct cachedesc cacheinfo[] = {
 		EventTriggerOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_event_trigger_oid,
 			0,
 			0,
 			0
@@ -434,7 +434,7 @@ static const struct cachedesc cacheinfo[] = {
 		ForeignDataWrapperOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_foreign_data_wrapper_oid,
 			0,
 			0,
 			0
@@ -456,7 +456,7 @@ static const struct cachedesc cacheinfo[] = {
 		ForeignServerOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_foreign_server_oid,
 			0,
 			0,
 			0
@@ -500,7 +500,7 @@ static const struct cachedesc cacheinfo[] = {
 		LanguageOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_language_oid,
 			0,
 			0,
 			0
@@ -522,7 +522,7 @@ static const struct cachedesc cacheinfo[] = {
 		NamespaceOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_namespace_oid,
 			0,
 			0,
 			0
@@ -544,7 +544,7 @@ static const struct cachedesc cacheinfo[] = {
 		OperatorOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_operator_oid,
 			0,
 			0,
 			0
@@ -566,7 +566,7 @@ static const struct cachedesc cacheinfo[] = {
 		OpfamilyOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_opfamily_oid,
 			0,
 			0,
 			0
@@ -599,7 +599,7 @@ static const struct cachedesc cacheinfo[] = {
 		ProcedureOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_proc_oid,
 			0,
 			0,
 			0
@@ -621,7 +621,7 @@ static const struct cachedesc cacheinfo[] = {
 		PublicationObjectIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_publication_oid,
 			0,
 			0,
 			0
@@ -632,7 +632,7 @@ static const struct cachedesc cacheinfo[] = {
 		PublicationRelObjectIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_publication_rel_oid,
 			0,
 			0,
 			0
@@ -676,7 +676,7 @@ static const struct cachedesc cacheinfo[] = {
 		ClassOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_class_oid,
 			0,
 			0,
 			0
@@ -742,7 +742,7 @@ static const struct cachedesc cacheinfo[] = {
 		StatisticExtOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_statistic_ext_oid,
 			0,
 			0,
 			0
@@ -775,7 +775,7 @@ static const struct cachedesc cacheinfo[] = {
 		SubscriptionObjectIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_subscription_oid,
 			0,
 			0,
 			0
@@ -797,7 +797,7 @@ static const struct cachedesc cacheinfo[] = {
 		TablespaceOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_tablespace_oid,
 			0,
 			0,
 			0,
@@ -808,7 +808,7 @@ static const struct cachedesc cacheinfo[] = {
 		TransformOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_transform_oid,
 			0,
 			0,
 			0,
@@ -852,7 +852,7 @@ static const struct cachedesc cacheinfo[] = {
 		TSConfigOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_ts_config_oid,
 			0,
 			0,
 			0
@@ -874,7 +874,7 @@ static const struct cachedesc cacheinfo[] = {
 		TSDictionaryOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_ts_dict_oid,
 			0,
 			0,
 			0
@@ -896,7 +896,7 @@ static const struct cachedesc cacheinfo[] = {
 		TSParserOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_ts_parser_oid,
 			0,
 			0,
 			0
@@ -918,7 +918,7 @@ static const struct cachedesc cacheinfo[] = {
 		TSTemplateOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_ts_template_oid,
 			0,
 			0,
 			0
@@ -940,7 +940,7 @@ static const struct cachedesc cacheinfo[] = {
 		TypeOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_type_oid,
 			0,
 			0,
 			0
@@ -951,7 +951,7 @@ static const struct cachedesc cacheinfo[] = {
 		UserMappingOidIndexId,
 		1,
 		{
-			ObjectIdAttributeNumber,
+			Anum_pg_user_mapping_oid,
 			0,
 			0,
 			0
@@ -1230,7 +1230,9 @@ GetSysCacheOid(int cacheId,
 	tuple = SearchSysCache(cacheId, key1, key2, key3, key4);
 	if (!HeapTupleIsValid(tuple))
 		return InvalidOid;
-	result = HeapTupleGetOid(tuple);
+	/* XXX: THIS IS UNBELIEVABLY DIRTY AND NEEDS TO BE REWRITTEN */
+	result = ((Form_pg_class) GETSTRUCT(tuple))->oid;
+	//result = HeapTupleGetOid(tuple);
 	ReleaseSysCache(tuple);
 	return result;
 }
diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c
index e38fd16eb09..e0478e33bcf 100644
--- a/src/backend/utils/cache/typcache.c
+++ b/src/backend/utils/cache/typcache.c
@@ -2351,7 +2351,7 @@ load_enum_cache_data(TypeCacheEntry *tcache)
 			maxitems *= 2;
 			items = (EnumItem *) repalloc(items, sizeof(EnumItem) * maxitems);
 		}
-		items[numitems].enum_oid = HeapTupleGetOid(enum_tuple);
+		items[numitems].enum_oid = en->oid;
 		items[numitems].sort_order = en->enumsortorder;
 		numitems++;
 	}
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 6cbbd5b78b0..73ff48c1963 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -529,7 +529,7 @@ fetch_finfo_record(void *filehandle, const char *funcname)
 static CFuncHashTabEntry *
 lookup_C_func(HeapTuple procedureTuple)
 {
-	Oid			fn_oid = HeapTupleGetOid(procedureTuple);
+	Oid			fn_oid = ((Form_pg_proc) GETSTRUCT(procedureTuple))->oid;
 	CFuncHashTabEntry *entry;
 
 	if (CFuncHash == NULL)
@@ -554,7 +554,7 @@ static void
 record_C_func(HeapTuple procedureTuple,
 			  PGFunction user_fn, const Pg_finfo_record *inforec)
 {
-	Oid			fn_oid = HeapTupleGetOid(procedureTuple);
+	Oid			fn_oid =  ((Form_pg_proc) GETSTRUCT(procedureTuple))->oid;
 	CFuncHashTabEntry *entry;
 	bool		found;
 
diff --git a/src/backend/utils/fmgr/funcapi.c b/src/backend/utils/fmgr/funcapi.c
index 30923518f5e..c4df255f101 100644
--- a/src/backend/utils/fmgr/funcapi.c
+++ b/src/backend/utils/fmgr/funcapi.c
@@ -1301,7 +1301,7 @@ build_function_result_tupdesc_d(char prokind,
 	if (numoutargs < 2 && prokind != PROKIND_PROCEDURE)
 		return NULL;
 
-	desc = CreateTemplateTupleDesc(numoutargs, false);
+	desc = CreateTemplateTupleDesc(numoutargs);
 	for (i = 0; i < numoutargs; i++)
 	{
 		TupleDescInitEntry(desc, i + 1,
@@ -1421,7 +1421,7 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases)
 		/* OK, get the column alias */
 		attname = strVal(linitial(colaliases));
 
-		tupdesc = CreateTemplateTupleDesc(1, false);
+		tupdesc = CreateTemplateTupleDesc(1);
 		TupleDescInitEntry(tupdesc,
 						   (AttrNumber) 1,
 						   attname,
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index f590ecb25e8..ded332ced5e 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -628,7 +628,7 @@ InitializeSessionUserId(const char *rolename, Oid roleid)
 	}
 
 	rform = (Form_pg_authid) GETSTRUCT(roleTup);
-	roleid = HeapTupleGetOid(roleTup);
+	roleid = rform->oid;
 	rname = NameStr(rform->rolname);
 
 	AuthenticatedUserId = roleid;
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 5ef6315d206..0e85b50f4d0 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -146,7 +146,7 @@ GetDatabaseTupleByOid(Oid dboid)
 	 * form a scan key
 	 */
 	ScanKeyInit(&key[0],
-				ObjectIdAttributeNumber,
+				Anum_pg_database_oid,
 				BTEqualStrategyNumber, F_OIDEQ,
 				ObjectIdGetDatum(dboid));
 
@@ -863,7 +863,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 					(errcode(ERRCODE_UNDEFINED_DATABASE),
 					 errmsg("database \"%s\" does not exist", in_dbname)));
 		dbform = (Form_pg_database) GETSTRUCT(tuple);
-		MyDatabaseId = HeapTupleGetOid(tuple);
+		MyDatabaseId = dbform->oid;
 		MyDatabaseTableSpace = dbform->dattablespace;
 		/* take database name from the caller, just for paranoia */
 		strlcpy(dbname, in_dbname, sizeof(dbname));
@@ -880,7 +880,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 					(errcode(ERRCODE_UNDEFINED_DATABASE),
 					 errmsg("database %u does not exist", dboid)));
 		dbform = (Form_pg_database) GETSTRUCT(tuple);
-		MyDatabaseId = HeapTupleGetOid(tuple);
+		MyDatabaseId = dbform->oid;
 		MyDatabaseTableSpace = dbform->dattablespace;
 		Assert(MyDatabaseId == dboid);
 		strlcpy(dbname, NameStr(dbform->datname), sizeof(dbname));
@@ -962,7 +962,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 
 		tuple = GetDatabaseTuple(dbname);
 		if (!HeapTupleIsValid(tuple) ||
-			MyDatabaseId != HeapTupleGetOid(tuple) ||
+			MyDatabaseId != ((Form_pg_database) GETSTRUCT(tuple))->oid ||
 			MyDatabaseTableSpace != ((Form_pg_database) GETSTRUCT(tuple))->dattablespace)
 			ereport(FATAL,
 					(errcode(ERRCODE_UNDEFINED_DATABASE),
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index d14ea851847..33f44a8d13c 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -8220,7 +8220,7 @@ GetPGVariableResultDesc(const char *name)
 	if (guc_name_compare(name, "all") == 0)
 	{
 		/* need a tuple descriptor representing three TEXT columns */
-		tupdesc = CreateTemplateTupleDesc(3, false);
+		tupdesc = CreateTemplateTupleDesc(3);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
 						   TEXTOID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
@@ -8236,7 +8236,7 @@ GetPGVariableResultDesc(const char *name)
 		(void) GetConfigOptionByName(name, &varname, false);
 
 		/* need a tuple descriptor representing a single TEXT column */
-		tupdesc = CreateTemplateTupleDesc(1, false);
+		tupdesc = CreateTemplateTupleDesc(1);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname,
 						   TEXTOID, -1, 0);
 	}
@@ -8259,7 +8259,7 @@ ShowGUCConfigOption(const char *name, DestReceiver *dest)
 	value = GetConfigOptionByName(name, &varname, false);
 
 	/* need a tuple descriptor representing a single TEXT column */
-	tupdesc = CreateTemplateTupleDesc(1, false);
+	tupdesc = CreateTemplateTupleDesc(1);
 	TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, varname,
 							  TEXTOID, -1, 0);
 
@@ -8285,7 +8285,7 @@ ShowAllGUCConfig(DestReceiver *dest)
 	bool		isnull[3] = {false, false, false};
 
 	/* need a tuple descriptor representing three TEXT columns */
-	tupdesc = CreateTemplateTupleDesc(3, false);
+	tupdesc = CreateTemplateTupleDesc(3);
 	TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, "name",
 							  TEXTOID, -1, 0);
 	TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "setting",
@@ -8727,7 +8727,7 @@ show_all_settings(PG_FUNCTION_ARGS)
 		 * need a tuple descriptor representing NUM_PG_SETTINGS_ATTS columns
 		 * of the appropriate types
 		 */
-		tupdesc = CreateTemplateTupleDesc(NUM_PG_SETTINGS_ATTS, false);
+		tupdesc = CreateTemplateTupleDesc(NUM_PG_SETTINGS_ATTS);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
 						   TEXTOID, -1, 0);
 		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting",
@@ -8867,7 +8867,7 @@ show_all_file_settings(PG_FUNCTION_ARGS)
 	oldcontext = MemoryContextSwitchTo(per_query_ctx);
 
 	/* Build a tuple descriptor for our result type */
-	tupdesc = CreateTemplateTupleDesc(NUM_PG_FILE_SETTINGS_ATTS, false);
+	tupdesc = CreateTemplateTupleDesc(NUM_PG_FILE_SETTINGS_ATTS);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "sourcefile",
 					   TEXTOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "sourceline",
diff --git a/src/backend/utils/misc/pg_controldata.c b/src/backend/utils/misc/pg_controldata.c
index 3fc8b6a8a84..a3768752698 100644
--- a/src/backend/utils/misc/pg_controldata.c
+++ b/src/backend/utils/misc/pg_controldata.c
@@ -41,7 +41,7 @@ pg_control_system(PG_FUNCTION_ARGS)
 	 * Construct a tuple descriptor for the result row.  This must match this
 	 * function's pg_proc entry!
 	 */
-	tupdesc = CreateTemplateTupleDesc(4, false);
+	tupdesc = CreateTemplateTupleDesc(4);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pg_control_version",
 					   INT4OID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "catalog_version_no",
@@ -91,7 +91,7 @@ pg_control_checkpoint(PG_FUNCTION_ARGS)
 	 * Construct a tuple descriptor for the result row.  This must match this
 	 * function's pg_proc entry!
 	 */
-	tupdesc = CreateTemplateTupleDesc(18, false);
+	tupdesc = CreateTemplateTupleDesc(18);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "checkpoint_lsn",
 					   LSNOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "redo_lsn",
@@ -221,7 +221,7 @@ pg_control_recovery(PG_FUNCTION_ARGS)
 	 * Construct a tuple descriptor for the result row.  This must match this
 	 * function's pg_proc entry!
 	 */
-	tupdesc = CreateTemplateTupleDesc(5, false);
+	tupdesc = CreateTemplateTupleDesc(5);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "min_recovery_end_lsn",
 					   LSNOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "min_recovery_end_timeline",
@@ -274,7 +274,7 @@ pg_control_init(PG_FUNCTION_ARGS)
 	 * Construct a tuple descriptor for the result row.  This must match this
 	 * function's pg_proc entry!
 	 */
-	tupdesc = CreateTemplateTupleDesc(12, false);
+	tupdesc = CreateTemplateTupleDesc(12);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "max_data_alignment",
 					   INT4OID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database_block_size",
diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c
index d34cab0eb88..2b014c86bd1 100644
--- a/src/backend/utils/mmgr/portalmem.c
+++ b/src/backend/utils/mmgr/portalmem.c
@@ -1146,7 +1146,7 @@ pg_cursor(PG_FUNCTION_ARGS)
 	 * build tupdesc for result tuples. This must match the definition of the
 	 * pg_cursors view in system_views.sql
 	 */
-	tupdesc = CreateTemplateTupleDesc(6, false);
+	tupdesc = CreateTemplateTupleDesc(6);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name",
 					   TEXTOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "statement",
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index c8d01ed4a4c..1d2033289b8 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -16158,8 +16158,6 @@ getAttrName(int attrnum, TableInfo *tblInfo)
 	{
 		case SelfItemPointerAttributeNumber:
 			return "ctid";
-		case ObjectIdAttributeNumber:
-			return "oid";
 		case MinTransactionIdAttributeNumber:
 			return "xmin";
 		case MinCommandIdAttributeNumber:
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 4ca0db1d0ca..d23247a592f 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -1496,7 +1496,24 @@ describeOneTableDetails(const char *schemaname,
 	initPQExpBuffer(&tmpbuf);
 
 	/* Get general table info */
-	if (pset.sversion >= 90500)
+	if (pset.sversion >= 120000)
+	{
+		printfPQExpBuffer(&buf,
+						  "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
+						  "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, "
+						  "false, %s, c.reltablespace, "
+						  "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, "
+						  "c.relpersistence, c.relreplident\n"
+						  "FROM pg_catalog.pg_class c\n "
+						  "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n"
+						  "WHERE c.oid = '%s';",
+						  (verbose ?
+						   "pg_catalog.array_to_string(c.reloptions || "
+						   "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n"
+						   : "''"),
+						  oid);
+	}
+	else if (pset.sversion >= 90500)
 	{
 		printfPQExpBuffer(&buf,
 						  "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, "
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index ca5cad7497f..8f6a1ecb38e 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -150,7 +150,7 @@ extern BulkInsertState GetBulkInsertState(void);
 extern void FreeBulkInsertState(BulkInsertState);
 extern void ReleaseBulkInsertStatePin(BulkInsertState bistate);
 
-extern Oid heap_insert(Relation relation, HeapTuple tup, CommandId cid,
+extern void heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 			int options, BulkInsertState bistate);
 extern void heap_multi_insert(Relation relation, HeapTuple *tuples, int ntuples,
 				  CommandId cid, int options, BulkInsertState bistate);
@@ -175,7 +175,7 @@ extern bool heap_tuple_needs_freeze(HeapTupleHeader tuple, TransactionId cutoff_
 						MultiXactId cutoff_multi, Buffer buf);
 extern bool heap_tuple_needs_eventual_freeze(HeapTupleHeader tuple);
 
-extern Oid	simple_heap_insert(Relation relation, HeapTuple tup);
+extern void simple_heap_insert(Relation relation, HeapTuple tup);
 extern void simple_heap_delete(Relation relation, ItemPointer tid);
 extern void simple_heap_update(Relation relation, ItemPointer otid,
 				   HeapTuple tup);
diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h
index 1867a70f6f3..17e16087711 100644
--- a/src/include/access/htup_details.h
+++ b/src/include/access/htup_details.h
@@ -65,7 +65,7 @@
  *			fixed fields (HeapTupleHeaderData struct)
  *			nulls bitmap (if HEAP_HASNULL is set in t_infomask)
  *			alignment padding (as needed to make user data MAXALIGN'd)
- *			object ID (if HEAP_HASOID is set in t_infomask)
+ *			object ID (if HEAP_HASOID is set in t_infomask) (not anymore)
  *			user data fields
  *
  * We store five "virtual" fields Xmin, Cmin, Xmax, Cmax, and Xvac in three
@@ -188,7 +188,7 @@ struct HeapTupleHeaderData
 #define HEAP_HASNULL			0x0001	/* has null attribute(s) */
 #define HEAP_HASVARWIDTH		0x0002	/* has variable-width attribute(s) */
 #define HEAP_HASEXTERNAL		0x0004	/* has external stored attribute(s) */
-#define HEAP_HASOID				0x0008	/* has an object-id field */
+#define HEAP_HASOID_OLD			0x0008	/* has an object-id field */
 #define HEAP_XMAX_KEYSHR_LOCK	0x0010	/* xmax is a key-shared locker */
 #define HEAP_COMBOCID			0x0020	/* t_cid is a combo cid */
 #define HEAP_XMAX_EXCL_LOCK		0x0040	/* xmax is exclusive locker */
@@ -474,20 +474,6 @@ do { \
 	(tup)->t_choice.t_datum.datum_typmod = (typmod) \
 )
 
-#define HeapTupleHeaderGetOid(tup) \
-( \
-	((tup)->t_infomask & HEAP_HASOID) ? \
-		*((Oid *) ((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) \
-	: \
-		InvalidOid \
-)
-
-#define HeapTupleHeaderSetOid(tup, oid) \
-do { \
-	Assert((tup)->t_infomask & HEAP_HASOID); \
-	*((Oid *) ((char *)(tup) + (tup)->t_hoff - sizeof(Oid))) = (oid); \
-} while (0)
-
 /*
  * Note that we stop considering a tuple HOT-updated as soon as it is known
  * aborted or the would-be updating transaction is known aborted.  For best
diff --git a/src/include/access/sysattr.h b/src/include/access/sysattr.h
index c6f244011ab..e3df369d962 100644
--- a/src/include/access/sysattr.h
+++ b/src/include/access/sysattr.h
@@ -19,12 +19,12 @@
  * Attribute numbers for the system-defined attributes
  */
 #define SelfItemPointerAttributeNumber			(-1)
-#define ObjectIdAttributeNumber					(-2)
-#define MinTransactionIdAttributeNumber			(-3)
-#define MinCommandIdAttributeNumber				(-4)
-#define MaxTransactionIdAttributeNumber			(-5)
-#define MaxCommandIdAttributeNumber				(-6)
-#define TableOidAttributeNumber					(-7)
-#define FirstLowInvalidHeapAttributeNumber		(-8)
+/* #define ObjectIdAttributeNumber					(-2) */
+#define MinTransactionIdAttributeNumber			(-2)
+#define MinCommandIdAttributeNumber				(-3)
+#define MaxTransactionIdAttributeNumber			(-4)
+#define MaxCommandIdAttributeNumber				(-5)
+#define TableOidAttributeNumber					(-6)
+#define FirstLowInvalidHeapAttributeNumber		(-7)
 
 #endif							/* SYSATTR_H */
diff --git a/src/include/access/transam.h b/src/include/access/transam.h
index 83ec3f19797..4d8e05997f9 100644
--- a/src/include/access/transam.h
+++ b/src/include/access/transam.h
@@ -90,7 +90,7 @@
  * reassigning OIDs that might have been assigned during initdb.
  * ----------
  */
-#define FirstBootstrapObjectId	10000
+#define FirstBootstrapObjectId	14000
 #define FirstNormalObjectId		16384
 
 /*
diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h
index 708160f645e..06af39ff2a3 100644
--- a/src/include/access/tupdesc.h
+++ b/src/include/access/tupdesc.h
@@ -55,7 +55,7 @@ typedef struct tupleConstr
  * structure is designed to let the constraints be omitted efficiently.
  *
  * Note that only user attributes, not system attributes, are mentioned in
- * TupleDesc; with the exception that tdhasoid indicates if OID is present.
+ * TupleDesc.
  *
  * If the tupdesc is known to correspond to a named rowtype (such as a table's
  * rowtype) then tdtypeid identifies that type and tdtypmod is -1.  Otherwise
@@ -82,7 +82,6 @@ typedef struct tupleDesc
 	int			natts;			/* number of attributes in the tuple */
 	Oid			tdtypeid;		/* composite type ID for tuple type */
 	int32		tdtypmod;		/* typmod for tuple type */
-	bool		tdhasoid;		/* tuple has oid attribute in its header */
 	int			tdrefcount;		/* reference count, or -1 if not counting */
 	TupleConstr *constr;		/* constraints, or NULL if none */
 	/* attrs[N] is the description of Attribute Number N+1 */
@@ -92,10 +91,9 @@ typedef struct tupleDesc
 /* Accessor for the i'th attribute of tupdesc. */
 #define TupleDescAttr(tupdesc, i) (&(tupdesc)->attrs[(i)])
 
-extern TupleDesc CreateTemplateTupleDesc(int natts, bool hasoid);
+extern TupleDesc CreateTemplateTupleDesc(int natts);
 
-extern TupleDesc CreateTupleDesc(int natts, bool hasoid,
-				Form_pg_attribute *attrs);
+extern TupleDesc CreateTupleDesc(int natts, Form_pg_attribute *attrs);
 
 extern TupleDesc CreateTupleDescCopy(TupleDesc tupdesc);
 
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index b3e8fdd9c60..f670d4e9ed3 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.h
@@ -65,8 +65,6 @@ extern Oid heap_create_with_catalog(const char *relname,
 						 char relpersistence,
 						 bool shared_relation,
 						 bool mapped_relation,
-						 bool oidislocal,
-						 int oidinhcount,
 						 OnCommitAction oncommit,
 						 Datum reloptions,
 						 bool use_user_acl,
@@ -127,11 +125,9 @@ extern void RemoveAttrDefault(Oid relid, AttrNumber attnum,
 extern void RemoveAttrDefaultById(Oid attrdefId);
 extern void RemoveStatistics(Oid relid, AttrNumber attnum);
 
-extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno,
-						  bool relhasoids);
+extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno);
 
-extern Form_pg_attribute SystemAttributeByName(const char *attname,
-					  bool relhasoids);
+extern Form_pg_attribute SystemAttributeByName(const char *attname);
 
 extern void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind,
 						 bool allow_system_table_mods);
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index 254fbef1f78..a672fd8ce3f 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -30,8 +30,8 @@ typedef struct ResultRelInfo *CatalogIndexState;
  */
 extern CatalogIndexState CatalogOpenIndexes(Relation heapRel);
 extern void CatalogCloseIndexes(CatalogIndexState indstate);
-extern Oid	CatalogTupleInsert(Relation heapRel, HeapTuple tup);
-extern Oid CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup,
+extern void	CatalogTupleInsert(Relation heapRel, HeapTuple tup);
+extern void CatalogTupleInsertWithInfo(Relation heapRel, HeapTuple tup,
 						   CatalogIndexState indstate);
 extern void CatalogTupleUpdate(Relation heapRel, ItemPointer otid,
 				   HeapTuple tup);
diff --git a/src/include/catalog/objectaddress.h b/src/include/catalog/objectaddress.h
index 6a9b1eec73f..3f95733eb1a 100644
--- a/src/include/catalog/objectaddress.h
+++ b/src/include/catalog/objectaddress.h
@@ -58,6 +58,7 @@ extern bool is_objectclass_supported(Oid class_id);
 extern Oid	get_object_oid_index(Oid class_id);
 extern int	get_object_catcache_oid(Oid class_id);
 extern int	get_object_catcache_name(Oid class_id);
+extern AttrNumber get_object_attnum_oid(Oid class_id);
 extern AttrNumber get_object_attnum_name(Oid class_id);
 extern AttrNumber get_object_attnum_namespace(Oid class_id);
 extern AttrNumber get_object_attnum_owner(Oid class_id);
@@ -66,7 +67,7 @@ extern ObjectType get_object_type(Oid class_id, Oid object_id);
 extern bool get_object_namensp_unique(Oid class_id);
 
 extern HeapTuple get_catalog_object_by_oid(Relation catalog,
-						  Oid objectId);
+						  AttrNumber oidcol, Oid objectId);
 
 extern char *getObjectDescription(const ObjectAddress *object);
 extern char *getObjectDescriptionOids(Oid classid, Oid objid);
diff --git a/src/include/catalog/pg_aggregate.h b/src/include/catalog/pg_aggregate.h
index bcae93f5e14..c88ba91401f 100644
--- a/src/include/catalog/pg_aggregate.h
+++ b/src/include/catalog/pg_aggregate.h
@@ -29,7 +29,7 @@
  *		cpp turns this into typedef struct FormData_pg_aggregate
  * ----------------------------------------------------------------
  */
-CATALOG(pg_aggregate,2600,AggregateRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_aggregate,2600,AggregateRelationId)
 {
 	/* pg_proc OID of the aggregate itself */
 	regproc		aggfnoid BKI_LOOKUP(pg_proc);
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
index 26cb2349875..57d65f830fc 100644
--- a/src/include/catalog/pg_am.h
+++ b/src/include/catalog/pg_am.h
@@ -28,6 +28,8 @@
  */
 CATALOG(pg_am,2601,AccessMethodRelationId)
 {
+	Oid			oid;			/* oid */
+
 	/* access method name */
 	NameData	amname;
 
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index 8e6f7408872..f110fdd7413 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -53,6 +53,8 @@
  */
 CATALOG(pg_amop,2602,AccessMethodOperatorRelationId)
 {
+	Oid			oid;			/* oid */
+
 	/* the index opfamily this entry is for */
 	Oid			amopfamily BKI_LOOKUP(pg_opfamily);
 
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
index c34c3faa8ff..c5f79ba5939 100644
--- a/src/include/catalog/pg_amproc.h
+++ b/src/include/catalog/pg_amproc.h
@@ -42,6 +42,8 @@
  */
 CATALOG(pg_amproc,2603,AccessMethodProcedureRelationId)
 {
+	Oid			oid;			/* oid */
+
 	/* the index opfamily this entry is for */
 	Oid			amprocfamily BKI_LOOKUP(pg_opfamily);
 
diff --git a/src/include/catalog/pg_attrdef.h b/src/include/catalog/pg_attrdef.h
index e4a37ec3268..911ac40087a 100644
--- a/src/include/catalog/pg_attrdef.h
+++ b/src/include/catalog/pg_attrdef.h
@@ -28,6 +28,8 @@
  */
 CATALOG(pg_attrdef,2604,AttrDefaultRelationId)
 {
+	Oid			oid;			/* oid XXX: Why? */
+
 	Oid			adrelid;		/* OID of table containing attribute */
 	int16		adnum;			/* attnum of attribute */
 
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index dc36753ede0..1bac59bf26e 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -34,7 +34,7 @@
  *		You may need to change catalog/genbki.pl as well.
  * ----------------
  */
-CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_WITHOUT_OIDS BKI_ROWTYPE_OID(75,AttributeRelation_Rowtype_Id) BKI_SCHEMA_MACRO
+CATALOG(pg_attribute,1249,AttributeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(75,AttributeRelation_Rowtype_Id) BKI_SCHEMA_MACRO
 {
 	Oid			attrelid;		/* OID of relation containing this attribute */
 	NameData	attname;		/* name of attribute */
diff --git a/src/include/catalog/pg_auth_members.h b/src/include/catalog/pg_auth_members.h
index 277ea89c6f2..6d93038f6cd 100644
--- a/src/include/catalog/pg_auth_members.h
+++ b/src/include/catalog/pg_auth_members.h
@@ -27,7 +27,7 @@
  *		typedef struct FormData_pg_auth_members
  * ----------------
  */
-CATALOG(pg_auth_members,1261,AuthMemRelationId) BKI_SHARED_RELATION BKI_WITHOUT_OIDS BKI_ROWTYPE_OID(2843,AuthMemRelation_Rowtype_Id) BKI_SCHEMA_MACRO
+CATALOG(pg_auth_members,1261,AuthMemRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(2843,AuthMemRelation_Rowtype_Id) BKI_SCHEMA_MACRO
 {
 	Oid			roleid;			/* ID of a role */
 	Oid			member;			/* ID of a member of that role */
diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h
index ba482f1cb91..ee0c8da6120 100644
--- a/src/include/catalog/pg_authid.h
+++ b/src/include/catalog/pg_authid.h
@@ -30,6 +30,7 @@
  */
 CATALOG(pg_authid,1260,AuthIdRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(2842,AuthIdRelation_Rowtype_Id) BKI_SCHEMA_MACRO
 {
+	Oid			oid;			/* oid */
 	NameData	rolname;		/* name of role */
 	bool		rolsuper;		/* read this field via superuser() only! */
 	bool		rolinherit;		/* inherit privileges from other roles? */
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
index 7f4a25b2dad..dd207bf318d 100644
--- a/src/include/catalog/pg_cast.h
+++ b/src/include/catalog/pg_cast.h
@@ -30,6 +30,8 @@
  */
 CATALOG(pg_cast,2605,CastRelationId)
 {
+	Oid			oid;			/* oid */
+
 	/* source datatype for cast */
 	Oid			castsource BKI_LOOKUP(pg_type);
 
diff --git a/src/include/catalog/pg_class.dat b/src/include/catalog/pg_class.dat
index 9fffdef3790..848264d9846 100644
--- a/src/include/catalog/pg_class.dat
+++ b/src/include/catalog/pg_class.dat
@@ -25,8 +25,8 @@
   reloftype => '0', relowner => 'PGUID', relam => '0', relfilenode => '0',
   reltablespace => '0', relpages => '0', reltuples => '0', relallvisible => '0',
   reltoastrelid => '0', relhasindex => 'f', relisshared => 'f',
-  relpersistence => 'p', relkind => 'r', relnatts => '30', relchecks => '0',
-  relhasoids => 't', relhasrules => 'f', relhastriggers => 'f',
+  relpersistence => 'p', relkind => 'r', relnatts => '31', relchecks => '0',
+  relhasrules => 'f', relhastriggers => 'f',
   relhassubclass => 'f', relrowsecurity => 'f', relforcerowsecurity => 'f',
   relispopulated => 't', relreplident => 'n', relispartition => 'f',
   relrewrite => '0', relfrozenxid => '3', relminmxid => '1', relacl => '_null_',
@@ -37,7 +37,7 @@
   reltablespace => '0', relpages => '0', reltuples => '0', relallvisible => '0',
   reltoastrelid => '0', relhasindex => 'f', relisshared => 'f',
   relpersistence => 'p', relkind => 'r', relnatts => '24', relchecks => '0',
-  relhasoids => 'f', relhasrules => 'f', relhastriggers => 'f',
+  relhasrules => 'f', relhastriggers => 'f',
   relhassubclass => 'f', relrowsecurity => 'f', relforcerowsecurity => 'f',
   relispopulated => 't', relreplident => 'n', relispartition => 'f',
   relrewrite => '0', relfrozenxid => '3', relminmxid => '1', relacl => '_null_',
@@ -47,8 +47,8 @@
   reloftype => '0', relowner => 'PGUID', relam => '0', relfilenode => '0',
   reltablespace => '0', relpages => '0', reltuples => '0', relallvisible => '0',
   reltoastrelid => '0', relhasindex => 'f', relisshared => 'f',
-  relpersistence => 'p', relkind => 'r', relnatts => '28', relchecks => '0',
-  relhasoids => 't', relhasrules => 'f', relhastriggers => 'f',
+  relpersistence => 'p', relkind => 'r', relnatts => '29', relchecks => '0',
+  relhasrules => 'f', relhastriggers => 'f',
   relhassubclass => 'f', relrowsecurity => 'f', relforcerowsecurity => 'f',
   relispopulated => 't', relreplident => 'n', relispartition => 'f',
   relrewrite => '0', relfrozenxid => '3', relminmxid => '1', relacl => '_null_',
@@ -59,7 +59,7 @@
   reltablespace => '0', relpages => '0', reltuples => '0', relallvisible => '0',
   reltoastrelid => '0', relhasindex => 'f', relisshared => 'f',
   relpersistence => 'p', relkind => 'r', relnatts => '33', relchecks => '0',
-  relhasoids => 't', relhasrules => 'f', relhastriggers => 'f',
+  relhasrules => 'f', relhastriggers => 'f',
   relhassubclass => 'f', relrowsecurity => 'f', relforcerowsecurity => 'f',
   relispopulated => 't', relreplident => 'n', relispartition => 'f',
   relrewrite => '0', relfrozenxid => '3', relminmxid => '1', relacl => '_null_',
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index dc6c415c586..a73431081bb 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -28,6 +28,7 @@
  */
 CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,RelationRelation_Rowtype_Id) BKI_SCHEMA_MACRO
 {
+	Oid			oid;			/* oid */
 	NameData	relname;		/* class name */
 	Oid			relnamespace;	/* OID of namespace containing this class */
 	Oid			reltype;		/* OID of entry in pg_type for table's
@@ -57,7 +58,6 @@ CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,Relat
 	 * contain entries with negative attnums for system attributes.
 	 */
 	int16		relchecks;		/* # of CHECK constraints for class */
-	bool		relhasoids;		/* T if we generate OIDs for rows of rel */
 	bool		relhasrules;	/* has (or has had) any rules */
 	bool		relhastriggers; /* has (or has had) any TRIGGERs */
 	bool		relhassubclass; /* has (or has had) derived classes */
diff --git a/src/include/catalog/pg_collation.h b/src/include/catalog/pg_collation.h
index 7e0f4461c61..51f9b2a2ca4 100644
--- a/src/include/catalog/pg_collation.h
+++ b/src/include/catalog/pg_collation.h
@@ -28,6 +28,7 @@
  */
 CATALOG(pg_collation,3456,CollationRelationId)
 {
+	Oid			oid;			/* oid */
 	NameData	collname;		/* collation name */
 	Oid			collnamespace;	/* OID of namespace containing collation */
 	Oid			collowner;		/* owner of collation */
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index 66b3f13f74a..0d751599ebc 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -31,6 +31,8 @@
  */
 CATALOG(pg_constraint,2606,ConstraintRelationId)
 {
+	Oid			oid;			/* oid */
+
 	/*
 	 * conname + connamespace is deliberately not unique; we allow, for
 	 * example, the same name to be used for constraints of different
diff --git a/src/include/catalog/pg_conversion.h b/src/include/catalog/pg_conversion.h
index 37515f64c2f..6e8f054306f 100644
--- a/src/include/catalog/pg_conversion.h
+++ b/src/include/catalog/pg_conversion.h
@@ -39,6 +39,7 @@
  */
 CATALOG(pg_conversion,2607,ConversionRelationId)
 {
+	Oid			oid;			/* oid */
 	NameData	conname;
 	Oid			connamespace;
 	Oid			conowner;
diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h
index ac027b79199..f6aebad8ef0 100644
--- a/src/include/catalog/pg_database.h
+++ b/src/include/catalog/pg_database.h
@@ -28,6 +28,7 @@
  */
 CATALOG(pg_database,1262,DatabaseRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(1248,DatabaseRelation_Rowtype_Id) BKI_SCHEMA_MACRO
 {
+	Oid			oid;			/* oid */
 	NameData	datname;		/* database name */
 	Oid			datdba;			/* owner of database */
 	int32		encoding;		/* character encoding */
diff --git a/src/include/catalog/pg_db_role_setting.h b/src/include/catalog/pg_db_role_setting.h
index eff801c3ce5..96440342f28 100644
--- a/src/include/catalog/pg_db_role_setting.h
+++ b/src/include/catalog/pg_db_role_setting.h
@@ -31,7 +31,7 @@
  *		typedef struct FormData_pg_db_role_setting
  * ----------------
  */
-CATALOG(pg_db_role_setting,2964,DbRoleSettingRelationId) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
+CATALOG(pg_db_role_setting,2964,DbRoleSettingRelationId) BKI_SHARED_RELATION
 {
 	Oid			setdatabase;	/* database */
 	Oid			setrole;		/* role */
diff --git a/src/include/catalog/pg_default_acl.h b/src/include/catalog/pg_default_acl.h
index aee49fdb6da..f4f8f99b3e3 100644
--- a/src/include/catalog/pg_default_acl.h
+++ b/src/include/catalog/pg_default_acl.h
@@ -29,6 +29,7 @@
  */
 CATALOG(pg_default_acl,826,DefaultAclRelationId)
 {
+	Oid			oid;			/* oid */
 	Oid			defaclrole;		/* OID of role owning this ACL */
 	Oid			defaclnamespace;	/* OID of namespace, or 0 for all */
 	char		defaclobjtype;	/* see DEFACLOBJ_xxx constants below */
diff --git a/src/include/catalog/pg_depend.h b/src/include/catalog/pg_depend.h
index 482b8bd2516..8f2d95210fa 100644
--- a/src/include/catalog/pg_depend.h
+++ b/src/include/catalog/pg_depend.h
@@ -38,7 +38,7 @@
  *		typedef struct FormData_pg_depend
  * ----------------
  */
-CATALOG(pg_depend,2608,DependRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_depend,2608,DependRelationId)
 {
 	/*
 	 * Identification of the dependent (referencing) object.
diff --git a/src/include/catalog/pg_description.h b/src/include/catalog/pg_description.h
index 74302bd451d..1f21a83ba2a 100644
--- a/src/include/catalog/pg_description.h
+++ b/src/include/catalog/pg_description.h
@@ -45,7 +45,7 @@
  *		typedef struct FormData_pg_description
  * ----------------
  */
-CATALOG(pg_description,2609,DescriptionRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_description,2609,DescriptionRelationId)
 {
 	Oid			objoid;			/* OID of object itself */
 	Oid			classoid;		/* OID of table containing object */
diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h
index e6fd41e5b23..a7c88806457 100644
--- a/src/include/catalog/pg_enum.h
+++ b/src/include/catalog/pg_enum.h
@@ -30,6 +30,7 @@
  */
 CATALOG(pg_enum,3501,EnumRelationId)
 {
+	Oid			oid;			/* oid */
 	Oid			enumtypid;		/* OID of owning enum type */
 	float4		enumsortorder;	/* sort position of this enum value */
 	NameData	enumlabel;		/* text representation of enum value */
diff --git a/src/include/catalog/pg_event_trigger.h b/src/include/catalog/pg_event_trigger.h
index 9af00fd68ff..16ee3098edd 100644
--- a/src/include/catalog/pg_event_trigger.h
+++ b/src/include/catalog/pg_event_trigger.h
@@ -28,6 +28,7 @@
  */
 CATALOG(pg_event_trigger,3466,EventTriggerRelationId)
 {
+	Oid			oid;			/* oid */
 	NameData	evtname;		/* trigger's name */
 	NameData	evtevent;		/* trigger's event */
 	Oid			evtowner;		/* trigger's owner */
diff --git a/src/include/catalog/pg_extension.h b/src/include/catalog/pg_extension.h
index c698ddd699a..e3773f67251 100644
--- a/src/include/catalog/pg_extension.h
+++ b/src/include/catalog/pg_extension.h
@@ -28,6 +28,7 @@
  */
 CATALOG(pg_extension,3079,ExtensionRelationId)
 {
+	Oid			oid;			/* oid */
 	NameData	extname;		/* extension name */
 	Oid			extowner;		/* extension owner */
 	Oid			extnamespace;	/* namespace of contained objects */
diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h
index 3e6191e3e25..e70823c4393 100644
--- a/src/include/catalog/pg_foreign_data_wrapper.h
+++ b/src/include/catalog/pg_foreign_data_wrapper.h
@@ -28,6 +28,7 @@
  */
 CATALOG(pg_foreign_data_wrapper,2328,ForeignDataWrapperRelationId)
 {
+	Oid			oid;			/* oid */
 	NameData	fdwname;		/* foreign-data wrapper name */
 	Oid			fdwowner;		/* FDW owner */
 	Oid			fdwhandler;		/* handler function, or 0 if none */
diff --git a/src/include/catalog/pg_foreign_server.h b/src/include/catalog/pg_foreign_server.h
index 3f7cc0c0469..49649bbd683 100644
--- a/src/include/catalog/pg_foreign_server.h
+++ b/src/include/catalog/pg_foreign_server.h
@@ -27,6 +27,7 @@
  */
 CATALOG(pg_foreign_server,1417,ForeignServerRelationId)
 {
+	Oid			oid;			/* oid */
 	NameData	srvname;		/* foreign server name */
 	Oid			srvowner;		/* server owner */
 	Oid			srvfdw;			/* server FDW */
diff --git a/src/include/catalog/pg_foreign_table.h b/src/include/catalog/pg_foreign_table.h
index 6e8b4195201..d21dec3766e 100644
--- a/src/include/catalog/pg_foreign_table.h
+++ b/src/include/catalog/pg_foreign_table.h
@@ -25,7 +25,7 @@
  *		typedef struct FormData_pg_foreign_table
  * ----------------
  */
-CATALOG(pg_foreign_table,3118,ForeignTableRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_foreign_table,3118,ForeignTableRelationId)
 {
 	Oid			ftrelid;		/* OID of foreign table */
 	Oid			ftserver;		/* OID of foreign server */
diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h
index 5f72a5571f2..ebe8955bf38 100644
--- a/src/include/catalog/pg_index.h
+++ b/src/include/catalog/pg_index.h
@@ -26,7 +26,7 @@
  *		typedef struct FormData_pg_index.
  * ----------------
  */
-CATALOG(pg_index,2610,IndexRelationId) BKI_WITHOUT_OIDS BKI_SCHEMA_MACRO
+CATALOG(pg_index,2610,IndexRelationId) BKI_SCHEMA_MACRO
 {
 	Oid			indexrelid;		/* OID of the index */
 	Oid			indrelid;		/* OID of the relation it indexes */
diff --git a/src/include/catalog/pg_inherits.h b/src/include/catalog/pg_inherits.h
index 2a98e02c6ac..07dfb63068b 100644
--- a/src/include/catalog/pg_inherits.h
+++ b/src/include/catalog/pg_inherits.h
@@ -29,7 +29,7 @@
  *		typedef struct FormData_pg_inherits
  * ----------------
  */
-CATALOG(pg_inherits,2611,InheritsRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_inherits,2611,InheritsRelationId)
 {
 	Oid			inhrelid;
 	Oid			inhparent;
diff --git a/src/include/catalog/pg_init_privs.h b/src/include/catalog/pg_init_privs.h
index 39de09cb9da..8a6da5ecf2d 100644
--- a/src/include/catalog/pg_init_privs.h
+++ b/src/include/catalog/pg_init_privs.h
@@ -43,7 +43,7 @@
  *		typedef struct FormData_pg_init_privs
  * ----------------
  */
-CATALOG(pg_init_privs,3394,InitPrivsRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_init_privs,3394,InitPrivsRelationId)
 {
 	Oid			objoid;			/* OID of object itself */
 	Oid			classoid;		/* OID of table containing object */
diff --git a/src/include/catalog/pg_language.h b/src/include/catalog/pg_language.h
index 359701b4522..03654d8d074 100644
--- a/src/include/catalog/pg_language.h
+++ b/src/include/catalog/pg_language.h
@@ -28,6 +28,8 @@
  */
 CATALOG(pg_language,2612,LanguageRelationId)
 {
+	Oid			oid;			/* oid */
+
 	/* Language name */
 	NameData	lanname;
 
diff --git a/src/include/catalog/pg_largeobject.h b/src/include/catalog/pg_largeobject.h
index a8aa42e049a..1497c97cee5 100644
--- a/src/include/catalog/pg_largeobject.h
+++ b/src/include/catalog/pg_largeobject.h
@@ -26,7 +26,7 @@
  *		typedef struct FormData_pg_largeobject
  * ----------------
  */
-CATALOG(pg_largeobject,2613,LargeObjectRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_largeobject,2613,LargeObjectRelationId)
 {
 	Oid			loid;			/* Identifier of large object */
 	int32		pageno;			/* Page number (starting from 0) */
diff --git a/src/include/catalog/pg_largeobject_metadata.h b/src/include/catalog/pg_largeobject_metadata.h
index c8560dc2afb..ef6427b8cc3 100644
--- a/src/include/catalog/pg_largeobject_metadata.h
+++ b/src/include/catalog/pg_largeobject_metadata.h
@@ -29,6 +29,8 @@
  */
 CATALOG(pg_largeobject_metadata,2995,LargeObjectMetadataRelationId)
 {
+	Oid			oid;			/* oid */
+
 	Oid			lomowner;		/* OID of the largeobject owner */
 
 #ifdef CATALOG_VARLEN			/* variable-length fields start here */
diff --git a/src/include/catalog/pg_namespace.h b/src/include/catalog/pg_namespace.h
index 0923e066b46..a7e101202f0 100644
--- a/src/include/catalog/pg_namespace.h
+++ b/src/include/catalog/pg_namespace.h
@@ -33,6 +33,8 @@
  */
 CATALOG(pg_namespace,2615,NamespaceRelationId)
 {
+	Oid			oid;			/* oid */
+
 	NameData	nspname;
 	Oid			nspowner;
 
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
index b980327fc03..5d229505077 100644
--- a/src/include/catalog/pg_opclass.h
+++ b/src/include/catalog/pg_opclass.h
@@ -48,6 +48,8 @@
  */
 CATALOG(pg_opclass,2616,OperatorClassRelationId)
 {
+	Oid			oid;			/* oid */
+
 	/* index access method opclass is for */
 	Oid			opcmethod BKI_LOOKUP(pg_am);
 
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index 3212b21418b..ca3ae6e191f 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -31,6 +31,8 @@
  */
 CATALOG(pg_operator,2617,OperatorRelationId)
 {
+	Oid			oid;			/* oid */
+
 	/* name of operator */
 	NameData	oprname;
 
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
index 99dedbc42d1..ce37ede57bf 100644
--- a/src/include/catalog/pg_opfamily.h
+++ b/src/include/catalog/pg_opfamily.h
@@ -28,6 +28,8 @@
  */
 CATALOG(pg_opfamily,2753,OperatorFamilyRelationId)
 {
+	Oid			oid;			/* oid */
+
 	/* index access method opfamily is for */
 	Oid			opfmethod BKI_LOOKUP(pg_am);
 
diff --git a/src/include/catalog/pg_partitioned_table.h b/src/include/catalog/pg_partitioned_table.h
index 78bc5c81fbc..39095fa69b1 100644
--- a/src/include/catalog/pg_partitioned_table.h
+++ b/src/include/catalog/pg_partitioned_table.h
@@ -27,7 +27,7 @@
  *		typedef struct FormData_pg_partitioned_table
  * ----------------
  */
-CATALOG(pg_partitioned_table,3350,PartitionedRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_partitioned_table,3350,PartitionedRelationId)
 {
 	Oid			partrelid;		/* partitioned table oid */
 	char		partstrat;		/* partitioning strategy */
diff --git a/src/include/catalog/pg_pltemplate.h b/src/include/catalog/pg_pltemplate.h
index ae06b752125..fba9efac90e 100644
--- a/src/include/catalog/pg_pltemplate.h
+++ b/src/include/catalog/pg_pltemplate.h
@@ -26,7 +26,7 @@
  *		typedef struct FormData_pg_pltemplate
  * ----------------
  */
-CATALOG(pg_pltemplate,1136,PLTemplateRelationId) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
+CATALOG(pg_pltemplate,1136,PLTemplateRelationId) BKI_SHARED_RELATION
 {
 	NameData	tmplname;		/* name of PL */
 	bool		tmpltrusted;	/* PL is trusted? */
diff --git a/src/include/catalog/pg_policy.h b/src/include/catalog/pg_policy.h
index 0dd9c50e536..d7eb1bd7596 100644
--- a/src/include/catalog/pg_policy.h
+++ b/src/include/catalog/pg_policy.h
@@ -28,6 +28,7 @@
  */
 CATALOG(pg_policy,3256,PolicyRelationId)
 {
+	Oid			oid;			/* oid */
 	NameData	polname;		/* Policy name. */
 	Oid			polrelid;		/* Oid of the relation with policy. */
 	char		polcmd;			/* One of ACL_*_CHR, or '*' for all */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index a34b2596fa0..b25dec6c311 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -30,6 +30,8 @@
  */
 CATALOG(pg_proc,1255,ProcedureRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(81,ProcedureRelation_Rowtype_Id) BKI_SCHEMA_MACRO
 {
+	Oid			oid;			/* oid */
+
 	/* procedure name */
 	NameData	proname;
 
diff --git a/src/include/catalog/pg_publication.h b/src/include/catalog/pg_publication.h
index a5d5570f76e..062b5afa0b5 100644
--- a/src/include/catalog/pg_publication.h
+++ b/src/include/catalog/pg_publication.h
@@ -29,6 +29,8 @@
  */
 CATALOG(pg_publication,6104,PublicationRelationId)
 {
+	Oid			oid;			/* oid */
+
 	NameData	pubname;		/* name of the publication */
 
 	Oid			pubowner;		/* publication owner */
diff --git a/src/include/catalog/pg_publication_rel.h b/src/include/catalog/pg_publication_rel.h
index d97b0fe9bd3..dbb4f3d9747 100644
--- a/src/include/catalog/pg_publication_rel.h
+++ b/src/include/catalog/pg_publication_rel.h
@@ -28,6 +28,7 @@
  */
 CATALOG(pg_publication_rel,6106,PublicationRelRelationId)
 {
+	Oid			oid;			/* oid: XXX: Needed? */
 	Oid			prpubid;		/* Oid of the publication */
 	Oid			prrelid;		/* Oid of the relation */
 } FormData_pg_publication_rel;
diff --git a/src/include/catalog/pg_range.h b/src/include/catalog/pg_range.h
index ca2b28b4936..32a7b2d1ae3 100644
--- a/src/include/catalog/pg_range.h
+++ b/src/include/catalog/pg_range.h
@@ -26,7 +26,7 @@
  *		typedef struct FormData_pg_range
  * ----------------
  */
-CATALOG(pg_range,3541,RangeRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_range,3541,RangeRelationId)
 {
 	/* OID of owning range type */
 	Oid			rngtypid BKI_LOOKUP(pg_type);
diff --git a/src/include/catalog/pg_replication_origin.h b/src/include/catalog/pg_replication_origin.h
index 82ff7a7c692..dd5a2e29648 100644
--- a/src/include/catalog/pg_replication_origin.h
+++ b/src/include/catalog/pg_replication_origin.h
@@ -28,7 +28,7 @@
  *		typedef struct FormData_pg_replication_origin
  * ----------------
  */
-CATALOG(pg_replication_origin,6000,ReplicationOriginRelationId) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
+CATALOG(pg_replication_origin,6000,ReplicationOriginRelationId) BKI_SHARED_RELATION
 {
 	/*
 	 * Locally known id that get included into WAL.
diff --git a/src/include/catalog/pg_rewrite.h b/src/include/catalog/pg_rewrite.h
index 0e50b879265..9b2b06dfa4d 100644
--- a/src/include/catalog/pg_rewrite.h
+++ b/src/include/catalog/pg_rewrite.h
@@ -31,6 +31,7 @@
  */
 CATALOG(pg_rewrite,2618,RewriteRelationId)
 {
+	Oid			oid;			/* oid */
 	NameData	rulename;
 	Oid			ev_class;
 	char		ev_type;
diff --git a/src/include/catalog/pg_seclabel.h b/src/include/catalog/pg_seclabel.h
index 6889369b5de..6bef8353b64 100644
--- a/src/include/catalog/pg_seclabel.h
+++ b/src/include/catalog/pg_seclabel.h
@@ -25,7 +25,7 @@
  *		typedef struct FormData_pg_seclabel
  * ----------------
  */
-CATALOG(pg_seclabel,3596,SecLabelRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_seclabel,3596,SecLabelRelationId)
 {
 	Oid			objoid;			/* OID of the object itself */
 	Oid			classoid;		/* OID of table containing the object */
diff --git a/src/include/catalog/pg_sequence.h b/src/include/catalog/pg_sequence.h
index beea215c81e..abd1a9d0437 100644
--- a/src/include/catalog/pg_sequence.h
+++ b/src/include/catalog/pg_sequence.h
@@ -20,7 +20,7 @@
 #include "catalog/genbki.h"
 #include "catalog/pg_sequence_d.h"
 
-CATALOG(pg_sequence,2224,SequenceRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_sequence,2224,SequenceRelationId)
 {
 	Oid			seqrelid;
 	Oid			seqtypid;
diff --git a/src/include/catalog/pg_shdepend.h b/src/include/catalog/pg_shdepend.h
index 01e1eb760c7..3d560f4295f 100644
--- a/src/include/catalog/pg_shdepend.h
+++ b/src/include/catalog/pg_shdepend.h
@@ -34,7 +34,7 @@
  *		typedef struct FormData_pg_shdepend
  * ----------------
  */
-CATALOG(pg_shdepend,1214,SharedDependRelationId) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
+CATALOG(pg_shdepend,1214,SharedDependRelationId) BKI_SHARED_RELATION
 {
 	/*
 	 * Identification of the dependent (referencing) object.
diff --git a/src/include/catalog/pg_shdescription.h b/src/include/catalog/pg_shdescription.h
index 53cade15488..47a6729f003 100644
--- a/src/include/catalog/pg_shdescription.h
+++ b/src/include/catalog/pg_shdescription.h
@@ -38,7 +38,7 @@
  *		typedef struct FormData_pg_shdescription
  * ----------------
  */
-CATALOG(pg_shdescription,2396,SharedDescriptionRelationId) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
+CATALOG(pg_shdescription,2396,SharedDescriptionRelationId) BKI_SHARED_RELATION
 {
 	Oid			objoid;			/* OID of object itself */
 	Oid			classoid;		/* OID of table containing object */
diff --git a/src/include/catalog/pg_shseclabel.h b/src/include/catalog/pg_shseclabel.h
index 2630f965fd3..2a66ca36025 100644
--- a/src/include/catalog/pg_shseclabel.h
+++ b/src/include/catalog/pg_shseclabel.h
@@ -25,7 +25,7 @@
  *		typedef struct FormData_pg_shseclabel
  * ----------------
  */
-CATALOG(pg_shseclabel,3592,SharedSecLabelRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(4066,SharedSecLabelRelation_Rowtype_Id) BKI_WITHOUT_OIDS BKI_SCHEMA_MACRO
+CATALOG(pg_shseclabel,3592,SharedSecLabelRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(4066,SharedSecLabelRelation_Rowtype_Id) BKI_SCHEMA_MACRO
 {
 	Oid			objoid;			/* OID of the shared object itself */
 	Oid			classoid;		/* OID of table containing the shared object */
diff --git a/src/include/catalog/pg_statistic.h b/src/include/catalog/pg_statistic.h
index 141e260de94..49223aab4fc 100644
--- a/src/include/catalog/pg_statistic.h
+++ b/src/include/catalog/pg_statistic.h
@@ -26,7 +26,7 @@
  *		typedef struct FormData_pg_statistic
  * ----------------
  */
-CATALOG(pg_statistic,2619,StatisticRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_statistic,2619,StatisticRelationId)
 {
 	/* These fields form the unique key for the entry: */
 	Oid			starelid;		/* relation containing attribute */
diff --git a/src/include/catalog/pg_statistic_ext.h b/src/include/catalog/pg_statistic_ext.h
index 443798ae523..51ebd5d969f 100644
--- a/src/include/catalog/pg_statistic_ext.h
+++ b/src/include/catalog/pg_statistic_ext.h
@@ -28,6 +28,8 @@
  */
 CATALOG(pg_statistic_ext,3381,StatisticExtRelationId)
 {
+	Oid			oid;			/* oid: XXX: Why? */
+
 	Oid			stxrelid;		/* relation containing attributes */
 
 	/* These two fields form the unique key for the entry: */
diff --git a/src/include/catalog/pg_subscription.h b/src/include/catalog/pg_subscription.h
index e4dc771cf53..4298c3cbf29 100644
--- a/src/include/catalog/pg_subscription.h
+++ b/src/include/catalog/pg_subscription.h
@@ -38,6 +38,8 @@
  */
 CATALOG(pg_subscription,6100,SubscriptionRelationId) BKI_SHARED_RELATION BKI_ROWTYPE_OID(6101,SubscriptionRelation_Rowtype_Id) BKI_SCHEMA_MACRO
 {
+	Oid			oid;			/* oid */
+
 	Oid			subdbid;		/* Database the subscription is in. */
 	NameData	subname;		/* Name of the subscription */
 
diff --git a/src/include/catalog/pg_subscription_rel.h b/src/include/catalog/pg_subscription_rel.h
index 556cb94841d..efd7901032e 100644
--- a/src/include/catalog/pg_subscription_rel.h
+++ b/src/include/catalog/pg_subscription_rel.h
@@ -29,7 +29,7 @@
  *		typedef struct FormData_pg_subscription_rel
  * ----------------
  */
-CATALOG(pg_subscription_rel,6102,SubscriptionRelRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_subscription_rel,6102,SubscriptionRelRelationId)
 {
 	Oid			srsubid;		/* Oid of subscription */
 	Oid			srrelid;		/* Oid of relation */
@@ -67,9 +67,9 @@ typedef struct SubscriptionRelState
 	char		state;
 } SubscriptionRelState;
 
-extern Oid AddSubscriptionRelState(Oid subid, Oid relid, char state,
+extern void AddSubscriptionRelState(Oid subid, Oid relid, char state,
 						XLogRecPtr sublsn);
-extern Oid UpdateSubscriptionRelState(Oid subid, Oid relid, char state,
+extern void UpdateSubscriptionRelState(Oid subid, Oid relid, char state,
 						   XLogRecPtr sublsn);
 extern char GetSubscriptionRelState(Oid subid, Oid relid,
 						XLogRecPtr *sublsn, bool missing_ok);
diff --git a/src/include/catalog/pg_tablespace.h b/src/include/catalog/pg_tablespace.h
index 4010f1b5a73..80caefd77aa 100644
--- a/src/include/catalog/pg_tablespace.h
+++ b/src/include/catalog/pg_tablespace.h
@@ -28,6 +28,7 @@
  */
 CATALOG(pg_tablespace,1213,TableSpaceRelationId) BKI_SHARED_RELATION
 {
+	Oid			oid;			/* oid */
 	NameData	spcname;		/* tablespace name */
 	Oid			spcowner;		/* owner of tablespace */
 
diff --git a/src/include/catalog/pg_transform.h b/src/include/catalog/pg_transform.h
index f46ff0a90e0..e92f0bccd1c 100644
--- a/src/include/catalog/pg_transform.h
+++ b/src/include/catalog/pg_transform.h
@@ -28,6 +28,7 @@
  */
 CATALOG(pg_transform,3576,TransformRelationId)
 {
+	Oid			oid;			/* oid */
 	Oid			trftype;
 	Oid			trflang;
 	regproc		trffromsql;
diff --git a/src/include/catalog/pg_trigger.h b/src/include/catalog/pg_trigger.h
index 951d7d86e75..c3a685304b0 100644
--- a/src/include/catalog/pg_trigger.h
+++ b/src/include/catalog/pg_trigger.h
@@ -33,6 +33,7 @@
  */
 CATALOG(pg_trigger,2620,TriggerRelationId)
 {
+	Oid			oid;			/* oid */
 	Oid			tgrelid;		/* relation trigger is attached to */
 	NameData	tgname;			/* trigger's name */
 	Oid			tgfoid;			/* OID of function to be called */
diff --git a/src/include/catalog/pg_ts_config.h b/src/include/catalog/pg_ts_config.h
index ce93c2b7ffb..d15db9b4b91 100644
--- a/src/include/catalog/pg_ts_config.h
+++ b/src/include/catalog/pg_ts_config.h
@@ -29,6 +29,7 @@
  */
 CATALOG(pg_ts_config,3602,TSConfigRelationId)
 {
+	Oid			oid;			/* oid */
 	NameData	cfgname;		/* name of configuration */
 	Oid			cfgnamespace;	/* name space */
 	Oid			cfgowner;		/* owner */
diff --git a/src/include/catalog/pg_ts_config_map.h b/src/include/catalog/pg_ts_config_map.h
index 58563233733..37d81e5597e 100644
--- a/src/include/catalog/pg_ts_config_map.h
+++ b/src/include/catalog/pg_ts_config_map.h
@@ -27,7 +27,7 @@
  *		typedef struct FormData_pg_ts_config_map
  * ----------------
  */
-CATALOG(pg_ts_config_map,3603,TSConfigMapRelationId) BKI_WITHOUT_OIDS
+CATALOG(pg_ts_config_map,3603,TSConfigMapRelationId)
 {
 	Oid			mapcfg;			/* OID of configuration owning this entry */
 	int32		maptokentype;	/* token type from parser */
diff --git a/src/include/catalog/pg_ts_dict.h b/src/include/catalog/pg_ts_dict.h
index cd5f150fe8e..5c4182abac1 100644
--- a/src/include/catalog/pg_ts_dict.h
+++ b/src/include/catalog/pg_ts_dict.h
@@ -28,6 +28,7 @@
  */
 CATALOG(pg_ts_dict,3600,TSDictionaryRelationId)
 {
+	Oid			oid;			/* oid */
 	NameData	dictname;		/* dictionary name */
 	Oid			dictnamespace;	/* name space */
 	Oid			dictowner;		/* owner */
diff --git a/src/include/catalog/pg_ts_parser.h b/src/include/catalog/pg_ts_parser.h
index 34585eac00c..b46a91525e3 100644
--- a/src/include/catalog/pg_ts_parser.h
+++ b/src/include/catalog/pg_ts_parser.h
@@ -28,6 +28,8 @@
  */
 CATALOG(pg_ts_parser,3601,TSParserRelationId)
 {
+	Oid			oid;			/* oid */
+
 	/* parser's name */
 	NameData	prsname;
 
diff --git a/src/include/catalog/pg_ts_template.h b/src/include/catalog/pg_ts_template.h
index 50be08eca56..d970ebf659d 100644
--- a/src/include/catalog/pg_ts_template.h
+++ b/src/include/catalog/pg_ts_template.h
@@ -28,6 +28,8 @@
  */
 CATALOG(pg_ts_template,3764,TSTemplateRelationId)
 {
+	Oid			oid;			/* oid */
+
 	/* template name */
 	NameData	tmplname;
 
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 76f3297e1d9..91e2ba7070e 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -36,6 +36,8 @@
  */
 CATALOG(pg_type,1247,TypeRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(71,TypeRelation_Rowtype_Id) BKI_SCHEMA_MACRO
 {
+	Oid			oid;			/* oid */
+
 	/* type name */
 	NameData	typname;
 
diff --git a/src/include/catalog/pg_user_mapping.h b/src/include/catalog/pg_user_mapping.h
index e4e2ff36dcf..985ad9b94cd 100644
--- a/src/include/catalog/pg_user_mapping.h
+++ b/src/include/catalog/pg_user_mapping.h
@@ -27,6 +27,8 @@
  */
 CATALOG(pg_user_mapping,1418,UserMappingRelationId)
 {
+	Oid			oid;			/* oid */
+
 	Oid			umuser;			/* Id of the user, InvalidOid if PUBLIC is
 								 * wanted */
 	Oid			umserver;		/* server of this mapping */
diff --git a/src/include/commands/copy.h b/src/include/commands/copy.h
index f393e7e73d7..b5cadce3efa 100644
--- a/src/include/commands/copy.h
+++ b/src/include/commands/copy.h
@@ -32,7 +32,7 @@ extern CopyState BeginCopyFrom(ParseState *pstate, Relation rel, const char *fil
 			  bool is_program, copy_data_source_cb data_source_cb, List *attnamelist, List *options);
 extern void EndCopyFrom(CopyState cstate);
 extern bool NextCopyFrom(CopyState cstate, ExprContext *econtext,
-			 Datum *values, bool *nulls, Oid *tupleOid);
+			 Datum *values, bool *nulls);
 extern bool NextCopyFromRawFields(CopyState cstate,
 					  char ***fields, int *nfields);
 extern void CopyFromErrorCallback(void *arg);
diff --git a/src/include/commands/event_trigger.h b/src/include/commands/event_trigger.h
index 0e1959462eb..5a2fc6c8d71 100644
--- a/src/include/commands/event_trigger.h
+++ b/src/include/commands/event_trigger.h
@@ -31,7 +31,6 @@ typedef struct EventTriggerData
 #define AT_REWRITE_ALTER_PERSISTENCE	0x01
 #define AT_REWRITE_DEFAULT_VAL			0x02
 #define AT_REWRITE_COLUMN_REWRITE		0x04
-#define AT_REWRITE_ALTER_OID			0x08
 
 /*
  * EventTriggerData is the node type that is passed as fmgr "context" info
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index f82b51667f4..9e2f208e11f 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -50,18 +50,13 @@
  * AfterTriggerBeginQuery/AfterTriggerEndQuery.  This does not necessarily
  * mean that the plan can't queue any AFTER triggers; just that the caller
  * is responsible for there being a trigger context for them to be queued in.
- *
- * WITH/WITHOUT_OIDS tell the executor to emit tuples with or without space
- * for OIDs, respectively.  These are currently used only for CREATE TABLE AS.
- * If neither is set, the plan may or may not produce tuples including OIDs.
  */
 #define EXEC_FLAG_EXPLAIN_ONLY	0x0001	/* EXPLAIN, no ANALYZE */
 #define EXEC_FLAG_REWIND		0x0002	/* need efficient rescan */
 #define EXEC_FLAG_BACKWARD		0x0004	/* need backward scan */
 #define EXEC_FLAG_MARK			0x0008	/* need mark/restore */
 #define EXEC_FLAG_SKIP_TRIGGERS 0x0010	/* skip AfterTrigger calls */
-#define EXEC_FLAG_WITH_OIDS		0x0020	/* force OIDs in returned tuples */
-#define EXEC_FLAG_WITHOUT_OIDS	0x0040	/* force no OIDs in returned tuples */
+/* space, XXX: renumber? */
 #define EXEC_FLAG_WITH_NO_DATA	0x0080	/* rel scannability doesn't matter */
 
 
@@ -140,7 +135,7 @@ extern TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable,
 /*
  * prototypes from functions in execJunk.c
  */
-extern JunkFilter *ExecInitJunkFilter(List *targetList, bool hasoid,
+extern JunkFilter *ExecInitJunkFilter(List *targetList,
 				   TupleTableSlot *slot);
 extern JunkFilter *ExecInitJunkFilterConversion(List *targetList,
 							 TupleDesc cleanTupType,
@@ -178,7 +173,6 @@ extern void InitResultRelInfo(ResultRelInfo *resultRelInfo,
 				  int instrument_options);
 extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid);
 extern void ExecCleanUpTriggerState(EState *estate);
-extern bool ExecContextForcesOids(PlanState *planstate, bool *hasoids);
 extern void ExecConstraints(ResultRelInfo *resultRelInfo,
 				TupleTableSlot *slot, EState *estate);
 extern bool ExecPartitionCheck(ResultRelInfo *resultRelInfo,
@@ -435,8 +429,8 @@ extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate,
 					   TupleDesc tupleDesc);
 extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate,
 					  TupleDesc tupType);
-extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid);
-extern TupleDesc ExecCleanTypeFromTL(List *targetList, bool hasoid);
+extern TupleDesc ExecTypeFromTL(List *targetList);
+extern TupleDesc ExecCleanTypeFromTL(List *targetList);
 extern TupleDesc ExecTypeFromExprList(List *exprList);
 extern void ExecTypeSetColNames(TupleDesc typeInfo, List *namesList);
 extern void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg);
diff --git a/src/include/executor/spi_priv.h b/src/include/executor/spi_priv.h
index 0da3a41050e..d86d7e0a831 100644
--- a/src/include/executor/spi_priv.h
+++ b/src/include/executor/spi_priv.h
@@ -23,7 +23,6 @@ typedef struct
 {
 	/* current results */
 	uint64		processed;		/* by Executor */
-	Oid			lastoid;
 	SPITupleTable *tuptable;	/* tuptable currently being built */
 
 	/* subtransaction in which current Executor call was started */
@@ -45,7 +44,6 @@ typedef struct
 
 	/* saved values of API global variables for previous nesting level */
 	uint64		outer_processed;
-	Oid			outer_lastoid;
 	SPITupleTable *outer_tuptable;
 	int			outer_result;
 } _SPI_connection;
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 03ad5169762..d91206b8349 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -528,7 +528,6 @@ typedef struct EState
 	List	   *es_rowMarks;	/* List of ExecRowMarks */
 
 	uint64		es_processed;	/* # of tuples processed */
-	Oid			es_lastoid;		/* last oid processed (by INSERT) */
 
 	int			es_top_eflags;	/* eflags passed to ExecutorStart */
 	int			es_instrument;	/* OR of InstrumentOption flags */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 62209a8f102..d02fc59ee67 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1683,7 +1683,8 @@ typedef enum ObjectType
 	OBJECT_TSTEMPLATE,
 	OBJECT_TYPE,
 	OBJECT_USER_MAPPING,
-	OBJECT_VIEW
+	OBJECT_VIEW,
+	OBJECT_ENUM
 } ObjectType;
 
 /* ----------------------
@@ -1758,9 +1759,6 @@ typedef enum AlterTableType
 	AT_DropCluster,				/* SET WITHOUT CLUSTER */
 	AT_SetLogged,				/* SET LOGGED */
 	AT_SetUnLogged,				/* SET UNLOGGED */
-	AT_AddOids,					/* SET WITH OIDS */
-	AT_AddOidsRecurse,			/* internal to commands/tablecmds.c */
-	AT_DropOids,				/* SET WITHOUT OIDS */
 	AT_SetTableSpace,			/* SET TABLESPACE */
 	AT_SetRelOptions,			/* SET (...) -- AM specific parameters */
 	AT_ResetRelOptions,			/* RESET (...) -- AM specific parameters */
diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h
index 2c0e0928628..f37f55302fb 100644
--- a/src/include/parser/parse_clause.h
+++ b/src/include/parser/parse_clause.h
@@ -19,7 +19,6 @@
 extern void transformFromClause(ParseState *pstate, List *frmList);
 extern int setTargetTable(ParseState *pstate, RangeVar *relation,
 			   bool inh, bool alsoSource, AclMode requiredPerms);
-extern bool interpretOidsOption(List *defList, bool allowOids);
 
 extern Node *transformWhereClause(ParseState *pstate, Node *clause,
 					 ParseExprKind exprKind, const char *constructName);
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 6ecbdb62944..5d585204c85 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -103,7 +103,9 @@ typedef struct RelationData
 
 	/* data managed by RelationGetIndexList: */
 	List	   *rd_indexlist;	/* list of OIDs of indexes on relation */
+#if 0
 	Oid			rd_oidindex;	/* OID of unique index on OID, if any */
+#endif
 	Oid			rd_pkindex;		/* OID of primary key, if any */
 	Oid			rd_replidindex; /* OID of replica identity index, if any */
 
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index dbbf41b0c16..23082656b8d 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -45,7 +45,6 @@ extern void RelationClose(Relation relation);
 extern List *RelationGetFKeyList(Relation relation);
 extern List *RelationGetIndexList(Relation relation);
 extern List *RelationGetStatExtList(Relation relation);
-extern Oid	RelationGetOidIndex(Relation relation);
 extern Oid	RelationGetPrimaryKeyIndex(Relation relation);
 extern Oid	RelationGetReplicaIndex(Relation relation);
 extern List *RelationGetIndexExpressions(Relation relation);
diff --git a/src/interfaces/ecpg/preproc/ecpg.addons b/src/interfaces/ecpg/preproc/ecpg.addons
index ca3efadc481..0167ee4620a 100644
--- a/src/interfaces/ecpg/preproc/ecpg.addons
+++ b/src/interfaces/ecpg/preproc/ecpg.addons
@@ -192,7 +192,7 @@ ECPG: where_or_current_clauseWHERECURRENT_POFcursor_name block
 		char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4;
 		$$ = cat_str(2,mm_strdup("where current of"), cursor_marker);
 	}
-ECPG: CopyStmtCOPYopt_binaryqualified_nameopt_column_listopt_oidscopy_fromopt_programcopy_file_namecopy_delimiteropt_withcopy_options addon
+ECPG: CopyStmtCOPYopt_binaryqualified_nameopt_column_listcopy_fromopt_programcopy_file_namecopy_delimiteropt_withcopy_options addon
 			if (strcmp($6, "from") == 0 &&
 			   (strcmp($7, "stdin") == 0 || strcmp($7, "stdout") == 0))
 				mmerror(PARSE_ERROR, ET_WARNING, "COPY FROM STDIN is not implemented");
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 4cfc5062531..fe54b209035 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -2825,7 +2825,7 @@ compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger)
 			elog(ERROR, "cache lookup failed for language %u",
 				 procStruct->prolang);
 		langStruct = (Form_pg_language) GETSTRUCT(langTup);
-		prodesc->lang_oid = HeapTupleGetOid(langTup);
+		prodesc->lang_oid = langStruct->oid;
 		prodesc->lanpltrusted = langStruct->lanpltrusted;
 		ReleaseSysCache(langTup);
 
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 721234d6d29..9af8d59befa 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -1896,7 +1896,7 @@ build_row_from_vars(PLpgSQL_variable **vars, int numvars)
 
 	row = palloc0(sizeof(PLpgSQL_row));
 	row->dtype = PLPGSQL_DTYPE_ROW;
-	row->rowtupdesc = CreateTemplateTupleDesc(numvars, false);
+	row->rowtupdesc = CreateTemplateTupleDesc(numvars);
 	row->nfields = numvars;
 	row->fieldnames = palloc(numvars * sizeof(char *));
 	row->varnos = palloc(numvars * sizeof(int));
@@ -2029,7 +2029,7 @@ build_datatype(HeapTuple typeTup, int32 typmod, Oid collation)
 	typ = (PLpgSQL_type *) palloc(sizeof(PLpgSQL_type));
 
 	typ->typname = pstrdup(NameStr(typeStruct->typname));
-	typ->typoid = HeapTupleGetOid(typeTup);
+	typ->typoid = typeStruct->oid;
 	switch (typeStruct->typtype)
 	{
 		case TYPTYPE_BASE:
diff --git a/src/test/modules/test_predtest/test_predtest.c b/src/test/modules/test_predtest/test_predtest.c
index 51320ade2e5..1e699e6556e 100644
--- a/src/test/modules/test_predtest/test_predtest.c
+++ b/src/test/modules/test_predtest/test_predtest.c
@@ -185,7 +185,7 @@ test_predtest(PG_FUNCTION_ARGS)
 	if (SPI_finish() != SPI_OK_FINISH)
 		elog(ERROR, "SPI_finish failed");
 
-	tupdesc = CreateTemplateTupleDesc(8, false);
+	tupdesc = CreateTemplateTupleDesc(8);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1,
 					   "strong_implied_by", BOOLOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2,
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index dccc9b27c59..1c06636b59e 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -855,7 +855,7 @@ ERROR:  check constraint "foo" is violated by some row
 drop table atacc2;
 drop table atacc1;
 -- test unique constraint adding
-create table atacc1 ( test int ) with oids;
+create table atacc1 ( test int ) ;
 -- add a unique constraint
 alter table atacc1 add constraint atacc_test1 unique (test);
 -- insert first value
@@ -866,8 +866,6 @@ ERROR:  duplicate key value violates unique constraint "atacc_test1"
 DETAIL:  Key (test)=(2) already exists.
 -- should succeed
 insert into atacc1 (test) values (4);
--- try adding a unique oid constraint
-alter table atacc1 add constraint atacc_oid1 unique(oid);
 -- try to create duplicates via alter table using - should fail
 alter table atacc1 alter column test type integer using 0;
 ERROR:  could not create unique index "atacc_test1"
@@ -916,7 +914,7 @@ ERROR:  duplicate key value violates unique constraint "atacc1_test_key"
 DETAIL:  Key (test)=(3) already exists.
 drop table atacc1;
 -- test primary key constraint adding
-create table atacc1 ( test int ) with oids;
+create table atacc1 ( id serial, test int) ;
 -- add a primary key constraint
 alter table atacc1 add constraint atacc_test1 primary key (test);
 -- insert first value
@@ -930,14 +928,14 @@ insert into atacc1 (test) values (4);
 -- inserting NULL should fail
 insert into atacc1 (test) values(NULL);
 ERROR:  null value in column "test" violates not-null constraint
-DETAIL:  Failing row contains (null).
+DETAIL:  Failing row contains (4, null).
 -- try adding a second primary key (should fail)
-alter table atacc1 add constraint atacc_oid1 primary key(oid);
+alter table atacc1 add constraint atacc_oid1 primary key(id);
 ERROR:  multiple primary keys for table "atacc1" are not allowed
 -- drop first primary key constraint
 alter table atacc1 drop constraint atacc_test1 restrict;
 -- try adding a primary key on oid (should succeed)
-alter table atacc1 add constraint atacc_oid1 primary key(oid);
+alter table atacc1 add constraint atacc_oid1 primary key(id);
 drop table atacc1;
 -- let's do one where the primary key constraint fails when added
 create table atacc1 ( test int );
@@ -1027,7 +1025,7 @@ alter table non_existent alter column bar drop not null;
 ERROR:  relation "non_existent" does not exist
 -- test setting columns to null and not null and vice versa
 -- test checking for null values and primary key
-create table atacc1 (test int not null) with oids;
+create table atacc1 (test int not null);
 alter table atacc1 add constraint "atacc1_pkey" primary key (test);
 alter table atacc1 alter column test drop not null;
 ERROR:  column "test" is in a primary key
@@ -1043,11 +1041,6 @@ alter table atacc1 alter bar set not null;
 ERROR:  column "bar" of relation "atacc1" does not exist
 alter table atacc1 alter bar drop not null;
 ERROR:  column "bar" of relation "atacc1" does not exist
--- try altering the oid column, should fail
-alter table atacc1 alter oid set not null;
-ERROR:  cannot alter system column "oid"
-alter table atacc1 alter oid drop not null;
-ERROR:  cannot alter system column "oid"
 -- try creating a view and altering that, should fail
 create view myview as select * from atacc1;
 alter table myview alter column test drop not null;
@@ -1153,7 +1146,7 @@ ERROR:  permission denied: "pg_class" is a system catalog
 alter table nosuchtable drop column bar;
 ERROR:  relation "nosuchtable" does not exist
 -- test dropping columns
-create table atacc1 (a int4 not null, b int4, c int4 not null, d int4) with oids;
+create table atacc1 (a int4 not null, b int4, c int4 not null, d int4);
 insert into atacc1 values (1, 2, 3, 4);
 alter table atacc1 drop a;
 alter table atacc1 drop a;
@@ -1298,8 +1291,6 @@ delete from atacc1;
 -- try dropping a non-existent column, should fail
 alter table atacc1 drop bar;
 ERROR:  column "bar" of relation "atacc1" does not exist
--- try dropping the oid column, should succeed
-alter table atacc1 drop oid;
 -- try dropping the xmin column, should fail
 alter table atacc1 drop xmin;
 ERROR:  cannot drop system column "xmin"
@@ -1697,131 +1688,6 @@ order by attrelid::regclass::text, attnum;
  depth2   | c       |           1 | f
 (3 rows)
 
---
--- Test the ALTER TABLE SET WITH/WITHOUT OIDS command
---
-create table altstartwith (col integer) with oids;
-insert into altstartwith values (1);
-select oid > 0, * from altstartwith;
- ?column? | col 
-----------+-----
- t        |   1
-(1 row)
-
-alter table altstartwith set without oids;
-select oid > 0, * from altstartwith; -- fails
-ERROR:  column "oid" does not exist
-LINE 1: select oid > 0, * from altstartwith;
-               ^
-select * from altstartwith;
- col 
------
-   1
-(1 row)
-
-alter table altstartwith set with oids;
-select oid > 0, * from altstartwith;
- ?column? | col 
-----------+-----
- t        |   1
-(1 row)
-
-drop table altstartwith;
--- Check inheritance cases
-create table altwithoid (col integer) with oids;
--- Inherits parents oid column anyway
-create table altinhoid () inherits (altwithoid) without oids;
-insert into altinhoid values (1);
-select oid > 0, * from altwithoid;
- ?column? | col 
-----------+-----
- t        |   1
-(1 row)
-
-select oid > 0, * from altinhoid;
- ?column? | col 
-----------+-----
- t        |   1
-(1 row)
-
-alter table altwithoid set without oids;
-select oid > 0, * from altwithoid; -- fails
-ERROR:  column "oid" does not exist
-LINE 1: select oid > 0, * from altwithoid;
-               ^
-select oid > 0, * from altinhoid; -- fails
-ERROR:  column "oid" does not exist
-LINE 1: select oid > 0, * from altinhoid;
-               ^
-select * from altwithoid;
- col 
------
-   1
-(1 row)
-
-select * from altinhoid;
- col 
------
-   1
-(1 row)
-
-alter table altwithoid set with oids;
-select oid > 0, * from altwithoid;
- ?column? | col 
-----------+-----
- t        |   1
-(1 row)
-
-select oid > 0, * from altinhoid;
- ?column? | col 
-----------+-----
- t        |   1
-(1 row)
-
-drop table altwithoid cascade;
-NOTICE:  drop cascades to table altinhoid
-create table altwithoid (col integer) without oids;
--- child can have local oid column
-create table altinhoid () inherits (altwithoid) with oids;
-insert into altinhoid values (1);
-select oid > 0, * from altwithoid; -- fails
-ERROR:  column "oid" does not exist
-LINE 1: select oid > 0, * from altwithoid;
-               ^
-select oid > 0, * from altinhoid;
- ?column? | col 
-----------+-----
- t        |   1
-(1 row)
-
-alter table altwithoid set with oids;
-NOTICE:  merging definition of column "oid" for child "altinhoid"
-select oid > 0, * from altwithoid;
- ?column? | col 
-----------+-----
- t        |   1
-(1 row)
-
-select oid > 0, * from altinhoid;
- ?column? | col 
-----------+-----
- t        |   1
-(1 row)
-
--- the child's local definition should remain
-alter table altwithoid set without oids;
-select oid > 0, * from altwithoid; -- fails
-ERROR:  column "oid" does not exist
-LINE 1: select oid > 0, * from altwithoid;
-               ^
-select oid > 0, * from altinhoid;
- ?column? | col 
-----------+-----
- t        |   1
-(1 row)
-
-drop table altwithoid cascade;
-NOTICE:  drop cascades to table altinhoid
 -- test renumbering of child-table columns in inherited operations
 create table p1 (f1 int);
 create table c1 (f2 text, f3 int) inherits (p1);
@@ -2922,7 +2788,7 @@ CREATE TABLE tt3 (y numeric(8,2), x int);			-- wrong column order
 CREATE TABLE tt4 (x int);							-- too few columns
 CREATE TABLE tt5 (x int, y numeric(8,2), z int);	-- too few columns
 CREATE TABLE tt6 () INHERITS (tt0);					-- can't have a parent
-CREATE TABLE tt7 (x int, q text, y numeric(8,2)) WITH OIDS;
+CREATE TABLE tt7 (x int, q text, y numeric(8,2));
 ALTER TABLE tt7 DROP q;								-- OK
 ALTER TABLE tt0 OF tt_t0;
 ALTER TABLE tt1 OF tt_t0;
@@ -3447,16 +3313,6 @@ ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1);
 ERROR:  cannot attach a typed table as partition
 DROP TYPE mytype CASCADE;
 NOTICE:  drop cascades to table fail_part
--- check existence (or non-existence) of oid column
-ALTER TABLE list_parted SET WITH OIDS;
-CREATE TABLE fail_part (a int);
-ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1);
-ERROR:  cannot attach table "fail_part" without OIDs as partition of table "list_parted" with OIDs
-ALTER TABLE list_parted SET WITHOUT OIDS;
-ALTER TABLE fail_part SET WITH OIDS;
-ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1);
-ERROR:  cannot attach table "fail_part" with OIDs as partition of table "list_parted" without OIDs
-DROP TABLE fail_part;
 -- check that the table being attached has only columns present in the parent
 CREATE TABLE fail_part (like list_parted, c int);
 ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1);
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index eb9e4b97741..19bb5384110 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -4,7 +4,7 @@ CREATE TEMP TABLE x (
 	c text not null default 'stuff',
 	d text,
 	e text
-) WITH OIDS;
+) ;
 CREATE FUNCTION fn_x_before () RETURNS TRIGGER AS '
   BEGIN
 		NEW.e := ''before trigger fired''::text;
@@ -46,7 +46,7 @@ COPY x from stdin;
 ERROR:  extra data after last expected column
 CONTEXT:  COPY x, line 1: "2002	232	40	50	60	70	80"
 -- various COPY options: delimiters, oids, NULL string, encoding
-COPY x (b, c, d, e) from stdin with oids delimiter ',' null 'x';
+COPY x (b, c, d, e) from stdin delimiter ',' null 'x';
 COPY x from stdin WITH DELIMITER AS ';' NULL AS '';
 COPY x from stdin WITH DELIMITER AS ':' NULL AS E'\\X' ENCODING 'sql_ascii';
 -- check results of copy in
@@ -80,18 +80,6 @@ SELECT * FROM x;
      5 |  5 | stuff      | test_5 | after trigger fired
 (25 rows)
 
--- COPY w/ oids on a table w/o oids should fail
-CREATE TABLE no_oids (
-	a	int,
-	b	int
-) WITHOUT OIDS;
-INSERT INTO no_oids (a, b) VALUES (5, 10);
-INSERT INTO no_oids (a, b) VALUES (20, 30);
--- should fail
-COPY no_oids FROM stdin WITH OIDS;
-ERROR:  table "no_oids" does not have OIDs
-COPY no_oids TO stdout WITH OIDS;
-ERROR:  table "no_oids" does not have OIDs
 -- check copy out
 COPY x TO stdout;
 9999	\N	\\N	NN	before trigger fired
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 297535bb8fd..46deb55c679 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -2779,19 +2779,17 @@ DROP TABLE cwi_test;
 --
 -- Check handling of indexes on system columns
 --
-CREATE TABLE oid_table (a INT) WITH OIDS;
--- An index on the OID column should be allowed
-CREATE INDEX ON oid_table (oid);
--- Other system columns cannot be indexed
-CREATE INDEX ON oid_table (ctid);
-ERROR:  index creation on system columns is not supported
+CREATE TABLE syscol_table (a INT);
+-- System columns cannot be indexed
+CREATE INDEX ON syscolcol_table (ctid);
+ERROR:  relation "syscolcol_table" does not exist
 -- nor used in expressions
-CREATE INDEX ON oid_table ((ctid >= '(1000,0)'));
+CREATE INDEX ON syscol_table ((ctid >= '(1000,0)'));
 ERROR:  index creation on system columns is not supported
 -- nor used in predicates
-CREATE INDEX ON oid_table (a) WHERE ctid >= '(1000,0)';
+CREATE INDEX ON syscol_table (a) WHERE ctid >= '(1000,0)';
 ERROR:  index creation on system columns is not supported
-DROP TABLE oid_table;
+DROP TABLE syscol_table;
 --
 -- Tests for IS NULL/IS NOT NULL with b-tree indexes
 --
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index 744b9990a6b..16bf18e526b 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -47,7 +47,7 @@ CREATE TABLE tenk1 (
 	stringu1	name,
 	stringu2	name,
 	string4		name
-) WITH OIDS;
+);
 CREATE TABLE tenk2 (
 	unique1 	int4,
 	unique2 	int4,
@@ -74,7 +74,7 @@ CREATE TABLE person (
 CREATE TABLE emp (
 	salary 		int4,
 	manager 	name
-) INHERITS (person) WITH OIDS;
+) INHERITS (person);
 CREATE TABLE student (
 	gpa 		float8
 ) INHERITS (person);
@@ -218,8 +218,6 @@ NOTICE:  relation "test_tsvector" already exists, skipping
 -- invalid: non-lowercase quoted reloptions identifiers
 CREATE TABLE tas_case WITH ("Fillfactor" = 10) AS SELECT 1 a;
 ERROR:  unrecognized parameter "Fillfactor"
-CREATE TABLE tas_case (a text) WITH ("Oids" = true);
-ERROR:  unrecognized parameter "Oids"
 CREATE UNLOGGED TABLE unlogged1 (a int primary key);			-- OK
 CREATE TEMPORARY TABLE unlogged2 (a int primary key);			-- OK
 SELECT relname, relkind, relpersistence FROM pg_class WHERE relname ~ '^unlogged\d' ORDER BY relname;
@@ -263,9 +261,6 @@ ERROR:  relation "as_select1" already exists
 CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
 NOTICE:  relation "as_select1" already exists, skipping
 DROP TABLE as_select1;
--- check that the oid column is added before the primary key is checked
-CREATE TABLE oid_pk (f1 INT, PRIMARY KEY(oid)) WITH OIDS;
-DROP TABLE oid_pk;
 --
 -- Partitioned tables
 --
@@ -575,29 +570,6 @@ CREATE TEMP TABLE temp_parted (
 CREATE TABLE fail_part PARTITION OF temp_parted FOR VALUES IN ('a');
 ERROR:  cannot create a permanent relation as partition of temporary relation "temp_parted"
 DROP TABLE temp_parted;
--- cannot create a table with oids as partition of table without oids
-CREATE TABLE no_oids_parted (
-	a int
-) PARTITION BY RANGE (a) WITHOUT OIDS;
-CREATE TABLE fail_part PARTITION OF no_oids_parted FOR VALUES FROM (1) TO (10) WITH OIDS;
-ERROR:  cannot create table with OIDs as partition of table without OIDs
-DROP TABLE no_oids_parted;
--- If the partitioned table has oids, then the partition must have them.
--- If the WITHOUT OIDS option is specified for partition, it is overridden.
-CREATE TABLE oids_parted (
-	a int
-) PARTITION BY RANGE (a) WITH OIDS;
-CREATE TABLE part_forced_oids PARTITION OF oids_parted FOR VALUES FROM (1) TO (10) WITHOUT OIDS;
-\d+ part_forced_oids
-                             Table "public.part_forced_oids"
- Column |  Type   | Collation | Nullable | Default | Storage | Stats target | Description 
---------+---------+-----------+----------+---------+---------+--------------+-------------
- a      | integer |           |          |         | plain   |              | 
-Partition of: oids_parted FOR VALUES FROM (1) TO (10)
-Partition constraint: ((a IS NOT NULL) AND (a >= 1) AND (a < 10))
-Has OIDs: yes
-
-DROP TABLE oids_parted, part_forced_oids;
 -- check for partition bound overlap and other invalid specifications
 CREATE TABLE list_parted2 (
 	a varchar
diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out
index 8d4543bfe8d..b5822112706 100644
--- a/src/test/regress/expected/create_table_like.out
+++ b/src/test/regress/expected/create_table_like.out
@@ -285,37 +285,3 @@ DROP TYPE ctlty1;
 DROP VIEW ctlv1;
 DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12;
 NOTICE:  table "ctlt10" does not exist, skipping
-/* LIKE WITH OIDS */
-CREATE TABLE has_oid (x INTEGER) WITH OIDS;
-CREATE TABLE no_oid (y INTEGER);
-CREATE TABLE like_test (z INTEGER, LIKE has_oid);
-SELECT oid FROM like_test;
- oid 
------
-(0 rows)
-
-CREATE TABLE like_test2 (z INTEGER, LIKE no_oid);
-SELECT oid FROM like_test2; -- fail
-ERROR:  column "oid" does not exist
-LINE 1: SELECT oid FROM like_test2;
-               ^
-CREATE TABLE like_test3 (z INTEGER, LIKE has_oid, LIKE no_oid);
-SELECT oid FROM like_test3;
- oid 
------
-(0 rows)
-
-CREATE TABLE like_test4 (z INTEGER, PRIMARY KEY(oid), LIKE has_oid);
-SELECT oid FROM like_test4;
- oid 
------
-(0 rows)
-
-CREATE TABLE like_test5 (z INTEGER, LIKE no_oid) WITH OIDS;
-SELECT oid FROM like_test5;
- oid 
------
-(0 rows)
-
-DROP TABLE has_oid, no_oid, like_test, like_test2, like_test3,
-  like_test4, like_test5;
diff --git a/src/test/regress/expected/enum.out b/src/test/regress/expected/enum.out
index a0b81608a1b..36c52090002 100644
--- a/src/test/regress/expected/enum.out
+++ b/src/test/regress/expected/enum.out
@@ -629,7 +629,7 @@ SELECT COUNT(*) FROM pg_type WHERE typname = 'rainbow';
 
 SELECT * FROM pg_enum WHERE NOT EXISTS
   (SELECT 1 FROM pg_type WHERE pg_type.oid = enumtypid);
- enumtypid | enumsortorder | enumlabel 
------------+---------------+-----------
+ oid | enumtypid | enumsortorder | enumlabel 
+-----+-----------+---------------+-----------
 (0 rows)
 
diff --git a/src/test/regress/expected/errors.out b/src/test/regress/expected/errors.out
index ce473a03efd..7dd8a5b33e4 100644
--- a/src/test/regress/expected/errors.out
+++ b/src/test/regress/expected/errors.out
@@ -103,8 +103,8 @@ ERROR:  column "nonesuchatt" does not exist
 alter table emp rename column salary to manager;
 ERROR:  column "manager" of relation "stud_emp" already exists
 -- conflict
-alter table emp rename column salary to oid;
-ERROR:  column name "oid" conflicts with a system column name
+alter table emp rename column salary to ctid;
+ERROR:  column name "ctid" conflicts with a system column name
 --
 -- TRANSACTION STUFF
 -- not in a xact
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index 75365501d4a..0ef37e42bd7 100644
--- a/src/test/regress/expected/foreign_data.out
+++ b/src/test/regress/expected/foreign_data.out
@@ -30,8 +30,8 @@ SELECT srvname, srvoptions FROM pg_foreign_server;
 (0 rows)
 
 SELECT * FROM pg_user_mapping;
- umuser | umserver | umoptions 
---------+----------+-----------
+ oid | umuser | umserver | umoptions 
+-----+--------+----------+-----------
 (0 rows)
 
 -- CREATE FOREIGN DATA WRAPPER
@@ -684,10 +684,6 @@ LINE 1: CREATE FOREIGN TABLE ft1 ();
                                    ^
 CREATE FOREIGN TABLE ft1 () SERVER no_server;                   -- ERROR
 ERROR:  server "no_server" does not exist
-CREATE FOREIGN TABLE ft1 () SERVER s0 WITH OIDS;                -- ERROR
-ERROR:  syntax error at or near "WITH"
-LINE 1: CREATE FOREIGN TABLE ft1 () SERVER s0 WITH OIDS;
-                                              ^
 CREATE FOREIGN TABLE ft1 (
 	c1 integer OPTIONS ("param 1" 'val1') PRIMARY KEY,
 	c2 text OPTIONS (param2 'val2', param3 'val3'),
@@ -822,7 +818,6 @@ ALTER FOREIGN TABLE ft1 DROP CONSTRAINT no_const;               -- ERROR
 ERROR:  constraint "no_const" of relation "ft1" does not exist
 ALTER FOREIGN TABLE ft1 DROP CONSTRAINT IF EXISTS no_const;
 NOTICE:  constraint "no_const" of relation "ft1" does not exist, skipping
-ALTER FOREIGN TABLE ft1 SET WITH OIDS;
 ALTER FOREIGN TABLE ft1 OWNER TO regress_test_role;
 ALTER FOREIGN TABLE ft1 OPTIONS (DROP delimiter, SET quote '~', ADD escape '@');
 ALTER FOREIGN TABLE ft1 DROP COLUMN no_column;                  -- ERROR
@@ -1725,63 +1720,6 @@ Server: s0
 FDW options: (delimiter ',', quote '"', "be quoted" 'value')
 Inherits: fd_pt1
 
--- OID system column
-ALTER TABLE fd_pt1 SET WITH OIDS;
-\d+ fd_pt1
-                                   Table "public.fd_pt1"
- Column |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description 
---------+---------+-----------+----------+---------+----------+--------------+-------------
- c1     | integer |           | not null |         | plain    | 10000        | 
- c2     | text    |           |          |         | extended |              | 
- c3     | date    |           |          |         | plain    |              | 
-Check constraints:
-    "fd_pt1chk3" CHECK (c2 <> ''::text)
-Child tables: ft2
-Has OIDs: yes
-
-\d+ ft2
-                                       Foreign table "public.ft2"
- Column |  Type   | Collation | Nullable | Default | FDW options | Storage  | Stats target | Description 
---------+---------+-----------+----------+---------+-------------+----------+--------------+-------------
- c1     | integer |           | not null |         |             | plain    |              | 
- c2     | text    |           |          |         |             | extended |              | 
- c3     | date    |           |          |         |             | plain    |              | 
-Check constraints:
-    "fd_pt1chk2" CHECK (c2 <> ''::text)
-    "fd_pt1chk3" CHECK (c2 <> ''::text)
-Server: s0
-FDW options: (delimiter ',', quote '"', "be quoted" 'value')
-Inherits: fd_pt1
-Has OIDs: yes
-
-ALTER TABLE ft2 SET WITHOUT OIDS;  -- ERROR
-ERROR:  cannot drop inherited column "oid"
-ALTER TABLE fd_pt1 SET WITHOUT OIDS;
-\d+ fd_pt1
-                                   Table "public.fd_pt1"
- Column |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description 
---------+---------+-----------+----------+---------+----------+--------------+-------------
- c1     | integer |           | not null |         | plain    | 10000        | 
- c2     | text    |           |          |         | extended |              | 
- c3     | date    |           |          |         | plain    |              | 
-Check constraints:
-    "fd_pt1chk3" CHECK (c2 <> ''::text)
-Child tables: ft2
-
-\d+ ft2
-                                       Foreign table "public.ft2"
- Column |  Type   | Collation | Nullable | Default | FDW options | Storage  | Stats target | Description 
---------+---------+-----------+----------+---------+-------------+----------+--------------+-------------
- c1     | integer |           | not null |         |             | plain    |              | 
- c2     | text    |           |          |         |             | extended |              | 
- c3     | date    |           |          |         |             | plain    |              | 
-Check constraints:
-    "fd_pt1chk2" CHECK (c2 <> ''::text)
-    "fd_pt1chk3" CHECK (c2 <> ''::text)
-Server: s0
-FDW options: (delimiter ',', quote '"', "be quoted" 'value')
-Inherits: fd_pt1
-
 -- changes name of an attribute recursively
 ALTER TABLE fd_pt1 RENAME COLUMN c1 TO f1;
 ALTER TABLE fd_pt1 RENAME COLUMN c2 TO f2;
@@ -2097,7 +2035,7 @@ SELECT srvname, srvoptions FROM pg_foreign_server;
 (0 rows)
 
 SELECT * FROM pg_user_mapping;
- umuser | umserver | umoptions 
---------+----------+-----------
+ oid | umuser | umserver | umoptions 
+-----+--------+----------+-----------
 (0 rows)
 
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index 4f29d9f891c..ad7b1f4e4b3 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -673,55 +673,6 @@ select * from d;
  32 | one | two | three
 (1 row)
 
--- check that oid column is handled properly during alter table inherit
-create table oid_parent (a int) with oids;
-create table oid_child () inherits (oid_parent);
-select attinhcount, attislocal from pg_attribute
-  where attrelid = 'oid_child'::regclass and attname = 'oid';
- attinhcount | attislocal 
--------------+------------
-           1 | f
-(1 row)
-
-drop table oid_child;
-create table oid_child (a int) without oids;
-alter table oid_child inherit oid_parent;  -- fail
-ERROR:  table "oid_child" without OIDs cannot inherit from table "oid_parent" with OIDs
-alter table oid_child set with oids;
-select attinhcount, attislocal from pg_attribute
-  where attrelid = 'oid_child'::regclass and attname = 'oid';
- attinhcount | attislocal 
--------------+------------
-           0 | t
-(1 row)
-
-alter table oid_child inherit oid_parent;
-select attinhcount, attislocal from pg_attribute
-  where attrelid = 'oid_child'::regclass and attname = 'oid';
- attinhcount | attislocal 
--------------+------------
-           1 | t
-(1 row)
-
-alter table oid_child set without oids;  -- fail
-ERROR:  cannot drop inherited column "oid"
-alter table oid_parent set without oids;
-select attinhcount, attislocal from pg_attribute
-  where attrelid = 'oid_child'::regclass and attname = 'oid';
- attinhcount | attislocal 
--------------+------------
-           0 | t
-(1 row)
-
-alter table oid_child set without oids;
-select attinhcount, attislocal from pg_attribute
-  where attrelid = 'oid_child'::regclass and attname = 'oid';
- attinhcount | attislocal 
--------------+------------
-(0 rows)
-
-drop table oid_parent cascade;
-NOTICE:  drop cascades to table oid_child
 -- Test non-inheritable parent constraints
 create table p1(ff1 int);
 alter table p1 add constraint p1chk check (ff1 > 0) no inherit;
diff --git a/src/test/regress/expected/insert_conflict.out b/src/test/regress/expected/insert_conflict.out
index 27cf5a01b36..ec946729f30 100644
--- a/src/test/regress/expected/insert_conflict.out
+++ b/src/test/regress/expected/insert_conflict.out
@@ -443,18 +443,14 @@ drop table insertconflicttest;
 --
 -- Verify that EXCLUDED does not allow system column references. These
 -- do not make sense because EXCLUDED isn't an already stored tuple
--- (and thus doesn't have a ctid, oids are not assigned yet, etc).
+-- (and thus doesn't have a ctid etc).
 --
-create table syscolconflicttest(key int4, data text) WITH OIDS;
+create table syscolconflicttest(key int4, data text);
 insert into syscolconflicttest values (1);
 insert into syscolconflicttest values (1) on conflict (key) do update set data = excluded.ctid::text;
 ERROR:  column excluded.ctid does not exist
 LINE 1: ...values (1) on conflict (key) do update set data = excluded.c...
                                                              ^
-insert into syscolconflicttest values (1) on conflict (key) do update set data = excluded.oid::text;
-ERROR:  column excluded.oid does not exist
-LINE 1: ...values (1) on conflict (key) do update set data = excluded.o...
-                                                             ^
 drop table syscolconflicttest;
 --
 -- Previous tests all managed to not test any expressions requiring
@@ -620,65 +616,6 @@ insert into excluded values(1, '2') on conflict (key) do update set data = 3 RET
 
 -- clean up
 drop table excluded;
--- Check tables w/o oids are handled correctly
-create table testoids(key int primary key, data text) without oids;
--- first without oids
-insert into testoids values(1, '1') on conflict (key) do update set data = excluded.data RETURNING *;
- key | data 
------+------
-   1 | 1
-(1 row)
-
-insert into testoids values(1, '2') on conflict (key) do update set data = excluded.data RETURNING *;
- key | data 
------+------
-   1 | 2
-(1 row)
-
--- add oids
-alter table testoids set with oids;
--- update existing row, that didn't have an oid
-insert into testoids values(1, '3') on conflict (key) do update set data = excluded.data RETURNING *;
- key | data 
------+------
-   1 | 3
-(1 row)
-
--- insert a new row
-insert into testoids values(2, '1') on conflict (key) do update set data = excluded.data RETURNING *;
- key | data 
------+------
-   2 | 1
-(1 row)
-
--- and update it
-insert into testoids values(2, '2') on conflict (key) do update set data = excluded.data RETURNING *;
- key | data 
------+------
-   2 | 2
-(1 row)
-
--- remove oids again, test
-alter table testoids set without oids;
-insert into testoids values(1, '4') on conflict (key) do update set data = excluded.data RETURNING *;
- key | data 
------+------
-   1 | 4
-(1 row)
-
-insert into testoids values(3, '1') on conflict (key) do update set data = excluded.data RETURNING *;
- key | data 
------+------
-   3 | 1
-(1 row)
-
-insert into testoids values(3, '2') on conflict (key) do update set data = excluded.data RETURNING *;
- key | data 
------+------
-   3 | 2
-(1 row)
-
-DROP TABLE testoids;
 -- check that references to columns after dropped columns are handled correctly
 create table dropcol(key int primary key, drop1 int, keep1 text, drop2 numeric, keep2 float);
 insert into dropcol(key, drop1, keep1, drop2, keep2) values(1, 1, '1', '1', 1);
diff --git a/src/test/regress/expected/misc_sanity.out b/src/test/regress/expected/misc_sanity.out
index 2d3522b500d..3503aa69e81 100644
--- a/src/test/regress/expected/misc_sanity.out
+++ b/src/test/regress/expected/misc_sanity.out
@@ -52,7 +52,7 @@ declare relnm text;
 begin
 for relnm, reloid, shared in
   select relname, oid, relisshared from pg_class
-  where relhasoids and oid < 16384 order by 1
+  where EXISTS(SELECT * FROM pg_attribute WHERE attrelid = pg_class.oid AND attname = 'oid') and relkind = 'r' and oid < 16384 order by 1
 loop
   execute 'select min(oid) from ' || relnm into lowoid;
   continue when lowoid is null or lowoid >= 16384;
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 7bcc03b9ada..25ec00fea7f 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -817,8 +817,8 @@ SELECT *
 FROM pg_cast c
 WHERE castsource = 0 OR casttarget = 0 OR castcontext NOT IN ('e', 'a', 'i')
     OR castmethod NOT IN ('f', 'b' ,'i');
- castsource | casttarget | castfunc | castcontext | castmethod 
-------------+------------+----------+-------------+------------
+ oid | castsource | casttarget | castfunc | castcontext | castmethod 
+-----+------------+------------+----------+-------------+------------
 (0 rows)
 
 -- Check that castfunc is nonzero only for cast methods that need a function,
@@ -827,8 +827,8 @@ SELECT *
 FROM pg_cast c
 WHERE (castmethod = 'f' AND castfunc = 0)
    OR (castmethod IN ('b', 'i') AND castfunc <> 0);
- castsource | casttarget | castfunc | castcontext | castmethod 
-------------+------------+----------+-------------+------------
+ oid | castsource | casttarget | castfunc | castcontext | castmethod 
+-----+------------+------------+----------+-------------+------------
 (0 rows)
 
 -- Look for casts to/from the same type that aren't length coercion functions.
@@ -837,15 +837,15 @@ WHERE (castmethod = 'f' AND castfunc = 0)
 SELECT *
 FROM pg_cast c
 WHERE castsource = casttarget AND castfunc = 0;
- castsource | casttarget | castfunc | castcontext | castmethod 
-------------+------------+----------+-------------+------------
+ oid | castsource | casttarget | castfunc | castcontext | castmethod 
+-----+------------+------------+----------+-------------+------------
 (0 rows)
 
 SELECT c.*
 FROM pg_cast c, pg_proc p
 WHERE c.castfunc = p.oid AND p.pronargs < 2 AND castsource = casttarget;
- castsource | casttarget | castfunc | castcontext | castmethod 
-------------+------------+----------+-------------+------------
+ oid | castsource | casttarget | castfunc | castcontext | castmethod 
+-----+------------+------------+----------+-------------+------------
 (0 rows)
 
 -- Look for cast functions that don't have the right signature.  The
@@ -863,8 +863,8 @@ WHERE c.castfunc = p.oid AND
              OR (c.castsource = 'character'::regtype AND
                  p.proargtypes[0] = 'text'::regtype))
      OR NOT binary_coercible(p.prorettype, c.casttarget));
- castsource | casttarget | castfunc | castcontext | castmethod 
-------------+------------+----------+-------------+------------
+ oid | castsource | casttarget | castfunc | castcontext | castmethod 
+-----+------------+------------+----------+-------------+------------
 (0 rows)
 
 SELECT c.*
@@ -872,8 +872,8 @@ FROM pg_cast c, pg_proc p
 WHERE c.castfunc = p.oid AND
     ((p.pronargs > 1 AND p.proargtypes[1] != 'int4'::regtype) OR
      (p.pronargs > 2 AND p.proargtypes[2] != 'bool'::regtype));
- castsource | casttarget | castfunc | castcontext | castmethod 
-------------+------------+----------+-------------+------------
+ oid | castsource | casttarget | castfunc | castcontext | castmethod 
+-----+------------+------------+----------+-------------+------------
 (0 rows)
 
 -- Look for binary compatible casts that do not have the reverse
diff --git a/src/test/regress/expected/prepare.out b/src/test/regress/expected/prepare.out
index 7016e82bd42..d07c0cc9c91 100644
--- a/src/test/regress/expected/prepare.out
+++ b/src/test/regress/expected/prepare.out
@@ -64,11 +64,11 @@ EXECUTE q2('postgres');
  postgres | f             | t
 (1 row)
 
-PREPARE q3(text, int, float, boolean, oid, smallint) AS
+PREPARE q3(text, int, float, boolean, smallint) AS
 	SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR
-	ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int)
+	ten = $3::bigint OR true = $4 OR odd = $5::int)
 	ORDER BY unique1;
-EXECUTE q3('AAAAxx', 5::smallint, 10.5::float, false, 500::oid, 4::bigint);
+EXECUTE q3('AAAAxx', 5::smallint, 10.5::float, false, 4::bigint);
  unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 
 ---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+---------
        2 |    2716 |   0 |    2 |   2 |      2 |       2 |        2 |           2 |         2 |        2 |   4 |    5 | CAAAAA   | MAEAAA   | AAAAxx
@@ -105,13 +105,13 @@ EXECUTE q3('AAAAxx', 5::smallint, 10.5::float, false, 500::oid, 4::bigint);
 -- too few params
 EXECUTE q3('bool');
 ERROR:  wrong number of parameters for prepared statement "q3"
-DETAIL:  Expected 6 parameters but got 1.
+DETAIL:  Expected 5 parameters but got 1.
 -- too many params
-EXECUTE q3('bytea', 5::smallint, 10.5::float, false, 500::oid, 4::bigint, true);
+EXECUTE q3('bytea', 5::smallint, 10.5::float, false, 4::bigint, true);
 ERROR:  wrong number of parameters for prepared statement "q3"
-DETAIL:  Expected 6 parameters but got 7.
+DETAIL:  Expected 5 parameters but got 6.
 -- wrong param types
-EXECUTE q3(5::smallint, 10.5::float, false, 500::oid, 4::bigint, 'bytea');
+EXECUTE q3(5::smallint, 10.5::float, false, 4::bigint, 'bytea');
 ERROR:  parameter $3 of type boolean cannot be coerced to the expected type double precision
 HINT:  You will need to rewrite or cast the expression.
 -- invalid type
@@ -152,22 +152,22 @@ PREPARE q7(unknown) AS
     SELECT * FROM road WHERE thepath = $1;
 SELECT name, statement, parameter_types FROM pg_prepared_statements
     ORDER BY name;
- name |                              statement                              |                    parameter_types                     
-------+---------------------------------------------------------------------+--------------------------------------------------------
- q2   | PREPARE q2(text) AS                                                +| {text}
-      |         SELECT datname, datistemplate, datallowconn                +| 
-      |         FROM pg_database WHERE datname = $1;                        | 
- q3   | PREPARE q3(text, int, float, boolean, oid, smallint) AS            +| {text,integer,"double precision",boolean,oid,smallint}
-      |         SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR   +| 
-      |         ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int)+| 
-      |         ORDER BY unique1;                                           | 
- q5   | PREPARE q5(int, text) AS                                           +| {integer,text}
-      |         SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2    +| 
-      |         ORDER BY unique1;                                           | 
- q6   | PREPARE q6 AS                                                      +| {integer,name}
-      |     SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2;       | 
- q7   | PREPARE q7(unknown) AS                                             +| {path}
-      |     SELECT * FROM road WHERE thepath = $1;                          | 
+ name |                            statement                             |                  parameter_types                   
+------+------------------------------------------------------------------+----------------------------------------------------
+ q2   | PREPARE q2(text) AS                                             +| {text}
+      |         SELECT datname, datistemplate, datallowconn             +| 
+      |         FROM pg_database WHERE datname = $1;                     | 
+ q3   | PREPARE q3(text, int, float, boolean, smallint) AS              +| {text,integer,"double precision",boolean,smallint}
+      |         SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR+| 
+      |         ten = $3::bigint OR true = $4 OR odd = $5::int)         +| 
+      |         ORDER BY unique1;                                        | 
+ q5   | PREPARE q5(int, text) AS                                        +| {integer,text}
+      |         SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2 +| 
+      |         ORDER BY unique1;                                        | 
+ q6   | PREPARE q6 AS                                                   +| {integer,name}
+      |     SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2;    | 
+ q7   | PREPARE q7(unknown) AS                                          +| {path}
+      |     SELECT * FROM road WHERE thepath = $1;                       | 
 (5 rows)
 
 -- test DEALLOCATE ALL;
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index ac8968d24f5..757047df06e 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -587,10 +587,10 @@ ERROR:  permission denied for table atest5
 DELETE FROM atest5 WHERE two = 2; -- ok
 -- check inheritance cases
 SET SESSION AUTHORIZATION regress_priv_user1;
-CREATE TABLE atestp1 (f1 int, f2 int) WITH OIDS;
-CREATE TABLE atestp2 (fx int, fy int) WITH OIDS;
+CREATE TABLE atestp1 (f1 int, f2 int);
+CREATE TABLE atestp2 (fx int, fy int);
 CREATE TABLE atestc (fz int) INHERITS (atestp1, atestp2);
-GRANT SELECT(fx,fy,oid) ON atestp2 TO regress_priv_user2;
+GRANT SELECT(fx,fy,tableoid) ON atestp2 TO regress_priv_user2;
 GRANT SELECT(fx) ON atestc TO regress_priv_user2;
 SET SESSION AUTHORIZATION regress_priv_user2;
 SELECT fx FROM atestp2; -- ok
@@ -608,15 +608,15 @@ SELECT atestp2 FROM atestp2; -- ok
 ---------
 (0 rows)
 
-SELECT oid FROM atestp2; -- ok
- oid 
------
+SELECT tableoid FROM atestp2; -- ok
+ tableoid 
+----------
 (0 rows)
 
 SELECT fy FROM atestc; -- fail
 ERROR:  permission denied for table atestc
 SET SESSION AUTHORIZATION regress_priv_user1;
-GRANT SELECT(fy,oid) ON atestc TO regress_priv_user2;
+GRANT SELECT(fy,tableoid) ON atestc TO regress_priv_user2;
 SET SESSION AUTHORIZATION regress_priv_user2;
 SELECT fx FROM atestp2; -- still ok
  fx 
@@ -633,9 +633,9 @@ SELECT atestp2 FROM atestp2; -- ok
 ---------
 (0 rows)
 
-SELECT oid FROM atestp2; -- ok
- oid 
------
+SELECT tableoid FROM atestp2; -- ok
+ tableoid 
+----------
 (0 rows)
 
 -- privileges on functions, languages
@@ -1655,8 +1655,8 @@ DROP SCHEMA testns5 CASCADE;
 SELECT d.*     -- check that entries went away
   FROM pg_default_acl d LEFT JOIN pg_namespace n ON defaclnamespace = n.oid
   WHERE nspname IS NULL AND defaclnamespace != 0;
- defaclrole | defaclnamespace | defaclobjtype | defaclacl 
-------------+-----------------+---------------+-----------
+ oid | defaclrole | defaclnamespace | defaclobjtype | defaclacl 
+-----+------------+-----------------+---------------+-----------
 (0 rows)
 
 -- Grant on all objects of given type in a schema
diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index df3c99d1eb1..f90c267c87e 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -86,15 +86,6 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass AND
 -- RESET fails if a value is specified
 ALTER TABLE reloptions_test RESET (fillfactor=12);
 ERROR:  RESET must not include values for parameters
--- The OIDS option is not stored as reloption
-DROP TABLE reloptions_test;
-CREATE TABLE reloptions_test(i INT) WITH (fillfactor=20, oids=true);
-SELECT reloptions, relhasoids FROM pg_class WHERE oid = 'reloptions_test'::regclass;
-   reloptions    | relhasoids 
------------------+------------
- {fillfactor=20} | t
-(1 row)
-
 -- Test toast.* options
 DROP TABLE reloptions_test;
 CREATE TABLE reloptions_test (s VARCHAR)
diff --git a/src/test/regress/expected/replica_identity.out b/src/test/regress/expected/replica_identity.out
index 67c34a92a4e..175ecd28794 100644
--- a/src/test/regress/expected/replica_identity.out
+++ b/src/test/regress/expected/replica_identity.out
@@ -5,11 +5,10 @@ CREATE TABLE test_replica_identity (
        nonkey text,
        CONSTRAINT test_replica_identity_unique_defer UNIQUE (keya, keyb) DEFERRABLE,
        CONSTRAINT test_replica_identity_unique_nondefer UNIQUE (keya, keyb)
-) WITH OIDS;
+) ;
 CREATE TABLE test_replica_identity_othertable (id serial primary key);
 CREATE INDEX test_replica_identity_keyab ON test_replica_identity (keya, keyb);
 CREATE UNIQUE INDEX test_replica_identity_keyab_key ON test_replica_identity (keya, keyb);
-CREATE UNIQUE INDEX test_replica_identity_oid_idx ON test_replica_identity (oid);
 CREATE UNIQUE INDEX test_replica_identity_nonkey ON test_replica_identity (keya, nonkey);
 CREATE INDEX test_replica_identity_hash ON test_replica_identity USING hash (nonkey);
 CREATE UNIQUE INDEX test_replica_identity_expr ON test_replica_identity (keya, keyb, (3));
@@ -88,15 +87,12 @@ Indexes:
     "test_replica_identity_expr" UNIQUE, btree (keya, keyb, (3))
     "test_replica_identity_keyab_key" UNIQUE, btree (keya, keyb)
     "test_replica_identity_nonkey" UNIQUE, btree (keya, nonkey)
-    "test_replica_identity_oid_idx" UNIQUE, btree (oid)
     "test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text
     "test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE
     "test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb)
     "test_replica_identity_hash" hash (nonkey)
     "test_replica_identity_keyab" btree (keya, keyb)
 
--- succeed, oid unique index
-ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_oid_idx;
 -- succeed, nondeferrable unique constraint over nonnullable cols
 ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_unique_nondefer;
 -- succeed unique index over nonnullable cols
@@ -121,7 +117,6 @@ Indexes:
     "test_replica_identity_expr" UNIQUE, btree (keya, keyb, (3))
     "test_replica_identity_keyab_key" UNIQUE, btree (keya, keyb) REPLICA IDENTITY
     "test_replica_identity_nonkey" UNIQUE, btree (keya, nonkey)
-    "test_replica_identity_oid_idx" UNIQUE, btree (oid)
     "test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text
     "test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE
     "test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb)
@@ -170,14 +165,12 @@ Indexes:
     "test_replica_identity_expr" UNIQUE, btree (keya, keyb, (3))
     "test_replica_identity_keyab_key" UNIQUE, btree (keya, keyb)
     "test_replica_identity_nonkey" UNIQUE, btree (keya, nonkey)
-    "test_replica_identity_oid_idx" UNIQUE, btree (oid)
     "test_replica_identity_partial" UNIQUE, btree (keya, keyb) WHERE keyb <> '3'::text
     "test_replica_identity_unique_defer" UNIQUE CONSTRAINT, btree (keya, keyb) DEFERRABLE
     "test_replica_identity_unique_nondefer" UNIQUE CONSTRAINT, btree (keya, keyb)
     "test_replica_identity_hash" hash (nonkey)
     "test_replica_identity_keyab" btree (keya, keyb)
 Replica Identity: FULL
-Has OIDs: yes
 
 ALTER TABLE test_replica_identity REPLICA IDENTITY NOTHING;
 SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;
diff --git a/src/test/regress/expected/roleattributes.out b/src/test/regress/expected/roleattributes.out
index 570aa5f8343..5e6969b173e 100644
--- a/src/test/regress/expected/roleattributes.out
+++ b/src/test/regress/expected/roleattributes.out
@@ -1,27 +1,27 @@
 -- default for superuser is false
 CREATE ROLE regress_test_def_superuser;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_superuser';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_superuser';
           rolname           | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_def_superuser | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 CREATE ROLE regress_test_superuser WITH SUPERUSER;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_superuser';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_superuser';
         rolname         | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_superuser | t        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_superuser WITH NOSUPERUSER;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_superuser';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_superuser';
         rolname         | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_superuser | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_superuser WITH SUPERUSER;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_superuser';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_superuser';
         rolname         | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_superuser | t        | t          | f             | f           | f           | f              | f            |           -1 |             | 
@@ -29,28 +29,28 @@ SELECT * FROM pg_authid WHERE rolname = 'regress_test_superuser';
 
 -- default for inherit is true
 CREATE ROLE regress_test_def_inherit;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_inherit';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_inherit';
          rolname          | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 --------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_def_inherit | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 CREATE ROLE regress_test_inherit WITH NOINHERIT;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_inherit';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_inherit';
        rolname        | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ----------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_inherit | f        | f          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_inherit WITH INHERIT;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_inherit';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_inherit';
        rolname        | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ----------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_inherit | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_inherit WITH NOINHERIT;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_inherit';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_inherit';
        rolname        | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ----------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_inherit | f        | f          | f             | f           | f           | f              | f            |           -1 |             | 
@@ -58,28 +58,28 @@ SELECT * FROM pg_authid WHERE rolname = 'regress_test_inherit';
 
 -- default for create role is false
 CREATE ROLE regress_test_def_createrole;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_createrole';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_createrole';
            rolname           | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 -----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_def_createrole | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 CREATE ROLE regress_test_createrole WITH CREATEROLE;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_createrole';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_createrole';
          rolname         | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 -------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_createrole | f        | t          | t             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_createrole WITH NOCREATEROLE;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_createrole';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_createrole';
          rolname         | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 -------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_createrole | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_createrole WITH CREATEROLE;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_createrole';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_createrole';
          rolname         | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 -------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_createrole | f        | t          | t             | f           | f           | f              | f            |           -1 |             | 
@@ -87,28 +87,28 @@ SELECT * FROM pg_authid WHERE rolname = 'regress_test_createrole';
 
 -- default for create database is false
 CREATE ROLE regress_test_def_createdb;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_createdb';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_createdb';
           rolname          | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ---------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_def_createdb | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 CREATE ROLE regress_test_createdb WITH CREATEDB;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_createdb';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_createdb';
         rolname        | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 -----------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_createdb | f        | t          | f             | t           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_createdb WITH NOCREATEDB;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_createdb';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_createdb';
         rolname        | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 -----------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_createdb | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_createdb WITH CREATEDB;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_createdb';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_createdb';
         rolname        | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 -----------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_createdb | f        | t          | f             | t           | f           | f              | f            |           -1 |             | 
@@ -116,28 +116,28 @@ SELECT * FROM pg_authid WHERE rolname = 'regress_test_createdb';
 
 -- default for can login is false for role
 CREATE ROLE regress_test_def_role_canlogin;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_role_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_role_canlogin';
             rolname             | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 --------------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_def_role_canlogin | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 CREATE ROLE regress_test_role_canlogin WITH LOGIN;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_role_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_role_canlogin';
           rolname           | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_role_canlogin | f        | t          | f             | f           | t           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_role_canlogin WITH NOLOGIN;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_role_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_role_canlogin';
           rolname           | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_role_canlogin | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_role_canlogin WITH LOGIN;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_role_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_role_canlogin';
           rolname           | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_role_canlogin | f        | t          | f             | f           | t           | f              | f            |           -1 |             | 
@@ -145,28 +145,28 @@ SELECT * FROM pg_authid WHERE rolname = 'regress_test_role_canlogin';
 
 -- default for can login is true for user
 CREATE USER regress_test_def_user_canlogin;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_user_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_user_canlogin';
             rolname             | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 --------------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_def_user_canlogin | f        | t          | f             | f           | t           | f              | f            |           -1 |             | 
 (1 row)
 
 CREATE USER regress_test_user_canlogin WITH NOLOGIN;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_user_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_user_canlogin';
           rolname           | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_user_canlogin | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER USER regress_test_user_canlogin WITH LOGIN;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_user_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_user_canlogin';
           rolname           | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_user_canlogin | f        | t          | f             | f           | t           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER USER regress_test_user_canlogin WITH NOLOGIN;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_user_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_user_canlogin';
           rolname           | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_user_canlogin | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
@@ -174,28 +174,28 @@ SELECT * FROM pg_authid WHERE rolname = 'regress_test_user_canlogin';
 
 -- default for replication is false
 CREATE ROLE regress_test_def_replication;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_replication';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_replication';
            rolname            | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ------------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_def_replication | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 CREATE ROLE regress_test_replication WITH REPLICATION;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_replication';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_replication';
          rolname          | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 --------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_replication | f        | t          | f             | f           | f           | t              | f            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_replication WITH NOREPLICATION;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_replication';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_replication';
          rolname          | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 --------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_replication | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_replication WITH REPLICATION;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_replication';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_replication';
          rolname          | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 --------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_replication | f        | t          | f             | f           | f           | t              | f            |           -1 |             | 
@@ -203,28 +203,28 @@ SELECT * FROM pg_authid WHERE rolname = 'regress_test_replication';
 
 -- default for bypassrls is false
 CREATE ROLE regress_test_def_bypassrls;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_bypassrls';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_bypassrls';
           rolname           | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ----------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_def_bypassrls | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 CREATE ROLE regress_test_bypassrls WITH BYPASSRLS;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_bypassrls';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_bypassrls';
         rolname         | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_bypassrls | f        | t          | f             | f           | f           | f              | t            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_bypassrls WITH NOBYPASSRLS;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_bypassrls';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_bypassrls';
         rolname         | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_bypassrls | f        | t          | f             | f           | f           | f              | f            |           -1 |             | 
 (1 row)
 
 ALTER ROLE regress_test_bypassrls WITH BYPASSRLS;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_bypassrls';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_bypassrls';
         rolname         | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil 
 ------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------------
  regress_test_bypassrls | f        | t          | f             | f           | f           | f              | t            |           -1 |             | 
diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out
index bc16ca4c43f..233672e9d0a 100644
--- a/src/test/regress/expected/rowsecurity.out
+++ b/src/test/regress/expected/rowsecurity.out
@@ -632,30 +632,30 @@ SELECT * FROM category;
 --
 SET SESSION AUTHORIZATION regress_rls_alice;
 SET row_security TO ON;
-CREATE TABLE t1 (a int, junk1 text, b text) WITH OIDS;
+CREATE TABLE t1 (id int not null primary key, a int, junk1 text, b text);
 ALTER TABLE t1 DROP COLUMN junk1;    -- just a disturbing factor
 GRANT ALL ON t1 TO public;
-COPY t1 FROM stdin WITH (oids);
+COPY t1 FROM stdin WITH ;
 CREATE TABLE t2 (c float) INHERITS (t1);
 GRANT ALL ON t2 TO public;
-COPY t2 FROM stdin WITH (oids);
-CREATE TABLE t3 (c text, b text, a int) WITH OIDS;
+COPY t2 FROM stdin;
+CREATE TABLE t3 (id int not null primary key, c text, b text, a int);
 ALTER TABLE t3 INHERIT t1;
 GRANT ALL ON t3 TO public;
-COPY t3(a,b,c) FROM stdin WITH (oids);
+COPY t3(id, a,b,c) FROM stdin;
 CREATE POLICY p1 ON t1 FOR ALL TO PUBLIC USING (a % 2 = 0); -- be even number
 CREATE POLICY p2 ON t2 FOR ALL TO PUBLIC USING (a % 2 = 1); -- be odd number
 ALTER TABLE t1 ENABLE ROW LEVEL SECURITY;
 ALTER TABLE t2 ENABLE ROW LEVEL SECURITY;
 SET SESSION AUTHORIZATION regress_rls_bob;
 SELECT * FROM t1;
- a |  b  
----+-----
- 2 | bbb
- 4 | dad
- 2 | bcd
- 4 | def
- 2 | yyy
+ id  | a |  b  
+-----+---+-----
+ 102 | 2 | bbb
+ 104 | 4 | dad
+ 202 | 2 | bcd
+ 204 | 4 | def
+ 302 | 2 | yyy
 (5 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM t1;
@@ -676,13 +676,13 @@ NOTICE:  f_leak => dad
 NOTICE:  f_leak => bcd
 NOTICE:  f_leak => def
 NOTICE:  f_leak => yyy
- a |  b  
----+-----
- 2 | bbb
- 4 | dad
- 2 | bcd
- 4 | def
- 2 | yyy
+ id  | a |  b  
+-----+---+-----
+ 102 | 2 | bbb
+ 104 | 4 | dad
+ 202 | 2 | bcd
+ 204 | 4 | def
+ 302 | 2 | yyy
 (5 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
@@ -698,14 +698,14 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
 (7 rows)
 
 -- reference to system column
-SELECT oid, * FROM t1;
- oid | a |  b  
------+---+-----
- 102 | 2 | bbb
- 104 | 4 | dad
- 202 | 2 | bcd
- 204 | 4 | def
- 302 | 2 | yyy
+SELECT tableoid::regclass, * FROM t1;
+ tableoid | id  | a |  b  
+----------+-----+---+-----
+ t1       | 102 | 2 | bbb
+ t1       | 104 | 4 | dad
+ t2       | 202 | 2 | bcd
+ t2       | 204 | 4 | def
+ t3       | 302 | 2 | yyy
 (5 rows)
 
 EXPLAIN (COSTS OFF) SELECT *, t1 FROM t1;
@@ -722,13 +722,13 @@ EXPLAIN (COSTS OFF) SELECT *, t1 FROM t1;
 
 -- reference to whole-row reference
 SELECT *, t1 FROM t1;
- a |  b  |   t1    
----+-----+---------
- 2 | bbb | (2,bbb)
- 4 | dad | (4,dad)
- 2 | bcd | (2,bcd)
- 4 | def | (4,def)
- 2 | yyy | (2,yyy)
+ id  | a |  b  |     t1      
+-----+---+-----+-------------
+ 102 | 2 | bbb | (102,2,bbb)
+ 104 | 4 | dad | (104,4,dad)
+ 202 | 2 | bcd | (202,2,bcd)
+ 204 | 4 | def | (204,4,def)
+ 302 | 2 | yyy | (302,2,yyy)
 (5 rows)
 
 EXPLAIN (COSTS OFF) SELECT *, t1 FROM t1;
@@ -745,13 +745,13 @@ EXPLAIN (COSTS OFF) SELECT *, t1 FROM t1;
 
 -- for share/update lock
 SELECT * FROM t1 FOR SHARE;
- a |  b  
----+-----
- 2 | bbb
- 4 | dad
- 2 | bcd
- 4 | def
- 2 | yyy
+ id  | a |  b  
+-----+---+-----
+ 102 | 2 | bbb
+ 104 | 4 | dad
+ 202 | 2 | bcd
+ 204 | 4 | def
+ 302 | 2 | yyy
 (5 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM t1 FOR SHARE;
@@ -773,13 +773,13 @@ NOTICE:  f_leak => dad
 NOTICE:  f_leak => bcd
 NOTICE:  f_leak => def
 NOTICE:  f_leak => yyy
- a |  b  
----+-----
- 2 | bbb
- 4 | dad
- 2 | bcd
- 4 | def
- 2 | yyy
+ id  | a |  b  
+-----+---+-----
+ 102 | 2 | bbb
+ 104 | 4 | dad
+ 202 | 2 | bcd
+ 204 | 4 | def
+ 302 | 2 | yyy
 (5 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b) FOR SHARE;
@@ -796,17 +796,17 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b) FOR SHARE;
 (8 rows)
 
 -- union all query
-SELECT a, b, oid FROM t2 UNION ALL SELECT a, b, oid FROM t3;
- a |  b  | oid 
----+-----+-----
- 1 | abc | 201
- 3 | cde | 203
- 1 | xxx | 301
- 2 | yyy | 302
- 3 | zzz | 303
+SELECT a, b, tableoid::regclass FROM t2 UNION ALL SELECT a, b, tableoid::regclass FROM t3;
+ a |  b  | tableoid 
+---+-----+----------
+ 1 | abc | t2
+ 3 | cde | t2
+ 1 | xxx | t3
+ 2 | yyy | t3
+ 3 | zzz | t3
 (5 rows)
 
-EXPLAIN (COSTS OFF) SELECT a, b, oid FROM t2 UNION ALL SELECT a, b, oid FROM t3;
+EXPLAIN (COSTS OFF) SELECT a, b, tableoid::regclass FROM t2 UNION ALL SELECT a, b, tableoid::regclass FROM t3;
           QUERY PLAN           
 -------------------------------
  Append
@@ -830,19 +830,19 @@ NOTICE:  f_leak => def
 NOTICE:  f_leak => xxx
 NOTICE:  f_leak => yyy
 NOTICE:  f_leak => zzz
- a |  b  
----+-----
- 1 | aba
- 2 | bbb
- 3 | ccc
- 4 | dad
- 1 | abc
- 2 | bcd
- 3 | cde
- 4 | def
- 1 | xxx
- 2 | yyy
- 3 | zzz
+ id  | a |  b  
+-----+---+-----
+ 101 | 1 | aba
+ 102 | 2 | bbb
+ 103 | 3 | ccc
+ 104 | 4 | dad
+ 201 | 1 | abc
+ 202 | 2 | bcd
+ 203 | 3 | cde
+ 204 | 4 | def
+ 301 | 1 | xxx
+ 302 | 2 | yyy
+ 303 | 3 | zzz
 (11 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
@@ -872,19 +872,19 @@ NOTICE:  f_leak => def
 NOTICE:  f_leak => xxx
 NOTICE:  f_leak => yyy
 NOTICE:  f_leak => zzz
- a |  b  
----+-----
- 1 | aba
- 2 | bbb
- 3 | ccc
- 4 | dad
- 1 | abc
- 2 | bcd
- 3 | cde
- 4 | def
- 1 | xxx
- 2 | yyy
- 3 | zzz
+ id  | a |  b  
+-----+---+-----
+ 101 | 1 | aba
+ 102 | 2 | bbb
+ 103 | 3 | ccc
+ 104 | 4 | dad
+ 201 | 1 | abc
+ 202 | 2 | bcd
+ 203 | 3 | cde
+ 204 | 4 | def
+ 301 | 1 | xxx
+ 302 | 2 | yyy
+ 303 | 3 | zzz
 (11 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
@@ -1500,11 +1500,11 @@ ERROR:  infinite recursion detected in policy for relation "s1"
 -- prepared statement with regress_rls_alice privilege
 PREPARE p1(int) AS SELECT * FROM t1 WHERE a <= $1;
 EXECUTE p1(2);
- a |  b  
----+-----
- 2 | bbb
- 2 | bcd
- 2 | yyy
+ id  | a |  b  
+-----+---+-----
+ 102 | 2 | bbb
+ 202 | 2 | bcd
+ 302 | 2 | yyy
 (3 rows)
 
 EXPLAIN (COSTS OFF) EXECUTE p1(2);
@@ -1534,19 +1534,19 @@ NOTICE:  f_leak => def
 NOTICE:  f_leak => xxx
 NOTICE:  f_leak => yyy
 NOTICE:  f_leak => zzz
- a |  b  
----+-----
- 1 | aba
- 2 | bbb
- 3 | ccc
- 4 | dad
- 1 | abc
- 2 | bcd
- 3 | cde
- 4 | def
- 1 | xxx
- 2 | yyy
- 3 | zzz
+ id  | a |  b  
+-----+---+-----
+ 101 | 1 | aba
+ 102 | 2 | bbb
+ 103 | 3 | ccc
+ 104 | 4 | dad
+ 201 | 1 | abc
+ 202 | 2 | bcd
+ 203 | 3 | cde
+ 204 | 4 | def
+ 301 | 1 | xxx
+ 302 | 2 | yyy
+ 303 | 3 | zzz
 (11 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
@@ -1563,14 +1563,14 @@ EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
 
 -- plan cache should be invalidated
 EXECUTE p1(2);
- a |  b  
----+-----
- 1 | aba
- 2 | bbb
- 1 | abc
- 2 | bcd
- 1 | xxx
- 2 | yyy
+ id  | a |  b  
+-----+---+-----
+ 101 | 1 | aba
+ 102 | 2 | bbb
+ 201 | 1 | abc
+ 202 | 2 | bcd
+ 301 | 1 | xxx
+ 302 | 2 | yyy
 (6 rows)
 
 EXPLAIN (COSTS OFF) EXECUTE p1(2);
@@ -1587,11 +1587,11 @@ EXPLAIN (COSTS OFF) EXECUTE p1(2);
 
 PREPARE p2(int) AS SELECT * FROM t1 WHERE a = $1;
 EXECUTE p2(2);
- a |  b  
----+-----
- 2 | bbb
- 2 | bcd
- 2 | yyy
+ id  | a |  b  
+-----+---+-----
+ 102 | 2 | bbb
+ 202 | 2 | bcd
+ 302 | 2 | yyy
 (3 rows)
 
 EXPLAIN (COSTS OFF) EXECUTE p2(2);
@@ -1610,11 +1610,11 @@ EXPLAIN (COSTS OFF) EXECUTE p2(2);
 SET SESSION AUTHORIZATION regress_rls_bob;
 SET row_security TO ON;
 EXECUTE p2(2);
- a |  b  
----+-----
- 2 | bbb
- 2 | bcd
- 2 | yyy
+ id  | a |  b  
+-----+---+-----
+ 102 | 2 | bbb
+ 202 | 2 | bcd
+ 302 | 2 | yyy
 (3 rows)
 
 EXPLAIN (COSTS OFF) EXECUTE p2(2);
@@ -1666,13 +1666,13 @@ UPDATE only t1 SET b = b || '_updt' WHERE f_leak(b);
 NOTICE:  f_leak => bbbbbb
 NOTICE:  f_leak => daddad
 -- returning clause with system column
-UPDATE only t1 SET b = b WHERE f_leak(b) RETURNING oid, *, t1;
+UPDATE only t1 SET b = b WHERE f_leak(b) RETURNING tableoid::regclass, *, t1;
 NOTICE:  f_leak => bbbbbb_updt
 NOTICE:  f_leak => daddad_updt
- oid | a |      b      |       t1        
------+---+-------------+-----------------
- 102 | 2 | bbbbbb_updt | (2,bbbbbb_updt)
- 104 | 4 | daddad_updt | (4,daddad_updt)
+ tableoid | id  | a |      b      |         t1          
+----------+-----+---+-------------+---------------------
+ t1       | 102 | 2 | bbbbbb_updt | (102,2,bbbbbb_updt)
+ t1       | 104 | 4 | daddad_updt | (104,4,daddad_updt)
 (2 rows)
 
 UPDATE t1 SET b = b WHERE f_leak(b) RETURNING *;
@@ -1681,28 +1681,28 @@ NOTICE:  f_leak => daddad_updt
 NOTICE:  f_leak => bcdbcd
 NOTICE:  f_leak => defdef
 NOTICE:  f_leak => yyyyyy
- a |      b      
----+-------------
- 2 | bbbbbb_updt
- 4 | daddad_updt
- 2 | bcdbcd
- 4 | defdef
- 2 | yyyyyy
+ id  | a |      b      
+-----+---+-------------
+ 102 | 2 | bbbbbb_updt
+ 104 | 4 | daddad_updt
+ 202 | 2 | bcdbcd
+ 204 | 4 | defdef
+ 302 | 2 | yyyyyy
 (5 rows)
 
-UPDATE t1 SET b = b WHERE f_leak(b) RETURNING oid, *, t1;
+UPDATE t1 SET b = b WHERE f_leak(b) RETURNING tableoid::regclass, *, t1;
 NOTICE:  f_leak => bbbbbb_updt
 NOTICE:  f_leak => daddad_updt
 NOTICE:  f_leak => bcdbcd
 NOTICE:  f_leak => defdef
 NOTICE:  f_leak => yyyyyy
- oid | a |      b      |       t1        
------+---+-------------+-----------------
- 102 | 2 | bbbbbb_updt | (2,bbbbbb_updt)
- 104 | 4 | daddad_updt | (4,daddad_updt)
- 202 | 2 | bcdbcd      | (2,bcdbcd)
- 204 | 4 | defdef      | (4,defdef)
- 302 | 2 | yyyyyy      | (2,yyyyyy)
+ tableoid | id  | a |      b      |         t1          
+----------+-----+---+-------------+---------------------
+ t1       | 102 | 2 | bbbbbb_updt | (102,2,bbbbbb_updt)
+ t1       | 104 | 4 | daddad_updt | (104,4,daddad_updt)
+ t2       | 202 | 2 | bcdbcd      | (202,2,bcdbcd)
+ t2       | 204 | 4 | defdef      | (204,4,defdef)
+ t3       | 302 | 2 | yyyyyy      | (302,2,yyyyyy)
 (5 rows)
 
 -- updates with from clause
@@ -1789,9 +1789,9 @@ WHERE t2_1.a = 3 AND t2_2.a = t2_1.a AND t2_2.b = t2_1.b
 AND f_leak(t2_1.b) AND f_leak(t2_2.b) RETURNING *, t2_1, t2_2;
 NOTICE:  f_leak => cde
 NOTICE:  f_leak => cde
- a |  b  |  c  | a |  b  |  c  |    t2_1     |    t2_2     
----+-----+-----+---+-----+-----+-------------+-------------
- 3 | cde | 3.3 | 3 | cde | 3.3 | (3,cde,3.3) | (3,cde,3.3)
+ id  | a |  b  |  c  | id  | a |  b  |  c  |      t2_1       |      t2_2       
+-----+---+-----+-----+-----+---+-----+-----+-----------------+-----------------
+ 203 | 3 | cde | 3.3 | 203 | 3 | cde | 3.3 | (203,3,cde,3.3) | (203,3,cde,3.3)
 (1 row)
 
 EXPLAIN (COSTS OFF) UPDATE t1 t1_1 SET b = t1_2.b FROM t1 t1_2
@@ -1847,28 +1847,28 @@ NOTICE:  f_leak => defdef
 NOTICE:  f_leak => defdef
 NOTICE:  f_leak => daddad_updt
 NOTICE:  f_leak => defdef
- a |      b      | a |      b      |      t1_1       |      t1_2       
----+-------------+---+-------------+-----------------+-----------------
- 4 | daddad_updt | 4 | daddad_updt | (4,daddad_updt) | (4,daddad_updt)
- 4 | defdef      | 4 | defdef      | (4,defdef)      | (4,defdef)
+ id  | a |      b      | id  | a |      b      |        t1_1         |        t1_2         
+-----+---+-------------+-----+---+-------------+---------------------+---------------------
+ 104 | 4 | daddad_updt | 104 | 4 | daddad_updt | (104,4,daddad_updt) | (104,4,daddad_updt)
+ 204 | 4 | defdef      | 204 | 4 | defdef      | (204,4,defdef)      | (204,4,defdef)
 (2 rows)
 
 RESET SESSION AUTHORIZATION;
 SET row_security TO OFF;
 SELECT * FROM t1 ORDER BY a,b;
- a |      b      
----+-------------
- 1 | aba
- 1 | abc
- 1 | xxx
- 2 | bbbbbb_updt
- 2 | bcdbcd
- 2 | yyyyyy
- 3 | ccc
- 3 | cde
- 3 | zzz
- 4 | daddad_updt
- 4 | defdef
+ id  | a |      b      
+-----+---+-------------
+ 101 | 1 | aba
+ 201 | 1 | abc
+ 301 | 1 | xxx
+ 102 | 2 | bbbbbb_updt
+ 202 | 2 | bcdbcd
+ 302 | 2 | yyyyyy
+ 103 | 3 | ccc
+ 203 | 3 | cde
+ 303 | 3 | zzz
+ 104 | 4 | daddad_updt
+ 204 | 4 | defdef
 (11 rows)
 
 SET SESSION AUTHORIZATION regress_rls_bob;
@@ -1896,24 +1896,24 @@ EXPLAIN (COSTS OFF) DELETE FROM t1 WHERE f_leak(b);
          Filter: (((a % 2) = 0) AND f_leak(b))
 (10 rows)
 
-DELETE FROM only t1 WHERE f_leak(b) RETURNING oid, *, t1;
+DELETE FROM only t1 WHERE f_leak(b) RETURNING tableoid::regclass, *, t1;
 NOTICE:  f_leak => bbbbbb_updt
 NOTICE:  f_leak => daddad_updt
- oid | a |      b      |       t1        
------+---+-------------+-----------------
- 102 | 2 | bbbbbb_updt | (2,bbbbbb_updt)
- 104 | 4 | daddad_updt | (4,daddad_updt)
+ tableoid | id  | a |      b      |         t1          
+----------+-----+---+-------------+---------------------
+ t1       | 102 | 2 | bbbbbb_updt | (102,2,bbbbbb_updt)
+ t1       | 104 | 4 | daddad_updt | (104,4,daddad_updt)
 (2 rows)
 
-DELETE FROM t1 WHERE f_leak(b) RETURNING oid, *, t1;
+DELETE FROM t1 WHERE f_leak(b) RETURNING tableoid::regclass, *, t1;
 NOTICE:  f_leak => bcdbcd
 NOTICE:  f_leak => defdef
 NOTICE:  f_leak => yyyyyy
- oid | a |   b    |     t1     
------+---+--------+------------
- 202 | 2 | bcdbcd | (2,bcdbcd)
- 204 | 4 | defdef | (4,defdef)
- 302 | 2 | yyyyyy | (2,yyyyyy)
+ tableoid | id  | a |   b    |       t1       
+----------+-----+---+--------+----------------
+ t2       | 202 | 2 | bcdbcd | (202,2,bcdbcd)
+ t2       | 204 | 4 | defdef | (204,4,defdef)
+ t3       | 302 | 2 | yyyyyy | (302,2,yyyyyy)
 (3 rows)
 
 --
diff --git a/src/test/regress/expected/rowtypes.out b/src/test/regress/expected/rowtypes.out
index 30053d07dff..d6a1a3331e3 100644
--- a/src/test/regress/expected/rowtypes.out
+++ b/src/test/regress/expected/rowtypes.out
@@ -1067,7 +1067,7 @@ select r, r is null as isnull, r is not null as isnotnull from r;
 --
 -- Tests for component access / FieldSelect
 --
-CREATE TABLE compositetable(a text, b text) WITH OIDS;
+CREATE TABLE compositetable(a text, b text);
 INSERT INTO compositetable(a, b) VALUES('fa', 'fb');
 -- composite type columns can't directly be accessed (error)
 SELECT d.a FROM (SELECT compositetable AS d FROM compositetable) s;
@@ -1081,10 +1081,10 @@ SELECT (d).a, (d).b FROM (SELECT compositetable AS d FROM compositetable) s;
  fa | fb
 (1 row)
 
--- oids can't be accessed in composite types (error)
-SELECT (d).oid FROM (SELECT compositetable AS d FROM compositetable) s;
-ERROR:  column "oid" not found in data type compositetable
-LINE 1: SELECT (d).oid FROM (SELECT compositetable AS d FROM composi...
+-- system columns can't be accessed in composite types (error)
+SELECT (d).ctid FROM (SELECT compositetable AS d FROM compositetable) s;
+ERROR:  column "ctid" not found in data type compositetable
+LINE 1: SELECT (d).ctid FROM (SELECT compositetable AS d FROM compos...
                 ^
 -- accessing non-existing column in NULL datum errors out
 SELECT (NULL::compositetable).nonexistant;
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 48e0508a96b..a0c1c8e07c1 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -216,12 +216,12 @@ varchar_tbl|f
 -- We exclude non-system tables from the check by looking at nspname.
 --
 SELECT relname, nspname
-FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = relnamespace
-WHERE relhasoids
-    AND ((nspname ~ '^pg_') IS NOT FALSE)
-    AND NOT EXISTS (SELECT 1 FROM pg_index i WHERE indrelid = c.oid
-                    AND indkey[0] = -2 AND indnatts = 1
-                    AND indisunique AND indimmediate);
+ FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = relnamespace JOIN pg_attribute a ON (attrelid = c.oid AND attname = 'oid')
+ WHERE relkind = 'r' and c.oid < 16384
+     AND ((nspname ~ '^pg_') IS NOT FALSE)
+     AND NOT EXISTS (SELECT 1 FROM pg_index i WHERE indrelid = c.oid
+                     AND indkey[0] = a.attnum AND indnatts = 1
+                     AND indisunique AND indimmediate);
  relname | nspname 
 ---------+---------
 (0 rows)
diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out
index 7d59de98ebd..c62f88c169a 100644
--- a/src/test/regress/expected/triggers.out
+++ b/src/test/regress/expected/triggers.out
@@ -441,11 +441,11 @@ DROP TRIGGER delete_a ON main_table;
 DROP TRIGGER insert_when ON main_table;
 DROP TRIGGER delete_when ON main_table;
 -- Test WHEN condition accessing system columns.
-create table table_with_oids(a int) with oids;
+create table table_with_oids(a int);
 insert into table_with_oids values (1);
 create trigger oid_unchanged_trig after update on table_with_oids
 	for each row
-	when (new.oid = old.oid AND new.oid <> 0)
+	when (new.tableoid = old.tableoid AND new.tableoid <> 0)
 	execute procedure trigger_func('after_upd_oid_unchanged');
 update table_with_oids set a = a + 1;
 NOTICE:  trigger_func(after_upd_oid_unchanged) called: action = UPDATE, when = AFTER, level = ROW
@@ -834,18 +834,10 @@ CREATE TABLE min_updates_test (
 	f1	text,
 	f2 int,
 	f3 int);
-CREATE TABLE min_updates_test_oids (
-	f1	text,
-	f2 int,
-	f3 int) WITH OIDS;
 INSERT INTO min_updates_test VALUES ('a',1,2),('b','2',null);
-INSERT INTO min_updates_test_oids VALUES ('a',1,2),('b','2',null);
 CREATE TRIGGER z_min_update
 BEFORE UPDATE ON min_updates_test
 FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
-CREATE TRIGGER z_min_update
-BEFORE UPDATE ON min_updates_test_oids
-FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
 \set QUIET false
 UPDATE min_updates_test SET f1 = f1;
 UPDATE 0
@@ -853,12 +845,6 @@ UPDATE min_updates_test SET f2 = f2 + 1;
 UPDATE 2
 UPDATE min_updates_test SET f3 = 2 WHERE f3 is null;
 UPDATE 1
-UPDATE min_updates_test_oids SET f1 = f1;
-UPDATE 0
-UPDATE min_updates_test_oids SET f2 = f2 + 1;
-UPDATE 2
-UPDATE min_updates_test_oids SET f3 = 2 WHERE f3 is null;
-UPDATE 1
 \set QUIET true
 SELECT * FROM min_updates_test;
  f1 | f2 | f3 
@@ -867,15 +853,7 @@ SELECT * FROM min_updates_test;
  b  |  3 |  2
 (2 rows)
 
-SELECT * FROM min_updates_test_oids;
- f1 | f2 | f3 
-----+----+----
- a  |  2 |  2
- b  |  3 |  2
-(2 rows)
-
 DROP TABLE min_updates_test;
-DROP TABLE min_updates_test_oids;
 --
 -- Test triggers on views
 --
diff --git a/src/test/regress/expected/without_oid.out b/src/test/regress/expected/without_oid.out
deleted file mode 100644
index cb2c0c01371..00000000000
--- a/src/test/regress/expected/without_oid.out
+++ /dev/null
@@ -1,103 +0,0 @@
---
--- WITHOUT OID
---
---
--- This test tries to verify that WITHOUT OIDS actually saves space.
--- On machines where MAXALIGN is 8, WITHOUT OIDS may or may not save any
--- space, depending on the size of the tuple header + null bitmap.
--- As of 8.3 we need a null bitmap of 8 or less bits for the difference
--- to appear.
---
-CREATE TABLE wi (i INT,
-                 n1 int, n2 int, n3 int, n4 int,
-                 n5 int, n6 int, n7 int) WITH OIDS;
-CREATE TABLE wo (i INT,
-                 n1 int, n2 int, n3 int, n4 int,
-                 n5 int, n6 int, n7 int) WITHOUT OIDS;
-INSERT INTO wi VALUES (1);  -- 1
-INSERT INTO wo SELECT i FROM wi;  -- 1
-INSERT INTO wo SELECT i+1 FROM wi;  -- 1+1=2
-INSERT INTO wi SELECT i+1 FROM wo;  -- 1+2=3
-INSERT INTO wi SELECT i+3 FROM wi;  -- 3+3=6
-INSERT INTO wo SELECT i+2 FROM wi;  -- 2+6=8
-INSERT INTO wo SELECT i+8 FROM wo;  -- 8+8=16
-INSERT INTO wi SELECT i+6 FROM wo;  -- 6+16=22
-INSERT INTO wi SELECT i+22 FROM wi;  -- 22+22=44
-INSERT INTO wo SELECT i+16 FROM wi;  -- 16+44=60
-INSERT INTO wo SELECT i+60 FROM wo;  -- 60+60=120
-INSERT INTO wi SELECT i+44 FROM wo;  -- 44+120=164
-INSERT INTO wi SELECT i+164 FROM wi;  -- 164+164=328
-INSERT INTO wo SELECT i+120 FROM wi;  -- 120+328=448
-INSERT INTO wo SELECT i+448 FROM wo;  -- 448+448=896
-INSERT INTO wi SELECT i+328 FROM wo;  -- 328+896=1224
-INSERT INTO wi SELECT i+1224 FROM wi;  -- 1224+1224=2448
-INSERT INTO wo SELECT i+896 FROM wi;  -- 896+2448=3344
-INSERT INTO wo SELECT i+3344 FROM wo;  -- 3344+3344=6688
-INSERT INTO wi SELECT i+2448 FROM wo;  -- 2448+6688=9136
-INSERT INTO wo SELECT i+6688 FROM wi WHERE i<=2448;  -- 6688+2448=9136
-SELECT count(oid) FROM wi;
- count 
--------
-  9136
-(1 row)
-
--- should fail
-SELECT count(oid) FROM wo;
-ERROR:  column "oid" does not exist
-LINE 1: SELECT count(oid) FROM wo;
-                     ^
-VACUUM ANALYZE wi;
-VACUUM ANALYZE wo;
-SELECT min(relpages) < max(relpages), min(reltuples) - max(reltuples)
-  FROM pg_class
- WHERE relname IN ('wi', 'wo');
- ?column? | ?column? 
-----------+----------
- t        |        0
-(1 row)
-
-DROP TABLE wi;
-DROP TABLE wo;
---
--- WITH / WITHOUT OIDS in CREATE TABLE AS
---
-CREATE TABLE create_table_test (
-    a int,
-    b int
-);
-COPY create_table_test FROM stdin;
-CREATE TABLE create_table_test2 WITH OIDS AS
-    SELECT a + b AS c1, a - b AS c2 FROM create_table_test;
-CREATE TABLE create_table_test3 WITHOUT OIDS AS
-    SELECT a + b AS c1, a - b AS c2 FROM create_table_test;
-SELECT count(oid) FROM create_table_test2;
- count 
--------
-     2
-(1 row)
-
--- should fail
-SELECT count(oid) FROM create_table_test3;
-ERROR:  column "oid" does not exist
-LINE 1: SELECT count(oid) FROM create_table_test3;
-                     ^
-PREPARE table_source(int) AS
-    SELECT a + b AS c1, a - b AS c2, $1 AS c3 FROM create_table_test;
-CREATE TABLE execute_with WITH OIDS AS EXECUTE table_source(1);
-CREATE TABLE execute_without WITHOUT OIDS AS EXECUTE table_source(2);
-SELECT count(oid) FROM execute_with;
- count 
--------
-     2
-(1 row)
-
--- should fail
-SELECT count(oid) FROM execute_without;
-ERROR:  column "oid" does not exist
-LINE 1: SELECT count(oid) FROM execute_without;
-                     ^
-DROP TABLE create_table_test;
-DROP TABLE create_table_test2;
-DROP TABLE create_table_test3;
-DROP TABLE execute_with;
-DROP TABLE execute_without;
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 16f979c8d93..5459e194097 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -111,7 +111,7 @@ test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combo
 # NB: temp.sql does a reconnect which transiently uses 2 connections,
 # so keep this parallel group to at most 19 tests
 # ----------
-test: plancache limit plpgsql copy2 temp domain rangefuncs prepare without_oid conversion truncate alter_table sequence polymorphism rowtypes returning largeobject with xml
+test: plancache limit plpgsql copy2 temp domain rangefuncs prepare conversion truncate alter_table sequence polymorphism rowtypes returning largeobject with xml
 
 # ----------
 # Another group of parallel tests
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 42632be6750..89d0fe1012f 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -170,7 +170,6 @@ test: temp
 test: domain
 test: rangefuncs
 test: prepare
-test: without_oid
 test: conversion
 test: truncate
 test: alter_table
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index b90497804b0..cbe402c81e3 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -638,7 +638,7 @@ drop table atacc1;
 
 -- test unique constraint adding
 
-create table atacc1 ( test int ) with oids;
+create table atacc1 ( test int ) ;
 -- add a unique constraint
 alter table atacc1 add constraint atacc_test1 unique (test);
 -- insert first value
@@ -647,8 +647,6 @@ insert into atacc1 (test) values (2);
 insert into atacc1 (test) values (2);
 -- should succeed
 insert into atacc1 (test) values (4);
--- try adding a unique oid constraint
-alter table atacc1 add constraint atacc_oid1 unique(oid);
 -- try to create duplicates via alter table using - should fail
 alter table atacc1 alter column test type integer using 0;
 drop table atacc1;
@@ -694,7 +692,7 @@ drop table atacc1;
 
 -- test primary key constraint adding
 
-create table atacc1 ( test int ) with oids;
+create table atacc1 ( id serial, test int) ;
 -- add a primary key constraint
 alter table atacc1 add constraint atacc_test1 primary key (test);
 -- insert first value
@@ -706,11 +704,11 @@ insert into atacc1 (test) values (4);
 -- inserting NULL should fail
 insert into atacc1 (test) values(NULL);
 -- try adding a second primary key (should fail)
-alter table atacc1 add constraint atacc_oid1 primary key(oid);
+alter table atacc1 add constraint atacc_oid1 primary key(id);
 -- drop first primary key constraint
 alter table atacc1 drop constraint atacc_test1 restrict;
 -- try adding a primary key on oid (should succeed)
-alter table atacc1 add constraint atacc_oid1 primary key(oid);
+alter table atacc1 add constraint atacc_oid1 primary key(id);
 drop table atacc1;
 
 -- let's do one where the primary key constraint fails when added
@@ -787,7 +785,7 @@ alter table non_existent alter column bar drop not null;
 
 -- test setting columns to null and not null and vice versa
 -- test checking for null values and primary key
-create table atacc1 (test int not null) with oids;
+create table atacc1 (test int not null);
 alter table atacc1 add constraint "atacc1_pkey" primary key (test);
 alter table atacc1 alter column test drop not null;
 alter table atacc1 drop constraint "atacc1_pkey";
@@ -801,10 +799,6 @@ alter table atacc1 alter test set not null;
 alter table atacc1 alter bar set not null;
 alter table atacc1 alter bar drop not null;
 
--- try altering the oid column, should fail
-alter table atacc1 alter oid set not null;
-alter table atacc1 alter oid drop not null;
-
 -- try creating a view and altering that, should fail
 create view myview as select * from atacc1;
 alter table myview alter column test drop not null;
@@ -884,7 +878,7 @@ alter table pg_class drop column relname;
 alter table nosuchtable drop column bar;
 
 -- test dropping columns
-create table atacc1 (a int4 not null, b int4, c int4 not null, d int4) with oids;
+create table atacc1 (a int4 not null, b int4, c int4 not null, d int4);
 insert into atacc1 values (1, 2, 3, 4);
 alter table atacc1 drop a;
 alter table atacc1 drop a;
@@ -934,9 +928,6 @@ delete from atacc1;
 -- try dropping a non-existent column, should fail
 alter table atacc1 drop bar;
 
--- try dropping the oid column, should succeed
-alter table atacc1 drop oid;
-
 -- try dropping the xmin column, should fail
 alter table atacc1 drop xmin;
 
@@ -1195,74 +1186,6 @@ from pg_attribute
 where attnum > 0 and attrelid::regclass in ('depth0', 'depth1', 'depth2')
 order by attrelid::regclass::text, attnum;
 
---
--- Test the ALTER TABLE SET WITH/WITHOUT OIDS command
---
-create table altstartwith (col integer) with oids;
-
-insert into altstartwith values (1);
-
-select oid > 0, * from altstartwith;
-
-alter table altstartwith set without oids;
-
-select oid > 0, * from altstartwith; -- fails
-select * from altstartwith;
-
-alter table altstartwith set with oids;
-
-select oid > 0, * from altstartwith;
-
-drop table altstartwith;
-
--- Check inheritance cases
-create table altwithoid (col integer) with oids;
-
--- Inherits parents oid column anyway
-create table altinhoid () inherits (altwithoid) without oids;
-
-insert into altinhoid values (1);
-
-select oid > 0, * from altwithoid;
-select oid > 0, * from altinhoid;
-
-alter table altwithoid set without oids;
-
-select oid > 0, * from altwithoid; -- fails
-select oid > 0, * from altinhoid; -- fails
-select * from altwithoid;
-select * from altinhoid;
-
-alter table altwithoid set with oids;
-
-select oid > 0, * from altwithoid;
-select oid > 0, * from altinhoid;
-
-drop table altwithoid cascade;
-
-create table altwithoid (col integer) without oids;
-
--- child can have local oid column
-create table altinhoid () inherits (altwithoid) with oids;
-
-insert into altinhoid values (1);
-
-select oid > 0, * from altwithoid; -- fails
-select oid > 0, * from altinhoid;
-
-alter table altwithoid set with oids;
-
-select oid > 0, * from altwithoid;
-select oid > 0, * from altinhoid;
-
--- the child's local definition should remain
-alter table altwithoid set without oids;
-
-select oid > 0, * from altwithoid; -- fails
-select oid > 0, * from altinhoid;
-
-drop table altwithoid cascade;
-
 -- test renumbering of child-table columns in inherited operations
 
 create table p1 (f1 int);
@@ -1815,7 +1738,7 @@ CREATE TABLE tt3 (y numeric(8,2), x int);			-- wrong column order
 CREATE TABLE tt4 (x int);							-- too few columns
 CREATE TABLE tt5 (x int, y numeric(8,2), z int);	-- too few columns
 CREATE TABLE tt6 () INHERITS (tt0);					-- can't have a parent
-CREATE TABLE tt7 (x int, q text, y numeric(8,2)) WITH OIDS;
+CREATE TABLE tt7 (x int, q text, y numeric(8,2));
 ALTER TABLE tt7 DROP q;								-- OK
 
 ALTER TABLE tt0 OF tt_t0;
@@ -2148,16 +2071,6 @@ CREATE TABLE fail_part OF mytype;
 ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1);
 DROP TYPE mytype CASCADE;
 
--- check existence (or non-existence) of oid column
-ALTER TABLE list_parted SET WITH OIDS;
-CREATE TABLE fail_part (a int);
-ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1);
-
-ALTER TABLE list_parted SET WITHOUT OIDS;
-ALTER TABLE fail_part SET WITH OIDS;
-ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1);
-DROP TABLE fail_part;
-
 -- check that the table being attached has only columns present in the parent
 CREATE TABLE fail_part (like list_parted, c int);
 ALTER TABLE list_parted ATTACH PARTITION fail_part FOR VALUES IN (1);
diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql
index f3a6d228fae..e36df8858eb 100644
--- a/src/test/regress/sql/copy2.sql
+++ b/src/test/regress/sql/copy2.sql
@@ -4,7 +4,7 @@ CREATE TEMP TABLE x (
 	c text not null default 'stuff',
 	d text,
 	e text
-) WITH OIDS;
+) ;
 
 CREATE FUNCTION fn_x_before () RETURNS TRIGGER AS '
   BEGIN
@@ -73,10 +73,10 @@ COPY x from stdin;
 \.
 
 -- various COPY options: delimiters, oids, NULL string, encoding
-COPY x (b, c, d, e) from stdin with oids delimiter ',' null 'x';
-500000,x,45,80,90
-500001,x,\x,\\x,\\\x
-500002,x,\,,\\\,,\\
+COPY x (b, c, d, e) from stdin delimiter ',' null 'x';
+x,45,80,90
+x,\x,\\x,\\\x
+x,\,,\\\,,\\
 \.
 
 COPY x from stdin WITH DELIMITER AS ';' NULL AS '';
@@ -98,19 +98,6 @@ COPY x from stdin WITH DELIMITER AS ':' NULL AS E'\\X' ENCODING 'sql_ascii';
 -- check results of copy in
 SELECT * FROM x;
 
--- COPY w/ oids on a table w/o oids should fail
-CREATE TABLE no_oids (
-	a	int,
-	b	int
-) WITHOUT OIDS;
-
-INSERT INTO no_oids (a, b) VALUES (5, 10);
-INSERT INTO no_oids (a, b) VALUES (20, 30);
-
--- should fail
-COPY no_oids FROM stdin WITH OIDS;
-COPY no_oids TO stdout WITH OIDS;
-
 -- check copy out
 COPY x TO stdout;
 COPY x (c, e) TO stdout;
diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql
index be7f261871e..59da6b65926 100644
--- a/src/test/regress/sql/create_index.sql
+++ b/src/test/regress/sql/create_index.sql
@@ -951,21 +951,18 @@ DROP TABLE cwi_test;
 --
 -- Check handling of indexes on system columns
 --
-CREATE TABLE oid_table (a INT) WITH OIDS;
+CREATE TABLE syscol_table (a INT);
 
--- An index on the OID column should be allowed
-CREATE INDEX ON oid_table (oid);
-
--- Other system columns cannot be indexed
-CREATE INDEX ON oid_table (ctid);
+-- System columns cannot be indexed
+CREATE INDEX ON syscolcol_table (ctid);
 
 -- nor used in expressions
-CREATE INDEX ON oid_table ((ctid >= '(1000,0)'));
+CREATE INDEX ON syscol_table ((ctid >= '(1000,0)'));
 
 -- nor used in predicates
-CREATE INDEX ON oid_table (a) WHERE ctid >= '(1000,0)';
+CREATE INDEX ON syscol_table (a) WHERE ctid >= '(1000,0)';
 
-DROP TABLE oid_table;
+DROP TABLE syscol_table;
 
 --
 -- Tests for IS NULL/IS NOT NULL with b-tree indexes
diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql
index 81fa7658b0d..3bf0119d807 100644
--- a/src/test/regress/sql/create_table.sql
+++ b/src/test/regress/sql/create_table.sql
@@ -51,7 +51,7 @@ CREATE TABLE tenk1 (
 	stringu1	name,
 	stringu2	name,
 	string4		name
-) WITH OIDS;
+);
 
 CREATE TABLE tenk2 (
 	unique1 	int4,
@@ -83,7 +83,7 @@ CREATE TABLE person (
 CREATE TABLE emp (
 	salary 		int4,
 	manager 	name
-) INHERITS (person) WITH OIDS;
+) INHERITS (person);
 
 
 CREATE TABLE student (
@@ -255,7 +255,6 @@ CREATE TABLE IF NOT EXISTS test_tsvector(
 
 -- invalid: non-lowercase quoted reloptions identifiers
 CREATE TABLE tas_case WITH ("Fillfactor" = 10) AS SELECT 1 a;
-CREATE TABLE tas_case (a text) WITH ("Oids" = true);
 
 CREATE UNLOGGED TABLE unlogged1 (a int primary key);			-- OK
 CREATE TEMPORARY TABLE unlogged2 (a int primary key);			-- OK
@@ -278,10 +277,6 @@ CREATE TABLE as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
 CREATE TABLE IF NOT EXISTS as_select1 AS SELECT * FROM pg_class WHERE relkind = 'r';
 DROP TABLE as_select1;
 
--- check that the oid column is added before the primary key is checked
-CREATE TABLE oid_pk (f1 INT, PRIMARY KEY(oid)) WITH OIDS;
-DROP TABLE oid_pk;
-
 --
 -- Partitioned tables
 --
@@ -520,22 +515,6 @@ CREATE TEMP TABLE temp_parted (
 CREATE TABLE fail_part PARTITION OF temp_parted FOR VALUES IN ('a');
 DROP TABLE temp_parted;
 
--- cannot create a table with oids as partition of table without oids
-CREATE TABLE no_oids_parted (
-	a int
-) PARTITION BY RANGE (a) WITHOUT OIDS;
-CREATE TABLE fail_part PARTITION OF no_oids_parted FOR VALUES FROM (1) TO (10) WITH OIDS;
-DROP TABLE no_oids_parted;
-
--- If the partitioned table has oids, then the partition must have them.
--- If the WITHOUT OIDS option is specified for partition, it is overridden.
-CREATE TABLE oids_parted (
-	a int
-) PARTITION BY RANGE (a) WITH OIDS;
-CREATE TABLE part_forced_oids PARTITION OF oids_parted FOR VALUES FROM (1) TO (10) WITHOUT OIDS;
-\d+ part_forced_oids
-DROP TABLE oids_parted, part_forced_oids;
-
 -- check for partition bound overlap and other invalid specifications
 
 CREATE TABLE list_parted2 (
diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql
index 42cad6826b0..65c3880792b 100644
--- a/src/test/regress/sql/create_table_like.sql
+++ b/src/test/regress/sql/create_table_like.sql
@@ -136,19 +136,3 @@ DROP SEQUENCE ctlseq1;
 DROP TYPE ctlty1;
 DROP VIEW ctlv1;
 DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12;
-
-/* LIKE WITH OIDS */
-CREATE TABLE has_oid (x INTEGER) WITH OIDS;
-CREATE TABLE no_oid (y INTEGER);
-CREATE TABLE like_test (z INTEGER, LIKE has_oid);
-SELECT oid FROM like_test;
-CREATE TABLE like_test2 (z INTEGER, LIKE no_oid);
-SELECT oid FROM like_test2; -- fail
-CREATE TABLE like_test3 (z INTEGER, LIKE has_oid, LIKE no_oid);
-SELECT oid FROM like_test3;
-CREATE TABLE like_test4 (z INTEGER, PRIMARY KEY(oid), LIKE has_oid);
-SELECT oid FROM like_test4;
-CREATE TABLE like_test5 (z INTEGER, LIKE no_oid) WITH OIDS;
-SELECT oid FROM like_test5;
-DROP TABLE has_oid, no_oid, like_test, like_test2, like_test3,
-  like_test4, like_test5;
diff --git a/src/test/regress/sql/errors.sql b/src/test/regress/sql/errors.sql
index 14bc723a52a..792c29c64b5 100644
--- a/src/test/regress/sql/errors.sql
+++ b/src/test/regress/sql/errors.sql
@@ -91,7 +91,7 @@ alter table emp rename column nonesuchatt to newnonesuchatt;
 alter table emp rename column salary to manager;
 
 -- conflict
-alter table emp rename column salary to oid;
+alter table emp rename column salary to ctid;
 
 
 --
diff --git a/src/test/regress/sql/foreign_data.sql b/src/test/regress/sql/foreign_data.sql
index dab9b62900e..d6fb3fae4e1 100644
--- a/src/test/regress/sql/foreign_data.sql
+++ b/src/test/regress/sql/foreign_data.sql
@@ -283,7 +283,6 @@ CREATE SCHEMA foreign_schema;
 CREATE SERVER s0 FOREIGN DATA WRAPPER dummy;
 CREATE FOREIGN TABLE ft1 ();                                    -- ERROR
 CREATE FOREIGN TABLE ft1 () SERVER no_server;                   -- ERROR
-CREATE FOREIGN TABLE ft1 () SERVER s0 WITH OIDS;                -- ERROR
 CREATE FOREIGN TABLE ft1 (
 	c1 integer OPTIONS ("param 1" 'val1') PRIMARY KEY,
 	c2 text OPTIONS (param2 'val2', param3 'val3'),
@@ -362,7 +361,6 @@ ALTER FOREIGN TABLE ft1 ALTER CONSTRAINT ft1_c9_check DEFERRABLE; -- ERROR
 ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c9_check;
 ALTER FOREIGN TABLE ft1 DROP CONSTRAINT no_const;               -- ERROR
 ALTER FOREIGN TABLE ft1 DROP CONSTRAINT IF EXISTS no_const;
-ALTER FOREIGN TABLE ft1 SET WITH OIDS;
 ALTER FOREIGN TABLE ft1 OWNER TO regress_test_role;
 ALTER FOREIGN TABLE ft1 OPTIONS (DROP delimiter, SET quote '~', ADD escape '@');
 ALTER FOREIGN TABLE ft1 DROP COLUMN no_column;                  -- ERROR
@@ -693,15 +691,6 @@ ALTER TABLE fd_pt1 VALIDATE CONSTRAINT fd_pt1chk3;
 \d+ fd_pt1
 \d+ ft2
 
--- OID system column
-ALTER TABLE fd_pt1 SET WITH OIDS;
-\d+ fd_pt1
-\d+ ft2
-ALTER TABLE ft2 SET WITHOUT OIDS;  -- ERROR
-ALTER TABLE fd_pt1 SET WITHOUT OIDS;
-\d+ fd_pt1
-\d+ ft2
-
 -- changes name of an attribute recursively
 ALTER TABLE fd_pt1 RENAME COLUMN c1 TO f1;
 ALTER TABLE fd_pt1 RENAME COLUMN c2 TO f2;
diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql
index a6e541d4dad..f5e6dabbf34 100644
--- a/src/test/regress/sql/inherit.sql
+++ b/src/test/regress/sql/inherit.sql
@@ -190,32 +190,6 @@ insert into d values('test','one','two','three');
 alter table a alter column aa type integer using bit_length(aa);
 select * from d;
 
--- check that oid column is handled properly during alter table inherit
-create table oid_parent (a int) with oids;
-
-create table oid_child () inherits (oid_parent);
-select attinhcount, attislocal from pg_attribute
-  where attrelid = 'oid_child'::regclass and attname = 'oid';
-drop table oid_child;
-
-create table oid_child (a int) without oids;
-alter table oid_child inherit oid_parent;  -- fail
-alter table oid_child set with oids;
-select attinhcount, attislocal from pg_attribute
-  where attrelid = 'oid_child'::regclass and attname = 'oid';
-alter table oid_child inherit oid_parent;
-select attinhcount, attislocal from pg_attribute
-  where attrelid = 'oid_child'::regclass and attname = 'oid';
-alter table oid_child set without oids;  -- fail
-alter table oid_parent set without oids;
-select attinhcount, attislocal from pg_attribute
-  where attrelid = 'oid_child'::regclass and attname = 'oid';
-alter table oid_child set without oids;
-select attinhcount, attislocal from pg_attribute
-  where attrelid = 'oid_child'::regclass and attname = 'oid';
-
-drop table oid_parent cascade;
-
 -- Test non-inheritable parent constraints
 create table p1(ff1 int);
 alter table p1 add constraint p1chk check (ff1 > 0) no inherit;
diff --git a/src/test/regress/sql/insert_conflict.sql b/src/test/regress/sql/insert_conflict.sql
index c677d70fb7b..2df1bbc4b4f 100644
--- a/src/test/regress/sql/insert_conflict.sql
+++ b/src/test/regress/sql/insert_conflict.sql
@@ -253,12 +253,11 @@ drop table insertconflicttest;
 --
 -- Verify that EXCLUDED does not allow system column references. These
 -- do not make sense because EXCLUDED isn't an already stored tuple
--- (and thus doesn't have a ctid, oids are not assigned yet, etc).
+-- (and thus doesn't have a ctid etc).
 --
-create table syscolconflicttest(key int4, data text) WITH OIDS;
+create table syscolconflicttest(key int4, data text);
 insert into syscolconflicttest values (1);
 insert into syscolconflicttest values (1) on conflict (key) do update set data = excluded.ctid::text;
-insert into syscolconflicttest values (1) on conflict (key) do update set data = excluded.oid::text;
 drop table syscolconflicttest;
 
 --
@@ -373,28 +372,6 @@ insert into excluded values(1, '2') on conflict (key) do update set data = 3 RET
 drop table excluded;
 
 
--- Check tables w/o oids are handled correctly
-create table testoids(key int primary key, data text) without oids;
--- first without oids
-insert into testoids values(1, '1') on conflict (key) do update set data = excluded.data RETURNING *;
-insert into testoids values(1, '2') on conflict (key) do update set data = excluded.data RETURNING *;
--- add oids
-alter table testoids set with oids;
--- update existing row, that didn't have an oid
-insert into testoids values(1, '3') on conflict (key) do update set data = excluded.data RETURNING *;
--- insert a new row
-insert into testoids values(2, '1') on conflict (key) do update set data = excluded.data RETURNING *;
--- and update it
-insert into testoids values(2, '2') on conflict (key) do update set data = excluded.data RETURNING *;
--- remove oids again, test
-alter table testoids set without oids;
-insert into testoids values(1, '4') on conflict (key) do update set data = excluded.data RETURNING *;
-insert into testoids values(3, '1') on conflict (key) do update set data = excluded.data RETURNING *;
-insert into testoids values(3, '2') on conflict (key) do update set data = excluded.data RETURNING *;
-
-DROP TABLE testoids;
-
-
 -- check that references to columns after dropped columns are handled correctly
 create table dropcol(key int primary key, drop1 int, keep1 text, drop2 numeric, keep2 float);
 insert into dropcol(key, drop1, keep1, drop2, keep2) values(1, 1, '1', '1', 1);
diff --git a/src/test/regress/sql/misc_sanity.sql b/src/test/regress/sql/misc_sanity.sql
index f2af5e37508..f2cd0b46e25 100644
--- a/src/test/regress/sql/misc_sanity.sql
+++ b/src/test/regress/sql/misc_sanity.sql
@@ -54,7 +54,7 @@ declare relnm text;
 begin
 for relnm, reloid, shared in
   select relname, oid, relisshared from pg_class
-  where relhasoids and oid < 16384 order by 1
+  where EXISTS(SELECT * FROM pg_attribute WHERE attrelid = pg_class.oid AND attname = 'oid') and relkind = 'r' and oid < 16384 order by 1
 loop
   execute 'select min(oid) from ' || relnm into lowoid;
   continue when lowoid is null or lowoid >= 16384;
diff --git a/src/test/regress/sql/prepare.sql b/src/test/regress/sql/prepare.sql
index 25f814b4667..7fe8c8d7f55 100644
--- a/src/test/regress/sql/prepare.sql
+++ b/src/test/regress/sql/prepare.sql
@@ -36,21 +36,21 @@ PREPARE q2(text) AS
 
 EXECUTE q2('postgres');
 
-PREPARE q3(text, int, float, boolean, oid, smallint) AS
+PREPARE q3(text, int, float, boolean, smallint) AS
 	SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR
-	ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int)
+	ten = $3::bigint OR true = $4 OR odd = $5::int)
 	ORDER BY unique1;
 
-EXECUTE q3('AAAAxx', 5::smallint, 10.5::float, false, 500::oid, 4::bigint);
+EXECUTE q3('AAAAxx', 5::smallint, 10.5::float, false, 4::bigint);
 
 -- too few params
 EXECUTE q3('bool');
 
 -- too many params
-EXECUTE q3('bytea', 5::smallint, 10.5::float, false, 500::oid, 4::bigint, true);
+EXECUTE q3('bytea', 5::smallint, 10.5::float, false, 4::bigint, true);
 
 -- wrong param types
-EXECUTE q3(5::smallint, 10.5::float, false, 500::oid, 4::bigint, 'bytea');
+EXECUTE q3(5::smallint, 10.5::float, false, 4::bigint, 'bytea');
 
 -- invalid type
 PREPARE q4(nonexistenttype) AS SELECT $1;
diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql
index f7f3bbbeeb6..764af93abb0 100644
--- a/src/test/regress/sql/privileges.sql
+++ b/src/test/regress/sql/privileges.sql
@@ -407,27 +407,27 @@ DELETE FROM atest5 WHERE two = 2; -- ok
 
 -- check inheritance cases
 SET SESSION AUTHORIZATION regress_priv_user1;
-CREATE TABLE atestp1 (f1 int, f2 int) WITH OIDS;
-CREATE TABLE atestp2 (fx int, fy int) WITH OIDS;
+CREATE TABLE atestp1 (f1 int, f2 int);
+CREATE TABLE atestp2 (fx int, fy int);
 CREATE TABLE atestc (fz int) INHERITS (atestp1, atestp2);
-GRANT SELECT(fx,fy,oid) ON atestp2 TO regress_priv_user2;
+GRANT SELECT(fx,fy,tableoid) ON atestp2 TO regress_priv_user2;
 GRANT SELECT(fx) ON atestc TO regress_priv_user2;
 
 SET SESSION AUTHORIZATION regress_priv_user2;
 SELECT fx FROM atestp2; -- ok
 SELECT fy FROM atestp2; -- ok
 SELECT atestp2 FROM atestp2; -- ok
-SELECT oid FROM atestp2; -- ok
+SELECT tableoid FROM atestp2; -- ok
 SELECT fy FROM atestc; -- fail
 
 SET SESSION AUTHORIZATION regress_priv_user1;
-GRANT SELECT(fy,oid) ON atestc TO regress_priv_user2;
+GRANT SELECT(fy,tableoid) ON atestc TO regress_priv_user2;
 
 SET SESSION AUTHORIZATION regress_priv_user2;
 SELECT fx FROM atestp2; -- still ok
 SELECT fy FROM atestp2; -- ok
 SELECT atestp2 FROM atestp2; -- ok
-SELECT oid FROM atestp2; -- ok
+SELECT tableoid FROM atestp2; -- ok
 
 -- privileges on functions, languages
 
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 37fbf41f7d5..44fcd8c4145 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -52,11 +52,6 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass AND
 -- RESET fails if a value is specified
 ALTER TABLE reloptions_test RESET (fillfactor=12);
 
--- The OIDS option is not stored as reloption
-DROP TABLE reloptions_test;
-CREATE TABLE reloptions_test(i INT) WITH (fillfactor=20, oids=true);
-SELECT reloptions, relhasoids FROM pg_class WHERE oid = 'reloptions_test'::regclass;
-
 -- Test toast.* options
 DROP TABLE reloptions_test;
 
diff --git a/src/test/regress/sql/replica_identity.sql b/src/test/regress/sql/replica_identity.sql
index 3d2171c7336..b08a3623b8c 100644
--- a/src/test/regress/sql/replica_identity.sql
+++ b/src/test/regress/sql/replica_identity.sql
@@ -5,13 +5,12 @@ CREATE TABLE test_replica_identity (
        nonkey text,
        CONSTRAINT test_replica_identity_unique_defer UNIQUE (keya, keyb) DEFERRABLE,
        CONSTRAINT test_replica_identity_unique_nondefer UNIQUE (keya, keyb)
-) WITH OIDS;
+) ;
 
 CREATE TABLE test_replica_identity_othertable (id serial primary key);
 
 CREATE INDEX test_replica_identity_keyab ON test_replica_identity (keya, keyb);
 CREATE UNIQUE INDEX test_replica_identity_keyab_key ON test_replica_identity (keya, keyb);
-CREATE UNIQUE INDEX test_replica_identity_oid_idx ON test_replica_identity (oid);
 CREATE UNIQUE INDEX test_replica_identity_nonkey ON test_replica_identity (keya, nonkey);
 CREATE INDEX test_replica_identity_hash ON test_replica_identity USING hash (nonkey);
 CREATE UNIQUE INDEX test_replica_identity_expr ON test_replica_identity (keya, keyb, (3));
@@ -53,9 +52,6 @@ ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_iden
 SELECT relreplident FROM pg_class WHERE oid = 'test_replica_identity'::regclass;
 \d test_replica_identity
 
--- succeed, oid unique index
-ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_oid_idx;
-
 -- succeed, nondeferrable unique constraint over nonnullable cols
 ALTER TABLE test_replica_identity REPLICA IDENTITY USING INDEX test_replica_identity_unique_nondefer;
 
diff --git a/src/test/regress/sql/roleattributes.sql b/src/test/regress/sql/roleattributes.sql
index 1b034d752fb..c961b2d7303 100644
--- a/src/test/regress/sql/roleattributes.sql
+++ b/src/test/regress/sql/roleattributes.sql
@@ -1,82 +1,83 @@
 -- default for superuser is false
 CREATE ROLE regress_test_def_superuser;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_superuser';
+
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_superuser';
 CREATE ROLE regress_test_superuser WITH SUPERUSER;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_superuser';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_superuser';
 ALTER ROLE regress_test_superuser WITH NOSUPERUSER;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_superuser';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_superuser';
 ALTER ROLE regress_test_superuser WITH SUPERUSER;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_superuser';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_superuser';
 
 -- default for inherit is true
 CREATE ROLE regress_test_def_inherit;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_inherit';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_inherit';
 CREATE ROLE regress_test_inherit WITH NOINHERIT;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_inherit';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_inherit';
 ALTER ROLE regress_test_inherit WITH INHERIT;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_inherit';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_inherit';
 ALTER ROLE regress_test_inherit WITH NOINHERIT;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_inherit';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_inherit';
 
 -- default for create role is false
 CREATE ROLE regress_test_def_createrole;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_createrole';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_createrole';
 CREATE ROLE regress_test_createrole WITH CREATEROLE;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_createrole';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_createrole';
 ALTER ROLE regress_test_createrole WITH NOCREATEROLE;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_createrole';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_createrole';
 ALTER ROLE regress_test_createrole WITH CREATEROLE;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_createrole';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_createrole';
 
 -- default for create database is false
 CREATE ROLE regress_test_def_createdb;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_createdb';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_createdb';
 CREATE ROLE regress_test_createdb WITH CREATEDB;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_createdb';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_createdb';
 ALTER ROLE regress_test_createdb WITH NOCREATEDB;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_createdb';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_createdb';
 ALTER ROLE regress_test_createdb WITH CREATEDB;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_createdb';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_createdb';
 
 -- default for can login is false for role
 CREATE ROLE regress_test_def_role_canlogin;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_role_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_role_canlogin';
 CREATE ROLE regress_test_role_canlogin WITH LOGIN;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_role_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_role_canlogin';
 ALTER ROLE regress_test_role_canlogin WITH NOLOGIN;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_role_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_role_canlogin';
 ALTER ROLE regress_test_role_canlogin WITH LOGIN;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_role_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_role_canlogin';
 
 -- default for can login is true for user
 CREATE USER regress_test_def_user_canlogin;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_user_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_user_canlogin';
 CREATE USER regress_test_user_canlogin WITH NOLOGIN;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_user_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_user_canlogin';
 ALTER USER regress_test_user_canlogin WITH LOGIN;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_user_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_user_canlogin';
 ALTER USER regress_test_user_canlogin WITH NOLOGIN;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_user_canlogin';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_user_canlogin';
 
 -- default for replication is false
 CREATE ROLE regress_test_def_replication;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_replication';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_replication';
 CREATE ROLE regress_test_replication WITH REPLICATION;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_replication';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_replication';
 ALTER ROLE regress_test_replication WITH NOREPLICATION;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_replication';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_replication';
 ALTER ROLE regress_test_replication WITH REPLICATION;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_replication';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_replication';
 
 -- default for bypassrls is false
 CREATE ROLE regress_test_def_bypassrls;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_def_bypassrls';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_def_bypassrls';
 CREATE ROLE regress_test_bypassrls WITH BYPASSRLS;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_bypassrls';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_bypassrls';
 ALTER ROLE regress_test_bypassrls WITH NOBYPASSRLS;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_bypassrls';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_bypassrls';
 ALTER ROLE regress_test_bypassrls WITH BYPASSRLS;
-SELECT * FROM pg_authid WHERE rolname = 'regress_test_bypassrls';
+SELECT rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, rolvaliduntil FROM pg_authid WHERE rolname = 'regress_test_bypassrls';
 
 -- clean up roles
 DROP ROLE regress_test_def_superuser;
diff --git a/src/test/regress/sql/rowsecurity.sql b/src/test/regress/sql/rowsecurity.sql
index 5a9fdcad742..38e9b38bc40 100644
--- a/src/test/regress/sql/rowsecurity.sql
+++ b/src/test/regress/sql/rowsecurity.sql
@@ -232,11 +232,11 @@ SET SESSION AUTHORIZATION regress_rls_alice;
 
 SET row_security TO ON;
 
-CREATE TABLE t1 (a int, junk1 text, b text) WITH OIDS;
+CREATE TABLE t1 (id int not null primary key, a int, junk1 text, b text);
 ALTER TABLE t1 DROP COLUMN junk1;    -- just a disturbing factor
 GRANT ALL ON t1 TO public;
 
-COPY t1 FROM stdin WITH (oids);
+COPY t1 FROM stdin WITH ;
 101	1	aba
 102	2	bbb
 103	3	ccc
@@ -246,18 +246,18 @@ COPY t1 FROM stdin WITH (oids);
 CREATE TABLE t2 (c float) INHERITS (t1);
 GRANT ALL ON t2 TO public;
 
-COPY t2 FROM stdin WITH (oids);
+COPY t2 FROM stdin;
 201	1	abc	1.1
 202	2	bcd	2.2
 203	3	cde	3.3
 204	4	def	4.4
 \.
 
-CREATE TABLE t3 (c text, b text, a int) WITH OIDS;
+CREATE TABLE t3 (id int not null primary key, c text, b text, a int);
 ALTER TABLE t3 INHERIT t1;
 GRANT ALL ON t3 TO public;
 
-COPY t3(a,b,c) FROM stdin WITH (oids);
+COPY t3(id, a,b,c) FROM stdin;
 301	1	xxx	X
 302	2	yyy	Y
 303	3	zzz	Z
@@ -278,7 +278,7 @@ SELECT * FROM t1 WHERE f_leak(b);
 EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b);
 
 -- reference to system column
-SELECT oid, * FROM t1;
+SELECT tableoid::regclass, * FROM t1;
 EXPLAIN (COSTS OFF) SELECT *, t1 FROM t1;
 
 -- reference to whole-row reference
@@ -293,8 +293,8 @@ SELECT * FROM t1 WHERE f_leak(b) FOR SHARE;
 EXPLAIN (COSTS OFF) SELECT * FROM t1 WHERE f_leak(b) FOR SHARE;
 
 -- union all query
-SELECT a, b, oid FROM t2 UNION ALL SELECT a, b, oid FROM t3;
-EXPLAIN (COSTS OFF) SELECT a, b, oid FROM t2 UNION ALL SELECT a, b, oid FROM t3;
+SELECT a, b, tableoid::regclass FROM t2 UNION ALL SELECT a, b, tableoid::regclass FROM t3;
+EXPLAIN (COSTS OFF) SELECT a, b, tableoid::regclass FROM t2 UNION ALL SELECT a, b, tableoid::regclass FROM t3;
 
 -- superuser is allowed to bypass RLS checks
 RESET SESSION AUTHORIZATION;
@@ -614,9 +614,9 @@ EXPLAIN (COSTS OFF) UPDATE only t1 SET b = b || '_updt' WHERE f_leak(b);
 UPDATE only t1 SET b = b || '_updt' WHERE f_leak(b);
 
 -- returning clause with system column
-UPDATE only t1 SET b = b WHERE f_leak(b) RETURNING oid, *, t1;
+UPDATE only t1 SET b = b WHERE f_leak(b) RETURNING tableoid::regclass, *, t1;
 UPDATE t1 SET b = b WHERE f_leak(b) RETURNING *;
-UPDATE t1 SET b = b WHERE f_leak(b) RETURNING oid, *, t1;
+UPDATE t1 SET b = b WHERE f_leak(b) RETURNING tableoid::regclass, *, t1;
 
 -- updates with from clause
 EXPLAIN (COSTS OFF) UPDATE t2 SET b=t2.b FROM t3
@@ -663,8 +663,8 @@ SET row_security TO ON;
 EXPLAIN (COSTS OFF) DELETE FROM only t1 WHERE f_leak(b);
 EXPLAIN (COSTS OFF) DELETE FROM t1 WHERE f_leak(b);
 
-DELETE FROM only t1 WHERE f_leak(b) RETURNING oid, *, t1;
-DELETE FROM t1 WHERE f_leak(b) RETURNING oid, *, t1;
+DELETE FROM only t1 WHERE f_leak(b) RETURNING tableoid::regclass, *, t1;
+DELETE FROM t1 WHERE f_leak(b) RETURNING tableoid::regclass, *, t1;
 
 --
 -- S.b. view on top of Row-level security
diff --git a/src/test/regress/sql/rowtypes.sql b/src/test/regress/sql/rowtypes.sql
index faf2e108d6a..e6d389805cd 100644
--- a/src/test/regress/sql/rowtypes.sql
+++ b/src/test/regress/sql/rowtypes.sql
@@ -442,15 +442,15 @@ select r, r is null as isnull, r is not null as isnotnull from r;
 --
 -- Tests for component access / FieldSelect
 --
-CREATE TABLE compositetable(a text, b text) WITH OIDS;
+CREATE TABLE compositetable(a text, b text);
 INSERT INTO compositetable(a, b) VALUES('fa', 'fb');
 
 -- composite type columns can't directly be accessed (error)
 SELECT d.a FROM (SELECT compositetable AS d FROM compositetable) s;
 -- but can be accessed with proper parens
 SELECT (d).a, (d).b FROM (SELECT compositetable AS d FROM compositetable) s;
--- oids can't be accessed in composite types (error)
-SELECT (d).oid FROM (SELECT compositetable AS d FROM compositetable) s;
+-- system columns can't be accessed in composite types (error)
+SELECT (d).ctid FROM (SELECT compositetable AS d FROM compositetable) s;
 
 -- accessing non-existing column in NULL datum errors out
 SELECT (NULL::compositetable).nonexistant;
diff --git a/src/test/regress/sql/sanity_check.sql b/src/test/regress/sql/sanity_check.sql
index 04aee457dda..a2feebc91bf 100644
--- a/src/test/regress/sql/sanity_check.sql
+++ b/src/test/regress/sql/sanity_check.sql
@@ -25,9 +25,9 @@ SELECT relname, relhasindex
 -- We exclude non-system tables from the check by looking at nspname.
 --
 SELECT relname, nspname
-FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = relnamespace
-WHERE relhasoids
-    AND ((nspname ~ '^pg_') IS NOT FALSE)
-    AND NOT EXISTS (SELECT 1 FROM pg_index i WHERE indrelid = c.oid
-                    AND indkey[0] = -2 AND indnatts = 1
-                    AND indisunique AND indimmediate);
+ FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = relnamespace JOIN pg_attribute a ON (attrelid = c.oid AND attname = 'oid')
+ WHERE relkind = 'r' and c.oid < 16384
+     AND ((nspname ~ '^pg_') IS NOT FALSE)
+     AND NOT EXISTS (SELECT 1 FROM pg_index i WHERE indrelid = c.oid
+                     AND indkey[0] = a.attnum AND indnatts = 1
+                     AND indisunique AND indimmediate);
diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql
index d7dfd753be2..5336185ed25 100644
--- a/src/test/regress/sql/triggers.sql
+++ b/src/test/regress/sql/triggers.sql
@@ -292,11 +292,11 @@ DROP TRIGGER insert_when ON main_table;
 DROP TRIGGER delete_when ON main_table;
 
 -- Test WHEN condition accessing system columns.
-create table table_with_oids(a int) with oids;
+create table table_with_oids(a int);
 insert into table_with_oids values (1);
 create trigger oid_unchanged_trig after update on table_with_oids
 	for each row
-	when (new.oid = old.oid AND new.oid <> 0)
+	when (new.tableoid = old.tableoid AND new.tableoid <> 0)
 	execute procedure trigger_func('after_upd_oid_unchanged');
 update table_with_oids set a = a + 1;
 drop table table_with_oids;
@@ -582,23 +582,12 @@ CREATE TABLE min_updates_test (
 	f2 int,
 	f3 int);
 
-CREATE TABLE min_updates_test_oids (
-	f1	text,
-	f2 int,
-	f3 int) WITH OIDS;
-
 INSERT INTO min_updates_test VALUES ('a',1,2),('b','2',null);
 
-INSERT INTO min_updates_test_oids VALUES ('a',1,2),('b','2',null);
-
 CREATE TRIGGER z_min_update
 BEFORE UPDATE ON min_updates_test
 FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
 
-CREATE TRIGGER z_min_update
-BEFORE UPDATE ON min_updates_test_oids
-FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
-
 \set QUIET false
 
 UPDATE min_updates_test SET f1 = f1;
@@ -607,22 +596,12 @@ UPDATE min_updates_test SET f2 = f2 + 1;
 
 UPDATE min_updates_test SET f3 = 2 WHERE f3 is null;
 
-UPDATE min_updates_test_oids SET f1 = f1;
-
-UPDATE min_updates_test_oids SET f2 = f2 + 1;
-
-UPDATE min_updates_test_oids SET f3 = 2 WHERE f3 is null;
-
 \set QUIET true
 
 SELECT * FROM min_updates_test;
 
-SELECT * FROM min_updates_test_oids;
-
 DROP TABLE min_updates_test;
 
-DROP TABLE min_updates_test_oids;
-
 --
 -- Test triggers on views
 --
diff --git a/src/test/regress/sql/without_oid.sql b/src/test/regress/sql/without_oid.sql
deleted file mode 100644
index 9fbb454d4dc..00000000000
--- a/src/test/regress/sql/without_oid.sql
+++ /dev/null
@@ -1,92 +0,0 @@
---
--- WITHOUT OID
---
-
---
--- This test tries to verify that WITHOUT OIDS actually saves space.
--- On machines where MAXALIGN is 8, WITHOUT OIDS may or may not save any
--- space, depending on the size of the tuple header + null bitmap.
--- As of 8.3 we need a null bitmap of 8 or less bits for the difference
--- to appear.
---
-CREATE TABLE wi (i INT,
-                 n1 int, n2 int, n3 int, n4 int,
-                 n5 int, n6 int, n7 int) WITH OIDS;
-CREATE TABLE wo (i INT,
-                 n1 int, n2 int, n3 int, n4 int,
-                 n5 int, n6 int, n7 int) WITHOUT OIDS;
-
-INSERT INTO wi VALUES (1);  -- 1
-INSERT INTO wo SELECT i FROM wi;  -- 1
-INSERT INTO wo SELECT i+1 FROM wi;  -- 1+1=2
-INSERT INTO wi SELECT i+1 FROM wo;  -- 1+2=3
-INSERT INTO wi SELECT i+3 FROM wi;  -- 3+3=6
-INSERT INTO wo SELECT i+2 FROM wi;  -- 2+6=8
-INSERT INTO wo SELECT i+8 FROM wo;  -- 8+8=16
-INSERT INTO wi SELECT i+6 FROM wo;  -- 6+16=22
-INSERT INTO wi SELECT i+22 FROM wi;  -- 22+22=44
-INSERT INTO wo SELECT i+16 FROM wi;  -- 16+44=60
-INSERT INTO wo SELECT i+60 FROM wo;  -- 60+60=120
-INSERT INTO wi SELECT i+44 FROM wo;  -- 44+120=164
-INSERT INTO wi SELECT i+164 FROM wi;  -- 164+164=328
-INSERT INTO wo SELECT i+120 FROM wi;  -- 120+328=448
-INSERT INTO wo SELECT i+448 FROM wo;  -- 448+448=896
-INSERT INTO wi SELECT i+328 FROM wo;  -- 328+896=1224
-INSERT INTO wi SELECT i+1224 FROM wi;  -- 1224+1224=2448
-INSERT INTO wo SELECT i+896 FROM wi;  -- 896+2448=3344
-INSERT INTO wo SELECT i+3344 FROM wo;  -- 3344+3344=6688
-INSERT INTO wi SELECT i+2448 FROM wo;  -- 2448+6688=9136
-INSERT INTO wo SELECT i+6688 FROM wi WHERE i<=2448;  -- 6688+2448=9136
-
-SELECT count(oid) FROM wi;
--- should fail
-SELECT count(oid) FROM wo;
-
-VACUUM ANALYZE wi;
-VACUUM ANALYZE wo;
-
-SELECT min(relpages) < max(relpages), min(reltuples) - max(reltuples)
-  FROM pg_class
- WHERE relname IN ('wi', 'wo');
-
-DROP TABLE wi;
-DROP TABLE wo;
-
---
--- WITH / WITHOUT OIDS in CREATE TABLE AS
---
-CREATE TABLE create_table_test (
-    a int,
-    b int
-);
-
-COPY create_table_test FROM stdin;
-5	10
-10	15
-\.
-
-CREATE TABLE create_table_test2 WITH OIDS AS
-    SELECT a + b AS c1, a - b AS c2 FROM create_table_test;
-
-CREATE TABLE create_table_test3 WITHOUT OIDS AS
-    SELECT a + b AS c1, a - b AS c2 FROM create_table_test;
-
-SELECT count(oid) FROM create_table_test2;
--- should fail
-SELECT count(oid) FROM create_table_test3;
-
-PREPARE table_source(int) AS
-    SELECT a + b AS c1, a - b AS c2, $1 AS c3 FROM create_table_test;
-
-CREATE TABLE execute_with WITH OIDS AS EXECUTE table_source(1);
-CREATE TABLE execute_without WITHOUT OIDS AS EXECUTE table_source(2);
-
-SELECT count(oid) FROM execute_with;
--- should fail
-SELECT count(oid) FROM execute_without;
-
-DROP TABLE create_table_test;
-DROP TABLE create_table_test2;
-DROP TABLE create_table_test3;
-DROP TABLE execute_with;
-DROP TABLE execute_without;
-- 
2.18.0.rc2.dirty

