Commit 2ef085d0 authored by Fujii Masao's avatar Fujii Masao

Get rid of pg_class.reltoastidxid.

Treat TOAST index just the same as normal one and get the OID
of TOAST index from pg_index but not pg_class.reltoastidxid.
This change allows us to handle multiple TOAST indexes, and
which is required infrastructure for upcoming
REINDEX CONCURRENTLY feature.

Patch by Michael Paquier, reviewed by Andres Freund and me.
parent f71939cd
...@@ -321,12 +321,19 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo) ...@@ -321,12 +321,19 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
"INSERT INTO info_rels " "INSERT INTO info_rels "
"SELECT reltoastrelid " "SELECT reltoastrelid "
"FROM info_rels i JOIN pg_catalog.pg_class c " "FROM info_rels i JOIN pg_catalog.pg_class c "
" ON i.reloid = c.oid")); " ON i.reloid = c.oid "
" AND c.reltoastrelid != %u", InvalidOid));
PQclear(executeQueryOrDie(conn, PQclear(executeQueryOrDie(conn,
"INSERT INTO info_rels " "INSERT INTO info_rels "
"SELECT reltoastidxid " "SELECT indexrelid "
"FROM info_rels i JOIN pg_catalog.pg_class c " "FROM pg_index "
" ON i.reloid = c.oid")); "WHERE indisvalid "
" AND indrelid IN (SELECT reltoastrelid "
" FROM info_rels i "
" JOIN pg_catalog.pg_class c "
" ON i.reloid = c.oid "
" AND c.reltoastrelid != %u)",
InvalidOid));
snprintf(query, sizeof(query), snprintf(query, sizeof(query),
"SELECT c.oid, n.nspname, c.relname, " "SELECT c.oid, n.nspname, c.relname, "
......
...@@ -1744,15 +1744,6 @@ ...@@ -1744,15 +1744,6 @@
</entry> </entry>
</row> </row>
<row>
<entry><structfield>reltoastidxid</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
<entry>
For a TOAST table, the OID of its index. 0 if not a TOAST table.
</entry>
</row>
<row> <row>
<entry><structfield>relhasindex</structfield></entry> <entry><structfield>relhasindex</structfield></entry>
<entry><type>bool</type></entry> <entry><type>bool</type></entry>
......
...@@ -20,12 +20,12 @@ ...@@ -20,12 +20,12 @@
stored. If the table has any columns with potentially-wide values, stored. If the table has any columns with potentially-wide values,
there also might be a <acronym>TOAST</> file associated with the table, there also might be a <acronym>TOAST</> file associated with the table,
which is used to store values too wide to fit comfortably in the main which is used to store values too wide to fit comfortably in the main
table (see <xref linkend="storage-toast">). There will be one index on the table (see <xref linkend="storage-toast">). There will be one valid index
<acronym>TOAST</> table, if present. There also might be indexes associated on the <acronym>TOAST</> table, if present. There also might be indexes
with the base table. Each table and index is stored in a separate disk associated with the base table. Each table and index is stored in a
file &mdash; possibly more than one file, if the file would exceed one separate disk file &mdash; possibly more than one file, if the file would
gigabyte. Naming conventions for these files are described in <xref exceed one gigabyte. Naming conventions for these files are described
linkend="storage-file-layout">. in <xref linkend="storage-file-layout">.
</para> </para>
<para> <para>
...@@ -65,9 +65,9 @@ FROM pg_class, ...@@ -65,9 +65,9 @@ FROM pg_class,
FROM pg_class FROM pg_class
WHERE relname = 'customer') AS ss WHERE relname = 'customer') AS ss
WHERE oid = ss.reltoastrelid OR WHERE oid = ss.reltoastrelid OR
oid = (SELECT reltoastidxid oid = (SELECT indexrelid
FROM pg_class FROM pg_index
WHERE oid = ss.reltoastrelid) WHERE indrelid = ss.reltoastrelid)
ORDER BY relname; ORDER BY relname;
relname | relpages relname | relpages
......
...@@ -1163,12 +1163,12 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re ...@@ -1163,12 +1163,12 @@ postgres: <replaceable>user</> <replaceable>database</> <replaceable>host</> <re
<row> <row>
<entry><structfield>tidx_blks_read</></entry> <entry><structfield>tidx_blks_read</></entry>
<entry><type>bigint</></entry> <entry><type>bigint</></entry>
<entry>Number of disk blocks read from this table's TOAST table index (if any)</entry> <entry>Number of disk blocks read from this table's TOAST table indexes (if any)</entry>
</row> </row>
<row> <row>
<entry><structfield>tidx_blks_hit</></entry> <entry><structfield>tidx_blks_hit</></entry>
<entry><type>bigint</></entry> <entry><type>bigint</></entry>
<entry>Number of buffer hits in this table's TOAST table index (if any)</entry> <entry>Number of buffer hits in this table's TOAST table indexes (if any)</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
......
This diff is collapsed.
...@@ -781,7 +781,6 @@ InsertPgClassTuple(Relation pg_class_desc, ...@@ -781,7 +781,6 @@ InsertPgClassTuple(Relation pg_class_desc,
values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples); values[Anum_pg_class_reltuples - 1] = Float4GetDatum(rd_rel->reltuples);
values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible); values[Anum_pg_class_relallvisible - 1] = Int32GetDatum(rd_rel->relallvisible);
values[Anum_pg_class_reltoastrelid - 1] = ObjectIdGetDatum(rd_rel->reltoastrelid); 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_relhasindex - 1] = BoolGetDatum(rd_rel->relhasindex);
values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared); values[Anum_pg_class_relisshared - 1] = BoolGetDatum(rd_rel->relisshared);
values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence); values[Anum_pg_class_relpersistence - 1] = CharGetDatum(rd_rel->relpersistence);
......
...@@ -103,7 +103,7 @@ static void UpdateIndexRelation(Oid indexoid, Oid heapoid, ...@@ -103,7 +103,7 @@ static void UpdateIndexRelation(Oid indexoid, Oid heapoid,
bool isvalid); bool isvalid);
static void index_update_stats(Relation rel, static void index_update_stats(Relation rel,
bool hasindex, bool isprimary, bool hasindex, bool isprimary,
Oid reltoastidxid, double reltuples); double reltuples);
static void IndexCheckExclusion(Relation heapRelation, static void IndexCheckExclusion(Relation heapRelation,
Relation indexRelation, Relation indexRelation,
IndexInfo *indexInfo); IndexInfo *indexInfo);
...@@ -1072,7 +1072,6 @@ index_create(Relation heapRelation, ...@@ -1072,7 +1072,6 @@ index_create(Relation heapRelation,
index_update_stats(heapRelation, index_update_stats(heapRelation,
true, true,
isprimary, isprimary,
InvalidOid,
-1.0); -1.0);
/* Make the above update visible */ /* Make the above update visible */
CommandCounterIncrement(); CommandCounterIncrement();
...@@ -1254,7 +1253,6 @@ index_constraint_create(Relation heapRelation, ...@@ -1254,7 +1253,6 @@ index_constraint_create(Relation heapRelation,
index_update_stats(heapRelation, index_update_stats(heapRelation,
true, true,
true, true,
InvalidOid,
-1.0); -1.0);
/* /*
...@@ -1764,8 +1762,6 @@ FormIndexDatum(IndexInfo *indexInfo, ...@@ -1764,8 +1762,6 @@ FormIndexDatum(IndexInfo *indexInfo,
* *
* hasindex: set relhasindex to this value * hasindex: set relhasindex to this value
* isprimary: if true, set relhaspkey true; else no change * 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 * reltuples: if >= 0, set reltuples to this value; else no change
* *
* If reltuples >= 0, relpages and relallvisible are also updated (using * If reltuples >= 0, relpages and relallvisible are also updated (using
...@@ -1781,8 +1777,9 @@ FormIndexDatum(IndexInfo *indexInfo, ...@@ -1781,8 +1777,9 @@ FormIndexDatum(IndexInfo *indexInfo,
*/ */
static void static void
index_update_stats(Relation rel, index_update_stats(Relation rel,
bool hasindex, bool isprimary, bool hasindex,
Oid reltoastidxid, double reltuples) bool isprimary,
double reltuples)
{ {
Oid relid = RelationGetRelid(rel); Oid relid = RelationGetRelid(rel);
Relation pg_class; Relation pg_class;
...@@ -1876,15 +1873,6 @@ index_update_stats(Relation rel, ...@@ -1876,15 +1873,6 @@ index_update_stats(Relation rel,
dirty = true; 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) if (reltuples >= 0)
{ {
...@@ -2072,14 +2060,11 @@ index_build(Relation heapRelation, ...@@ -2072,14 +2060,11 @@ index_build(Relation heapRelation,
index_update_stats(heapRelation, index_update_stats(heapRelation,
true, true,
isprimary, isprimary,
(heapRelation->rd_rel->relkind == RELKIND_TOASTVALUE) ?
RelationGetRelid(indexRelation) : InvalidOid,
stats->heap_tuples); stats->heap_tuples);
index_update_stats(indexRelation, index_update_stats(indexRelation,
false, false,
false, false,
InvalidOid,
stats->index_tuples); stats->index_tuples);
/* Make the updated catalog row versions visible */ /* Make the updated catalog row versions visible */
......
...@@ -473,16 +473,16 @@ CREATE VIEW pg_statio_all_tables AS ...@@ -473,16 +473,16 @@ CREATE VIEW pg_statio_all_tables AS
pg_stat_get_blocks_fetched(T.oid) - 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_read,
pg_stat_get_blocks_hit(T.oid) AS toast_blks_hit, pg_stat_get_blocks_hit(T.oid) AS toast_blks_hit,
pg_stat_get_blocks_fetched(X.oid) - sum(pg_stat_get_blocks_fetched(X.indexrelid) -
pg_stat_get_blocks_hit(X.oid) AS tidx_blks_read, pg_stat_get_blocks_hit(X.indexrelid))::bigint AS tidx_blks_read,
pg_stat_get_blocks_hit(X.oid) AS tidx_blks_hit sum(pg_stat_get_blocks_hit(X.indexrelid))::bigint AS tidx_blks_hit
FROM pg_class C LEFT JOIN FROM pg_class C LEFT JOIN
pg_index I ON C.oid = I.indrelid LEFT JOIN pg_index I ON C.oid = I.indrelid LEFT JOIN
pg_class T ON C.reltoastrelid = T.oid 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) LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE C.relkind IN ('r', 't', 'm') 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 CREATE VIEW pg_statio_sys_tables AS
SELECT * FROM pg_statio_all_tables SELECT * FROM pg_statio_all_tables
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "access/relscan.h" #include "access/relscan.h"
#include "access/rewriteheap.h" #include "access/rewriteheap.h"
#include "access/transam.h" #include "access/transam.h"
#include "access/tuptoaster.h"
#include "access/xact.h" #include "access/xact.h"
#include "catalog/catalog.h" #include "catalog/catalog.h"
#include "catalog/dependency.h" #include "catalog/dependency.h"
...@@ -1177,8 +1178,6 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, ...@@ -1177,8 +1178,6 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
swaptemp = relform1->reltoastrelid; swaptemp = relform1->reltoastrelid;
relform1->reltoastrelid = relform2->reltoastrelid; relform1->reltoastrelid = relform2->reltoastrelid;
relform2->reltoastrelid = swaptemp; relform2->reltoastrelid = swaptemp;
/* we should NOT swap reltoastidxid */
} }
} }
else else
...@@ -1398,18 +1397,30 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, ...@@ -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 * 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 && if (swap_toast_by_content &&
relform1->reltoastidxid && relform2->reltoastidxid) relform1->relkind == RELKIND_TOASTVALUE &&
swap_relation_files(relform1->reltoastidxid, relform2->relkind == RELKIND_TOASTVALUE)
relform2->reltoastidxid, {
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, target_is_pg_class,
swap_toast_by_content, swap_toast_by_content,
is_internal, is_internal,
InvalidTransactionId, InvalidTransactionId,
InvalidMultiXactId, InvalidMultiXactId,
mapped_tables); mapped_tables);
}
/* Clean up. */ /* Clean up. */
heap_freetuple(reltup1); heap_freetuple(reltup1);
...@@ -1533,14 +1544,12 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, ...@@ -1533,14 +1544,12 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
newrel = heap_open(OIDOldHeap, NoLock); newrel = heap_open(OIDOldHeap, NoLock);
if (OidIsValid(newrel->rd_rel->reltoastrelid)) if (OidIsValid(newrel->rd_rel->reltoastrelid))
{ {
Relation toastrel;
Oid toastidx; Oid toastidx;
char NewToastName[NAMEDATALEN]; char NewToastName[NAMEDATALEN];
toastrel = relation_open(newrel->rd_rel->reltoastrelid, /* Get the associated valid index to be renamed */
toastidx = toast_get_valid_index(newrel->rd_rel->reltoastrelid,
AccessShareLock); AccessShareLock);
toastidx = toastrel->rd_rel->reltoastidxid;
relation_close(toastrel, AccessShareLock);
/* rename the toast table ... */ /* rename the toast table ... */
snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u", snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u",
...@@ -1548,9 +1557,10 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap, ...@@ -1548,9 +1557,10 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
RenameRelationInternal(newrel->rd_rel->reltoastrelid, RenameRelationInternal(newrel->rd_rel->reltoastrelid,
NewToastName, true); NewToastName, true);
/* ... and its index too */ /* ... and its valid index too. */
snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u_index", snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u_index",
OIDOldHeap); OIDOldHeap);
RenameRelationInternal(toastidx, RenameRelationInternal(toastidx,
NewToastName, true); NewToastName, true);
} }
......
...@@ -8878,7 +8878,6 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) ...@@ -8878,7 +8878,6 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
Relation rel; Relation rel;
Oid oldTableSpace; Oid oldTableSpace;
Oid reltoastrelid; Oid reltoastrelid;
Oid reltoastidxid;
Oid newrelfilenode; Oid newrelfilenode;
RelFileNode newrnode; RelFileNode newrnode;
SMgrRelation dstrel; SMgrRelation dstrel;
...@@ -8886,6 +8885,8 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) ...@@ -8886,6 +8885,8 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
HeapTuple tuple; HeapTuple tuple;
Form_pg_class rd_rel; Form_pg_class rd_rel;
ForkNumber forkNum; ForkNumber forkNum;
List *reltoastidxids = NIL;
ListCell *lc;
/* /*
* Need lock here in case we are recursing to toast table or index * Need lock here in case we are recursing to toast table or index
...@@ -8932,7 +8933,13 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) ...@@ -8932,7 +8933,13 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
errmsg("cannot move temporary tables of other sessions"))); errmsg("cannot move temporary tables of other sessions")));
reltoastrelid = rel->rd_rel->reltoastrelid; 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 */ /* Get a modifiable copy of the relation's pg_class row */
pg_class = heap_open(RelationRelationId, RowExclusiveLock); pg_class = heap_open(RelationRelationId, RowExclusiveLock);
...@@ -9010,11 +9017,14 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) ...@@ -9010,11 +9017,14 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
/* Make sure the reltablespace change is visible */ /* Make sure the reltablespace change is visible */
CommandCounterIncrement(); CommandCounterIncrement();
/* Move associated toast relation and/or index, too */ /* Move associated toast relation and/or indexes, too */
if (OidIsValid(reltoastrelid)) if (OidIsValid(reltoastrelid))
ATExecSetTableSpace(reltoastrelid, newTableSpace, lockmode); ATExecSetTableSpace(reltoastrelid, newTableSpace, lockmode);
if (OidIsValid(reltoastidxid)) foreach(lc, reltoastidxids)
ATExecSetTableSpace(reltoastidxid, newTableSpace, lockmode); ATExecSetTableSpace(lfirst_oid(lc), newTableSpace, lockmode);
/* Clean up */
list_free(reltoastidxids);
} }
/* /*
......
...@@ -579,8 +579,8 @@ DefineQueryRewrite(char *rulename, ...@@ -579,8 +579,8 @@ DefineQueryRewrite(char *rulename,
/* /*
* Fix pg_class entry to look like a normal view's, including setting * Fix pg_class entry to look like a normal view's, including setting
* the correct relkind and removal of reltoastrelid/reltoastidxid of * the correct relkind and removal of reltoastrelid of the toast table
* the toast table we potentially removed above. * we potentially removed above.
*/ */
classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(event_relid)); classTup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(event_relid));
if (!HeapTupleIsValid(classTup)) if (!HeapTupleIsValid(classTup))
...@@ -592,7 +592,6 @@ DefineQueryRewrite(char *rulename, ...@@ -592,7 +592,6 @@ DefineQueryRewrite(char *rulename,
classForm->reltuples = 0; classForm->reltuples = 0;
classForm->relallvisible = 0; classForm->relallvisible = 0;
classForm->reltoastrelid = InvalidOid; classForm->reltoastrelid = InvalidOid;
classForm->reltoastidxid = InvalidOid;
classForm->relhasindex = false; classForm->relhasindex = false;
classForm->relkind = RELKIND_VIEW; classForm->relkind = RELKIND_VIEW;
classForm->relhasoids = false; classForm->relhasoids = false;
......
...@@ -332,7 +332,7 @@ pg_relation_size(PG_FUNCTION_ARGS) ...@@ -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. * Must not be applied to non-TOAST relations.
*/ */
static int64 static int64
...@@ -340,8 +340,9 @@ calculate_toast_table_size(Oid toastrelid) ...@@ -340,8 +340,9 @@ calculate_toast_table_size(Oid toastrelid)
{ {
int64 size = 0; int64 size = 0;
Relation toastRel; Relation toastRel;
Relation toastIdxRel;
ForkNumber forkNum; ForkNumber forkNum;
ListCell *lc;
List *indexlist;
toastRel = relation_open(toastrelid, AccessShareLock); toastRel = relation_open(toastrelid, AccessShareLock);
...@@ -351,12 +352,21 @@ calculate_toast_table_size(Oid toastrelid) ...@@ -351,12 +352,21 @@ calculate_toast_table_size(Oid toastrelid)
toastRel->rd_backend, forkNum); toastRel->rd_backend, forkNum);
/* toast index size, including FSM and VM size */ /* toast index size, including FSM and VM size */
toastIdxRel = relation_open(toastRel->rd_rel->reltoastidxid, AccessShareLock); indexlist = RelationGetIndexList(toastRel);
/* 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++) for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
size += calculate_relation_size(&(toastIdxRel->rd_node), size += calculate_relation_size(&(toastIdxRel->rd_node),
toastIdxRel->rd_backend, forkNum); toastIdxRel->rd_backend, forkNum);
relation_close(toastIdxRel, AccessShareLock); relation_close(toastIdxRel, AccessShareLock);
}
list_free(indexlist);
relation_close(toastRel, AccessShareLock); relation_close(toastRel, AccessShareLock);
return size; return size;
......
...@@ -2778,19 +2778,19 @@ binary_upgrade_set_pg_class_oids(Archive *fout, ...@@ -2778,19 +2778,19 @@ binary_upgrade_set_pg_class_oids(Archive *fout,
PQExpBuffer upgrade_query = createPQExpBuffer(); PQExpBuffer upgrade_query = createPQExpBuffer();
PGresult *upgrade_res; PGresult *upgrade_res;
Oid pg_class_reltoastrelid; Oid pg_class_reltoastrelid;
Oid pg_class_reltoastidxid; Oid pg_index_indexrelid;
appendPQExpBuffer(upgrade_query, appendPQExpBuffer(upgrade_query,
"SELECT c.reltoastrelid, t.reltoastidxid " "SELECT c.reltoastrelid, i.indexrelid "
"FROM pg_catalog.pg_class c LEFT JOIN " "FROM pg_catalog.pg_class c LEFT JOIN "
"pg_catalog.pg_class t ON (c.reltoastrelid = t.oid) " "pg_catalog.pg_index i ON (c.reltoastrelid = i.indrelid AND i.indisvalid) "
"WHERE c.oid = '%u'::pg_catalog.oid;", "WHERE c.oid = '%u'::pg_catalog.oid;",
pg_class_oid); pg_class_oid);
upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data); upgrade_res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
pg_class_reltoastrelid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "reltoastrelid"))); pg_class_reltoastrelid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "reltoastrelid")));
pg_class_reltoastidxid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "reltoastidxid"))); pg_index_indexrelid = atooid(PQgetvalue(upgrade_res, 0, PQfnumber(upgrade_res, "indexrelid")));
appendPQExpBuffer(upgrade_buffer, appendPQExpBuffer(upgrade_buffer,
"\n-- For binary upgrade, must preserve pg_class oids\n"); "\n-- For binary upgrade, must preserve pg_class oids\n");
...@@ -2819,7 +2819,7 @@ binary_upgrade_set_pg_class_oids(Archive *fout, ...@@ -2819,7 +2819,7 @@ binary_upgrade_set_pg_class_oids(Archive *fout,
/* every toast table has an index */ /* every toast table has an index */
appendPQExpBuffer(upgrade_buffer, appendPQExpBuffer(upgrade_buffer,
"SELECT binary_upgrade.set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n", "SELECT binary_upgrade.set_next_index_pg_class_oid('%u'::pg_catalog.oid);\n",
pg_class_reltoastidxid); pg_index_indexrelid);
} }
} }
else else
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "access/htup_details.h" #include "access/htup_details.h"
#include "utils/relcache.h" #include "utils/relcache.h"
#include "storage/lock.h"
/* /*
* This enables de-toasting of index entries. Needed until VACUUM is * This enables de-toasting of index entries. Needed until VACUUM is
...@@ -193,4 +194,12 @@ extern Size toast_raw_datum_size(Datum value); ...@@ -193,4 +194,12 @@ extern Size toast_raw_datum_size(Datum value);
*/ */
extern Size toast_datum_size(Datum value); extern Size toast_datum_size(Datum value);
/* ----------
* toast_get_valid_index -
*
* Return OID of valid index associated to a toast relation
* ----------
*/
extern Oid toast_get_valid_index(Oid toastoid, LOCKMODE lock);
#endif /* TUPTOASTER_H */ #endif /* TUPTOASTER_H */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201306121 #define CATALOG_VERSION_NO 201307031
#endif #endif
...@@ -48,7 +48,6 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83) BKI_SCHEMA_MACRO ...@@ -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 int32 relallvisible; /* # of all-visible blocks (not always
* up-to-date) */ * up-to-date) */
Oid reltoastrelid; /* OID of toast table; 0 if none */ 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 relhasindex; /* T if has (or has had) any indexes */
bool relisshared; /* T if shared across databases */ bool relisshared; /* T if shared across databases */
char relpersistence; /* see RELPERSISTENCE_xxx constants below */ char relpersistence; /* see RELPERSISTENCE_xxx constants below */
...@@ -94,7 +93,7 @@ typedef FormData_pg_class *Form_pg_class; ...@@ -94,7 +93,7 @@ typedef FormData_pg_class *Form_pg_class;
* ---------------- * ----------------
*/ */
#define Natts_pg_class 29 #define Natts_pg_class 28
#define Anum_pg_class_relname 1 #define Anum_pg_class_relname 1
#define Anum_pg_class_relnamespace 2 #define Anum_pg_class_relnamespace 2
#define Anum_pg_class_reltype 3 #define Anum_pg_class_reltype 3
...@@ -107,23 +106,22 @@ typedef FormData_pg_class *Form_pg_class; ...@@ -107,23 +106,22 @@ typedef FormData_pg_class *Form_pg_class;
#define Anum_pg_class_reltuples 10 #define Anum_pg_class_reltuples 10
#define Anum_pg_class_relallvisible 11 #define Anum_pg_class_relallvisible 11
#define Anum_pg_class_reltoastrelid 12 #define Anum_pg_class_reltoastrelid 12
#define Anum_pg_class_reltoastidxid 13 #define Anum_pg_class_relhasindex 13
#define Anum_pg_class_relhasindex 14 #define Anum_pg_class_relisshared 14
#define Anum_pg_class_relisshared 15 #define Anum_pg_class_relpersistence 15
#define Anum_pg_class_relpersistence 16 #define Anum_pg_class_relkind 16
#define Anum_pg_class_relkind 17 #define Anum_pg_class_relnatts 17
#define Anum_pg_class_relnatts 18 #define Anum_pg_class_relchecks 18
#define Anum_pg_class_relchecks 19 #define Anum_pg_class_relhasoids 19
#define Anum_pg_class_relhasoids 20 #define Anum_pg_class_relhaspkey 20
#define Anum_pg_class_relhaspkey 21 #define Anum_pg_class_relhasrules 21
#define Anum_pg_class_relhasrules 22 #define Anum_pg_class_relhastriggers 22
#define Anum_pg_class_relhastriggers 23 #define Anum_pg_class_relhassubclass 23
#define Anum_pg_class_relhassubclass 24 #define Anum_pg_class_relispopulated 24
#define Anum_pg_class_relispopulated 25 #define Anum_pg_class_relfrozenxid 25
#define Anum_pg_class_relfrozenxid 26 #define Anum_pg_class_relminmxid 26
#define Anum_pg_class_relminmxid 27 #define Anum_pg_class_relacl 27
#define Anum_pg_class_relacl 28 #define Anum_pg_class_reloptions 28
#define Anum_pg_class_reloptions 29
/* ---------------- /* ----------------
* initial contents of pg_class * initial contents of pg_class
...@@ -138,13 +136,13 @@ typedef FormData_pg_class *Form_pg_class; ...@@ -138,13 +136,13 @@ typedef FormData_pg_class *Form_pg_class;
* Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId; * Note: "3" in the relfrozenxid column stands for FirstNormalTransactionId;
* similarly, "1" in relminmxid stands for FirstMultiXactId * 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 t 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 t 3 1 _null_ _null_ ));
DESCR(""); 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 t 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 t 3 1 _null_ _null_ ));
DESCR(""); 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 t 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 t 3 1 _null_ _null_ ));
DESCR(""); DESCR("");
DATA(insert OID = 1259 ( pg_class PGNSP 83 0 PGUID 0 0 0 0 0 0 0 0 f f p r 29 0 t f f f f t 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 28 0 t f f f f t 3 1 _null_ _null_ ));
DESCR(""); DESCR("");
......
...@@ -353,14 +353,6 @@ WHERE reltoastrelid != 0 AND ...@@ -353,14 +353,6 @@ WHERE reltoastrelid != 0 AND
------+--------------- ------+---------------
(0 rows) (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 SELECT ctid, collnamespace
FROM pg_catalog.pg_collation fk FROM pg_catalog.pg_collation fk
WHERE collnamespace != 0 AND WHERE collnamespace != 0 AND
......
...@@ -1852,15 +1852,15 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem ...@@ -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, + | (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_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_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, + | (sum((pg_stat_get_blocks_fetched(x.indexrelid) - pg_stat_get_blocks_hit(x.indexrelid))))::bigint AS tidx_blks_read, +
| pg_stat_get_blocks_hit(x.oid) AS tidx_blks_hit + | (sum(pg_stat_get_blocks_hit(x.indexrelid)))::bigint AS tidx_blks_hit +
| FROM ((((pg_class c + | FROM ((((pg_class c +
| LEFT JOIN pg_index i ON ((c.oid = i.indrelid))) + | LEFT JOIN pg_index i ON ((c.oid = i.indrelid))) +
| LEFT JOIN pg_class t ON ((c.reltoastrelid = t.oid))) + | 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))) + | LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) +
| WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char", 'm'::"char"])) + | 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_sys_indexes | SELECT pg_statio_all_indexes.relid, +
| pg_statio_all_indexes.indexrelid, + | pg_statio_all_indexes.indexrelid, +
| pg_statio_all_indexes.schemaname, + | pg_statio_all_indexes.schemaname, +
...@@ -2347,11 +2347,11 @@ select xmin, * from fooview; -- fail, views don't have such a column ...@@ -2347,11 +2347,11 @@ select xmin, * from fooview; -- fail, views don't have such a column
ERROR: column "xmin" does not exist ERROR: column "xmin" does not exist
LINE 1: select xmin, * from fooview; LINE 1: select xmin, * from fooview;
^ ^
select reltoastrelid, reltoastidxid, relkind, relfrozenxid select reltoastrelid, relkind, relfrozenxid
from pg_class where oid = 'fooview'::regclass; from pg_class where oid = 'fooview'::regclass;
reltoastrelid | reltoastidxid | relkind | relfrozenxid reltoastrelid | relkind | relfrozenxid
---------------+---------------+---------+-------------- ---------------+---------+--------------
0 | 0 | v | 0 0 | v | 0
(1 row) (1 row)
drop view fooview; drop view fooview;
......
...@@ -177,10 +177,6 @@ SELECT ctid, reltoastrelid ...@@ -177,10 +177,6 @@ SELECT ctid, reltoastrelid
FROM pg_catalog.pg_class fk FROM pg_catalog.pg_class fk
WHERE reltoastrelid != 0 AND WHERE reltoastrelid != 0 AND
NOT EXISTS(SELECT 1 FROM pg_catalog.pg_class pk WHERE pk.oid = fk.reltoastrelid); 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 SELECT ctid, collnamespace
FROM pg_catalog.pg_collation fk FROM pg_catalog.pg_collation fk
WHERE collnamespace != 0 AND WHERE collnamespace != 0 AND
......
...@@ -872,7 +872,7 @@ create rule "_RETURN" as on select to fooview do instead ...@@ -872,7 +872,7 @@ create rule "_RETURN" as on select to fooview do instead
select * from fooview; select * from fooview;
select xmin, * from fooview; -- fail, views don't have such a column 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; from pg_class where oid = 'fooview'::regclass;
drop view fooview; drop view fooview;
......
...@@ -86,7 +86,6 @@ Join pg_catalog.pg_class.relowner => pg_catalog.pg_authid.oid ...@@ -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.relam => pg_catalog.pg_am.oid
Join pg_catalog.pg_class.reltablespace => pg_catalog.pg_tablespace.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.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.collnamespace => pg_catalog.pg_namespace.oid
Join pg_catalog.pg_collation.collowner => pg_catalog.pg_authid.oid Join pg_catalog.pg_collation.collowner => pg_catalog.pg_authid.oid
Join pg_catalog.pg_constraint.connamespace => pg_catalog.pg_namespace.oid Join pg_catalog.pg_constraint.connamespace => pg_catalog.pg_namespace.oid
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment