8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
20
20
#include "catalog/catname.h"
21
21
#include "catalog/heap.h"
22
22
#include "catalog/index.h"
23
+ #include "catalog/pg_amop.h"
24
+ #include "catalog/pg_database.h"
23
25
#include "catalog/pg_index.h"
24
26
#include "catalog/pg_opclass.h"
25
27
#include "catalog/pg_proc.h"
26
- #include "catalog/pg_type.h"
27
- #include "catalog/pg_database.h"
28
28
#include "catalog/pg_shadow.h"
29
+ #include "catalog/pg_type.h"
29
30
#include "commands/defrem.h"
30
31
#include "optimizer/clauses.h"
31
32
#include "optimizer/planmain.h"
32
33
#include "optimizer/prep.h"
33
34
#include "parser/parsetree.h"
34
35
#include "parser/parse_func.h"
36
+ #include "parser/parse_type.h"
35
37
#include "utils/builtins.h"
36
38
#include "utils/syscache.h"
37
39
#include "miscadmin.h" /* ReindexDatabase() */
@@ -45,12 +47,15 @@ static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
45
47
static void CheckPredExpr (Node * predicate , List * rangeTable , Oid baseRelOid );
46
48
static void CheckPredClause (Expr * predicate , List * rangeTable , Oid baseRelOid );
47
49
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 );
49
52
static void NormIndexAttrs (List * attList , AttrNumber * attNumP ,
50
- Oid * opOidP , Oid relId );
53
+ Oid * opOidP , Oid relId ,
54
+ char * accessMethodName , Oid accessMethodId );
51
55
static void ProcessAttrTypename (IndexElem * attribute ,
52
56
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 );
54
59
static char * GetDefaultOpClass (Oid atttypid );
55
60
56
61
/*
@@ -91,7 +96,7 @@ DefineIndex(char *heapRelationName,
91
96
List * pl ;
92
97
93
98
/*
94
- * Handle attributes
99
+ * count attributes
95
100
*/
96
101
numberOfAttributes = length (attributeList );
97
102
if (numberOfAttributes <= 0 )
@@ -105,10 +110,15 @@ DefineIndex(char *heapRelationName,
105
110
*/
106
111
if ((relationId = RelnameFindRelid (heapRelationName )) == InvalidOid )
107
112
{
108
- elog (ERROR , "DefineIndex: %s relation not found" ,
113
+ elog (ERROR , "DefineIndex: relation \"%s\" not found" ,
109
114
heapRelationName );
110
115
}
111
116
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
+ */
112
122
if (unique && strcmp (accessMethodName , "btree" ) != 0 )
113
123
elog (ERROR , "DefineIndex: unique indices are only available with the btree access method" );
114
124
@@ -123,7 +133,7 @@ DefineIndex(char *heapRelationName,
123
133
0 , 0 , 0 );
124
134
if (!HeapTupleIsValid (tuple ))
125
135
{
126
- elog (ERROR , "DefineIndex: %s access method not found" ,
136
+ elog (ERROR , "DefineIndex: access method \"%s\" not found" ,
127
137
accessMethodName );
128
138
}
129
139
accessMethodId = tuple -> t_data -> t_oid ;
@@ -138,7 +148,7 @@ DefineIndex(char *heapRelationName,
138
148
if (!strcasecmp (param -> defname , "islossy" ))
139
149
lossy = TRUE;
140
150
else
141
- elog (NOTICE , "Unrecognized index attribute '%s' ignored" ,
151
+ elog (NOTICE , "Unrecognized index attribute \"%s\" ignored" ,
142
152
param -> defname );
143
153
}
144
154
@@ -158,7 +168,8 @@ DefineIndex(char *heapRelationName,
158
168
}
159
169
160
170
if (!IsBootstrapProcessingMode () && !IndexesAreActive (relationId , false))
161
- elog (ERROR , "existent indexes are inactive. REINDEX first" );
171
+ elog (ERROR , "Existing indexes are inactive. REINDEX first" );
172
+
162
173
if (IsFuncIndex (attributeList ))
163
174
{
164
175
IndexElem * funcIndex = lfirst (attributeList );
@@ -179,12 +190,12 @@ DefineIndex(char *heapRelationName,
179
190
classObjectId = (Oid * ) palloc (sizeof (Oid ));
180
191
181
192
FuncIndexArgs (funcIndex , & fInfo , attributeNumberA ,
182
- classObjectId , relationId );
193
+ classObjectId , relationId ,
194
+ accessMethodName , accessMethodId );
183
195
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 ,
188
199
classObjectId , parameterCount , parameterA ,
189
200
(Node * ) cnfPred ,
190
201
lossy , unique , primary );
@@ -197,10 +208,11 @@ DefineIndex(char *heapRelationName,
197
208
classObjectId = (Oid * ) palloc (numberOfAttributes * sizeof (Oid ));
198
209
199
210
NormIndexAttrs (attributeList , attributeNumberA ,
200
- classObjectId , relationId );
211
+ classObjectId , relationId ,
212
+ accessMethodName , accessMethodId );
201
213
202
- index_create (heapRelationName , indexRelationName , NULL ,
203
- attributeList ,
214
+ index_create (heapRelationName , indexRelationName ,
215
+ NULL , attributeList ,
204
216
accessMethodId , numberOfAttributes , attributeNumberA ,
205
217
classObjectId , parameterCount , parameterA ,
206
218
(Node * ) cnfPred ,
@@ -247,7 +259,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
247
259
0 , 0 , 0 );
248
260
if (!HeapTupleIsValid (tuple ))
249
261
{
250
- elog (ERROR , "ExtendIndex: %s index not found" ,
262
+ elog (ERROR , "ExtendIndex: index \"%s\" not found" ,
251
263
indexRelationName );
252
264
}
253
265
indexId = tuple -> t_data -> t_oid ;
@@ -261,7 +273,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
261
273
0 , 0 , 0 );
262
274
if (!HeapTupleIsValid (tuple ))
263
275
{
264
- elog (ERROR , "ExtendIndex: %s is not an index" ,
276
+ elog (ERROR , "ExtendIndex: relation \"%s\" is not an index" ,
265
277
indexRelationName );
266
278
}
267
279
@@ -289,7 +301,7 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
289
301
pfree (predString );
290
302
}
291
303
if (oldPred == NULL )
292
- elog (ERROR , "ExtendIndex: %s is not a partial index" ,
304
+ elog (ERROR , "ExtendIndex: \"%s\" is not a partial index" ,
293
305
indexRelationName );
294
306
295
307
/*
@@ -330,7 +342,8 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
330
342
ObjectIdGetDatum (indproc ),
331
343
0 , 0 , 0 );
332
344
if (!HeapTupleIsValid (tuple ))
333
- elog (ERROR , "ExtendIndex: index procedure not found" );
345
+ elog (ERROR , "ExtendIndex: index procedure %u not found" ,
346
+ indproc );
334
347
335
348
namecpy (& (funcInfo -> funcName ),
336
349
& (((Form_pg_proc ) GETSTRUCT (tuple ))-> proname ));
@@ -413,7 +426,9 @@ FuncIndexArgs(IndexElem *funcIndex,
413
426
FuncIndexInfo * funcInfo ,
414
427
AttrNumber * attNumP ,
415
428
Oid * opOidP ,
416
- Oid relId )
429
+ Oid relId ,
430
+ char * accessMethodName ,
431
+ Oid accessMethodId )
417
432
{
418
433
List * rest ;
419
434
HeapTuple tuple ;
@@ -465,14 +480,17 @@ FuncIndexArgs(IndexElem *funcIndex,
465
480
466
481
ProcessAttrTypename (funcIndex , retType , -1 );
467
482
468
- * opOidP = GetAttrOpClass (funcIndex , retType );
483
+ * opOidP = GetAttrOpClass (funcIndex , retType ,
484
+ accessMethodName , accessMethodId );
469
485
}
470
486
471
487
static void
472
488
NormIndexAttrs (List * attList , /* list of IndexElem's */
473
489
AttrNumber * attNumP ,
474
490
Oid * classOidP ,
475
- Oid relId )
491
+ Oid relId ,
492
+ char * accessMethodName ,
493
+ Oid accessMethodId )
476
494
{
477
495
List * rest ;
478
496
@@ -501,7 +519,8 @@ NormIndexAttrs(List *attList, /* list of IndexElem's */
501
519
502
520
ProcessAttrTypename (attribute , attform -> atttypid , attform -> atttypmod );
503
521
504
- * classOidP ++ = GetAttrOpClass (attribute , attform -> atttypid );
522
+ * classOidP ++ = GetAttrOpClass (attribute , attform -> atttypid ,
523
+ accessMethodName , accessMethodId );
505
524
506
525
heap_freetuple (atttuple );
507
526
}
@@ -520,7 +539,7 @@ ProcessAttrTypename(IndexElem *attribute,
520
539
ObjectIdGetDatum (defType ),
521
540
0 , 0 , 0 );
522
541
if (!HeapTupleIsValid (tuple ))
523
- elog (ERROR , "DefineIndex: type for attribute '%s' undefined" ,
542
+ elog (ERROR , "DefineIndex: type for attribute \"%s\" undefined" ,
524
543
attribute -> name );
525
544
526
545
attribute -> typename = makeNode (TypeName );
@@ -530,28 +549,58 @@ ProcessAttrTypename(IndexElem *attribute,
530
549
}
531
550
532
551
static Oid
533
- GetAttrOpClass (IndexElem * attribute , Oid attrType )
552
+ GetAttrOpClass (IndexElem * attribute , Oid attrType ,
553
+ char * accessMethodName , Oid accessMethodId )
534
554
{
555
+ Relation relation ;
556
+ HeapScanDesc scan ;
557
+ ScanKeyData entry [2 ];
535
558
HeapTuple tuple ;
559
+ Oid opClassId ;
536
560
537
561
if (attribute -> class == NULL )
538
562
{
539
563
/* no operator class specified, so find the default */
540
564
attribute -> class = GetDefaultOpClass (attrType );
541
565
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 ) );
544
568
}
545
569
546
570
tuple = SearchSysCacheTuple (CLANAME ,
547
571
PointerGetDatum (attribute -> class ),
548
572
0 , 0 , 0 );
549
-
550
573
if (!HeapTupleIsValid (tuple ))
551
- elog (ERROR , "DefineIndex: %s opclass not found" ,
574
+ elog (ERROR , "DefineIndex: opclass \"%s\" not found" ,
552
575
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 );
553
602
554
- return tuple -> t_data -> t_oid ;
603
+ return opClassId ;
555
604
}
556
605
557
606
static char *
@@ -563,7 +612,7 @@ GetDefaultOpClass(Oid atttypid)
563
612
ObjectIdGetDatum (atttypid ),
564
613
0 , 0 , 0 );
565
614
if (!HeapTupleIsValid (tuple ))
566
- return 0 ;
615
+ return NULL ;
567
616
568
617
return nameout (& ((Form_pg_opclass ) GETSTRUCT (tuple ))-> opcname );
569
618
}
@@ -697,7 +746,7 @@ ReindexDatabase(const char *dbname, bool force, bool all)
697
746
usertuple = SearchSysCacheTuple (SHADOWNAME , PointerGetDatum (username ),
698
747
0 , 0 , 0 );
699
748
if (!HeapTupleIsValid (usertuple ))
700
- elog (ERROR , "Current user '%s' is invalid." , username );
749
+ elog (ERROR , "Current user \"%s\" is invalid." , username );
701
750
user_id = ((Form_pg_shadow ) GETSTRUCT (usertuple ))-> usesysid ;
702
751
superuser = ((Form_pg_shadow ) GETSTRUCT (usertuple ))-> usesuper ;
703
752
@@ -707,7 +756,7 @@ ReindexDatabase(const char *dbname, bool force, bool all)
707
756
scan = heap_beginscan (relation , 0 , SnapshotNow , 1 , & scankey );
708
757
dbtuple = heap_getnext (scan , 0 );
709
758
if (!HeapTupleIsValid (dbtuple ))
710
- elog (ERROR , "Database '%s' doesn't exist" , dbname );
759
+ elog (ERROR , "Database \"%s\" doesn't exist" , dbname );
711
760
db_id = dbtuple -> t_data -> t_oid ;
712
761
db_owner = ((Form_pg_database ) GETSTRUCT (dbtuple ))-> datdba ;
713
762
heap_endscan (scan );
0 commit comments