2323#include "catalog/pg_opclass.h"
2424#include "catalog/pg_opfamily.h"
2525#include "catalog/pg_tablespace.h"
26+ #include "catalog/pg_type.h"
2627#include "commands/dbcommands.h"
2728#include "commands/defrem.h"
2829#include "commands/tablecmds.h"
5253/* non-export function prototypes */
5354static void CheckPredicate (Expr * predicate );
5455static void ComputeIndexAttrs (IndexInfo * indexInfo ,
56+ Oid * typeOidP ,
5557 Oid * collationOidP ,
5658 Oid * classOidP ,
5759 int16 * colOptionP ,
@@ -87,18 +89,17 @@ static void RangeVarCallbackForReindexIndex(const RangeVar *relation,
8789 * of columns and that if one has an expression column or predicate, both do.
8890 * Errors arising from the attribute list still apply.
8991 *
90- * Most column type changes that can skip a table rewrite will not invalidate
91- * indexes. For btree and hash indexes, we assume continued validity when
92- * each column of an index would have the same operator family before and
93- * after the change. Since we do not document a contract for GIN or GiST
94- * operator families, we require an exact operator class match for them and
95- * for any other access methods.
96- *
97- * DefineIndex always verifies that each exclusion operator shares an operator
98- * family with its corresponding index operator class. For access methods
99- * having no operator family contract, confirm that the old and new indexes
100- * use the exact same exclusion operator. For btree and hash, there's nothing
101- * more to check.
92+ * Most column type changes that can skip a table rewrite do not invalidate
93+ * indexes. We ackowledge this when all operator classes, collations and
94+ * exclusion operators match. Though we could further permit intra-opfamily
95+ * changes for btree and hash indexes, that adds subtle complexity with no
96+ * concrete benefit for core types.
97+
98+ * When a comparison or exclusion operator has a polymorphic input type, the
99+ * actual input types must also match. This defends against the possibility
100+ * that operators could vary behavior in response to get_fn_expr_argtype().
101+ * At present, this hazard is theoretical: check_exclusion_constraint() and
102+ * all core index access methods decline to set fn_expr for such calls.
102103 *
103104 * We do not yet implement a test to verify compatibility of expression
104105 * columns or predicates, so assume any such index is incompatible.
@@ -111,6 +112,7 @@ CheckIndexCompatible(Oid oldId,
111112 List * exclusionOpNames )
112113{
113114 bool isconstraint ;
115+ Oid * typeObjectId ;
114116 Oid * collationObjectId ;
115117 Oid * classObjectId ;
116118 Oid accessMethodId ;
@@ -123,10 +125,10 @@ CheckIndexCompatible(Oid oldId,
123125 int numberOfAttributes ;
124126 int old_natts ;
125127 bool isnull ;
126- bool family_am ;
127128 bool ret = true;
128129 oidvector * old_indclass ;
129130 oidvector * old_indcollation ;
131+ Relation irel ;
130132 int i ;
131133 Datum d ;
132134
@@ -168,10 +170,12 @@ CheckIndexCompatible(Oid oldId,
168170 indexInfo -> ii_ExclusionOps = NULL ;
169171 indexInfo -> ii_ExclusionProcs = NULL ;
170172 indexInfo -> ii_ExclusionStrats = NULL ;
173+ typeObjectId = (Oid * ) palloc (numberOfAttributes * sizeof (Oid ));
171174 collationObjectId = (Oid * ) palloc (numberOfAttributes * sizeof (Oid ));
172175 classObjectId = (Oid * ) palloc (numberOfAttributes * sizeof (Oid ));
173176 coloptions = (int16 * ) palloc (numberOfAttributes * sizeof (int16 ));
174- ComputeIndexAttrs (indexInfo , collationObjectId , classObjectId ,
177+ ComputeIndexAttrs (indexInfo ,
178+ typeObjectId , collationObjectId , classObjectId ,
175179 coloptions , attributeList ,
176180 exclusionOpNames , relationId ,
177181 accessMethodName , accessMethodId ,
@@ -191,12 +195,7 @@ CheckIndexCompatible(Oid oldId,
191195 return false;
192196 }
193197
194- /*
195- * If the old and new operator class of any index column differ in
196- * operator family or collation, regard the old index as incompatible.
197- * For access methods other than btree and hash, a family match has no
198- * defined meaning; require an exact operator class match.
199- */
198+ /* Any change in operator class or collation breaks compatibility. */
200199 old_natts = ((Form_pg_index ) GETSTRUCT (tuple ))-> indnatts ;
201200 Assert (old_natts == numberOfAttributes );
202201
@@ -208,52 +207,42 @@ CheckIndexCompatible(Oid oldId,
208207 Assert (!isnull );
209208 old_indclass = (oidvector * ) DatumGetPointer (d );
210209
211- family_am = accessMethodId == BTREE_AM_OID || accessMethodId == HASH_AM_OID ;
212-
213- for (i = 0 ; i < old_natts ; i ++ )
214- {
215- Oid old_class = old_indclass -> values [i ];
216- Oid new_class = classObjectId [i ];
217-
218- if (!(old_indcollation -> values [i ] == collationObjectId [i ]
219- && (old_class == new_class
220- || (family_am && (get_opclass_family (old_class )
221- == get_opclass_family (new_class ))))))
222- {
223- ret = false;
224- break ;
225- }
226- }
210+ ret = (memcmp (old_indclass -> values , classObjectId ,
211+ old_natts * sizeof (Oid )) == 0 &&
212+ memcmp (old_indcollation -> values , collationObjectId ,
213+ old_natts * sizeof (Oid )) == 0 );
227214
228215 ReleaseSysCache (tuple );
229216
230- /*
231- * For btree and hash, exclusion operators need only fall in the same
232- * operator family; ComputeIndexAttrs already verified that much. If we
233- * get this far, we know that the index operator family has not changed,
234- * and we're done. For other access methods, require exact matches for
235- * all exclusion operators.
236- */
237- if (ret && ! family_am && indexInfo -> ii_ExclusionOps != NULL )
217+ /* For polymorphic opcintype, column type changes break compatibility. */
218+ irel = index_open ( oldId , AccessShareLock ); /* caller probably has a lock */
219+ for ( i = 0 ; i < old_natts && ret ; i ++ )
220+ ret = (! IsPolymorphicType ( get_opclass_input_type ( classObjectId [ i ])) ||
221+ irel -> rd_att -> attrs [ i ] -> atttypid == typeObjectId [ i ]);
222+
223+ /* Any change in exclusion operator selections breaks compatibility. */
224+ if (ret && indexInfo -> ii_ExclusionOps != NULL )
238225 {
239- Relation irel ;
240226 Oid * old_operators , * old_procs ;
241227 uint16 * old_strats ;
242228
243- /* Caller probably already holds a stronger lock. */
244- irel = index_open (oldId , AccessShareLock );
245229 RelationGetExclusionInfo (irel , & old_operators , & old_procs , & old_strats );
230+ ret = memcmp (old_operators , indexInfo -> ii_ExclusionOps ,
231+ old_natts * sizeof (Oid )) == 0 ;
246232
247- for (i = 0 ; i < old_natts ; i ++ )
248- if (old_operators [i ] != indexInfo -> ii_ExclusionOps [i ])
249- {
250- ret = false;
251- break ;
252- }
233+ /* Require an exact input type match for polymorphic operators. */
234+ for (i = 0 ; i < old_natts && ret ; i ++ )
235+ {
236+ Oid left ,
237+ right ;
253238
254- index_close (irel , NoLock );
239+ op_input_types (indexInfo -> ii_ExclusionOps [i ], & left , & right );
240+ ret = (!(IsPolymorphicType (left ) || IsPolymorphicType (right )) ||
241+ irel -> rd_att -> attrs [i ]-> atttypid == typeObjectId [i ]);
242+ }
255243 }
256244
245+ index_close (irel , NoLock );
257246 return ret ;
258247}
259248
@@ -315,6 +304,7 @@ DefineIndex(RangeVar *heapRelation,
315304 bool quiet ,
316305 bool concurrent )
317306{
307+ Oid * typeObjectId ;
318308 Oid * collationObjectId ;
319309 Oid * classObjectId ;
320310 Oid accessMethodId ;
@@ -550,10 +540,12 @@ DefineIndex(RangeVar *heapRelation,
550540 indexInfo -> ii_Concurrent = concurrent ;
551541 indexInfo -> ii_BrokenHotChain = false;
552542
543+ typeObjectId = (Oid * ) palloc (numberOfAttributes * sizeof (Oid ));
553544 collationObjectId = (Oid * ) palloc (numberOfAttributes * sizeof (Oid ));
554545 classObjectId = (Oid * ) palloc (numberOfAttributes * sizeof (Oid ));
555546 coloptions = (int16 * ) palloc (numberOfAttributes * sizeof (int16 ));
556- ComputeIndexAttrs (indexInfo , collationObjectId , classObjectId ,
547+ ComputeIndexAttrs (indexInfo ,
548+ typeObjectId , collationObjectId , classObjectId ,
557549 coloptions , attributeList ,
558550 exclusionOpNames , relationId ,
559551 accessMethodName , accessMethodId ,
@@ -980,6 +972,7 @@ CheckPredicate(Expr *predicate)
980972 */
981973static void
982974ComputeIndexAttrs (IndexInfo * indexInfo ,
975+ Oid * typeOidP ,
983976 Oid * collationOidP ,
984977 Oid * classOidP ,
985978 int16 * colOptionP ,
@@ -1108,6 +1101,8 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
11081101 }
11091102 }
11101103
1104+ typeOidP [attn ] = atttype ;
1105+
11111106 /*
11121107 * Apply collation override if any
11131108 */
0 commit comments