diff --git a/contrib/pg_upgrade/info.c b/contrib/pg_upgrade/info.c
index a5aa40f..6db6851 100644
--- a/contrib/pg_upgrade/info.c
+++ b/contrib/pg_upgrade/info.c
@@ -313,9 +313,13 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
" ON i.reloid = c.oid"));
PQclear(executeQueryOrDie(conn,
"INSERT INTO info_rels "
- "SELECT reltoastidxid "
- "FROM info_rels i JOIN pg_catalog.pg_class c "
- " ON i.reloid = c.oid"));
+ "SELECT indexrelid "
+ "FROM info_rels i "
+ " JOIN pg_catalog.pg_class c "
+ " ON i.reloid = c.oid "
+ " JOIN pg_catalog.pg_index p "
+ " ON i.reloid = p.indrelid "
+ "WHERE p.indexrelid >= %u ", FirstNormalObjectId));
snprintf(query, sizeof(query),
"SELECT c.oid, n.nspname, c.relname, "
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 81c1be3..e1475e6 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -1745,15 +1745,6 @@
- reltoastidxid
- oid
- pg_class.oid
-
- For a TOAST table, the OID of its index. 0 if not a TOAST table.
-
-
-
-
relhasindex
bool
diff --git a/doc/src/sgml/diskusage.sgml b/doc/src/sgml/diskusage.sgml
index de1d0b4..e12d1c1 100644
--- a/doc/src/sgml/diskusage.sgml
+++ b/doc/src/sgml/diskusage.sgml
@@ -44,7 +44,7 @@
SELECT pg_relation_filepath(oid), relpages FROM pg_class WHERE relname = 'customer';
- pg_relation_filepath | relpages
+ pg_relation_filepath | relpages
----------------------+----------
base/16384/16806 | 60
(1 row)
@@ -65,12 +65,12 @@ FROM pg_class,
FROM pg_class
WHERE relname = 'customer') AS ss
WHERE oid = ss.reltoastrelid OR
- oid = (SELECT reltoastidxid
- FROM pg_class
- WHERE oid = ss.reltoastrelid)
+ oid = (SELECT indexrelid
+ FROM pg_index
+ WHERE indrelid = ss.reltoastrelid)
ORDER BY relname;
- relname | relpages
+ relname | relpages
----------------------+----------
pg_toast_16806 | 0
pg_toast_16806_index | 1
@@ -87,7 +87,7 @@ WHERE c.relname = 'customer' AND
c2.oid = i.indexrelid
ORDER BY c2.relname;
- relname | relpages
+ relname | relpages
----------------------+----------
customer_id_indexdex | 26
@@ -101,7 +101,7 @@ SELECT relname, relpages
FROM pg_class
ORDER BY relpages DESC;
- relname | relpages
+ relname | relpages
----------------------+----------
bigtable | 3290
customer | 3144
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index fc37ceb..be27211 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -1238,7 +1238,7 @@ toast_save_datum(Relation rel, Datum value,
struct varlena * oldexternal, int options)
{
Relation toastrel;
- Relation toastidx;
+ Relation *toastidxs;
HeapTuple toasttup;
TupleDesc toasttupDesc;
Datum t_values[3];
@@ -1257,15 +1257,26 @@ toast_save_datum(Relation rel, Datum value,
char *data_p;
int32 data_todo;
Pointer dval = DatumGetPointer(value);
+ ListCell *lc;
+ int count = 0;
+ int num_indexes;
/*
* Open the toast relation and its index. We can use the index to check
* uniqueness of the OID we assign to the toasted item, even though it has
- * additional columns besides OID.
+ * additional columns besides OID. A toast table can have multiple identical
+ * indexes associated to it.
*/
toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock);
toasttupDesc = toastrel->rd_att;
- toastidx = index_open(toastrel->rd_rel->reltoastidxid, RowExclusiveLock);
+ if (toastrel->rd_indexvalid == 0)
+ RelationGetIndexList(toastrel);
+ num_indexes = list_length(toastrel->rd_indexlist);
+
+ toastidxs = (Relation *) palloc(num_indexes * sizeof(Relation));
+
+ foreach(lc, toastrel->rd_indexlist)
+ toastidxs[count++] = index_open(lfirst_oid(lc), RowExclusiveLock);
/*
* Get the data pointer and length, and compute va_rawsize and va_extsize.
@@ -1327,10 +1338,13 @@ toast_save_datum(Relation rel, Datum value,
*/
if (!OidIsValid(rel->rd_toastoid))
{
- /* normal case: just choose an unused OID */
+ /*
+ * normal case: just choose an unused OID. Simply use the first
+ * index relation.
+ */
toast_pointer.va_valueid =
GetNewOidWithIndex(toastrel,
- RelationGetRelid(toastidx),
+ RelationGetRelid(toastidxs[0]),
(AttrNumber) 1);
}
else
@@ -1384,7 +1398,7 @@ toast_save_datum(Relation rel, Datum value,
{
toast_pointer.va_valueid =
GetNewOidWithIndex(toastrel,
- RelationGetRelid(toastidx),
+ RelationGetRelid(toastidxs[0]),
(AttrNumber) 1);
} while (toastid_valueid_exists(rel->rd_toastoid,
toast_pointer.va_valueid));
@@ -1423,16 +1437,18 @@ toast_save_datum(Relation rel, Datum value,
/*
* Create the index entry. We cheat a little here by not using
* FormIndexDatum: this relies on the knowledge that the index columns
- * are the same as the initial columns of the table.
+ * are the same as the initial columns of the table for all the
+ * indexes.
*
* Note also that there had better not be any user-created index on
* the TOAST table, since we don't bother to update anything else.
*/
- index_insert(toastidx, t_values, t_isnull,
- &(toasttup->t_self),
- toastrel,
- toastidx->rd_index->indisunique ?
- UNIQUE_CHECK_YES : UNIQUE_CHECK_NO);
+ for (count = 0; count < num_indexes; count++)
+ index_insert(toastidxs[count], t_values, t_isnull,
+ &(toasttup->t_self),
+ toastrel,
+ toastidxs[count]->rd_index->indisunique ?
+ UNIQUE_CHECK_YES : UNIQUE_CHECK_NO);
/*
* Free memory
@@ -1449,8 +1465,10 @@ toast_save_datum(Relation rel, Datum value,
/*
* Done - close toast relation
*/
- index_close(toastidx, RowExclusiveLock);
+ for (count = 0; count < num_indexes; count++)
+ index_close(toastidxs[count], RowExclusiveLock);
heap_close(toastrel, RowExclusiveLock);
+ pfree(toastidxs);
/*
* Create the TOAST pointer value that we'll return
@@ -1475,10 +1493,13 @@ toast_delete_datum(Relation rel, Datum value)
struct varlena *attr = (struct varlena *) DatumGetPointer(value);
struct varatt_external toast_pointer;
Relation toastrel;
- Relation toastidx;
+ Relation *toastidxs;
ScanKeyData toastkey;
SysScanDesc toastscan;
HeapTuple toasttup;
+ ListCell *lc;
+ int num_indexes;
+ int count = 0;
if (!VARATT_IS_EXTERNAL(attr))
return;
@@ -1487,10 +1508,20 @@ toast_delete_datum(Relation rel, Datum value)
VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
/*
- * Open the toast relation and its index
+ * Open the toast relation and its indexes
*/
toastrel = heap_open(toast_pointer.va_toastrelid, RowExclusiveLock);
- toastidx = index_open(toastrel->rd_rel->reltoastidxid, RowExclusiveLock);
+ if (toastrel->rd_indexvalid == 0)
+ RelationGetIndexList(toastrel);
+ num_indexes = list_length(toastrel->rd_indexlist);
+ toastidxs = (Relation *) palloc(num_indexes * sizeof(Relation));
+
+ /*
+ * We actually use only the first index but taking a lock on all is
+ * necessary.
+ */
+ foreach(lc, toastrel->rd_indexlist)
+ toastidxs[count++] = index_open(lfirst_oid(lc), RowExclusiveLock);
/*
* Setup a scan key to find chunks with matching va_valueid
@@ -1505,7 +1536,7 @@ toast_delete_datum(Relation rel, Datum value)
* sequence or not, but since we've already locked the index we might as
* well use systable_beginscan_ordered.)
*/
- toastscan = systable_beginscan_ordered(toastrel, toastidx,
+ toastscan = systable_beginscan_ordered(toastrel, toastidxs[0],
SnapshotToast, 1, &toastkey);
while ((toasttup = systable_getnext_ordered(toastscan, ForwardScanDirection)) != NULL)
{
@@ -1519,8 +1550,10 @@ toast_delete_datum(Relation rel, Datum value)
* End scan and close relations
*/
systable_endscan_ordered(toastscan);
- index_close(toastidx, RowExclusiveLock);
+ for (count = 0; count < num_indexes; count++)
+ index_close(toastidxs[count], RowExclusiveLock);
heap_close(toastrel, RowExclusiveLock);
+ pfree(toastidxs);
}
@@ -1537,6 +1570,10 @@ toastrel_valueid_exists(Relation toastrel, Oid valueid)
ScanKeyData toastkey;
SysScanDesc toastscan;
+ /* Ensure that the list of indexes of toast relation is computed */
+ if (toastrel->rd_indexvalid == 0)
+ RelationGetIndexList(toastrel);
+
/*
* Setup a scan key to find chunks with matching va_valueid
*/
@@ -1546,9 +1583,10 @@ toastrel_valueid_exists(Relation toastrel, Oid valueid)
ObjectIdGetDatum(valueid));
/*
- * Is there any such chunk?
+ * Is there any such chunk? Use the first index available for scan
*/
- toastscan = systable_beginscan(toastrel, toastrel->rd_rel->reltoastidxid,
+ toastscan = systable_beginscan(toastrel,
+ linitial_oid(toastrel->rd_indexlist),
true, SnapshotToast, 1, &toastkey);
if (systable_getnext(toastscan) != NULL)
@@ -1592,7 +1630,7 @@ static struct varlena *
toast_fetch_datum(struct varlena * attr)
{
Relation toastrel;
- Relation toastidx;
+ Relation *toastidxs;
ScanKeyData toastkey;
SysScanDesc toastscan;
HeapTuple ttup;
@@ -1607,6 +1645,9 @@ toast_fetch_datum(struct varlena * attr)
bool isnull;
char *chunkdata;
int32 chunksize;
+ ListCell *lc;
+ int num_indexes;
+ int count = 0;
/* Must copy to access aligned fields */
VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
@@ -1622,11 +1663,18 @@ toast_fetch_datum(struct varlena * attr)
SET_VARSIZE(result, ressize + VARHDRSZ);
/*
- * Open the toast relation and its index
+ * Open the toast relation and its indexes
*/
toastrel = heap_open(toast_pointer.va_toastrelid, AccessShareLock);
toasttupDesc = toastrel->rd_att;
- toastidx = index_open(toastrel->rd_rel->reltoastidxid, AccessShareLock);
+ if (toastrel->rd_indexvalid == 0)
+ RelationGetIndexList(toastrel);
+ num_indexes = list_length(toastrel->rd_indexlist);
+
+ toastidxs = (Relation *) palloc(num_indexes * sizeof(Relation));
+
+ foreach(lc, toastrel->rd_indexlist)
+ toastidxs[count++] = index_open(lfirst_oid(lc), AccessShareLock);
/*
* Setup a scan key to fetch from the index by va_valueid
@@ -1645,7 +1693,7 @@ toast_fetch_datum(struct varlena * attr)
*/
nextidx = 0;
- toastscan = systable_beginscan_ordered(toastrel, toastidx,
+ toastscan = systable_beginscan_ordered(toastrel, toastidxs[0],
SnapshotToast, 1, &toastkey);
while ((ttup = systable_getnext_ordered(toastscan, ForwardScanDirection)) != NULL)
{
@@ -1734,8 +1782,10 @@ toast_fetch_datum(struct varlena * attr)
* End scan and close relations
*/
systable_endscan_ordered(toastscan);
- index_close(toastidx, AccessShareLock);
+ for (count = 0; count < num_indexes; count++)
+ index_close(toastidxs[count], AccessShareLock);
heap_close(toastrel, AccessShareLock);
+ pfree(toastidxs);
return result;
}
@@ -1751,7 +1801,7 @@ static struct varlena *
toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length)
{
Relation toastrel;
- Relation toastidx;
+ Relation *toastidxs;
ScanKeyData toastkey[3];
int nscankeys;
SysScanDesc toastscan;
@@ -1774,6 +1824,9 @@ toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length)
int32 chunksize;
int32 chcpystrt;
int32 chcpyend;
+ int num_indexes;
+ int count = 0;
+ ListCell *lc;
Assert(VARATT_IS_EXTERNAL(attr));
@@ -1816,11 +1869,18 @@ toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length)
endoffset = (sliceoffset + length - 1) % TOAST_MAX_CHUNK_SIZE;
/*
- * Open the toast relation and its index
+ * Open the toast relation and its indexes
*/
toastrel = heap_open(toast_pointer.va_toastrelid, AccessShareLock);
toasttupDesc = toastrel->rd_att;
- toastidx = index_open(toastrel->rd_rel->reltoastidxid, AccessShareLock);
+ if (toastrel->rd_indexvalid == 0)
+ RelationGetIndexList(toastrel);
+ num_indexes = list_length(toastrel->rd_indexlist);
+
+ toastidxs = (Relation *) palloc(num_indexes * sizeof(Relation));
+
+ foreach(lc, toastrel->rd_indexlist)
+ toastidxs[count++] = index_open(lfirst_oid(lc), AccessShareLock);
/*
* Setup a scan key to fetch from the index. This is either two keys or
@@ -1861,7 +1921,7 @@ toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length)
* The index is on (valueid, chunkidx) so they will come in order
*/
nextidx = startchunk;
- toastscan = systable_beginscan_ordered(toastrel, toastidx,
+ toastscan = systable_beginscan_ordered(toastrel, toastidxs[0],
SnapshotToast, nscankeys, toastkey);
while ((ttup = systable_getnext_ordered(toastscan, ForwardScanDirection)) != NULL)
{
@@ -1958,8 +2018,10 @@ toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length)
* End scan and close relations
*/
systable_endscan_ordered(toastscan);
- index_close(toastidx, AccessShareLock);
+ for (count = 0; count < num_indexes; count++)
+ index_close(toastidxs[count], AccessShareLock);
heap_close(toastrel, AccessShareLock);
+ pfree(toastidxs);
return result;
}
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 0ecfc78..043b279 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -767,7 +767,6 @@ InsertPgClassTuple(Relation pg_class_desc,
values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid);
- values[Anum_pg_class_reltoastidxid - 1] = ObjectIdGetDatum(rd_rel->reltoastidxid);
values[Anum_pg_class_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 9b33929..0f3b45f 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -103,7 +103,7 @@ static void UpdateIndexRelation(Oid indexoid, Oid heapoid,
bool isvalid);
static void index_update_stats(Relation rel,
bool hasindex, bool isprimary,
- Oid reltoastidxid, double reltuples);
+ double reltuples);
static void IndexCheckExclusion(Relation heapRelation,
Relation indexRelation,
IndexInfo *indexInfo);
@@ -1077,7 +1077,6 @@ index_create(Relation heapRelation,
index_update_stats(heapRelation,
true,
isprimary,
- InvalidOid,
-1.0);
/* Make the above update visible */
CommandCounterIncrement();
@@ -1256,7 +1255,6 @@ index_constraint_create(Relation heapRelation,
index_update_stats(heapRelation,
true,
true,
- InvalidOid,
-1.0);
/*
@@ -1763,8 +1761,6 @@ FormIndexDatum(IndexInfo *indexInfo,
*
* hasindex: set relhasindex to this value
* isprimary: if true, set relhaspkey true; else no change
- * reltoastidxid: if not InvalidOid, set reltoastidxid to this value;
- * else no change
* reltuples: if >= 0, set reltuples to this value; else no change
*
* If reltuples >= 0, relpages and relallvisible are also updated (using
@@ -1780,8 +1776,9 @@ FormIndexDatum(IndexInfo *indexInfo,
*/
static void
index_update_stats(Relation rel,
- bool hasindex, bool isprimary,
- Oid reltoastidxid, double reltuples)
+ bool hasindex,
+ bool isprimary,
+ double reltuples)
{
Oid relid = RelationGetRelid(rel);
Relation pg_class;
@@ -1875,15 +1872,6 @@ index_update_stats(Relation rel,
dirty = true;
}
}
- if (OidIsValid(reltoastidxid))
- {
- Assert(rd_rel->relkind == RELKIND_TOASTVALUE);
- if (rd_rel->reltoastidxid != reltoastidxid)
- {
- rd_rel->reltoastidxid = reltoastidxid;
- dirty = true;
- }
- }
if (reltuples >= 0)
{
@@ -2071,14 +2059,11 @@ index_build(Relation heapRelation,
index_update_stats(heapRelation,
true,
isprimary,
- (heapRelation->rd_rel->relkind == RELKIND_TOASTVALUE) ?
- RelationGetRelid(indexRelation) : InvalidOid,
stats->heap_tuples);
index_update_stats(indexRelation,
false,
false,
- InvalidOid,
stats->index_tuples);
/* Make the updated catalog row versions visible */
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index f727acd..01d58d9 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -473,16 +473,16 @@ CREATE VIEW pg_statio_all_tables AS
pg_stat_get_blocks_fetched(T.oid) -
pg_stat_get_blocks_hit(T.oid) AS toast_blks_read,
pg_stat_get_blocks_hit(T.oid) AS toast_blks_hit,
- pg_stat_get_blocks_fetched(X.oid) -
- pg_stat_get_blocks_hit(X.oid) AS tidx_blks_read,
- pg_stat_get_blocks_hit(X.oid) AS tidx_blks_hit
+ pg_stat_get_blocks_fetched(X.indrelid) -
+ pg_stat_get_blocks_hit(X.indrelid) AS tidx_blks_read,
+ pg_stat_get_blocks_hit(X.indrelid) AS tidx_blks_hit
FROM pg_class C LEFT JOIN
pg_index I ON C.oid = I.indrelid LEFT JOIN
pg_class T ON C.reltoastrelid = T.oid LEFT JOIN
- pg_class X ON T.reltoastidxid = X.oid
+ pg_index X ON T.oid = X.indrelid
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE C.relkind IN ('r', 't', 'm')
- GROUP BY C.oid, N.nspname, C.relname, T.oid, X.oid;
+ GROUP BY C.oid, N.nspname, C.relname, T.oid, X.indrelid;
CREATE VIEW pg_statio_sys_tables AS
SELECT * FROM pg_statio_all_tables
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 8ab8c17..c5f6a0a 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -1169,8 +1169,6 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
swaptemp = relform1->reltoastrelid;
relform1->reltoastrelid = relform2->reltoastrelid;
relform2->reltoastrelid = swaptemp;
-
- /* we should NOT swap reltoastidxid */
}
}
else
@@ -1379,18 +1377,53 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
}
/*
- * If we're swapping two toast tables by content, do the same for their
- * indexes.
+ * If we're swapping two toast tables by content, do the same for all of
+ * their indexes. The swap can actually be safely done only if all the indexes
+ * have valid Oids.
*/
if (swap_toast_by_content &&
- relform1->reltoastidxid && relform2->reltoastidxid)
- swap_relation_files(relform1->reltoastidxid,
- relform2->reltoastidxid,
- target_is_pg_class,
- swap_toast_by_content,
- InvalidTransactionId,
- InvalidMultiXactId,
- mapped_tables);
+ relform1->reltoastrelid &&
+ relform2->reltoastrelid)
+ {
+ Relation toastRel1, toastRel2;
+
+ /* Open relations */
+ toastRel1 = heap_open(relform1->reltoastrelid, RowExclusiveLock);
+ toastRel2 = heap_open(relform2->reltoastrelid, RowExclusiveLock);
+
+ /* Obtain index list if necessary */
+ if (toastRel1->rd_indexvalid == 0)
+ RelationGetIndexList(toastRel1);
+ if (toastRel2->rd_indexvalid == 0)
+ RelationGetIndexList(toastRel2);
+
+ /* Check if the swap is possible for all the toast indexes */
+ if (!list_member_oid(toastRel1->rd_indexlist, InvalidOid) &&
+ !list_member_oid(toastRel2->rd_indexlist, InvalidOid) &&
+ list_length(toastRel1->rd_indexlist) == list_length(toastRel2->rd_indexlist))
+ {
+ ListCell *lc1, *lc2;
+
+ /* Now swap each couple */
+ lc2 = list_head(toastRel2->rd_indexlist);
+ foreach(lc1, toastRel1->rd_indexlist)
+ {
+ Oid indexOid1 = lfirst_oid(lc1);
+ Oid indexOid2 = lfirst_oid(lc2);
+ swap_relation_files(indexOid1,
+ indexOid2,
+ target_is_pg_class,
+ swap_toast_by_content,
+ InvalidTransactionId,
+ InvalidMultiXactId,
+ mapped_tables);
+ lc2 = lnext(lc2);
+ }
+ }
+
+ heap_close(toastRel1, RowExclusiveLock);
+ heap_close(toastRel2, RowExclusiveLock);
+ }
/* Clean up. */
heap_freetuple(reltup1);
@@ -1514,12 +1547,14 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
if (OidIsValid(newrel->rd_rel->reltoastrelid))
{
Relation toastrel;
- Oid toastidx;
char NewToastName[NAMEDATALEN];
+ ListCell *lc;
+ int count = 0;
toastrel = relation_open(newrel->rd_rel->reltoastrelid,
AccessShareLock);
- toastidx = toastrel->rd_rel->reltoastidxid;
+ if (toastrel->rd_indexvalid == 0)
+ RelationGetIndexList(toastrel);
relation_close(toastrel, AccessShareLock);
/* rename the toast table ... */
@@ -1528,11 +1563,23 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
RenameRelationInternal(newrel->rd_rel->reltoastrelid,
NewToastName);
- /* ... and its index too */
- snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u_index",
- OIDOldHeap);
- RenameRelationInternal(toastidx,
- NewToastName);
+ /* ... and its indexes too */
+ foreach(lc, toastrel->rd_indexlist)
+ {
+ /*
+ * The first index keeps the former toast name and the
+ * following entries are thought as being concurrent indexes.
+ */
+ if (count == 0)
+ snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u_index",
+ OIDOldHeap);
+ else
+ snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u_index_cct%d",
+ OIDOldHeap, count);
+ RenameRelationInternal(lfirst_oid(lc),
+ NewToastName);
+ count++;
+ }
}
relation_close(newrel, NoLock);
}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 2a55e02..0d6f5c0 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8678,7 +8678,6 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
Relation rel;
Oid oldTableSpace;
Oid reltoastrelid;
- Oid reltoastidxid;
Oid newrelfilenode;
RelFileNode newrnode;
SMgrRelation dstrel;
@@ -8686,6 +8685,8 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
HeapTuple tuple;
Form_pg_class rd_rel;
ForkNumber forkNum;
+ List *reltoastidxids;
+ ListCell *lc;
/*
* Need lock here in case we are recursing to toast table or index
@@ -8729,7 +8730,8 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
errmsg("cannot move temporary tables of other sessions")));
reltoastrelid = rel->rd_rel->reltoastrelid;
- reltoastidxid = rel->rd_rel->reltoastidxid;
+ RelationGetIndexList(rel);
+ reltoastidxids = list_copy(rel->rd_indexlist);
/* Get a modifiable copy of the relation's pg_class row */
pg_class = heap_open(RelationRelationId, RowExclusiveLock);
@@ -8808,8 +8810,15 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
/* Move associated toast relation and/or index, too */
if (OidIsValid(reltoastrelid))
ATExecSetTableSpace(reltoastrelid, newTableSpace, lockmode);
- if (OidIsValid(reltoastidxid))
- ATExecSetTableSpace(reltoastidxid, newTableSpace, lockmode);
+ foreach(lc, reltoastidxids)
+ {
+ Oid idxid = lfirst_oid(lc);
+ if (OidIsValid(idxid))
+ ATExecSetTableSpace(idxid, newTableSpace, lockmode);
+ }
+
+ /* Clean up */
+ list_free(reltoastidxids);
}
/*
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 8963266..3dd2fda 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -577,8 +577,8 @@ DefineQueryRewrite(char *rulename,
/*
* Fix pg_class entry to look like a normal view's, including setting
- * the correct relkind and removal of reltoastrelid/reltoastidxid of
- * the toast table we potentially removed above.
+ * the correct relkind and removal of reltoastrelid of the toast table
+ * we potentially removed above.
*/
classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(event_relid));
if (!HeapTupleIsValid(classTup))
@@ -590,7 +590,6 @@ DefineQueryRewrite(char *rulename,
classForm->reltuples = 0;
classForm->relallvisible = 0;
classForm->reltoastrelid = InvalidOid;
- classForm->reltoastidxid = InvalidOid;
classForm->relhasindex = false;
classForm->relkind = RELKIND_VIEW;
classForm->relhasoids = false;
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index d589d26..11921ac 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -332,7 +332,7 @@ pg_relation_size(PG_FUNCTION_ARGS)
}
/*
- * Calculate total on-disk size of a TOAST relation, including its index.
+ * Calculate total on-disk size of a TOAST relation, including its indexes.
* Must not be applied to non-TOAST relations.
*/
static int64
@@ -340,8 +340,8 @@ calculate_toast_table_size(Oid toastrelid)
{
int64 size = 0;
Relation toastRel;
- Relation toastIdxRel;
ForkNumber forkNum;
+ ListCell *lc;
toastRel = relation_open(toastrelid, AccessShareLock);
@@ -351,12 +351,21 @@ calculate_toast_table_size(Oid toastrelid)
toastRel->rd_backend, forkNum);
/* toast index size, including FSM and VM size */
- toastIdxRel = relation_open(toastRel->rd_rel->reltoastidxid, AccessShareLock);
- for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
- size += calculate_relation_size(&(toastIdxRel->rd_node),
- toastIdxRel->rd_backend, forkNum);
+ if (toastRel->rd_indexvalid == 0)
+ RelationGetIndexList(toastRel);
- relation_close(toastIdxRel, AccessShareLock);
+ /* Size is evaluated based on the first index available */
+ foreach(lc, toastRel->rd_indexlist)
+ {
+ Relation toastIdxRel;
+ toastIdxRel = relation_open(lfirst_oid(lc),
+ AccessShareLock);
+ for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
+ size += calculate_relation_size(&(toastIdxRel->rd_node),
+ toastIdxRel->rd_backend, forkNum);
+
+ relation_close(toastIdxRel, AccessShareLock);
+ }
relation_close(toastRel, AccessShareLock);
return size;
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index e6c85ac..f15e6a2 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -2669,10 +2669,9 @@ binary_upgrade_set_pg_class_oids(Archive *fout,
PQExpBuffer upgrade_query = createPQExpBuffer();
PGresult *upgrade_res;
Oid pg_class_reltoastrelid;
- Oid pg_class_reltoastidxid;
appendPQExpBuffer(upgrade_query,
- "SELECT c.reltoastrelid, t.reltoastidxid "
+ "SELECT c.reltoastrelid "
"FROM pg_catalog.pg_class c LEFT JOIN "
"pg_catalog.pg_class t ON (c.reltoastrelid = t.oid) "
"WHERE c.oid = '%u'::pg_catalog.oid;",
@@ -2681,7 +2680,6 @@ binary_upgrade_set_pg_class_oids(Archive *fout,
upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
pg_class_reltoastrelid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "reltoastrelid")));
- pg_class_reltoastidxid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "reltoastidxid")));
appendPQExpBuffer(upgrade_buffer,
"\n-- For binary upgrade, must preserve pg_class oids\n");
@@ -2706,11 +2704,6 @@ binary_upgrade_set_pg_class_oids(Archive *fout,
appendPQExpBuffer(upgrade_buffer,
"SELECT binary_upgrade.set_next_toast_pg_class_oid('%u'::pg_catalog.oid);\n",
pg_class_reltoastrelid);
-
- /* every toast table has an index */
- appendPQExpBuffer(upgrade_buffer,
- "SELECT binary_upgrade.set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n",
- pg_class_reltoastidxid);
}
}
else
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index ab91ab0..7d137b4 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201302181
+#define CATALOG_VERSION_NO 20130219
#endif
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index fd97141..ea46e38 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -48,7 +48,6 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83) BKI_SCHEMA_MACRO
int32 relallvisible; /* # of all-visible blocks (not always
* up-to-date) */
Oid reltoastrelid; /* OID of toast table; 0 if none */
- Oid reltoastidxid; /* if toast table, OID of chunk_id index */
bool relhasindex; /* T if has (or has had) any indexes */
bool relisshared; /* T if shared across databases */
char relpersistence; /* see RELPERSISTENCE_xxx constants below */
@@ -93,7 +92,7 @@ typedef FormData_pg_class *Form_pg_class;
* ----------------
*/
-#define Natts_pg_class 28
+#define Natts_pg_class 27
#define Anum_pg_class_relname 1
#define Anum_pg_class_relnamespace 2
#define Anum_pg_class_reltype 3
@@ -106,22 +105,21 @@ typedef FormData_pg_class *Form_pg_class;
#define Anum_pg_class_reltuples 10
#define Anum_pg_class_relallvisible 11
#define Anum_pg_class_reltoastrelid 12
-#define Anum_pg_class_reltoastidxid 13
-#define Anum_pg_class_relhasindex 14
-#define Anum_pg_class_relisshared 15
-#define Anum_pg_class_relpersistence 16
-#define Anum_pg_class_relkind 17
-#define Anum_pg_class_relnatts 18
-#define Anum_pg_class_relchecks 19
-#define Anum_pg_class_relhasoids 20
-#define Anum_pg_class_relhaspkey 21
-#define Anum_pg_class_relhasrules 22
-#define Anum_pg_class_relhastriggers 23
-#define Anum_pg_class_relhassubclass 24
-#define Anum_pg_class_relfrozenxid 25
-#define Anum_pg_class_relminmxid 26
-#define Anum_pg_class_relacl 27
-#define Anum_pg_class_reloptions 28
+#define Anum_pg_class_relhasindex 13
+#define Anum_pg_class_relisshared 14
+#define Anum_pg_class_relpersistence 15
+#define Anum_pg_class_relkind 16
+#define Anum_pg_class_relnatts 17
+#define Anum_pg_class_relchecks 18
+#define Anum_pg_class_relhasoids 19
+#define Anum_pg_class_relhaspkey 20
+#define Anum_pg_class_relhasrules 21
+#define Anum_pg_class_relhastriggers 22
+#define Anum_pg_class_relhassubclass 23
+#define Anum_pg_class_relfrozenxid 24
+#define Anum_pg_class_relminmxid 25
+#define Anum_pg_class_relacl 26
+#define Anum_pg_class_reloptions 27
/* ----------------
* initial contents of pg_class
@@ -136,13 +134,13 @@ typedef FormData_pg_class *Form_pg_class;
* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId;
* similarly, "1" in relminmxid stands for FirstMultiXactId
*/
-DATA(insert OID = 1247 ( pg_type PGNSP 71 0 PGUID 0 0 0 0 0 0 0 0 f f p r 30 0 t f f f f 3 1 _null_ _null_ ));
+DATA(insert OID = 1247 ( pg_type PGNSP 71 0 PGUID 0 0 0 0 0 0 0 f f p r 30 0 t f f f f 3 1 _null_ _null_ ));
DESCR("");
-DATA(insert OID = 1249 ( pg_attribute PGNSP 75 0 PGUID 0 0 0 0 0 0 0 0 f f p r 21 0 f f f f f 3 1 _null_ _null_ ));
+DATA(insert OID = 1249 ( pg_attribute PGNSP 75 0 PGUID 0 0 0 0 0 0 0 f f p r 21 0 f f f f f 3 1 _null_ _null_ ));
DESCR("");
-DATA(insert OID = 1255 ( pg_proc PGNSP 81 0 PGUID 0 0 0 0 0 0 0 0 f f p r 27 0 t f f f f 3 1 _null_ _null_ ));
+DATA(insert OID = 1255 ( pg_proc PGNSP 81 0 PGUID 0 0 0 0 0 0 0 f f p r 27 0 t f f f f 3 1 _null_ _null_ ));
DESCR("");
-DATA(insert OID = 1259 ( pg_class PGNSP 83 0 PGUID 0 0 0 0 0 0 0 0 f f p r 28 0 t f f f f 3 1 _null_ _null_ ));
+DATA(insert OID = 1259 ( pg_class PGNSP 83 0 PGUID 0 0 0 0 0 0 0 f f p r 27 0 t f f f f 3 1 _null_ _null_ ));
DESCR("");
diff --git a/src/test/regress/expected/oidjoins.out b/src/test/regress/expected/oidjoins.out
index 06ed856..6c5cb5a 100644
--- a/src/test/regress/expected/oidjoins.out
+++ b/src/test/regress/expected/oidjoins.out
@@ -353,14 +353,6 @@ WHERE reltoastrelid != 0 AND
------+---------------
(0 rows)
-SELECT ctid, reltoastidxid
-FROM pg_catalog.pg_class fk
-WHERE reltoastidxid != 0 AND
- NOT EXISTS(SELECT 1 FROM pg_catalog.pg_class pk WHERE pk.oid = fk.reltoastidxid);
- ctid | reltoastidxid
-------+---------------
-(0 rows)
-
SELECT ctid, collnamespace
FROM pg_catalog.pg_collation fk
WHERE collnamespace != 0 AND
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index a4ecfd2..7a68fb9 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1852,15 +1852,15 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
| (sum(pg_stat_get_blocks_hit(i.indexrelid)))::bigint AS idx_blks_hit, +
| (pg_stat_get_blocks_fetched(t.oid) - pg_stat_get_blocks_hit(t.oid)) AS toast_blks_read, +
| pg_stat_get_blocks_hit(t.oid) AS toast_blks_hit, +
- | (pg_stat_get_blocks_fetched(x.oid) - pg_stat_get_blocks_hit(x.oid)) AS tidx_blks_read, +
- | pg_stat_get_blocks_hit(x.oid) AS tidx_blks_hit +
+ | (pg_stat_get_blocks_fetched(x.indrelid) - pg_stat_get_blocks_hit(x.indrelid)) AS tidx_blks_read, +
+ | pg_stat_get_blocks_hit(x.indrelid) AS tidx_blks_hit +
| FROM ((((pg_class c +
| LEFT JOIN pg_index i ON ((c.oid = i.indrelid))) +
| LEFT JOIN pg_class t ON ((c.reltoastrelid = t.oid))) +
- | LEFT JOIN pg_class x ON ((t.reltoastidxid = x.oid))) +
+ | LEFT JOIN pg_index x ON ((t.oid = x.indrelid))) +
| LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) +
| WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"])) +
- | GROUP BY c.oid, n.nspname, c.relname, t.oid, x.oid;
+ | GROUP BY c.oid, n.nspname, c.relname, t.oid, x.indrelid;
pg_statio_sys_indexes | SELECT pg_statio_all_indexes.relid, +
| pg_statio_all_indexes.indexrelid, +
| pg_statio_all_indexes.schemaname, +
@@ -2347,11 +2347,11 @@ select xmin, * from fooview; -- fail, views don't have such a column
ERROR: column "xmin" does not exist
LINE 1: select xmin, * from fooview;
^
-select reltoastrelid, reltoastidxid, relkind, relfrozenxid
+select reltoastrelid, relkind, relfrozenxid
from pg_class where oid = 'fooview'::regclass;
- reltoastrelid | reltoastidxid | relkind | relfrozenxid
----------------+---------------+---------+--------------
- 0 | 0 | v | 0
+ reltoastrelid | relkind | relfrozenxid
+---------------+---------+--------------
+ 0 | v | 0
(1 row)
drop view fooview;
diff --git a/src/test/regress/sql/oidjoins.sql b/src/test/regress/sql/oidjoins.sql
index 6422da2..9b91683 100644
--- a/src/test/regress/sql/oidjoins.sql
+++ b/src/test/regress/sql/oidjoins.sql
@@ -177,10 +177,6 @@ SELECT ctid, reltoastrelid
FROM pg_catalog.pg_class fk
WHERE reltoastrelid != 0 AND
NOT EXISTS(SELECT 1 FROM pg_catalog.pg_class pk WHERE pk.oid = fk.reltoastrelid);
-SELECT ctid, reltoastidxid
-FROM pg_catalog.pg_class fk
-WHERE reltoastidxid != 0 AND
- NOT EXISTS(SELECT 1 FROM pg_catalog.pg_class pk WHERE pk.oid = fk.reltoastidxid);
SELECT ctid, collnamespace
FROM pg_catalog.pg_collation fk
WHERE collnamespace != 0 AND
diff --git a/src/test/regress/sql/rules.sql b/src/test/regress/sql/rules.sql
index 4f49a0d..2d24961 100644
--- a/src/test/regress/sql/rules.sql
+++ b/src/test/regress/sql/rules.sql
@@ -872,7 +872,7 @@ create rule "_RETURN" as on select to fooview do instead
select * from fooview;
select xmin, * from fooview; -- fail, views don't have such a column
-select reltoastrelid, reltoastidxid, relkind, relfrozenxid
+select reltoastrelid, relkind, relfrozenxid
from pg_class where oid = 'fooview'::regclass;
drop view fooview;
diff --git a/src/tools/findoidjoins/README b/src/tools/findoidjoins/README
index b5c4d1b..e3e8a2a 100644
--- a/src/tools/findoidjoins/README
+++ b/src/tools/findoidjoins/README
@@ -86,7 +86,6 @@ Join pg_catalog.pg_class.relowner => pg_catalog.pg_authid.oid
Join pg_catalog.pg_class.relam => pg_catalog.pg_am.oid
Join pg_catalog.pg_class.reltablespace => pg_catalog.pg_tablespace.oid
Join pg_catalog.pg_class.reltoastrelid => pg_catalog.pg_class.oid
-Join pg_catalog.pg_class.reltoastidxid => pg_catalog.pg_class.oid
Join pg_catalog.pg_collation.collnamespace => pg_catalog.pg_namespace.oid
Join pg_catalog.pg_collation.collowner => pg_catalog.pg_authid.oid
Join pg_catalog.pg_constraint.connamespace => pg_catalog.pg_namespace.oid