88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.21 2000/02/18 09:29:37 inoue Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.22 2000/02/25 02:58:48 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
3131#include "optimizer/planmain.h"
3232#include "optimizer/prep.h"
3333#include "parser/parsetree.h"
34+ #include "parser/parse_func.h"
3435#include "utils/builtins.h"
3536#include "utils/syscache.h"
3637#include "miscadmin.h" /* ReindexDatabase() */
3738#include "utils/portal.h" /* ReindexDatabase() */
3839#include "catalog/catalog.h" /* ReindexDatabase() */
3940
40- #define IsFuncIndex (ATTR_LIST ) (((IndexElem*)lfirst(ATTR_LIST))->args!=NULL )
41+ #define IsFuncIndex (ATTR_LIST ) (((IndexElem*)lfirst(ATTR_LIST))->args != NIL )
4142
4243/* non-export function prototypes */
4344static void CheckPredicate (List * predList , List * rangeTable , Oid baseRelOid );
44- static void CheckPredExpr (Node * predicate , List * rangeTable ,
45- Oid baseRelOid );
46- static void
47- CheckPredClause (Expr * predicate , List * rangeTable , Oid baseRelOid );
48- static void FuncIndexArgs (IndexElem * funcIndex , AttrNumber * attNumP ,
49- Oid * argTypes , Oid * opOidP , Oid relId );
45+ static void CheckPredExpr (Node * predicate , List * rangeTable , Oid baseRelOid );
46+ static void CheckPredClause (Expr * predicate , List * rangeTable , Oid baseRelOid );
47+ static void FuncIndexArgs (IndexElem * funcIndex , FuncIndexInfo * funcInfo ,
48+ AttrNumber * attNumP , Oid * opOidP , Oid relId );
5049static void NormIndexAttrs (List * attList , AttrNumber * attNumP ,
51- Oid * opOidP , Oid relId );
50+ Oid * opOidP , Oid relId );
51+ static void ProcessAttrTypename (IndexElem * attribute ,
52+ Oid defType , int32 defTypmod );
53+ static Oid GetAttrOpClass (IndexElem * attribute , Oid attrType );
5254static char * GetDefaultOpClass (Oid atttypid );
5355
5456/*
@@ -169,40 +171,42 @@ DefineIndex(char *heapRelationName,
169171
170172 FIsetnArgs (& fInfo , nargs );
171173
172- strcpy (FIgetname (& fInfo ), funcIndex -> name );
173-
174- attributeNumberA = (AttrNumber * ) palloc (nargs * sizeof attributeNumberA [0 ]);
174+ namestrcpy (& fInfo .funcName , funcIndex -> name );
175175
176- classObjectId = (Oid * ) palloc (sizeof classObjectId [0 ]);
176+ attributeNumberA = (AttrNumber * ) palloc (nargs *
177+ sizeof attributeNumberA [0 ]);
177178
179+ classObjectId = (Oid * ) palloc (sizeof (Oid ));
178180
179- FuncIndexArgs (funcIndex , attributeNumberA ,
180- & (FIgetArg (& fInfo , 0 )),
181+ FuncIndexArgs (funcIndex , & fInfo , attributeNumberA ,
181182 classObjectId , relationId );
182183
183184 index_create (heapRelationName ,
184185 indexRelationName ,
185186 & fInfo , NULL , accessMethodId ,
186187 numberOfAttributes , attributeNumberA ,
187- classObjectId , parameterCount , parameterA , (Node * ) cnfPred ,
188+ classObjectId , parameterCount , parameterA ,
189+ (Node * ) cnfPred ,
188190 lossy , unique , primary );
189191 }
190192 else
191193 {
192194 attributeNumberA = (AttrNumber * ) palloc (numberOfAttributes *
193- sizeof attributeNumberA [0 ]);
195+ sizeof attributeNumberA [0 ]);
194196
195- classObjectId = (Oid * ) palloc (numberOfAttributes * sizeof classObjectId [ 0 ] );
197+ classObjectId = (Oid * ) palloc (numberOfAttributes * sizeof ( Oid ) );
196198
197199 NormIndexAttrs (attributeList , attributeNumberA ,
198200 classObjectId , relationId );
199201
200202 index_create (heapRelationName , indexRelationName , NULL ,
201203 attributeList ,
202204 accessMethodId , numberOfAttributes , attributeNumberA ,
203- classObjectId , parameterCount , parameterA , (Node * ) cnfPred ,
205+ classObjectId , parameterCount , parameterA ,
206+ (Node * ) cnfPred ,
204207 lossy , unique , primary );
205208 }
209+
206210 setRelhasindexInplace (relationId , true, false);
207211}
208212
@@ -320,7 +324,6 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
320324 if (indproc != InvalidOid )
321325 {
322326 funcInfo = & fInfo ;
323- /* FIgetnArgs(funcInfo) = numberOfAttributes; */
324327 FIsetnArgs (funcInfo , numberOfAttributes );
325328
326329 tuple = SearchSysCacheTuple (PROCOID ,
@@ -407,51 +410,62 @@ CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid)
407410
408411static void
409412FuncIndexArgs (IndexElem * funcIndex ,
413+ FuncIndexInfo * funcInfo ,
410414 AttrNumber * attNumP ,
411- Oid * argTypes ,
412415 Oid * opOidP ,
413416 Oid relId )
414417{
415418 List * rest ;
416419 HeapTuple tuple ;
417- Form_pg_attribute att ;
418-
419- tuple = SearchSysCacheTuple (CLANAME ,
420- PointerGetDatum (funcIndex -> class ),
421- 0 , 0 , 0 );
422-
423- if (!HeapTupleIsValid (tuple ))
424- {
425- elog (ERROR , "DefineIndex: %s class not found" ,
426- funcIndex -> class );
427- }
428- * opOidP = tuple -> t_data -> t_oid ;
429-
430- MemSet (argTypes , 0 , FUNC_MAX_ARGS * sizeof (Oid ));
420+ Oid retType ;
421+ int argn = 0 ;
431422
432423 /*
433- * process the function arguments
424+ * process the function arguments, which are a list of T_String
425+ * (someday ought to allow more general expressions?)
434426 */
435- for (rest = funcIndex -> args ; rest != NIL ; rest = lnext (rest ))
436- {
437- char * arg ;
427+ MemSet (funcInfo -> arglist , 0 , FUNC_MAX_ARGS * sizeof (Oid ));
438428
439- arg = strVal (lfirst (rest ));
429+ foreach (rest , funcIndex -> args )
430+ {
431+ char * arg = strVal (lfirst (rest ));
432+ Form_pg_attribute att ;
440433
441434 tuple = SearchSysCacheTuple (ATTNAME ,
442435 ObjectIdGetDatum (relId ),
443436 PointerGetDatum (arg ), 0 , 0 );
444437
445438 if (!HeapTupleIsValid (tuple ))
446- {
447- elog (ERROR ,
448- "DefineIndex: attribute \"%s\" not found" ,
449- arg );
450- }
439+ elog (ERROR , "DefineIndex: attribute \"%s\" not found" , arg );
451440 att = (Form_pg_attribute ) GETSTRUCT (tuple );
452441 * attNumP ++ = att -> attnum ;
453- * argTypes ++ = att -> atttypid ;
442+ funcInfo -> arglist [argn ++ ] = att -> atttypid ;
443+ }
444+
445+ /* ----------------
446+ * Lookup the function procedure to get its OID and result type.
447+ * ----------------
448+ */
449+ tuple = SearchSysCacheTuple (PROCNAME ,
450+ PointerGetDatum (FIgetname (funcInfo )),
451+ Int32GetDatum (FIgetnArgs (funcInfo )),
452+ PointerGetDatum (FIgetArglist (funcInfo )),
453+ 0 );
454+
455+ if (!HeapTupleIsValid (tuple ))
456+ {
457+ func_error ("DefineIndex" , FIgetname (funcInfo ),
458+ FIgetnArgs (funcInfo ), FIgetArglist (funcInfo ), NULL );
454459 }
460+
461+ FIsetProcOid (funcInfo , tuple -> t_data -> t_oid );
462+ retType = ((Form_pg_proc ) GETSTRUCT (tuple ))-> prorettype ;
463+
464+ /* Process type and opclass, using func return type as default */
465+
466+ ProcessAttrTypename (funcIndex , retType , -1 );
467+
468+ * opOidP = GetAttrOpClass (funcIndex , retType );
455469}
456470
457471static void
@@ -461,80 +475,85 @@ NormIndexAttrs(List *attList, /* list of IndexElem's */
461475 Oid relId )
462476{
463477 List * rest ;
464- HeapTuple atttuple ,
465- tuple ;
466478
467479 /*
468480 * process attributeList
469481 */
470-
471- for (rest = attList ; rest != NIL ; rest = lnext (rest ))
482+ foreach (rest , attList )
472483 {
473- IndexElem * attribute ;
484+ IndexElem * attribute = lfirst (rest );
485+ HeapTuple atttuple ;
474486 Form_pg_attribute attform ;
475487
476- attribute = lfirst (rest );
477-
478488 if (attribute -> name == NULL )
479489 elog (ERROR , "missing attribute for define index" );
480490
481491 atttuple = SearchSysCacheTupleCopy (ATTNAME ,
482492 ObjectIdGetDatum (relId ),
483- PointerGetDatum (attribute -> name ),
493+ PointerGetDatum (attribute -> name ),
484494 0 , 0 );
485495 if (!HeapTupleIsValid (atttuple ))
486- {
487- elog (ERROR ,
488- "DefineIndex: attribute \"%s\" not found" ,
496+ elog (ERROR , "DefineIndex: attribute \"%s\" not found" ,
489497 attribute -> name );
490- }
491-
492498 attform = (Form_pg_attribute ) GETSTRUCT (atttuple );
499+
493500 * attNumP ++ = attform -> attnum ;
494501
495- /* we want the type so we can set the proper alignment, etc. */
496- if (attribute -> typename == NULL )
497- {
498- tuple = SearchSysCacheTuple (TYPEOID ,
499- ObjectIdGetDatum (attform -> atttypid ),
500- 0 , 0 , 0 );
501- if (!HeapTupleIsValid (tuple ))
502- elog (ERROR , "create index: type for attribute '%s' undefined" ,
503- attribute -> name );
504- /* we just set the type name because that is all we need */
505- attribute -> typename = makeNode (TypeName );
506- attribute -> typename -> name = nameout (& ((Form_pg_type ) GETSTRUCT (tuple ))-> typname );
507-
508- /* we all need the typmod for the char and varchar types. */
509- attribute -> typename -> typmod = attform -> atttypmod ;
510- }
502+ ProcessAttrTypename (attribute , attform -> atttypid , attform -> atttypmod );
511503
512- if (attribute -> class == NULL )
513- {
514- /* no operator class specified, so find the default */
515- attribute -> class = GetDefaultOpClass (attform -> atttypid );
516- if (attribute -> class == NULL )
517- {
518- elog (ERROR ,
519- "Can't find a default operator class for type %u." ,
520- attform -> atttypid );
521- }
522- }
504+ * classOidP ++ = GetAttrOpClass (attribute , attform -> atttypid );
523505
524- tuple = SearchSysCacheTuple ( CLANAME ,
525- PointerGetDatum ( attribute -> class ),
526- 0 , 0 , 0 );
506+ heap_freetuple ( atttuple );
507+ }
508+ }
527509
510+ static void
511+ ProcessAttrTypename (IndexElem * attribute ,
512+ Oid defType , int32 defTypmod )
513+ {
514+ HeapTuple tuple ;
515+
516+ /* build a type node so we can set the proper alignment, etc. */
517+ if (attribute -> typename == NULL )
518+ {
519+ tuple = SearchSysCacheTuple (TYPEOID ,
520+ ObjectIdGetDatum (defType ),
521+ 0 , 0 , 0 );
528522 if (!HeapTupleIsValid (tuple ))
529- {
530- elog ( ERROR , "DefineIndex: %s class not found" ,
531- attribute -> class );
532- }
533- * classOidP ++ = tuple -> t_data -> t_oid ;
534- heap_freetuple ( atttuple ) ;
523+ elog ( ERROR , "DefineIndex: type for attribute '%s' undefined" ,
524+ attribute -> name );
525+
526+ attribute -> typename = makeNode ( TypeName );
527+ attribute -> typename -> name = nameout ( & (( Form_pg_type ) GETSTRUCT ( tuple )) -> typname ) ;
528+ attribute -> typename -> typmod = defTypmod ;
535529 }
536530}
537531
532+ static Oid
533+ GetAttrOpClass (IndexElem * attribute , Oid attrType )
534+ {
535+ HeapTuple tuple ;
536+
537+ if (attribute -> class == NULL )
538+ {
539+ /* no operator class specified, so find the default */
540+ attribute -> class = GetDefaultOpClass (attrType );
541+ if (attribute -> class == NULL )
542+ elog (ERROR , "Can't find a default operator class for type %u" ,
543+ attrType );
544+ }
545+
546+ tuple = SearchSysCacheTuple (CLANAME ,
547+ PointerGetDatum (attribute -> class ),
548+ 0 , 0 , 0 );
549+
550+ if (!HeapTupleIsValid (tuple ))
551+ elog (ERROR , "DefineIndex: %s opclass not found" ,
552+ attribute -> class );
553+
554+ return tuple -> t_data -> t_oid ;
555+ }
556+
538557static char *
539558GetDefaultOpClass (Oid atttypid )
540559{
0 commit comments