diff --git a/src/bin/pg_upgrade/info.c b/src/bin/pg_upgrade/info.c
index 5d83455..0653ff1 100644
*** a/src/bin/pg_upgrade/info.c
--- b/src/bin/pg_upgrade/info.c
*************** get_db_infos(ClusterInfo *cluster)
*** 301,311 ****
  /*
   * get_rel_infos()
   *
!  * gets the relinfos for all the user tables of the database referred
!  * by "db".
   *
!  * NOTE: we assume that relations/entities with oids greater than
!  * FirstNormalObjectId belongs to the user
   */
  static void
  get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
--- 301,311 ----
  /*
   * get_rel_infos()
   *
!  * gets the relinfos for all the user tables and indexes of the database
!  * referred to by "dbinfo".
   *
!  * Note: the resulting RelInfo array is assumed to be sorted by OID.
!  * This allows later processing to match up old and new databases efficiently.
   */
  static void
  get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
*************** get_rel_infos(ClusterInfo *cluster, DbIn
*** 330,415 ****
  	char	   *last_namespace = NULL,
  			   *last_tablespace = NULL;
  
  	/*
  	 * pg_largeobject contains user data that does not appear in pg_dump
! 	 * --schema-only output, so we have to copy that system table heap and
! 	 * index.  We could grab the pg_largeobject oids from template1, but it is
! 	 * easy to treat it as a normal table. Order by oid so we can join old/new
! 	 * structures efficiently.
  	 */
! 
! 	snprintf(query, sizeof(query),
! 	/* get regular heap */
  			 "WITH regular_heap (reloid) AS ( "
! 			 "	SELECT c.oid "
! 			 "	FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n "
! 			 "		   ON c.relnamespace = n.oid "
! 			 "	LEFT OUTER JOIN pg_catalog.pg_index i "
! 			 "		   ON c.oid = i.indexrelid "
! 			 "	WHERE relkind IN ('r', 'm', 'i', 'S') AND "
  
  	/*
! 	 * pg_dump only dumps valid indexes;  testing indisready is necessary in
! 	 * 9.2, and harmless in earlier/later versions.
  	 */
! 			 "		i.indisvalid IS DISTINCT FROM false AND "
! 			 "		i.indisready IS DISTINCT FROM false AND "
! 	/* exclude possible orphaned temp tables */
! 			 "	  ((n.nspname !~ '^pg_temp_' AND "
! 			 "	    n.nspname !~ '^pg_toast_temp_' AND "
! 	/* skip pg_toast because toast index have relkind == 'i', not 't' */
! 			 "	    n.nspname NOT IN ('pg_catalog', 'information_schema', "
! 			 "							'binary_upgrade', 'pg_toast') AND "
! 			 "		  c.oid >= %u) OR "
! 			 "	  (n.nspname = 'pg_catalog' AND "
! 			 "    relname IN ('pg_largeobject', 'pg_largeobject_loid_pn_index'%s) ))), "
  
  	/*
! 	 * We have to gather the TOAST tables in later steps because we can't
! 	 * schema-qualify TOAST tables.
  	 */
! 	/* get TOAST heap */
! 			 "	toast_heap (reloid) AS ( "
! 			 "	SELECT reltoastrelid "
! 			 "	FROM regular_heap JOIN pg_catalog.pg_class c "
! 			 "		ON regular_heap.reloid = c.oid "
! 			 "		AND c.reltoastrelid != %u), "
! 	/* get indexes on regular and TOAST heap */
! 			 "	all_index (reloid) AS ( "
! 			 "	SELECT indexrelid "
! 			 "	FROM pg_index "
! 			 "	WHERE indisvalid "
! 			 "    AND indrelid IN (SELECT reltoastrelid "
! 			 "        FROM (SELECT reloid FROM regular_heap "
! 			 "			   UNION ALL "
! 			 "			   SELECT reloid FROM toast_heap) all_heap "
! 			 "            JOIN pg_catalog.pg_class c "
! 			 "            ON all_heap.reloid = c.oid "
! 			 "            AND c.reltoastrelid != %u)) "
! 	/* get all rels */
  			 "SELECT c.oid, n.nspname, c.relname, "
! 			 "	c.relfilenode, c.reltablespace, %s "
  			 "FROM (SELECT reloid FROM regular_heap "
! 			 "	   UNION ALL "
! 			 "	   SELECT reloid FROM toast_heap  "
! 			 "	   UNION ALL "
! 			 "	   SELECT reloid FROM all_index) all_rels "
  			 "  JOIN pg_catalog.pg_class c "
! 			 "		ON all_rels.reloid = c.oid "
  			 "  JOIN pg_catalog.pg_namespace n "
! 			 "	   ON c.relnamespace = n.oid "
  			 "  LEFT OUTER JOIN pg_catalog.pg_tablespace t "
! 			 "	   ON c.reltablespace = t.oid "
! 	/* we preserve pg_class.oid so we sort by it to match old/new */
  			 "ORDER BY 1;",
! 			 FirstNormalObjectId,
! 	/* does pg_largeobject_metadata need to be migrated? */
! 			 (GET_MAJOR_VERSION(old_cluster.major_version) <= 804) ?
! 	 "" : ", 'pg_largeobject_metadata', 'pg_largeobject_metadata_oid_index'",
! 			 InvalidOid, InvalidOid,
! 	/* 9.2 removed the spclocation column */
! 			 (GET_MAJOR_VERSION(cluster->major_version) <= 901) ?
! 			 "t.spclocation" : "pg_catalog.pg_tablespace_location(t.oid) AS spclocation");
  
  	res = executeQueryOrDie(conn, "%s", query);
  
--- 330,418 ----
  	char	   *last_namespace = NULL,
  			   *last_tablespace = NULL;
  
+ 	query[0] = '\0';			/* initialize query string to empty */
+ 
  	/*
+ 	 * Create a CTE that collects OIDs of regular user tables, including
+ 	 * matviews and sequences, but excluding toast tables and indexes.  We
+ 	 * assume that relations with OIDs >= FirstNormalObjectId belong to the
+ 	 * user.  (That's probably redundant with the namespace-name exclusions,
+ 	 * but let's be safe.)
+ 	 *
  	 * pg_largeobject contains user data that does not appear in pg_dump
! 	 * output, so we have to copy that system table.  It's easiest to do that
! 	 * by treating it as a user table.  Likewise for pg_largeobject_metadata,
! 	 * if it exists.
  	 */
! 	snprintf(query + strlen(query), sizeof(query) - strlen(query),
  			 "WITH regular_heap (reloid) AS ( "
! 			 "  SELECT c.oid "
! 			 "  FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n "
! 			 "         ON c.relnamespace = n.oid "
! 			 "  WHERE relkind IN ('r', 'm', 'S') AND "
! 	/* exclude possible orphaned temp tables */
! 			 "    ((n.nspname !~ '^pg_temp_' AND "
! 			 "      n.nspname !~ '^pg_toast_temp_' AND "
! 			 "      n.nspname NOT IN ('pg_catalog', 'information_schema', "
! 			 "                        'binary_upgrade', 'pg_toast') AND "
! 			 "      c.oid >= %u::pg_catalog.oid) OR "
! 			 "     (n.nspname = 'pg_catalog' AND "
! 			 "      relname IN ('pg_largeobject'%s) ))), ",
! 			 FirstNormalObjectId,
! 			 (GET_MAJOR_VERSION(old_cluster.major_version) >= 900) ?
! 			 ", 'pg_largeobject_metadata'" : "");
  
  	/*
! 	 * Add a CTE that collects OIDs of toast tables belonging to the tables
! 	 * selected by the regular_heap CTE.  (We have to do this separately
! 	 * because the namespace-name rules above don't work for toast tables.)
  	 */
! 	snprintf(query + strlen(query), sizeof(query) - strlen(query),
! 			 "  toast_heap (reloid) AS ( "
! 			 "  SELECT c.reltoastrelid "
! 			 "  FROM regular_heap JOIN pg_catalog.pg_class c "
! 			 "      ON regular_heap.reloid = c.oid "
! 			 "  WHERE c.reltoastrelid != 0), ");
  
  	/*
! 	 * Add a CTE that collects OIDs of all valid indexes on the previously
! 	 * selected tables.  We can ignore invalid indexes since pg_dump does.
! 	 * Testing indisready is necessary in 9.2, and harmless in earlier/later
! 	 * versions.
  	 */
! 	snprintf(query + strlen(query), sizeof(query) - strlen(query),
! 			 "  all_index (reloid) AS ( "
! 			 "  SELECT indexrelid "
! 			 "  FROM pg_catalog.pg_index "
! 			 "  WHERE indisvalid AND indisready "
! 			 "    AND indrelid IN "
! 			 "        (SELECT reloid FROM regular_heap "
! 			 "         UNION ALL "
! 			 "         SELECT reloid FROM toast_heap)) ");
! 
! 	/*
! 	 * And now we can write the query that retrieves the data we want for each
! 	 * heap and index relation.  Make sure result is sorted by OID.
! 	 */
! 	snprintf(query + strlen(query), sizeof(query) - strlen(query),
  			 "SELECT c.oid, n.nspname, c.relname, "
! 			 "  c.relfilenode, c.reltablespace, %s "
  			 "FROM (SELECT reloid FROM regular_heap "
! 			 "      UNION ALL "
! 			 "      SELECT reloid FROM toast_heap "
! 			 "      UNION ALL "
! 			 "      SELECT reloid FROM all_index) all_rels "
  			 "  JOIN pg_catalog.pg_class c "
! 			 "      ON all_rels.reloid = c.oid "
  			 "  JOIN pg_catalog.pg_namespace n "
! 			 "     ON c.relnamespace = n.oid "
  			 "  LEFT OUTER JOIN pg_catalog.pg_tablespace t "
! 			 "     ON c.reltablespace = t.oid "
  			 "ORDER BY 1;",
! 	/* 9.2 removed the pg_tablespace.spclocation column */
! 			 (GET_MAJOR_VERSION(cluster->major_version) >= 902) ?
! 			 "pg_catalog.pg_tablespace_location(t.oid) AS spclocation" :
! 			 "t.spclocation");
  
  	res = executeQueryOrDie(conn, "%s", query);
  
*************** get_rel_infos(ClusterInfo *cluster, DbIn
*** 453,459 ****
  		curr->relfilenode = atooid(PQgetvalue(res, relnum, i_relfilenode));
  		curr->tblsp_alloc = false;
  
! 		/* Is the tablespace oid non-zero? */
  		if (atooid(PQgetvalue(res, relnum, i_reltablespace)) != 0)
  		{
  			/*
--- 456,462 ----
  		curr->relfilenode = atooid(PQgetvalue(res, relnum, i_relfilenode));
  		curr->tblsp_alloc = false;
  
! 		/* Is the tablespace oid non-default? */
  		if (atooid(PQgetvalue(res, relnum, i_reltablespace)) != 0)
  		{
  			/*
