88 *
99 *
1010 * 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 $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
2424#include "catalog/pg_database.h"
2525#include "catalog/pg_index.h"
2626#include "catalog/pg_opclass.h"
27+ #include "catalog/pg_operator.h"
2728#include "catalog/pg_proc.h"
2829#include "catalog/pg_shadow.h"
2930#include "catalog/pg_type.h"
3233#include "optimizer/planmain.h"
3334#include "optimizer/prep.h"
3435#include "parser/parsetree.h"
36+ #include "parser/parse_coerce.h"
3537#include "parser/parse_func.h"
3638#include "parser/parse_type.h"
3739#include "utils/builtins.h"
@@ -556,7 +558,9 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
556558HeapScanDesc scan ;
557559ScanKeyData entry [2 ];
558560HeapTuple tuple ;
559- Oid opClassId ;
561+ Oid opClassId ,
562+ oprId ;
563+ bool doTypeCheck = true;
560564
561565if (attribute -> class == NULL )
562566{
@@ -565,6 +569,8 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
565569if (attribute -> class == NULL )
566570elog (ERROR ,"DefineIndex: type %s has no default operator class" ,
567571typeidTypeName (attrType ));
572+ /* assume we need not check type compatibility */
573+ doTypeCheck = false;
568574}
569575
570576tuple = SearchSysCacheTuple (CLANAME ,
@@ -597,9 +603,42 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
597603attribute -> class ,accessMethodName );
598604}
599605
606+ oprId = ((Form_pg_amop )GETSTRUCT (tuple ))-> amopopr ;
607+
600608heap_endscan (scan );
601609heap_close (relation ,AccessShareLock );
602610
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+
603642return opClassId ;
604643}
605644