summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-04-23 01:44:55 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-04-23 01:44:55 +0000
commit97f0521d8ec8bb440058e61d1349b88f66932788 (patch)
treee1248c26a83e0694336ce243fcd024b01631465c /src
parenta77c4df2c1558c84d06fb2a7a45a4ea09468eb95 (diff)
Produce an appropriate error message when opclass is not supported by
specified index access method. Clean up wording of some existing error messages, too.
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/indexcmds.c123
1 files changed, 86 insertions, 37 deletions
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 2577e4741b1..c1c16a844d4 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
*
*
* 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 @@
#include "catalog/catname.h"
#include "catalog/heap.h"
#include "catalog/index.h"
+#include "catalog/pg_amop.h"
+#include "catalog/pg_database.h"
#include "catalog/pg_index.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_proc.h"
-#include "catalog/pg_type.h"
-#include "catalog/pg_database.h"
#include "catalog/pg_shadow.h"
+#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "optimizer/clauses.h"
#include "optimizer/planmain.h"
#include "optimizer/prep.h"
#include "parser/parsetree.h"
#include "parser/parse_func.h"
+#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
#include "miscadmin.h" /* ReindexDatabase() */
@@ -45,12 +47,15 @@ static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid);
static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid);
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,
- Oid *opOidP, Oid relId);
+ Oid *opOidP, Oid relId,
+ char *accessMethodName, Oid accessMethodId);
static void ProcessAttrTypename(IndexElem *attribute,
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);
/*
@@ -91,7 +96,7 @@ DefineIndex(char *heapRelationName,
List *pl;
/*
- * Handle attributes
+ * count attributes
*/
numberOfAttributes = length(attributeList);
if (numberOfAttributes <= 0)
@@ -105,10 +110,15 @@ DefineIndex(char *heapRelationName,
*/
if ((relationId = RelnameFindRelid(heapRelationName)) == InvalidOid)
{
- elog(ERROR, "DefineIndex: %s relation not found",
+ elog(ERROR, "DefineIndex: relation \"%s\" not found",
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)
elog(ERROR, "DefineIndex: unique indices are only available with the btree access method");
@@ -123,7 +133,7 @@ DefineIndex(char *heapRelationName,
0, 0, 0);
if (!HeapTupleIsValid(tuple))
{
- elog(ERROR, "DefineIndex: %s access method not found",
+ elog(ERROR, "DefineIndex: access method \"%s\" not found",
accessMethodName);
}
accessMethodId = tuple->t_data->t_oid;
@@ -138,7 +148,7 @@ DefineIndex(char *heapRelationName,
if (!strcasecmp(param->defname, "islossy"))
lossy = TRUE;
else
- elog(NOTICE, "Unrecognized index attribute '%s' ignored",
+ elog(NOTICE, "Unrecognized index attribute \"%s\" ignored",
param->defname);
}
@@ -158,7 +168,8 @@ DefineIndex(char *heapRelationName,
}
if (!IsBootstrapProcessingMode() && !IndexesAreActive(relationId, false))
- elog(ERROR, "existent indexes are inactive. REINDEX first");
+ elog(ERROR, "Existing indexes are inactive. REINDEX first");
+
if (IsFuncIndex(attributeList))
{
IndexElem *funcIndex = lfirst(attributeList);
@@ -179,12 +190,12 @@ DefineIndex(char *heapRelationName,
classObjectId = (Oid *) palloc(sizeof(Oid));
FuncIndexArgs(funcIndex, &fInfo, attributeNumberA,
- classObjectId, relationId);
+ classObjectId, relationId,
+ accessMethodName, accessMethodId);
- index_create(heapRelationName,
- indexRelationName,
- &fInfo, NULL, accessMethodId,
- numberOfAttributes, attributeNumberA,
+ index_create(heapRelationName, indexRelationName,
+ &fInfo, NULL,
+ accessMethodId, numberOfAttributes, attributeNumberA,
classObjectId, parameterCount, parameterA,
(Node *) cnfPred,
lossy, unique, primary);
@@ -197,10 +208,11 @@ DefineIndex(char *heapRelationName,
classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
NormIndexAttrs(attributeList, attributeNumberA,
- classObjectId, relationId);
+ classObjectId, relationId,
+ accessMethodName, accessMethodId);
- index_create(heapRelationName, indexRelationName, NULL,
- attributeList,
+ index_create(heapRelationName, indexRelationName,
+ NULL, attributeList,
accessMethodId, numberOfAttributes, attributeNumberA,
classObjectId, parameterCount, parameterA,
(Node *) cnfPred,
@@ -247,7 +259,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
0, 0, 0);
if (!HeapTupleIsValid(tuple))
{
- elog(ERROR, "ExtendIndex: %s index not found",
+ elog(ERROR, "ExtendIndex: index \"%s\" not found",
indexRelationName);
}
indexId = tuple->t_data->t_oid;
@@ -261,7 +273,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
0, 0, 0);
if (!HeapTupleIsValid(tuple))
{
- elog(ERROR, "ExtendIndex: %s is not an index",
+ elog(ERROR, "ExtendIndex: relation \"%s\" is not an index",
indexRelationName);
}
@@ -289,7 +301,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
pfree(predString);
}
if (oldPred == NULL)
- elog(ERROR, "ExtendIndex: %s is not a partial index",
+ elog(ERROR, "ExtendIndex: \"%s\" is not a partial index",
indexRelationName);
/*
@@ -330,7 +342,8 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
ObjectIdGetDatum(indproc),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
- elog(ERROR, "ExtendIndex: index procedure not found");
+ elog(ERROR, "ExtendIndex: index procedure %u not found",
+ indproc);
namecpy(&(funcInfo->funcName),
&(((Form_pg_proc) GETSTRUCT(tuple))->proname));
@@ -413,7 +426,9 @@ FuncIndexArgs(IndexElem *funcIndex,
FuncIndexInfo *funcInfo,
AttrNumber *attNumP,
Oid *opOidP,
- Oid relId)
+ Oid relId,
+ char *accessMethodName,
+ Oid accessMethodId)
{
List *rest;
HeapTuple tuple;
@@ -465,14 +480,17 @@ FuncIndexArgs(IndexElem *funcIndex,
ProcessAttrTypename(funcIndex, retType, -1);
- *opOidP = GetAttrOpClass(funcIndex, retType);
+ *opOidP = GetAttrOpClass(funcIndex, retType,
+ accessMethodName, accessMethodId);
}
static void
NormIndexAttrs(List *attList, /* list of IndexElem's */
AttrNumber *attNumP,
Oid *classOidP,
- Oid relId)
+ Oid relId,
+ char *accessMethodName,
+ Oid accessMethodId)
{
List *rest;
@@ -501,7 +519,8 @@ NormIndexAttrs(List *attList, /* list of IndexElem's */
ProcessAttrTypename(attribute, attform->atttypid, attform->atttypmod);
- *classOidP++ = GetAttrOpClass(attribute, attform->atttypid);
+ *classOidP++ = GetAttrOpClass(attribute, attform->atttypid,
+ accessMethodName, accessMethodId);
heap_freetuple(atttuple);
}
@@ -520,7 +539,7 @@ ProcessAttrTypename(IndexElem *attribute,
ObjectIdGetDatum(defType),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
- elog(ERROR, "DefineIndex: type for attribute '%s' undefined",
+ elog(ERROR, "DefineIndex: type for attribute \"%s\" undefined",
attribute->name);
attribute->typename = makeNode(TypeName);
@@ -530,28 +549,58 @@ ProcessAttrTypename(IndexElem *attribute,
}
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;
+ Oid opClassId;
if (attribute->class == NULL)
{
/* no operator class specified, so find the default */
attribute->class = GetDefaultOpClass(attrType);
if (attribute->class == NULL)
- elog(ERROR, "Can't find a default operator class for type %u",
- attrType);
+ elog(ERROR, "DefineIndex: type %s has no default operator class",
+ typeidTypeName(attrType));
}
tuple = SearchSysCacheTuple(CLANAME,
PointerGetDatum(attribute->class),
0, 0, 0);
-
if (!HeapTupleIsValid(tuple))
- elog(ERROR, "DefineIndex: %s opclass not found",
+ elog(ERROR, "DefineIndex: opclass \"%s\" not found",
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 *
@@ -563,7 +612,7 @@ GetDefaultOpClass(Oid atttypid)
ObjectIdGetDatum(atttypid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
- return 0;
+ return NULL;
return nameout(&((Form_pg_opclass) GETSTRUCT(tuple))->opcname);
}
@@ -697,7 +746,7 @@ ReindexDatabase(const char *dbname, bool force, bool all)
usertuple = SearchSysCacheTuple(SHADOWNAME, PointerGetDatum(username),
0, 0, 0);
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;
superuser = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesuper;
@@ -707,7 +756,7 @@ ReindexDatabase(const char *dbname, bool force, bool all)
scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scankey);
dbtuple = heap_getnext(scan, 0);
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_owner = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
heap_endscan(scan);