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
170172FIsetnArgs (& 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 ,
181182classObjectId ,relationId );
182183
183184index_create (heapRelationName ,
184185indexRelationName ,
185186& fInfo ,NULL ,accessMethodId ,
186187numberOfAttributes ,attributeNumberA ,
187- classObjectId ,parameterCount ,parameterA , (Node * )cnfPred ,
188+ classObjectId ,parameterCount ,parameterA ,
189+ (Node * )cnfPred ,
188190lossy ,unique ,primary );
189191}
190192else
191193{
192194attributeNumberA = (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
197199NormIndexAttrs (attributeList ,attributeNumberA ,
198200classObjectId ,relationId );
199201
200202index_create (heapRelationName ,indexRelationName ,NULL ,
201203attributeList ,
202204accessMethodId ,numberOfAttributes ,attributeNumberA ,
203- classObjectId ,parameterCount ,parameterA , (Node * )cnfPred ,
205+ classObjectId ,parameterCount ,parameterA ,
206+ (Node * )cnfPred ,
204207lossy ,unique ,primary );
205208}
209+
206210setRelhasindexInplace (relationId , true, false);
207211}
208212
@@ -320,7 +324,6 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
320324if (indproc != InvalidOid )
321325{
322326funcInfo = & fInfo ;
323- /*FIgetnArgs(funcInfo) = numberOfAttributes; */
324327FIsetnArgs (funcInfo ,numberOfAttributes );
325328
326329tuple = SearchSysCacheTuple (PROCOID ,
@@ -407,51 +410,62 @@ CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid)
407410
408411static void
409412FuncIndexArgs (IndexElem * funcIndex ,
413+ FuncIndexInfo * funcInfo ,
410414AttrNumber * attNumP ,
411- Oid * argTypes ,
412415Oid * opOidP ,
413416Oid relId )
414417{
415418List * rest ;
416419HeapTuple 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
441434tuple = SearchSysCacheTuple (ATTNAME ,
442435ObjectIdGetDatum (relId ),
443436PointerGetDatum (arg ),0 ,0 );
444437
445438if (!HeapTupleIsValid (tuple ))
446- {
447- elog (ERROR ,
448- "DefineIndex: attribute \"%s\" not found" ,
449- arg );
450- }
439+ elog (ERROR ,"DefineIndex: attribute \"%s\" not found" ,arg );
451440att = (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 */
461475Oid relId )
462476{
463477List * 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 ;
474486Form_pg_attribute attform ;
475487
476- attribute = lfirst (rest );
477-
478488if (attribute -> name == NULL )
479489elog (ERROR ,"missing attribute for define index" );
480490
481491atttuple = SearchSysCacheTupleCopy (ATTNAME ,
482492ObjectIdGetDatum (relId ),
483- PointerGetDatum (attribute -> name ),
493+ PointerGetDatum (attribute -> name ),
4844940 ,0 );
485495if (!HeapTupleIsValid (atttuple ))
486- {
487- elog (ERROR ,
488- "DefineIndex: attribute \"%s\" not found" ,
496+ elog (ERROR ,"DefineIndex: attribute \"%s\" not found" ,
489497attribute -> name );
490- }
491-
492498attform = (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 );
528522if (!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{