mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-09 08:10:09 +08:00
Check that user-specified opclass in CREATE INDEX corresponds to operators
that will actually work on the column datatype.
This commit is contained in:
parent
e308786889
commit
f46c1f1e33
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.24 2000/04/23 01:44:55 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.25 2000/04/25 02:45:54 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -24,6 +24,7 @@
|
||||
#include "catalog/pg_database.h"
|
||||
#include "catalog/pg_index.h"
|
||||
#include "catalog/pg_opclass.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_shadow.h"
|
||||
#include "catalog/pg_type.h"
|
||||
@ -32,6 +33,7 @@
|
||||
#include "optimizer/planmain.h"
|
||||
#include "optimizer/prep.h"
|
||||
#include "parser/parsetree.h"
|
||||
#include "parser/parse_coerce.h"
|
||||
#include "parser/parse_func.h"
|
||||
#include "parser/parse_type.h"
|
||||
#include "utils/builtins.h"
|
||||
@ -556,7 +558,9 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
|
||||
HeapScanDesc scan;
|
||||
ScanKeyData entry[2];
|
||||
HeapTuple tuple;
|
||||
Oid opClassId;
|
||||
Oid opClassId,
|
||||
oprId;
|
||||
bool doTypeCheck = true;
|
||||
|
||||
if (attribute->class == NULL)
|
||||
{
|
||||
@ -565,6 +569,8 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
|
||||
if (attribute->class == NULL)
|
||||
elog(ERROR, "DefineIndex: type %s has no default operator class",
|
||||
typeidTypeName(attrType));
|
||||
/* assume we need not check type compatibility */
|
||||
doTypeCheck = false;
|
||||
}
|
||||
|
||||
tuple = SearchSysCacheTuple(CLANAME,
|
||||
@ -597,9 +603,42 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
|
||||
attribute->class, accessMethodName);
|
||||
}
|
||||
|
||||
oprId = ((Form_pg_amop) GETSTRUCT(tuple))->amopopr;
|
||||
|
||||
heap_endscan(scan);
|
||||
heap_close(relation, AccessShareLock);
|
||||
|
||||
/*
|
||||
* Make sure the operators associated with this opclass actually accept
|
||||
* the column data type. This prevents possible coredumps caused by
|
||||
* user errors like applying text_ops to an int4 column. We will accept
|
||||
* an opclass as OK if the operator's input datatype is binary-compatible
|
||||
* with the actual column datatype. Note we assume that all the operators
|
||||
* associated with an opclass accept the same datatypes, so checking the
|
||||
* first one we happened to find in the table is sufficient.
|
||||
*
|
||||
* If the opclass was the default for the datatype, assume we can skip
|
||||
* this check --- that saves a few cycles in the most common case.
|
||||
* If pg_opclass is messed up then we're probably screwed anyway...
|
||||
*/
|
||||
if (doTypeCheck)
|
||||
{
|
||||
tuple = SearchSysCacheTuple(OPEROID,
|
||||
ObjectIdGetDatum(oprId),
|
||||
0, 0, 0);
|
||||
if (HeapTupleIsValid(tuple))
|
||||
{
|
||||
Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tuple);
|
||||
Oid opInputType = (optup->oprkind == 'l') ?
|
||||
optup->oprright : optup->oprleft;
|
||||
|
||||
if (attrType != opInputType &&
|
||||
! IS_BINARY_COMPATIBLE(attrType, opInputType))
|
||||
elog(ERROR, "DefineIndex: opclass \"%s\" does not accept datatype \"%s\"",
|
||||
attribute->class, typeidTypeName(attrType));
|
||||
}
|
||||
}
|
||||
|
||||
return opClassId;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user