Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f46c1f1

Browse files
committed
Check that user-specified opclass in CREATE INDEX corresponds to operators
that will actually work on the column datatype.
1 parent e308786 commit f46c1f1

File tree

1 file changed

+41
-2
lines changed

1 file changed

+41
-2
lines changed

src/backend/commands/indexcmds.c

+41-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
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
*/
@@ -24,6 +24,7 @@
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"
@@ -32,6 +33,7 @@
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,
556558
HeapScanDesc scan;
557559
ScanKeyData entry[2];
558560
HeapTuple tuple;
559-
Oid opClassId;
561+
Oid opClassId,
562+
oprId;
563+
bool doTypeCheck = true;
560564

561565
if (attribute->class == NULL)
562566
{
@@ -565,6 +569,8 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
565569
if (attribute->class == NULL)
566570
elog(ERROR, "DefineIndex: type %s has no default operator class",
567571
typeidTypeName(attrType));
572+
/* assume we need not check type compatibility */
573+
doTypeCheck = false;
568574
}
569575

570576
tuple = SearchSysCacheTuple(CLANAME,
@@ -597,9 +603,42 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
597603
attribute->class, accessMethodName);
598604
}
599605

606+
oprId = ((Form_pg_amop) GETSTRUCT(tuple))->amopopr;
607+
600608
heap_endscan(scan);
601609
heap_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+
603642
return opClassId;
604643
}
605644

0 commit comments

Comments
 (0)