diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/access/heap/tuptoaster.c | 225 | ||||
-rw-r--r-- | src/backend/catalog/heap.c | 1 | ||||
-rw-r--r-- | src/backend/catalog/index.c | 23 | ||||
-rw-r--r-- | src/backend/catalog/system_views.sql | 10 | ||||
-rw-r--r-- | src/backend/commands/cluster.c | 34 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 20 | ||||
-rw-r--r-- | src/backend/rewrite/rewriteDefine.c | 5 | ||||
-rw-r--r-- | src/backend/utils/adt/dbsize.c | 24 |
8 files changed, 260 insertions, 82 deletions
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index 445a7ed9fbc..675bfcc81fe 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -78,6 +78,12 @@ static bool toastid_valueid_exists(Oid toastrelid, Oid valueid); static struct varlena *toast_fetch_datum(struct varlena * attr); static struct varlena *toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length); +static int toast_open_indexes(Relation toastrel, + LOCKMODE lock, + Relation **toastidxs, + int *num_indexes); +static void toast_close_indexes(Relation *toastidxs, int num_indexes, + LOCKMODE lock); /* ---------- @@ -1287,6 +1293,39 @@ toast_compress_datum(Datum value) /* ---------- + * toast_get_valid_index + * + * Get OID of valid index associated to given toast relation. A toast + * relation can have only one valid index at the same time. + */ +Oid +toast_get_valid_index(Oid toastoid, LOCKMODE lock) +{ + int num_indexes; + int validIndex; + Oid validIndexOid; + Relation *toastidxs; + Relation toastrel; + + /* Open the toast relation */ + toastrel = heap_open(toastoid, lock); + + /* Look for the valid index of the toast relation */ + validIndex = toast_open_indexes(toastrel, + lock, + &toastidxs, + &num_indexes); + validIndexOid = RelationGetRelid(toastidxs[validIndex]); + + /* Close the toast relation and all its indexes */ + toast_close_indexes(toastidxs, num_indexes, lock); + heap_close(toastrel, lock); + + return validIndexOid; +} + + +/* ---------- * toast_save_datum - * * Save one single datum into the secondary relation and return @@ -1303,7 +1342,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]; @@ -1322,17 +1361,24 @@ toast_save_datum(Relation rel, Datum value, char *data_p; int32 data_todo; Pointer dval = DatumGetPointer(value); + int num_indexes; + int validIndex; Assert(!VARATT_IS_EXTERNAL(value)); /* - * Open the toast relation and its index. We can use the index to check + * Open the toast relation and its indexes. 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. */ toastrel = heap_open(rel->rd_rel->reltoastrelid, RowExclusiveLock); toasttupDesc = toastrel->rd_att; - toastidx = index_open(toastrel->rd_rel->reltoastidxid, RowExclusiveLock); + + /* Open all the toast indexes and look for the valid */ + validIndex = toast_open_indexes(toastrel, + RowExclusiveLock, + &toastidxs, + &num_indexes); /* * Get the data pointer and length, and compute va_rawsize and va_extsize. @@ -1397,7 +1443,7 @@ toast_save_datum(Relation rel, Datum value, /* normal case: just choose an unused OID */ toast_pointer.va_valueid = GetNewOidWithIndex(toastrel, - RelationGetRelid(toastidx), + RelationGetRelid(toastidxs[validIndex]), (AttrNumber) 1); } else @@ -1451,7 +1497,7 @@ toast_save_datum(Relation rel, Datum value, { toast_pointer.va_valueid = GetNewOidWithIndex(toastrel, - RelationGetRelid(toastidx), + RelationGetRelid(toastidxs[validIndex]), (AttrNumber) 1); } while (toastid_valueid_exists(rel->rd_toastoid, toast_pointer.va_valueid)); @@ -1472,6 +1518,8 @@ toast_save_datum(Relation rel, Datum value, */ while (data_todo > 0) { + int i; + /* * Calculate the size of this chunk */ @@ -1490,16 +1538,22 @@ 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 (i = 0; i < num_indexes; i++) + { + /* Only index relations marked as ready can updated */ + if (IndexIsReady(toastidxs[i]->rd_index)) + index_insert(toastidxs[i], t_values, t_isnull, + &(toasttup->t_self), + toastrel, + toastidxs[i]->rd_index->indisunique ? + UNIQUE_CHECK_YES : UNIQUE_CHECK_NO); + } /* * Free memory @@ -1514,9 +1568,9 @@ toast_save_datum(Relation rel, Datum value, } /* - * Done - close toast relation + * Done - close toast relation and its indexes */ - index_close(toastidx, RowExclusiveLock); + toast_close_indexes(toastidxs, num_indexes, RowExclusiveLock); heap_close(toastrel, RowExclusiveLock); /* @@ -1542,10 +1596,12 @@ 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; + int num_indexes; + int validIndex; if (!VARATT_IS_EXTERNAL_ONDISK(attr)) return; @@ -1554,10 +1610,15 @@ 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); + + /* Fetch valid relation used for process */ + validIndex = toast_open_indexes(toastrel, + RowExclusiveLock, + &toastidxs, + &num_indexes); /* * Setup a scan key to find chunks with matching va_valueid @@ -1572,7 +1633,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[validIndex], SnapshotToast, 1, &toastkey); while ((toasttup = systable_getnext_ordered(toastscan, ForwardScanDirection)) != NULL) { @@ -1586,7 +1647,7 @@ toast_delete_datum(Relation rel, Datum value) * End scan and close relations */ systable_endscan_ordered(toastscan); - index_close(toastidx, RowExclusiveLock); + toast_close_indexes(toastidxs, num_indexes, RowExclusiveLock); heap_close(toastrel, RowExclusiveLock); } @@ -1603,6 +1664,15 @@ toastrel_valueid_exists(Relation toastrel, Oid valueid) bool result = false; ScanKeyData toastkey; SysScanDesc toastscan; + int num_indexes; + int validIndex; + Relation *toastidxs; + + /* Fetch a valid index relation */ + validIndex = toast_open_indexes(toastrel, + RowExclusiveLock, + &toastidxs, + &num_indexes); /* * Setup a scan key to find chunks with matching va_valueid @@ -1615,14 +1685,18 @@ toastrel_valueid_exists(Relation toastrel, Oid valueid) /* * Is there any such chunk? */ - toastscan = systable_beginscan(toastrel, toastrel->rd_rel->reltoastidxid, - true, SnapshotToast, 1, &toastkey); + toastscan = systable_beginscan(toastrel, + RelationGetRelid(toastidxs[validIndex]), + true, SnapshotToast, 1, &toastkey); if (systable_getnext(toastscan) != NULL) result = true; systable_endscan(toastscan); + /* Clean up */ + toast_close_indexes(toastidxs, num_indexes, RowExclusiveLock); + return result; } @@ -1659,7 +1733,7 @@ static struct varlena * toast_fetch_datum(struct varlena * attr) { Relation toastrel; - Relation toastidx; + Relation *toastidxs; ScanKeyData toastkey; SysScanDesc toastscan; HeapTuple ttup; @@ -1674,6 +1748,8 @@ toast_fetch_datum(struct varlena * attr) bool isnull; char *chunkdata; int32 chunksize; + int num_indexes; + int validIndex; if (VARATT_IS_EXTERNAL_INDIRECT(attr)) elog(ERROR, "shouldn't be called for indirect tuples"); @@ -1692,11 +1768,16 @@ 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); + + /* Look for the valid index of the toast relation */ + validIndex = toast_open_indexes(toastrel, + AccessShareLock, + &toastidxs, + &num_indexes); /* * Setup a scan key to fetch from the index by va_valueid @@ -1715,7 +1796,7 @@ toast_fetch_datum(struct varlena * attr) */ nextidx = 0; - toastscan = systable_beginscan_ordered(toastrel, toastidx, + toastscan = systable_beginscan_ordered(toastrel, toastidxs[validIndex], SnapshotToast, 1, &toastkey); while ((ttup = systable_getnext_ordered(toastscan, ForwardScanDirection)) != NULL) { @@ -1804,7 +1885,7 @@ toast_fetch_datum(struct varlena * attr) * End scan and close relations */ systable_endscan_ordered(toastscan); - index_close(toastidx, AccessShareLock); + toast_close_indexes(toastidxs, num_indexes, AccessShareLock); heap_close(toastrel, AccessShareLock); return result; @@ -1821,7 +1902,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; @@ -1844,6 +1925,8 @@ toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length) int32 chunksize; int32 chcpystrt; int32 chcpyend; + int num_indexes; + int validIndex; Assert(VARATT_IS_EXTERNAL_ONDISK(attr)); @@ -1886,11 +1969,16 @@ 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); + + /* Look for the valid index of toast relation */ + validIndex = toast_open_indexes(toastrel, + AccessShareLock, + &toastidxs, + &num_indexes); /* * Setup a scan key to fetch from the index. This is either two keys or @@ -1931,7 +2019,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[validIndex], SnapshotToast, nscankeys, toastkey); while ((ttup = systable_getnext_ordered(toastscan, ForwardScanDirection)) != NULL) { @@ -2028,8 +2116,85 @@ toast_fetch_datum_slice(struct varlena * attr, int32 sliceoffset, int32 length) * End scan and close relations */ systable_endscan_ordered(toastscan); - index_close(toastidx, AccessShareLock); + toast_close_indexes(toastidxs, num_indexes, AccessShareLock); heap_close(toastrel, AccessShareLock); return result; } + +/* ---------- + * toast_open_indexes + * + * Get an array of the indexes associated to the given toast relation + * and return as well the position of the valid index used by the toast + * relation in this array. It is the responsibility of the caller of this + * function to close the indexes as well as free them. + */ +static int +toast_open_indexes(Relation toastrel, + LOCKMODE lock, + Relation **toastidxs, + int *num_indexes) +{ + int i = 0; + int res = 0; + bool found = false; + List *indexlist; + ListCell *lc; + + /* Get index list of the toast relation */ + indexlist = RelationGetIndexList(toastrel); + Assert(indexlist != NIL); + + *num_indexes = list_length(indexlist); + + /* Open all the index relations */ + *toastidxs = (Relation *) palloc(*num_indexes * sizeof(Relation)); + foreach(lc, indexlist) + (*toastidxs)[i++] = index_open(lfirst_oid(lc), lock); + + /* Fetch the first valid index in list */ + for (i = 0; i < *num_indexes; i++) + { + Relation toastidx = *toastidxs[i]; + if (toastidx->rd_index->indisvalid) + { + res = i; + found = true; + break; + } + } + + /* + * Free index list, not necessary anymore as relations are opened + * and a valid index has been found. + */ + list_free(indexlist); + + /* + * The toast relation should have one valid index, so something is + * going wrong if there is nothing. + */ + if (!found) + elog(ERROR, "no valid index found for toast relation with Oid %d", + RelationGetRelid(toastrel)); + + return res; +} + +/* ---------- + * toast_close_indexes + * + * Close an array of indexes for a toast relation and free it. This should + * be called for a set of indexes opened previously with toast_open_indexes. + */ +static void +toast_close_indexes(Relation *toastidxs, int num_indexes, LOCKMODE lock) +{ + int i; + + /* Close relations and clean up things */ + for (i = 0; i < num_indexes; i++) + index_close(toastidxs[i], lock); + pfree(toastidxs); +} diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 4fd42ed1af5..f1cdef9e130 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -781,7 +781,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 ca0c672c381..8525cb9ec83 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); @@ -1072,7 +1072,6 @@ index_create(Relation heapRelation, index_update_stats(heapRelation, true, isprimary, - InvalidOid, -1.0); /* Make the above update visible */ CommandCounterIncrement(); @@ -1254,7 +1253,6 @@ index_constraint_create(Relation heapRelation, index_update_stats(heapRelation, true, true, - InvalidOid, -1.0); /* @@ -1764,8 +1762,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 @@ -1781,8 +1777,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; @@ -1876,15 +1873,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) { @@ -2072,14 +2060,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 81d7c4fec8c..d3086f43dd6 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 + sum(pg_stat_get_blocks_fetched(X.indexrelid) - + pg_stat_get_blocks_hit(X.indexrelid))::bigint AS tidx_blks_read, + sum(pg_stat_get_blocks_hit(X.indexrelid))::bigint 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 f23730c26f7..686770f881e 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -21,6 +21,7 @@ #include "access/relscan.h" #include "access/rewriteheap.h" #include "access/transam.h" +#include "access/tuptoaster.h" #include "access/xact.h" #include "catalog/catalog.h" #include "catalog/dependency.h" @@ -1177,8 +1178,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 @@ -1398,18 +1397,30 @@ 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. + * valid index. The swap can actually be safely done only if the relations + * have indexes. */ if (swap_toast_by_content && - relform1->reltoastidxid && relform2->reltoastidxid) - swap_relation_files(relform1->reltoastidxid, - relform2->reltoastidxid, + relform1->relkind == RELKIND_TOASTVALUE && + relform2->relkind == RELKIND_TOASTVALUE) + { + Oid toastIndex1, toastIndex2; + + /* Get valid index for each relation */ + toastIndex1 = toast_get_valid_index(r1, + AccessExclusiveLock); + toastIndex2 = toast_get_valid_index(r2, + AccessExclusiveLock); + + swap_relation_files(toastIndex1, + toastIndex2, target_is_pg_class, swap_toast_by_content, is_internal, InvalidTransactionId, InvalidMultiXactId, mapped_tables); + } /* Clean up. */ heap_freetuple(reltup1); @@ -1533,14 +1544,12 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, newrel = heap_open(OIDOldHeap, NoLock); if (OidIsValid(newrel->rd_rel->reltoastrelid)) { - Relation toastrel; Oid toastidx; char NewToastName[NAMEDATALEN]; - toastrel = relation_open(newrel->rd_rel->reltoastrelid, - AccessShareLock); - toastidx = toastrel->rd_rel->reltoastidxid; - relation_close(toastrel, AccessShareLock); + /* Get the associated valid index to be renamed */ + toastidx = toast_get_valid_index(newrel->rd_rel->reltoastrelid, + AccessShareLock); /* rename the toast table ... */ snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u", @@ -1548,9 +1557,10 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, RenameRelationInternal(newrel->rd_rel->reltoastrelid, NewToastName, true); - /* ... and its index too */ + /* ... and its valid index too. */ snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u_index", OIDOldHeap); + RenameRelationInternal(toastidx, NewToastName, true); } diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 6a7aa44ccc6..6708725d696 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8878,7 +8878,6 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) Relation rel; Oid oldTableSpace; Oid reltoastrelid; - Oid reltoastidxid; Oid newrelfilenode; RelFileNode newrnode; SMgrRelation dstrel; @@ -8886,6 +8885,8 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) HeapTuple tuple; Form_pg_class rd_rel; ForkNumber forkNum; + List *reltoastidxids = NIL; + ListCell *lc; /* * Need lock here in case we are recursing to toast table or index @@ -8932,7 +8933,13 @@ 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; + /* Fetch the list of indexes on toast relation if necessary */ + if (OidIsValid(reltoastrelid)) + { + Relation toastRel = relation_open(reltoastrelid, lockmode); + reltoastidxids = RelationGetIndexList(toastRel); + relation_close(toastRel, lockmode); + } /* Get a modifiable copy of the relation's pg_class row */ pg_class = heap_open(RelationRelationId, RowExclusiveLock); @@ -9010,11 +9017,14 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) /* Make sure the reltablespace change is visible */ CommandCounterIncrement(); - /* Move associated toast relation and/or index, too */ + /* Move associated toast relation and/or indexes, too */ if (OidIsValid(reltoastrelid)) ATExecSetTableSpace(reltoastrelid, newTableSpace, lockmode); - if (OidIsValid(reltoastidxid)) - ATExecSetTableSpace(reltoastidxid, newTableSpace, lockmode); + foreach(lc, reltoastidxids) + ATExecSetTableSpace(lfirst_oid(lc), newTableSpace, lockmode); + + /* Clean up */ + list_free(reltoastidxids); } /* diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 3157aba330d..92396b39bd3 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -579,8 +579,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)) @@ -592,7 +592,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 5ddeffe4820..34482abee3e 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,9 @@ calculate_toast_table_size(Oid toastrelid) { int64 size = 0; Relation toastRel; - Relation toastIdxRel; ForkNumber forkNum; + ListCell *lc; + List *indexlist; toastRel = relation_open(toastrelid, AccessShareLock); @@ -351,12 +352,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); + indexlist = RelationGetIndexList(toastRel); - relation_close(toastIdxRel, AccessShareLock); + /* Size is calculated using all the indexes available */ + foreach(lc, 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); + } + list_free(indexlist); relation_close(toastRel, AccessShareLock); return size; |