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 );