Commit 97f0521d authored by Tom Lane's avatar Tom Lane

Produce an appropriate error message when opclass is not supported by

specified index access method.  Clean up wording of some existing error
messages, too.
parent a77c4df2
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.23 2000/04/12 17:14:58 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.24 2000/04/23 01:44:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -20,18 +20,20 @@ ...@@ -20,18 +20,20 @@
#include "catalog/catname.h" #include "catalog/catname.h"
#include "catalog/heap.h" #include "catalog/heap.h"
#include "catalog/index.h" #include "catalog/index.h"
#include "catalog/pg_amop.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_proc.h" #include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "catalog/pg_database.h"
#include "catalog/pg_shadow.h" #include "catalog/pg_shadow.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#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_func.h" #include "parser/parse_func.h"
#include "parser/parse_type.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "miscadmin.h" /* ReindexDatabase() */ #include "miscadmin.h" /* ReindexDatabase() */
...@@ -45,12 +47,15 @@ static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid); ...@@ -45,12 +47,15 @@ static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid); static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid);
static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid); static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid);
static void FuncIndexArgs(IndexElem *funcIndex, FuncIndexInfo *funcInfo, static void FuncIndexArgs(IndexElem *funcIndex, FuncIndexInfo *funcInfo,
AttrNumber *attNumP, Oid *opOidP, Oid relId); AttrNumber *attNumP, Oid *opOidP, Oid relId,
char *accessMethodName, Oid accessMethodId);
static void NormIndexAttrs(List *attList, AttrNumber *attNumP, static void NormIndexAttrs(List *attList, AttrNumber *attNumP,
Oid *opOidP, Oid relId); Oid *opOidP, Oid relId,
char *accessMethodName, Oid accessMethodId);
static void ProcessAttrTypename(IndexElem *attribute, static void ProcessAttrTypename(IndexElem *attribute,
Oid defType, int32 defTypmod); Oid defType, int32 defTypmod);
static Oid GetAttrOpClass(IndexElem *attribute, Oid attrType); static Oid GetAttrOpClass(IndexElem *attribute, Oid attrType,
char *accessMethodName, Oid accessMethodId);
static char *GetDefaultOpClass(Oid atttypid); static char *GetDefaultOpClass(Oid atttypid);
/* /*
...@@ -91,7 +96,7 @@ DefineIndex(char *heapRelationName, ...@@ -91,7 +96,7 @@ DefineIndex(char *heapRelationName,
List *pl; List *pl;
/* /*
* Handle attributes * count attributes
*/ */
numberOfAttributes = length(attributeList); numberOfAttributes = length(attributeList);
if (numberOfAttributes <= 0) if (numberOfAttributes <= 0)
...@@ -105,10 +110,15 @@ DefineIndex(char *heapRelationName, ...@@ -105,10 +110,15 @@ DefineIndex(char *heapRelationName,
*/ */
if ((relationId = RelnameFindRelid(heapRelationName)) == InvalidOid) if ((relationId = RelnameFindRelid(heapRelationName)) == InvalidOid)
{ {
elog(ERROR, "DefineIndex: %s relation not found", elog(ERROR, "DefineIndex: relation \"%s\" not found",
heapRelationName); heapRelationName);
} }
/*
* XXX Hardwired hacks to check for limitations on supported index types.
* We really ought to be learning this info from entries in the pg_am
* table, instead of having it wired in here!
*/
if (unique && strcmp(accessMethodName, "btree") != 0) if (unique && strcmp(accessMethodName, "btree") != 0)
elog(ERROR, "DefineIndex: unique indices are only available with the btree access method"); elog(ERROR, "DefineIndex: unique indices are only available with the btree access method");
...@@ -123,7 +133,7 @@ DefineIndex(char *heapRelationName, ...@@ -123,7 +133,7 @@ DefineIndex(char *heapRelationName,
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
{ {
elog(ERROR, "DefineIndex: %s access method not found", elog(ERROR, "DefineIndex: access method \"%s\" not found",
accessMethodName); accessMethodName);
} }
accessMethodId = tuple->t_data->t_oid; accessMethodId = tuple->t_data->t_oid;
...@@ -138,7 +148,7 @@ DefineIndex(char *heapRelationName, ...@@ -138,7 +148,7 @@ DefineIndex(char *heapRelationName,
if (!strcasecmp(param->defname, "islossy")) if (!strcasecmp(param->defname, "islossy"))
lossy = TRUE; lossy = TRUE;
else else
elog(NOTICE, "Unrecognized index attribute '%s' ignored", elog(NOTICE, "Unrecognized index attribute \"%s\" ignored",
param->defname); param->defname);
} }
...@@ -158,7 +168,8 @@ DefineIndex(char *heapRelationName, ...@@ -158,7 +168,8 @@ DefineIndex(char *heapRelationName,
} }
if (!IsBootstrapProcessingMode() && !IndexesAreActive(relationId, false)) if (!IsBootstrapProcessingMode() && !IndexesAreActive(relationId, false))
elog(ERROR, "existent indexes are inactive. REINDEX first"); elog(ERROR, "Existing indexes are inactive. REINDEX first");
if (IsFuncIndex(attributeList)) if (IsFuncIndex(attributeList))
{ {
IndexElem *funcIndex = lfirst(attributeList); IndexElem *funcIndex = lfirst(attributeList);
...@@ -179,12 +190,12 @@ DefineIndex(char *heapRelationName, ...@@ -179,12 +190,12 @@ DefineIndex(char *heapRelationName,
classObjectId = (Oid *) palloc(sizeof(Oid)); classObjectId = (Oid *) palloc(sizeof(Oid));
FuncIndexArgs(funcIndex, &fInfo, attributeNumberA, FuncIndexArgs(funcIndex, &fInfo, attributeNumberA,
classObjectId, relationId); classObjectId, relationId,
accessMethodName, accessMethodId);
index_create(heapRelationName, index_create(heapRelationName, indexRelationName,
indexRelationName, &fInfo, NULL,
&fInfo, NULL, accessMethodId, accessMethodId, numberOfAttributes, attributeNumberA,
numberOfAttributes, attributeNumberA,
classObjectId, parameterCount, parameterA, classObjectId, parameterCount, parameterA,
(Node *) cnfPred, (Node *) cnfPred,
lossy, unique, primary); lossy, unique, primary);
...@@ -197,10 +208,11 @@ DefineIndex(char *heapRelationName, ...@@ -197,10 +208,11 @@ DefineIndex(char *heapRelationName,
classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid)); classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
NormIndexAttrs(attributeList, attributeNumberA, NormIndexAttrs(attributeList, attributeNumberA,
classObjectId, relationId); classObjectId, relationId,
accessMethodName, accessMethodId);
index_create(heapRelationName, indexRelationName, NULL, index_create(heapRelationName, indexRelationName,
attributeList, NULL, attributeList,
accessMethodId, numberOfAttributes, attributeNumberA, accessMethodId, numberOfAttributes, attributeNumberA,
classObjectId, parameterCount, parameterA, classObjectId, parameterCount, parameterA,
(Node *) cnfPred, (Node *) cnfPred,
...@@ -247,7 +259,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) ...@@ -247,7 +259,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
{ {
elog(ERROR, "ExtendIndex: %s index not found", elog(ERROR, "ExtendIndex: index \"%s\" not found",
indexRelationName); indexRelationName);
} }
indexId = tuple->t_data->t_oid; indexId = tuple->t_data->t_oid;
...@@ -261,7 +273,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) ...@@ -261,7 +273,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
{ {
elog(ERROR, "ExtendIndex: %s is not an index", elog(ERROR, "ExtendIndex: relation \"%s\" is not an index",
indexRelationName); indexRelationName);
} }
...@@ -289,7 +301,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) ...@@ -289,7 +301,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
pfree(predString); pfree(predString);
} }
if (oldPred == NULL) if (oldPred == NULL)
elog(ERROR, "ExtendIndex: %s is not a partial index", elog(ERROR, "ExtendIndex: \"%s\" is not a partial index",
indexRelationName); indexRelationName);
/* /*
...@@ -330,7 +342,8 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) ...@@ -330,7 +342,8 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
ObjectIdGetDatum(indproc), ObjectIdGetDatum(indproc),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
elog(ERROR, "ExtendIndex: index procedure not found"); elog(ERROR, "ExtendIndex: index procedure %u not found",
indproc);
namecpy(&(funcInfo->funcName), namecpy(&(funcInfo->funcName),
&(((Form_pg_proc) GETSTRUCT(tuple))->proname)); &(((Form_pg_proc) GETSTRUCT(tuple))->proname));
...@@ -413,7 +426,9 @@ FuncIndexArgs(IndexElem *funcIndex, ...@@ -413,7 +426,9 @@ FuncIndexArgs(IndexElem *funcIndex,
FuncIndexInfo *funcInfo, FuncIndexInfo *funcInfo,
AttrNumber *attNumP, AttrNumber *attNumP,
Oid *opOidP, Oid *opOidP,
Oid relId) Oid relId,
char *accessMethodName,
Oid accessMethodId)
{ {
List *rest; List *rest;
HeapTuple tuple; HeapTuple tuple;
...@@ -465,14 +480,17 @@ FuncIndexArgs(IndexElem *funcIndex, ...@@ -465,14 +480,17 @@ FuncIndexArgs(IndexElem *funcIndex,
ProcessAttrTypename(funcIndex, retType, -1); ProcessAttrTypename(funcIndex, retType, -1);
*opOidP = GetAttrOpClass(funcIndex, retType); *opOidP = GetAttrOpClass(funcIndex, retType,
accessMethodName, accessMethodId);
} }
static void static void
NormIndexAttrs(List *attList, /* list of IndexElem's */ NormIndexAttrs(List *attList, /* list of IndexElem's */
AttrNumber *attNumP, AttrNumber *attNumP,
Oid *classOidP, Oid *classOidP,
Oid relId) Oid relId,
char *accessMethodName,
Oid accessMethodId)
{ {
List *rest; List *rest;
...@@ -501,7 +519,8 @@ NormIndexAttrs(List *attList, /* list of IndexElem's */ ...@@ -501,7 +519,8 @@ NormIndexAttrs(List *attList, /* list of IndexElem's */
ProcessAttrTypename(attribute, attform->atttypid, attform->atttypmod); ProcessAttrTypename(attribute, attform->atttypid, attform->atttypmod);
*classOidP++ = GetAttrOpClass(attribute, attform->atttypid); *classOidP++ = GetAttrOpClass(attribute, attform->atttypid,
accessMethodName, accessMethodId);
heap_freetuple(atttuple); heap_freetuple(atttuple);
} }
...@@ -520,7 +539,7 @@ ProcessAttrTypename(IndexElem *attribute, ...@@ -520,7 +539,7 @@ ProcessAttrTypename(IndexElem *attribute,
ObjectIdGetDatum(defType), ObjectIdGetDatum(defType),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
elog(ERROR, "DefineIndex: type for attribute '%s' undefined", elog(ERROR, "DefineIndex: type for attribute \"%s\" undefined",
attribute->name); attribute->name);
attribute->typename = makeNode(TypeName); attribute->typename = makeNode(TypeName);
...@@ -530,28 +549,58 @@ ProcessAttrTypename(IndexElem *attribute, ...@@ -530,28 +549,58 @@ ProcessAttrTypename(IndexElem *attribute,
} }
static Oid static Oid
GetAttrOpClass(IndexElem *attribute, Oid attrType) GetAttrOpClass(IndexElem *attribute, Oid attrType,
char *accessMethodName, Oid accessMethodId)
{ {
Relation relation;
HeapScanDesc scan;
ScanKeyData entry[2];
HeapTuple tuple; HeapTuple tuple;
Oid opClassId;
if (attribute->class == NULL) if (attribute->class == NULL)
{ {
/* no operator class specified, so find the default */ /* no operator class specified, so find the default */
attribute->class = GetDefaultOpClass(attrType); attribute->class = GetDefaultOpClass(attrType);
if (attribute->class == NULL) if (attribute->class == NULL)
elog(ERROR, "Can't find a default operator class for type %u", elog(ERROR, "DefineIndex: type %s has no default operator class",
attrType); typeidTypeName(attrType));
} }
tuple = SearchSysCacheTuple(CLANAME, tuple = SearchSysCacheTuple(CLANAME,
PointerGetDatum(attribute->class), PointerGetDatum(attribute->class),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
elog(ERROR, "DefineIndex: %s opclass not found", elog(ERROR, "DefineIndex: opclass \"%s\" not found",
attribute->class); attribute->class);
opClassId = tuple->t_data->t_oid;
/*
* Assume the opclass is supported by this index access method
* if we can find at least one relevant entry in pg_amop.
*/
ScanKeyEntryInitialize(&entry[0], 0,
Anum_pg_amop_amopid,
F_OIDEQ,
ObjectIdGetDatum(accessMethodId));
ScanKeyEntryInitialize(&entry[1], 0,
Anum_pg_amop_amopclaid,
F_OIDEQ,
ObjectIdGetDatum(opClassId));
relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
scan = heap_beginscan(relation, false, SnapshotNow, 2, entry);
if (! HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
elog(ERROR, "DefineIndex: opclass \"%s\" not supported by access method \"%s\"",
attribute->class, accessMethodName);
}
heap_endscan(scan);
heap_close(relation, AccessShareLock);
return tuple->t_data->t_oid; return opClassId;
} }
static char * static char *
...@@ -563,7 +612,7 @@ GetDefaultOpClass(Oid atttypid) ...@@ -563,7 +612,7 @@ GetDefaultOpClass(Oid atttypid)
ObjectIdGetDatum(atttypid), ObjectIdGetDatum(atttypid),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
return 0; return NULL;
return nameout(&((Form_pg_opclass) GETSTRUCT(tuple))->opcname); return nameout(&((Form_pg_opclass) GETSTRUCT(tuple))->opcname);
} }
...@@ -697,7 +746,7 @@ ReindexDatabase(const char *dbname, bool force, bool all) ...@@ -697,7 +746,7 @@ ReindexDatabase(const char *dbname, bool force, bool all)
usertuple = SearchSysCacheTuple(SHADOWNAME, PointerGetDatum(username), usertuple = SearchSysCacheTuple(SHADOWNAME, PointerGetDatum(username),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(usertuple)) if (!HeapTupleIsValid(usertuple))
elog(ERROR, "Current user '%s' is invalid.", username); elog(ERROR, "Current user \"%s\" is invalid.", username);
user_id = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesysid; user_id = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesysid;
superuser = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesuper; superuser = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesuper;
...@@ -707,7 +756,7 @@ ReindexDatabase(const char *dbname, bool force, bool all) ...@@ -707,7 +756,7 @@ ReindexDatabase(const char *dbname, bool force, bool all)
scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scankey); scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scankey);
dbtuple = heap_getnext(scan, 0); dbtuple = heap_getnext(scan, 0);
if (!HeapTupleIsValid(dbtuple)) if (!HeapTupleIsValid(dbtuple))
elog(ERROR, "Database '%s' doesn't exist", dbname); elog(ERROR, "Database \"%s\" doesn't exist", dbname);
db_id = dbtuple->t_data->t_oid; db_id = dbtuple->t_data->t_oid;
db_owner = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba; db_owner = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
heap_endscan(scan); heap_endscan(scan);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment