23
23
#include "catalog/pg_opclass.h"
24
24
#include "catalog/pg_opfamily.h"
25
25
#include "catalog/pg_tablespace.h"
26
+ #include "catalog/pg_type.h"
26
27
#include "commands/dbcommands.h"
27
28
#include "commands/defrem.h"
28
29
#include "commands/tablecmds.h"
52
53
/* non-export function prototypes */
53
54
static void CheckPredicate (Expr * predicate );
54
55
static void ComputeIndexAttrs (IndexInfo * indexInfo ,
56
+ Oid * typeOidP ,
55
57
Oid * collationOidP ,
56
58
Oid * classOidP ,
57
59
int16 * colOptionP ,
@@ -87,18 +89,17 @@ static void RangeVarCallbackForReindexIndex(const RangeVar *relation,
87
89
* of columns and that if one has an expression column or predicate, both do.
88
90
* Errors arising from the attribute list still apply.
89
91
*
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.
102
103
*
103
104
* We do not yet implement a test to verify compatibility of expression
104
105
* columns or predicates, so assume any such index is incompatible.
@@ -111,6 +112,7 @@ CheckIndexCompatible(Oid oldId,
111
112
List * exclusionOpNames )
112
113
{
113
114
bool isconstraint ;
115
+ Oid * typeObjectId ;
114
116
Oid * collationObjectId ;
115
117
Oid * classObjectId ;
116
118
Oid accessMethodId ;
@@ -123,10 +125,10 @@ CheckIndexCompatible(Oid oldId,
123
125
int numberOfAttributes ;
124
126
int old_natts ;
125
127
bool isnull ;
126
- bool family_am ;
127
128
bool ret = true;
128
129
oidvector * old_indclass ;
129
130
oidvector * old_indcollation ;
131
+ Relation irel ;
130
132
int i ;
131
133
Datum d ;
132
134
@@ -168,10 +170,12 @@ CheckIndexCompatible(Oid oldId,
168
170
indexInfo -> ii_ExclusionOps = NULL ;
169
171
indexInfo -> ii_ExclusionProcs = NULL ;
170
172
indexInfo -> ii_ExclusionStrats = NULL ;
173
+ typeObjectId = (Oid * ) palloc (numberOfAttributes * sizeof (Oid ));
171
174
collationObjectId = (Oid * ) palloc (numberOfAttributes * sizeof (Oid ));
172
175
classObjectId = (Oid * ) palloc (numberOfAttributes * sizeof (Oid ));
173
176
coloptions = (int16 * ) palloc (numberOfAttributes * sizeof (int16 ));
174
- ComputeIndexAttrs (indexInfo , collationObjectId , classObjectId ,
177
+ ComputeIndexAttrs (indexInfo ,
178
+ typeObjectId , collationObjectId , classObjectId ,
175
179
coloptions , attributeList ,
176
180
exclusionOpNames , relationId ,
177
181
accessMethodName , accessMethodId ,
@@ -191,12 +195,7 @@ CheckIndexCompatible(Oid oldId,
191
195
return false;
192
196
}
193
197
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. */
200
199
old_natts = ((Form_pg_index ) GETSTRUCT (tuple ))-> indnatts ;
201
200
Assert (old_natts == numberOfAttributes );
202
201
@@ -208,52 +207,42 @@ CheckIndexCompatible(Oid oldId,
208
207
Assert (!isnull );
209
208
old_indclass = (oidvector * ) DatumGetPointer (d );
210
209
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 );
227
214
228
215
ReleaseSysCache (tuple );
229
216
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 )
238
225
{
239
- Relation irel ;
240
226
Oid * old_operators , * old_procs ;
241
227
uint16 * old_strats ;
242
228
243
- /* Caller probably already holds a stronger lock. */
244
- irel = index_open (oldId , AccessShareLock );
245
229
RelationGetExclusionInfo (irel , & old_operators , & old_procs , & old_strats );
230
+ ret = memcmp (old_operators , indexInfo -> ii_ExclusionOps ,
231
+ old_natts * sizeof (Oid )) == 0 ;
246
232
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 ;
253
238
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
+ }
255
243
}
256
244
245
+ index_close (irel , NoLock );
257
246
return ret ;
258
247
}
259
248
@@ -315,6 +304,7 @@ DefineIndex(RangeVar *heapRelation,
315
304
bool quiet ,
316
305
bool concurrent )
317
306
{
307
+ Oid * typeObjectId ;
318
308
Oid * collationObjectId ;
319
309
Oid * classObjectId ;
320
310
Oid accessMethodId ;
@@ -550,10 +540,12 @@ DefineIndex(RangeVar *heapRelation,
550
540
indexInfo -> ii_Concurrent = concurrent ;
551
541
indexInfo -> ii_BrokenHotChain = false;
552
542
543
+ typeObjectId = (Oid * ) palloc (numberOfAttributes * sizeof (Oid ));
553
544
collationObjectId = (Oid * ) palloc (numberOfAttributes * sizeof (Oid ));
554
545
classObjectId = (Oid * ) palloc (numberOfAttributes * sizeof (Oid ));
555
546
coloptions = (int16 * ) palloc (numberOfAttributes * sizeof (int16 ));
556
- ComputeIndexAttrs (indexInfo , collationObjectId , classObjectId ,
547
+ ComputeIndexAttrs (indexInfo ,
548
+ typeObjectId , collationObjectId , classObjectId ,
557
549
coloptions , attributeList ,
558
550
exclusionOpNames , relationId ,
559
551
accessMethodName , accessMethodId ,
@@ -980,6 +972,7 @@ CheckPredicate(Expr *predicate)
980
972
*/
981
973
static void
982
974
ComputeIndexAttrs (IndexInfo * indexInfo ,
975
+ Oid * typeOidP ,
983
976
Oid * collationOidP ,
984
977
Oid * classOidP ,
985
978
int16 * colOptionP ,
@@ -1108,6 +1101,8 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
1108
1101
}
1109
1102
}
1110
1103
1104
+ typeOidP [attn ] = atttype ;
1105
+
1111
1106
/*
1112
1107
* Apply collation override if any
1113
1108
*/
0 commit comments