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

Commit 97f0521

Browse files
committed
Produce an appropriate error message when opclass is not supported by
specified index access method. Clean up wording of some existing error messages, too.
1 parent a77c4df commit 97f0521

File tree

1 file changed

+86
-37
lines changed

1 file changed

+86
-37
lines changed

src/backend/commands/indexcmds.c

+86-37
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.23 2000/04/12 17:14:58 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.24 2000/04/23 01:44:55 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -20,18 +20,20 @@
2020
#include "catalog/catname.h"
2121
#include "catalog/heap.h"
2222
#include "catalog/index.h"
23+
#include "catalog/pg_amop.h"
24+
#include "catalog/pg_database.h"
2325
#include "catalog/pg_index.h"
2426
#include "catalog/pg_opclass.h"
2527
#include "catalog/pg_proc.h"
26-
#include "catalog/pg_type.h"
27-
#include "catalog/pg_database.h"
2828
#include "catalog/pg_shadow.h"
29+
#include "catalog/pg_type.h"
2930
#include "commands/defrem.h"
3031
#include "optimizer/clauses.h"
3132
#include "optimizer/planmain.h"
3233
#include "optimizer/prep.h"
3334
#include "parser/parsetree.h"
3435
#include "parser/parse_func.h"
36+
#include "parser/parse_type.h"
3537
#include "utils/builtins.h"
3638
#include "utils/syscache.h"
3739
#include "miscadmin.h" /* ReindexDatabase() */
@@ -45,12 +47,15 @@ static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
4547
static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid);
4648
static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid);
4749
static void FuncIndexArgs(IndexElem *funcIndex, FuncIndexInfo *funcInfo,
48-
AttrNumber *attNumP, Oid *opOidP, Oid relId);
50+
AttrNumber *attNumP, Oid *opOidP, Oid relId,
51+
char *accessMethodName, Oid accessMethodId);
4952
static void NormIndexAttrs(List *attList, AttrNumber *attNumP,
50-
Oid *opOidP, Oid relId);
53+
Oid *opOidP, Oid relId,
54+
char *accessMethodName, Oid accessMethodId);
5155
static void ProcessAttrTypename(IndexElem *attribute,
5256
Oid defType, int32 defTypmod);
53-
static Oid GetAttrOpClass(IndexElem *attribute, Oid attrType);
57+
static Oid GetAttrOpClass(IndexElem *attribute, Oid attrType,
58+
char *accessMethodName, Oid accessMethodId);
5459
static char *GetDefaultOpClass(Oid atttypid);
5560

