8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.24 2000/04/23 01:44:55 tgl Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.25 2000/04/25 02:45:54 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
24
24
#include "catalog/pg_database.h"
25
25
#include "catalog/pg_index.h"
26
26
#include "catalog/pg_opclass.h"
27
+ #include "catalog/pg_operator.h"
27
28
#include "catalog/pg_proc.h"
28
29
#include "catalog/pg_shadow.h"
29
30
#include "catalog/pg_type.h"
32
33
#include "optimizer/planmain.h"
33
34
#include "optimizer/prep.h"
34
35
#include "parser/parsetree.h"
36
+ #include "parser/parse_coerce.h"
35
37
#include "parser/parse_func.h"
36
38
#include "parser/parse_type.h"
37
39
#include "utils/builtins.h"
@@ -556,7 +558,9 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
556
558
HeapScanDesc scan ;
557
559
ScanKeyData entry [2 ];
558
560
HeapTuple tuple ;
559
- Oid opClassId ;
561
+ Oid opClassId ,
562
+ oprId ;
563
+ bool doTypeCheck = true;
560
564
561
565
if (attribute -> class == NULL )
562
566
{
@@ -565,6 +569,8 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
565
569
if (attribute -> class == NULL )
566
570
elog (ERROR , "DefineIndex: type %s has no default operator class" ,
567
571
typeidTypeName (attrType ));
572
+ /* assume we need not check type compatibility */
573
+ doTypeCheck = false;
568
574
}
569
575
570
576
tuple = SearchSysCacheTuple (CLANAME ,
@@ -597,9 +603,42 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
597
603
attribute -> class , accessMethodName );
598
604
}
599
605
606
+ oprId = ((Form_pg_amop ) GETSTRUCT (tuple ))-> amopopr ;
607
+
600
608
heap_endscan (scan );
601
609
heap_close (relation , AccessShareLock );
602
610
611
+ /*
612
+ * Make sure the operators associated with this opclass actually accept
613
+ * the column data type. This prevents possible coredumps caused by
614
+ * user errors like applying text_ops to an int4 column. We will accept
615
+ * an opclass as OK if the operator's input datatype is binary-compatible
616
+ * with the actual column datatype. Note we assume that all the operators
617
+ * associated with an opclass accept the same datatypes, so checking the
618
+ * first one we happened to find in the table is sufficient.
619
+ *
620
+ * If the opclass was the default for the datatype, assume we can skip
621
+ * this check --- that saves a few cycles in the most common case.
622
+ * If pg_opclass is messed up then we're probably screwed anyway...
623
+ */
624
+ if (doTypeCheck )
625
+ {
626
+ tuple = SearchSysCacheTuple (OPEROID ,
627
+ ObjectIdGetDatum (oprId ),
628
+ 0 , 0 , 0 );
629
+ if (HeapTupleIsValid (tuple ))
630
+ {
631
+ Form_pg_operator optup = (Form_pg_operator ) GETSTRUCT (tuple );
632
+ Oid opInputType = (optup -> oprkind == 'l' ) ?
633
+ optup -> oprright : optup -> oprleft ;
634
+
635
+ if (attrType != opInputType &&
636
+ ! IS_BINARY_COMPATIBLE (attrType , opInputType ))
637
+ elog (ERROR , "DefineIndex: opclass \"%s\" does not accept datatype \"%s\"" ,
638
+ attribute -> class , typeidTypeName (attrType ));
639
+ }
640
+ }
641
+
603
642
return opClassId ;
604
643
}
605
644
0 commit comments