mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-30 07:31:16 +02: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
|
* 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_database.h"
|
||||||
#include "catalog/pg_index.h"
|
#include "catalog/pg_index.h"
|
||||||
#include "catalog/pg_opclass.h"
|
#include "catalog/pg_opclass.h"
|
||||||
|
#include "catalog/pg_operator.h"
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
#include "catalog/pg_shadow.h"
|
#include "catalog/pg_shadow.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
@ -32,6 +33,7 @@
|
|||||||
#include "optimizer/planmain.h"
|
#include "optimizer/planmain.h"
|
||||||
#include "optimizer/prep.h"
|
#include "optimizer/prep.h"
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
|
#include "parser/parse_coerce.h"
|
||||||
#include "parser/parse_func.h"
|
#include "parser/parse_func.h"
|
||||||
#include "parser/parse_type.h"
|
#include "parser/parse_type.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
@ -556,7 +558,9 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
|
|||||||
HeapScanDesc scan;
|
HeapScanDesc scan;
|
||||||
ScanKeyData entry[2];
|
ScanKeyData entry[2];
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
Oid opClassId;
|
Oid opClassId,
|
||||||
|
oprId;
|
||||||
|
bool doTypeCheck = true;
|
||||||
|
|
||||||
if (attribute->class == NULL)
|
if (attribute->class == NULL)
|
||||||
{
|
{
|
||||||
@ -565,6 +569,8 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
|
|||||||
if (attribute->class == NULL)
|
if (attribute->class == NULL)
|
||||||
elog(ERROR, "DefineIndex: type %s has no default operator class",
|
elog(ERROR, "DefineIndex: type %s has no default operator class",
|
||||||
typeidTypeName(attrType));
|
typeidTypeName(attrType));
|
||||||
|
/* assume we need not check type compatibility */
|
||||||
|
doTypeCheck = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple = SearchSysCacheTuple(CLANAME,
|
tuple = SearchSysCacheTuple(CLANAME,
|
||||||
@ -597,9 +603,42 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
|
|||||||
attribute->class, accessMethodName);
|
attribute->class, accessMethodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oprId = ((Form_pg_amop) GETSTRUCT(tuple))->amopopr;
|
||||||
|
|
||||||
heap_endscan(scan);
|
heap_endscan(scan);
|
||||||
heap_close(relation, AccessShareLock);
|
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;
|
return opClassId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user