提交 bd1ad1b0 编写于 作者: T Tom Lane

Replace pg_class.relhasexclusion with pg_index.indisexclusion.

There isn't any need to track this state on a table-wide basis, and trying
to do so introduces undesirable semantic fuzziness.  Move the flag to
pg_index, where it clearly describes just a single index and can be
immutable after index creation.
上级 88452d5b
...@@ -1706,17 +1706,6 @@ ...@@ -1706,17 +1706,6 @@
</entry> </entry>
</row> </row>
<row>
<entry><structfield>relhasexclusion</structfield></entry>
<entry><type>bool</type></entry>
<entry></entry>
<entry>
For a table, true if the table has (or once had) any exclusion
constraints; for an index, true if the index supports an exclusion
constraint
</entry>
</row>
<row> <row>
<entry><structfield>relhasrules</structfield></entry> <entry><structfield>relhasrules</structfield></entry>
<entry><type>bool</type></entry> <entry><type>bool</type></entry>
...@@ -2046,8 +2035,7 @@ ...@@ -2046,8 +2035,7 @@
<para> <para>
<literal>pg_class.relchecks</literal> needs to agree with the <literal>pg_class.relchecks</literal> needs to agree with the
number of check-constraint entries found in this table for each number of check-constraint entries found in this table for each
relation. Also, <literal>pg_class.relhasexclusion</literal> must relation.
be true if there are any exclusion-constraint entries for the relation.
</para> </para>
</note> </note>
...@@ -3056,12 +3044,20 @@ ...@@ -3056,12 +3044,20 @@
(<structfield>indisunique</> should always be true when this is true)</entry> (<structfield>indisunique</> should always be true when this is true)</entry>
</row> </row>
<row>
<entry><structfield>indisexclusion</structfield></entry>
<entry><type>bool</type></entry>
<entry></entry>
<entry>If true, this index supports an exclusion constraint</entry>
</row>
<row> <row>
<entry><structfield>indimmediate</structfield></entry> <entry><structfield>indimmediate</structfield></entry>
<entry><type>bool</type></entry> <entry><type>bool</type></entry>
<entry></entry> <entry></entry>
<entry>If true, the uniqueness check is enforced immediately on insertion <entry>If true, the uniqueness check is enforced immediately on
(<structfield>indisunique</> should always be true when this is true)</entry> insertion
(irrelevant if <structfield>indisunique</> is not true)</entry>
</row> </row>
<row> <row>
......
...@@ -703,7 +703,6 @@ InsertPgClassTuple(Relation pg_class_desc, ...@@ -703,7 +703,6 @@ InsertPgClassTuple(Relation pg_class_desc,
values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks); values[Anum_pg_class_relchecks - 1] = Int16GetDatum(rd_rel->relchecks);
values[Anum_pg_class_relhasoids - 1] = BoolGetDatum(rd_rel->relhasoids); values[Anum_pg_class_relhasoids - 1] = BoolGetDatum(rd_rel->relhasoids);
values[Anum_pg_class_relhaspkey - 1] = BoolGetDatum(rd_rel->relhaspkey); values[Anum_pg_class_relhaspkey - 1] = BoolGetDatum(rd_rel->relhaspkey);
values[Anum_pg_class_relhasexclusion - 1] = BoolGetDatum(rd_rel->relhasexclusion);
values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules); values[Anum_pg_class_relhasrules - 1] = BoolGetDatum(rd_rel->relhasrules);
values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers); values[Anum_pg_class_relhastriggers - 1] = BoolGetDatum(rd_rel->relhastriggers);
values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass); values[Anum_pg_class_relhassubclass - 1] = BoolGetDatum(rd_rel->relhassubclass);
......
...@@ -96,10 +96,11 @@ static void UpdateIndexRelation(Oid indexoid, Oid heapoid, ...@@ -96,10 +96,11 @@ static void UpdateIndexRelation(Oid indexoid, Oid heapoid,
Oid *classOids, Oid *classOids,
int16 *coloptions, int16 *coloptions,
bool primary, bool primary,
bool isexclusion,
bool immediate, bool immediate,
bool isvalid); bool isvalid);
static void index_update_stats(Relation rel, static void index_update_stats(Relation rel,
bool hasindex, bool isprimary, bool hasexclusion, bool hasindex, bool isprimary,
Oid reltoastidxid, double reltuples); Oid reltoastidxid, double reltuples);
static void IndexCheckExclusion(Relation heapRelation, static void IndexCheckExclusion(Relation heapRelation,
Relation indexRelation, Relation indexRelation,
...@@ -523,6 +524,7 @@ UpdateIndexRelation(Oid indexoid, ...@@ -523,6 +524,7 @@ UpdateIndexRelation(Oid indexoid,
Oid *classOids, Oid *classOids,
int16 *coloptions, int16 *coloptions,
bool primary, bool primary,
bool isexclusion,
bool immediate, bool immediate,
bool isvalid) bool isvalid)
{ {
...@@ -591,6 +593,7 @@ UpdateIndexRelation(Oid indexoid, ...@@ -591,6 +593,7 @@ UpdateIndexRelation(Oid indexoid,
values[Anum_pg_index_indnatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexAttrs); values[Anum_pg_index_indnatts - 1] = Int16GetDatum(indexInfo->ii_NumIndexAttrs);
values[Anum_pg_index_indisunique - 1] = BoolGetDatum(indexInfo->ii_Unique); values[Anum_pg_index_indisunique - 1] = BoolGetDatum(indexInfo->ii_Unique);
values[Anum_pg_index_indisprimary - 1] = BoolGetDatum(primary); values[Anum_pg_index_indisprimary - 1] = BoolGetDatum(primary);
values[Anum_pg_index_indisexclusion - 1] = BoolGetDatum(isexclusion);
values[Anum_pg_index_indimmediate - 1] = BoolGetDatum(immediate); values[Anum_pg_index_indimmediate - 1] = BoolGetDatum(immediate);
values[Anum_pg_index_indisclustered - 1] = BoolGetDatum(false); values[Anum_pg_index_indisclustered - 1] = BoolGetDatum(false);
values[Anum_pg_index_indisvalid - 1] = BoolGetDatum(isvalid); values[Anum_pg_index_indisvalid - 1] = BoolGetDatum(isvalid);
...@@ -819,7 +822,6 @@ index_create(Relation heapRelation, ...@@ -819,7 +822,6 @@ index_create(Relation heapRelation,
indexRelation->rd_rel->relam = accessMethodObjectId; indexRelation->rd_rel->relam = accessMethodObjectId;
indexRelation->rd_rel->relkind = RELKIND_INDEX; indexRelation->rd_rel->relkind = RELKIND_INDEX;
indexRelation->rd_rel->relhasoids = false; indexRelation->rd_rel->relhasoids = false;
indexRelation->rd_rel->relhasexclusion = is_exclusion;
/* /*
* store index's pg_class entry * store index's pg_class entry
...@@ -854,7 +856,7 @@ index_create(Relation heapRelation, ...@@ -854,7 +856,7 @@ index_create(Relation heapRelation,
* ---------------- * ----------------
*/ */
UpdateIndexRelation(indexRelationId, heapRelationId, indexInfo, UpdateIndexRelation(indexRelationId, heapRelationId, indexInfo,
classObjectId, coloptions, isprimary, classObjectId, coloptions, isprimary, is_exclusion,
!deferrable, !deferrable,
!concurrent); !concurrent);
...@@ -1024,7 +1026,6 @@ index_create(Relation heapRelation, ...@@ -1024,7 +1026,6 @@ index_create(Relation heapRelation,
index_update_stats(heapRelation, index_update_stats(heapRelation,
true, true,
isprimary, isprimary,
is_exclusion,
InvalidOid, InvalidOid,
heapRelation->rd_rel->reltuples); heapRelation->rd_rel->reltuples);
/* Make the above update visible */ /* Make the above update visible */
...@@ -1190,7 +1191,6 @@ index_constraint_create(Relation heapRelation, ...@@ -1190,7 +1191,6 @@ index_constraint_create(Relation heapRelation,
index_update_stats(heapRelation, index_update_stats(heapRelation,
true, true,
true, true,
false,
InvalidOid, InvalidOid,
heapRelation->rd_rel->reltuples); heapRelation->rd_rel->reltuples);
...@@ -1375,7 +1375,7 @@ BuildIndexInfo(Relation index) ...@@ -1375,7 +1375,7 @@ BuildIndexInfo(Relation index)
ii->ii_PredicateState = NIL; ii->ii_PredicateState = NIL;
/* fetch exclusion constraint info if any */ /* fetch exclusion constraint info if any */
if (index->rd_rel->relhasexclusion) if (indexStruct->indisexclusion)
{ {
RelationGetExclusionInfo(index, RelationGetExclusionInfo(index,
&ii->ii_ExclusionOps, &ii->ii_ExclusionOps,
...@@ -1486,7 +1486,6 @@ FormIndexDatum(IndexInfo *indexInfo, ...@@ -1486,7 +1486,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
* hasexclusion: if true, set relhasexclusion true; else no change
* reltoastidxid: if not InvalidOid, set reltoastidxid to this value; * reltoastidxid: if not InvalidOid, set reltoastidxid to this value;
* else no change * else no change
* reltuples: set reltuples to this value * reltuples: set reltuples to this value
...@@ -1503,7 +1502,7 @@ FormIndexDatum(IndexInfo *indexInfo, ...@@ -1503,7 +1502,7 @@ FormIndexDatum(IndexInfo *indexInfo,
*/ */
static void static void
index_update_stats(Relation rel, index_update_stats(Relation rel,
bool hasindex, bool isprimary, bool hasexclusion, bool hasindex, bool isprimary,
Oid reltoastidxid, double reltuples) Oid reltoastidxid, double reltuples)
{ {
BlockNumber relpages = RelationGetNumberOfBlocks(rel); BlockNumber relpages = RelationGetNumberOfBlocks(rel);
...@@ -1542,9 +1541,9 @@ index_update_stats(Relation rel, ...@@ -1542,9 +1541,9 @@ index_update_stats(Relation rel,
* It is safe to use a non-transactional update even though our * It is safe to use a non-transactional update even though our
* transaction could still fail before committing. Setting relhasindex * transaction could still fail before committing. Setting relhasindex
* true is safe even if there are no indexes (VACUUM will eventually fix * true is safe even if there are no indexes (VACUUM will eventually fix
* it), likewise for relhaspkey and relhasexclusion. And of course the * it), likewise for relhaspkey. And of course the relpages and reltuples
* relpages and reltuples counts are correct (or at least more so than the * counts are correct (or at least more so than the old values)
* old values) regardless. * regardless.
*/ */
pg_class = heap_open(RelationRelationId, RowExclusiveLock); pg_class = heap_open(RelationRelationId, RowExclusiveLock);
...@@ -1597,14 +1596,6 @@ index_update_stats(Relation rel, ...@@ -1597,14 +1596,6 @@ index_update_stats(Relation rel,
dirty = true; dirty = true;
} }
} }
if (hasexclusion)
{
if (!rd_rel->relhasexclusion)
{
rd_rel->relhasexclusion = true;
dirty = true;
}
}
if (OidIsValid(reltoastidxid)) if (OidIsValid(reltoastidxid))
{ {
Assert(rd_rel->relkind == RELKIND_TOASTVALUE); Assert(rd_rel->relkind == RELKIND_TOASTVALUE);
...@@ -1760,13 +1751,11 @@ index_build(Relation heapRelation, ...@@ -1760,13 +1751,11 @@ index_build(Relation heapRelation,
index_update_stats(heapRelation, index_update_stats(heapRelation,
true, true,
isprimary, isprimary,
(indexInfo->ii_ExclusionOps != NULL),
(heapRelation->rd_rel->relkind == RELKIND_TOASTVALUE) ? (heapRelation->rd_rel->relkind == RELKIND_TOASTVALUE) ?
RelationGetRelid(indexRelation) : InvalidOid, RelationGetRelid(indexRelation) : InvalidOid,
stats->heap_tuples); stats->heap_tuples);
index_update_stats(indexRelation, index_update_stats(indexRelation,
false,
false, false,
false, false,
InvalidOid, InvalidOid,
......
...@@ -524,21 +524,12 @@ vac_update_relstats(Relation relation, ...@@ -524,21 +524,12 @@ vac_update_relstats(Relation relation,
/* /*
* If we have discovered that there are no indexes, then there's no * If we have discovered that there are no indexes, then there's no
* primary key either, nor any exclusion constraints. This could be done * primary key either. This could be done more thoroughly...
* more thoroughly...
*/ */
if (!hasindex) if (pgcform->relhaspkey && !hasindex)
{ {
if (pgcform->relhaspkey) pgcform->relhaspkey = false;
{ dirty = true;
pgcform->relhaspkey = false;
dirty = true;
}
if (pgcform->relhasexclusion && pgcform->relkind != RELKIND_INDEX)
{
pgcform->relhasexclusion = false;
dirty = true;
}
} }
/* We also clear relhasrules and relhastriggers if needed */ /* We also clear relhasrules and relhastriggers if needed */
......
...@@ -949,7 +949,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx, ...@@ -949,7 +949,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx,
* certainly isn't. If it is or might be from a constraint, we have to * certainly isn't. If it is or might be from a constraint, we have to
* fetch the pg_constraint record. * fetch the pg_constraint record.
*/ */
if (index->primary || index->unique || idxrelrec->relhasexclusion) if (index->primary || index->unique || idxrec->indisexclusion)
{ {
Oid constraintId = get_index_constraint(source_relid); Oid constraintId = get_index_constraint(source_relid);
...@@ -970,7 +970,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx, ...@@ -970,7 +970,7 @@ generateClonedIndexStmt(CreateStmtContext *cxt, Relation source_idx,
index->initdeferred = conrec->condeferred; index->initdeferred = conrec->condeferred;
/* If it's an exclusion constraint, we need the operator names */ /* If it's an exclusion constraint, we need the operator names */
if (idxrelrec->relhasexclusion) if (idxrec->indisexclusion)
{ {
Datum *elems; Datum *elems;
int nElems; int nElems;
......
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201101111 #define CATALOG_VERSION_NO 201101251
#endif #endif
...@@ -61,7 +61,6 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83) BKI_SCHEMA_MACRO ...@@ -61,7 +61,6 @@ CATALOG(pg_class,1259) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83) BKI_SCHEMA_MACRO
int2 relchecks; /* # of CHECK constraints for class */ int2 relchecks; /* # of CHECK constraints for class */
bool relhasoids; /* T if we generate OIDs for rows of rel */ bool relhasoids; /* T if we generate OIDs for rows of rel */
bool relhaspkey; /* has (or has had) PRIMARY KEY index */ bool relhaspkey; /* has (or has had) PRIMARY KEY index */
bool relhasexclusion; /* has (or has had) exclusion constraint */
bool relhasrules; /* has (or has had) any rules */ bool relhasrules; /* has (or has had) any rules */
bool relhastriggers; /* has (or has had) any TRIGGERs */ bool relhastriggers; /* has (or has had) any TRIGGERs */
bool relhassubclass; /* has (or has had) derived classes */ bool relhassubclass; /* has (or has had) derived classes */
...@@ -93,7 +92,7 @@ typedef FormData_pg_class *Form_pg_class; ...@@ -93,7 +92,7 @@ typedef FormData_pg_class *Form_pg_class;
* ---------------- * ----------------
*/ */
#define Natts_pg_class 27 #define Natts_pg_class 26
#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
...@@ -114,13 +113,12 @@ typedef FormData_pg_class *Form_pg_class; ...@@ -114,13 +113,12 @@ typedef FormData_pg_class *Form_pg_class;
#define Anum_pg_class_relchecks 18 #define Anum_pg_class_relchecks 18
#define Anum_pg_class_relhasoids 19 #define Anum_pg_class_relhasoids 19
#define Anum_pg_class_relhaspkey 20 #define Anum_pg_class_relhaspkey 20
#define Anum_pg_class_relhasexclusion 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_relfrozenxid 24
#define Anum_pg_class_relfrozenxid 25 #define Anum_pg_class_relacl 25
#define Anum_pg_class_relacl 26 #define Anum_pg_class_reloptions 26
#define Anum_pg_class_reloptions 27
/* ---------------- /* ----------------
* initial contents of pg_class * initial contents of pg_class
...@@ -132,13 +130,13 @@ typedef FormData_pg_class *Form_pg_class; ...@@ -132,13 +130,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 */
DATA(insert OID = 1247 ( pg_type PGNSP 71 0 PGUID 0 0 0 0 0 0 0 f f p r 28 0 t f f f f f 3 _null_ _null_ )); DATA(insert OID = 1247 ( pg_type PGNSP 71 0 PGUID 0 0 0 0 0 0 0 f f p r 28 0 t f f f f 3 _null_ _null_ ));
DESCR(""); DESCR("");
DATA(insert OID = 1249 ( pg_attribute PGNSP 75 0 PGUID 0 0 0 0 0 0 0 f f p r 19 0 f f f f f f 3 _null_ _null_ )); DATA(insert OID = 1249 ( pg_attribute PGNSP 75 0 PGUID 0 0 0 0 0 0 0 f f p r 19 0 f f f f f 3 _null_ _null_ ));
DESCR(""); DESCR("");
DATA(insert OID = 1255 ( pg_proc PGNSP 81 0 PGUID 0 0 0 0 0 0 0 f f p r 25 0 t f f f f f 3 _null_ _null_ )); DATA(insert OID = 1255 ( pg_proc PGNSP 81 0 PGUID 0 0 0 0 0 0 0 f f p r 25 0 t f f f f 3 _null_ _null_ ));
DESCR(""); DESCR("");
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 f 3 _null_ _null_ )); DATA(insert OID = 1259 ( pg_class PGNSP 83 0 PGUID 0 0 0 0 0 0 0 f f p r 26 0 t f f f f 3 _null_ _null_ ));
DESCR(""); DESCR("");
#define RELKIND_INDEX 'i' /* secondary index */ #define RELKIND_INDEX 'i' /* secondary index */
......
...@@ -35,6 +35,7 @@ CATALOG(pg_index,2610) BKI_WITHOUT_OIDS BKI_SCHEMA_MACRO ...@@ -35,6 +35,7 @@ CATALOG(pg_index,2610) BKI_WITHOUT_OIDS BKI_SCHEMA_MACRO
int2 indnatts; /* number of columns in index */ int2 indnatts; /* number of columns in index */
bool indisunique; /* is this a unique index? */ bool indisunique; /* is this a unique index? */
bool indisprimary; /* is this index for primary key? */ bool indisprimary; /* is this index for primary key? */
bool indisexclusion; /* is this index for exclusion constraint? */
bool indimmediate; /* is uniqueness enforced immediately? */ bool indimmediate; /* is uniqueness enforced immediately? */
bool indisclustered; /* is this the index last clustered by? */ bool indisclustered; /* is this the index last clustered by? */
bool indisvalid; /* is this index valid for use by queries? */ bool indisvalid; /* is this index valid for use by queries? */
...@@ -63,22 +64,23 @@ typedef FormData_pg_index *Form_pg_index; ...@@ -63,22 +64,23 @@ typedef FormData_pg_index *Form_pg_index;
* compiler constants for pg_index * compiler constants for pg_index
* ---------------- * ----------------
*/ */
#define Natts_pg_index 15 #define Natts_pg_index 16
#define Anum_pg_index_indexrelid 1 #define Anum_pg_index_indexrelid 1
#define Anum_pg_index_indrelid 2 #define Anum_pg_index_indrelid 2
#define Anum_pg_index_indnatts 3 #define Anum_pg_index_indnatts 3
#define Anum_pg_index_indisunique 4 #define Anum_pg_index_indisunique 4
#define Anum_pg_index_indisprimary 5 #define Anum_pg_index_indisprimary 5
#define Anum_pg_index_indimmediate 6 #define Anum_pg_index_indisexclusion 6
#define Anum_pg_index_indisclustered 7 #define Anum_pg_index_indimmediate 7
#define Anum_pg_index_indisvalid 8 #define Anum_pg_index_indisclustered 8
#define Anum_pg_index_indcheckxmin 9 #define Anum_pg_index_indisvalid 9
#define Anum_pg_index_indisready 10 #define Anum_pg_index_indcheckxmin 10
#define Anum_pg_index_indkey 11 #define Anum_pg_index_indisready 11
#define Anum_pg_index_indclass 12 #define Anum_pg_index_indkey 12
#define Anum_pg_index_indoption 13 #define Anum_pg_index_indclass 13
#define Anum_pg_index_indexprs 14 #define Anum_pg_index_indoption 14
#define Anum_pg_index_indpred 15 #define Anum_pg_index_indexprs 15
#define Anum_pg_index_indpred 16
/* /*
* Index AMs that support ordered scans must support these two indoption * Index AMs that support ordered scans must support these two indoption
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册