/* Var belongs to foreign table */
 
                                        /*
-                                        * System columns other than ctid should not be sent to
-                                        * the remote, since we don't make any effort to ensure
-                                        * that local and remote values match (tableoid, in
+                                        * System columns other than ctid and oid should not be
+                                        * sent to the remote, since we don't make any effort to
+                                        * ensure that local and remote values match (tableoid, in
                                         * particular, almost certainly doesn't match).
                                         */
                                        if (var->varattno < 0 &&
-                                               var->varattno != SelfItemPointerAttributeNumber)
+                                               var->varattno != SelfItemPointerAttributeNumber &&
+                                               var->varattno != ObjectIdAttributeNumber)
                                                return false;
 
                                        /* Else check the collation */
        }
 
        /*
-        * Add ctid if needed.  We currently don't support retrieving any other
-        * system columns.
+        * Add ctid and oid if needed.  We currently don't support retrieving any
+        * other system columns.
         */
        if (bms_is_member(SelfItemPointerAttributeNumber - FirstLowInvalidHeapAttributeNumber,
                                          attrs_used))
                *retrieved_attrs = lappend_int(*retrieved_attrs,
                                                                           SelfItemPointerAttributeNumber);
        }
+       if (bms_is_member(ObjectIdAttributeNumber - FirstLowInvalidHeapAttributeNumber,
+                                         attrs_used))
+       {
+               if (!first)
+                       appendStringInfoString(buf, ", ");
+               else if (is_returning)
+                       appendStringInfoString(buf, " RETURNING ");
+               first = false;
+
+               if (qualify_col)
+                       ADD_REL_QUALIFIER(buf, rtindex);
+               appendStringInfoString(buf, "oid");
+
+               *retrieved_attrs = lappend_int(*retrieved_attrs,
+                                                                          ObjectIdAttributeNumber);
+       }
 
        /* Don't generate bad syntax if no undropped columns */
        if (first && !is_returning)
 {
        RangeTblEntry *rte;
 
+       /* We support fetching the remote side's CTID and OID. */
        if (varattno == SelfItemPointerAttributeNumber)
        {
-               /* We support fetching the remote side's CTID. */
                if (qualify_col)
                        ADD_REL_QUALIFIER(buf, varno);
                appendStringInfoString(buf, "ctid");
        }
+       else if (varattno == ObjectIdAttributeNumber)
+       {
+               if (qualify_col)
+                       ADD_REL_QUALIFIER(buf, varno);
+               appendStringInfoString(buf, "oid");
+       }
        else if (varattno < 0)
        {
                /*
 
        c2 int NOT NULL,
        c3 text
 ) SERVER loopback2 OPTIONS (schema_name 'S 1', table_name 'T 4');
+-- A table with oids. CREATE FOREIGN TABLE doesn't support the
+-- WITH OIDS option, but ALTER does.
+CREATE FOREIGN TABLE ft_pg_type (
+       typname name,
+       typlen smallint
+) SERVER loopback OPTIONS (schema_name 'pg_catalog', table_name 'pg_type');
+ALTER TABLE ft_pg_type SET WITH OIDS;
 -- ===================================================================
 -- tests for validator
 -- ===================================================================
 ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
 ALTER FOREIGN TABLE ft2 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
 \det+
-                              List of foreign tables
- Schema | Table |  Server   |              FDW Options              | Description 
---------+-------+-----------+---------------------------------------+-------------
- public | ft1   | loopback  | (schema_name 'S 1', table_name 'T 1') | 
- public | ft2   | loopback  | (schema_name 'S 1', table_name 'T 1') | 
- public | ft4   | loopback  | (schema_name 'S 1', table_name 'T 3') | 
- public | ft5   | loopback  | (schema_name 'S 1', table_name 'T 4') | 
- public | ft6   | loopback2 | (schema_name 'S 1', table_name 'T 4') | 
-(5 rows)
+                                      List of foreign tables
+ Schema |   Table    |  Server   |                   FDW Options                    | Description 
+--------+------------+-----------+--------------------------------------------------+-------------
+ public | ft1        | loopback  | (schema_name 'S 1', table_name 'T 1')            | 
+ public | ft2        | loopback  | (schema_name 'S 1', table_name 'T 1')            | 
+ public | ft4        | loopback  | (schema_name 'S 1', table_name 'T 3')            | 
+ public | ft5        | loopback  | (schema_name 'S 1', table_name 'T 4')            | 
+ public | ft6        | loopback2 | (schema_name 'S 1', table_name 'T 4')            | 
+ public | ft_pg_type | loopback  | (schema_name 'pg_catalog', table_name 'pg_type') | 
+(6 rows)
 
 -- Now we should be able to run ANALYZE.
 -- To exercise multiple code paths, we use local stats on ft1
 DEALLOCATE st3;
 DEALLOCATE st4;
 DEALLOCATE st5;
--- System columns, except ctid, should not be sent to remote
+-- System columns, except ctid and oid, should not be sent to remote
 EXPLAIN (VERBOSE, COSTS OFF)
 SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1;
                                   QUERY PLAN                                   
  (0,1) |  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 (1 row)
 
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT oid, * FROM ft_pg_type WHERE typname = 'int4';
+                                             QUERY PLAN                                             
+----------------------------------------------------------------------------------------------------
+ Foreign Scan on public.ft_pg_type
+   Output: oid, typname, typlen
+   Remote SQL: SELECT typname, typlen, oid FROM pg_catalog.pg_type WHERE ((typname = 'int4'::name))
+(3 rows)
+
+SELECT oid, * FROM ft_pg_type WHERE typname = 'int4';
+ oid | typname | typlen 
+-----+---------+--------
+  23 | int4    |      4
+(1 row)
+
 -- ===================================================================
 -- used in pl/pgsql function
 -- ===================================================================
 
        Datum      *values;
        bool       *nulls;
        ItemPointer ctid = NULL;
+       Oid                     oid = InvalidOid;
        ConversionLocation errpos;
        ErrorContextCallback errcallback;
        MemoryContext oldcontext;
                else
                        valstr = PQgetvalue(res, row, j);
 
-               /* convert value to internal representation */
+               /*
+                * convert value to internal representation
+                *
+                * Note: we ignore system columns other than ctid and oid in result
+                */
                errpos.cur_attno = i;
                if (i > 0)
                {
                }
                else if (i == SelfItemPointerAttributeNumber)
                {
-                       /* ctid --- note we ignore any other system column in result */
+                       /* ctid */
                        if (valstr != NULL)
                        {
                                Datum           datum;
                                ctid = (ItemPointer) DatumGetPointer(datum);
                        }
                }
+               else if (i == ObjectIdAttributeNumber)
+               {
+                       /* oid */
+                       if (valstr != NULL)
+                       {
+                               Datum           datum;
+
+                               datum = DirectFunctionCall1(oidin, CStringGetDatum(valstr));
+                               oid = DatumGetObjectId(datum);
+                       }
+               }
                errpos.cur_attno = 0;
 
                j++;
        HeapTupleHeaderSetXmin(tuple->t_data, InvalidTransactionId);
        HeapTupleHeaderSetCmin(tuple->t_data, InvalidTransactionId);
 
+       /*
+        * If we have an OID to return, install it.
+        */
+       if (OidIsValid(oid))
+               HeapTupleSetOid(tuple, oid);
+
        /* Clean up */
        MemoryContextReset(temp_context);
 
                        attname = NameStr(tupdesc->attrs[errpos->cur_attno - 1]->attname);
                else if (errpos->cur_attno == SelfItemPointerAttributeNumber)
                        attname = "ctid";
+               else if (errpos->cur_attno == ObjectIdAttributeNumber)
+                       attname = "oid";
 
                relname = RelationGetRelationName(errpos->rel);
        }
 
        c3 text
 ) SERVER loopback2 OPTIONS (schema_name 'S 1', table_name 'T 4');
 
+-- A table with oids. CREATE FOREIGN TABLE doesn't support the
+-- WITH OIDS option, but ALTER does.
+CREATE FOREIGN TABLE ft_pg_type (
+       typname name,
+       typlen smallint
+) SERVER loopback OPTIONS (schema_name 'pg_catalog', table_name 'pg_type');
+ALTER TABLE ft_pg_type SET WITH OIDS;
+
 -- ===================================================================
 -- tests for validator
 -- ===================================================================
 DEALLOCATE st4;
 DEALLOCATE st5;
 
--- System columns, except ctid, should not be sent to remote
+-- System columns, except ctid and oid, should not be sent to remote
 EXPLAIN (VERBOSE, COSTS OFF)
 SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1;
 SELECT * FROM ft1 t1 WHERE t1.tableoid = 'ft1'::regclass LIMIT 1;
 EXPLAIN (VERBOSE, COSTS OFF)
 SELECT ctid, * FROM ft1 t1 LIMIT 1;
 SELECT ctid, * FROM ft1 t1 LIMIT 1;
+EXPLAIN (VERBOSE, COSTS OFF)
+SELECT oid, * FROM ft_pg_type WHERE typname = 'int4';
+SELECT oid, * FROM ft_pg_type WHERE typname = 'int4';
 
 -- ===================================================================
 -- used in pl/pgsql function