5661
/*
@@ -91,7 +96,7 @@ DefineIndex(char *heapRelationName,
9196
List *pl;
9297

9398
/*
94-
* Handle attributes
99+
* count attributes
95100
*/
96101
numberOfAttributes = length(attributeList);
97102
if (numberOfAttributes <= 0)
@@ -105,10 +110,15 @@ DefineIndex(char *heapRelationName,
105110
*/
106111
if ((relationId = RelnameFindRelid(heapRelationName)) == InvalidOid)
107112
{
108-
elog(ERROR, "DefineIndex: %s relation not found",
113+
elog(ERROR, "DefineIndex: relation \"%s\" not found",
109114
heapRelationName);
110115
}
111116

117+
/*
118+
* XXX Hardwired hacks to check for limitations on supported index types.
119+
* We really ought to be learning this info from entries in the pg_am
120+
* table, instead of having it wired in here!
121+
*/
112122
if (unique && strcmp(accessMethodName, "btree") != 0)
113123
elog(ERROR, "DefineIndex: unique indices are only available with the btree access method");
114124

@@ -123,7 +133,7 @@ DefineIndex(char *heapRelationName,
123133
0, 0, 0);
124134
if (!HeapTupleIsValid(tuple))
125135
{
126-
elog(ERROR, "DefineIndex: %s access method not found",
136+
elog(ERROR, "DefineIndex: access method \"%s\" not found",
127137
accessMethodName);
128138
}
129139
accessMethodId = tuple->t_data->t_oid;
@@ -138,7 +148,7 @@ DefineIndex(char *heapRelationName,
138148
if (!strcasecmp(param->defname, "islossy"))
139149
lossy = TRUE;
140150
else
141-
elog(NOTICE, "Unrecognized index attribute '%s' ignored",
151+
elog(NOTICE, "Unrecognized index attribute \"%s\" ignored",
142152
param->defname);
143153
}
144154

@@ -158,7 +168,8 @@ DefineIndex(char *heapRelationName,
158168
}
159169

160170
if (!IsBootstrapProcessingMode() && !IndexesAreActive(relationId, false))
161-
elog(ERROR, "existent indexes are inactive. REINDEX first");
171+
elog(ERROR, "Existing indexes are inactive. REINDEX first");
172+
162173
if (IsFuncIndex(attributeList))
163174
{
164175
IndexElem *funcIndex = lfirst(attributeList);
@@ -179,12 +190,12 @@ DefineIndex(char *heapRelationName,
179190
classObjectId = (Oid *) palloc(sizeof(Oid));
180191

181192
FuncIndexArgs(funcIndex, &fInfo, attributeNumberA,
182-
classObjectId, relationId);
193+
classObjectId, relationId,
194+
accessMethodName, accessMethodId);
183195

184-
index_create(heapRelationName,
185-
indexRelationName,
186-
&fInfo, NULL, accessMethodId,
187-
numberOfAttributes, attributeNumberA,
196+
index_create(heapRelationName, indexRelationName,
197+
&fInfo, NULL,
198+
accessMethodId, numberOfAttributes, attributeNumberA,
188199
classObjectId, parameterCount, parameterA,
189200
(Node *) cnfPred,
190201
lossy, unique, primary);
@@ -197,10 +208,11 @@ DefineIndex(char *heapRelationName,
197208
classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
198209

199210
NormIndexAttrs(attributeList, attributeNumberA,
200-
classObjectId, relationId);
211+
classObjectId, relationId,
212+
accessMethodName, accessMethodId);
201213

202-
index_create(heapRelationName, indexRelationName, NULL,
203-
attributeList,
214+
index_create(heapRelationName, indexRelationName,
215+
NULL, attributeList,
204216
accessMethodId, numberOfAttributes, attributeNumberA,
205217
classObjectId, parameterCount, parameterA,
206218
(Node *) cnfPred,
@@ -247,7 +259,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
247259
0, 0, 0);
248260
if (!HeapTupleIsValid(tuple))
249261
{
250-
elog(ERROR, "ExtendIndex: %s index not found",
262+
elog(ERROR, "ExtendIndex: index \"%s\" not found",
251263
indexRelationName);
252264
}
253265
indexId = tuple->t_data->t_oid;
@@ -261,7 +273,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
261273
0, 0, 0);
262274
if (!HeapTupleIsValid(tuple))
263275
{
264-
elog(ERROR, "ExtendIndex: %s is not an index",
276+
elog(ERROR, "ExtendIndex: relation \"%s\" is not an index",
265277
indexRelationName);
266278
}
267279

@@ -289,7 +301,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
289301
pfree(predString);
290302
}
291303
if (oldPred == NULL)
292-
elog(ERROR, "ExtendIndex: %s is not a partial index",
304+
elog(ERROR, "ExtendIndex: \"%s\" is not a partial index",
293305
indexRelationName);
294306

295307
/*
@@ -330,7 +342,8 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
330342
ObjectIdGetDatum(indproc),
331343
0, 0, 0);
332344
if (!HeapTupleIsValid(tuple))
333-
elog(ERROR, "ExtendIndex: index procedure not found");
345+
elog(ERROR, "ExtendIndex: index procedure %u not found",
346+
indproc);
334347

335348
namecpy(&(funcInfo->funcName),
336349
&(((Form_pg_proc) GETSTRUCT(tuple))->proname));
@@ -413,7 +426,9 @@ FuncIndexArgs(IndexElem *funcIndex,
413426
FuncIndexInfo *funcInfo,
414427
AttrNumber *attNumP,
415428
Oid *opOidP,
416-
Oid relId)
429+
Oid relId,
430+
char *accessMethodName,
431+
Oid accessMethodId)
417432
{
418433
List *rest;
419434
HeapTuple tuple;
@@ -465,14 +480,17 @@ FuncIndexArgs(IndexElem *funcIndex,
465480

466481
ProcessAttrTypename(funcIndex, retType, -1);
467482

468-
*opOidP = GetAttrOpClass(funcIndex, retType);
483+
*opOidP = GetAttrOpClass(funcIndex, retType,
484+
accessMethodName, accessMethodId);
469485
}
470486

471487
static void
472488
NormIndexAttrs(List *attList, /* list of IndexElem's */
473489
AttrNumber *attNumP,
474490
Oid *classOidP,
475-
Oid relId)
491+
Oid relId,
492+
char *accessMethodName,
493+
Oid accessMethodId)
476494
{
477495
List *rest;
478496

@@ -501,7 +519,8 @@ NormIndexAttrs(List *attList, /* list of IndexElem's */
501519

502520
ProcessAttrTypename(attribute, attform->atttypid, attform->atttypmod);
503521

504-
*classOidP++ = GetAttrOpClass(attribute, attform->atttypid);
522+
*classOidP++ = GetAttrOpClass(attribute, attform->atttypid,
523+
accessMethodName, accessMethodId);
505524

506525
heap_freetuple(atttuple);
507526
}
@@ -520,7 +539,7 @@ ProcessAttrTypename(IndexElem *attribute,
520539
ObjectIdGetDatum(defType),
521540
0, 0, 0);
522541
if (!HeapTupleIsValid(tuple))
523-
elog(ERROR, "DefineIndex: type for attribute '%s' undefined",
542+
elog(ERROR, "DefineIndex: type for attribute \"%s\" undefined",
524543
attribute->name);
525544

526545
attribute->typename = makeNode(TypeName);
@@ -530,28 +549,58 @@ ProcessAttrTypename(IndexElem *attribute,
530549
}
531550

532551
static Oid
533-
GetAttrOpClass(IndexElem *attribute, Oid attrType)
552+
GetAttrOpClass(IndexElem *attribute, Oid attrType,
553+
char *accessMethodName, Oid accessMethodId)
534554
{
555+
Relation relation;
556+
HeapScanDesc scan;
557+
ScanKeyData entry[2];
535558
HeapTuple tuple;
559+
Oid opClassId;
536560

537561
if (attribute->class == NULL)
538562
{
539563
/* no operator class specified, so find the default */
540564
attribute->class = GetDefaultOpClass(attrType);
541565
if (attribute->class == NULL)
542-
elog(ERROR, "Can't find a default operator class for type %u",
543-
attrType);
566+
elog(ERROR, "DefineIndex: type %s has no default operator class",
567+
typeidTypeName(attrType));
544568
}
545569

546570
tuple = SearchSysCacheTuple(CLANAME,
547571
PointerGetDatum(attribute->class),
548572
0, 0, 0);
549-
550573
if (!HeapTupleIsValid(tuple))
551-
elog(ERROR, "DefineIndex: %s opclass not found",
574+
elog(ERROR, "DefineIndex: opclass \"%s\" not found",
552575
attribute->class);
576+
opClassId = tuple->t_data->t_oid;
577+
578+
/*
579+
* Assume the opclass is supported by this index access method
580+
* if we can find at least one relevant entry in pg_amop.
581+
*/
582+
ScanKeyEntryInitialize(&entry[0], 0,
583+
Anum_pg_amop_amopid,
584+
F_OIDEQ,
585+
ObjectIdGetDatum(accessMethodId));
586+
ScanKeyEntryInitialize(&entry[1], 0,
587+
Anum_pg_amop_amopclaid,
588+
F_OIDEQ,
589+
ObjectIdGetDatum(opClassId));
590+
591+
relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
592+
scan = heap_beginscan(relation, false, SnapshotNow, 2, entry);
593+
594+
if (! HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
595+
{
596+
elog(ERROR, "DefineIndex: opclass \"%s\" not supported by access method \"%s\"",
597+
attribute->class, accessMethodName);
598+
}
599+
600+
heap_endscan(scan);
601+
heap_close(relation, AccessShareLock);
553602

554-
return tuple->t_data->t_oid;
603+
return opClassId;
555604
}
556605

557606
static char *
@@ -563,7 +612,7 @@ GetDefaultOpClass(Oid atttypid)
563612
ObjectIdGetDatum(atttypid),
564613
0, 0, 0);
565614
if (!HeapTupleIsValid(tuple))
566-
return 0;
615+
return NULL;
567616

568617
return nameout(&((Form_pg_opclass) GETSTRUCT(tuple))->opcname);
569618
}
@@ -697,7 +746,7 @@ ReindexDatabase(const char *dbname, bool force, bool all)
697746
usertuple = SearchSysCacheTuple(SHADOWNAME, PointerGetDatum(username),
698747
0, 0, 0);
699748
if (!HeapTupleIsValid(usertuple))
700-
elog(ERROR, "Current user '%s' is invalid.", username);
749+
elog(ERROR, "Current user \"%s\" is invalid.", username);
701750
user_id = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesysid;
702751
superuser = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesuper;
703752

@@ -707,7 +756,7 @@ ReindexDatabase(const char *dbname, bool force, bool all)
707756
scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scankey);
708757
dbtuple = heap_getnext(scan, 0);
709758
if (!HeapTupleIsValid(dbtuple))
710-
elog(ERROR, "Database '%s' doesn't exist", dbname);
759+
elog(ERROR, "Database \"%s\" doesn't exist", dbname);
711760
db_id = dbtuple->t_data->t_oid;
712761
db_owner = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
713762
heap_endscan(scan);

0 commit comments

Comments
 (0)