]> granicus.if.org Git - postgresql/commitdiff
Fix longstanding bug that kept functional indexes from working when you
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 25 Feb 2000 02:58:48 +0000 (02:58 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 25 Feb 2000 02:58:48 +0000 (02:58 +0000)
defaulted the opclass.  This addresses TODO item
* Allow creation of functional indexes to use default types
(Does that make it a feature?  Oh dear...)

src/backend/catalog/index.c
src/backend/commands/indexcmds.c

index b7d49ed3bc8c6f927cd989bbc17a9b01a5c52514..5bfc332f0dbebd5659d151eda3884df2f3a0db6e 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.105 2000/02/18 09:28:41 inoue Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.106 2000/02/25 02:58:47 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1032,28 +1032,6 @@ index_create(char *heapRelationName,
         * We create the disk file for this relation here
         */
        heap_storage_create(indexRelation);
-       /* ----------------
-        * Now get the index procedure (only relevant for functional indices).
-        * ----------------
-        */
-
-       if (PointerIsValid(funcInfo))
-       {
-               HeapTuple       proc_tup;
-
-               proc_tup = SearchSysCacheTuple(PROCNAME,
-                                                                       PointerGetDatum(FIgetname(funcInfo)),
-                                                                        Int32GetDatum(FIgetnArgs(funcInfo)),
-                                                                PointerGetDatum(FIgetArglist(funcInfo)),
-                                                                          0);
-
-               if (!HeapTupleIsValid(proc_tup))
-               {
-                       func_error("index_create", FIgetname(funcInfo),
-                                        FIgetnArgs(funcInfo), FIgetArglist(funcInfo), NULL);
-               }
-               FIgetProcOid(funcInfo) = proc_tup->t_data->t_oid;
-       }
 
        /* ----------------
         *      now update the object id's of all the attribute
index cbd7b26ae8ad2370693b03d1fd624bb7d8972bb2..93ad0eb63b47fdd601112ab075a1617ec64c9ba5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.21 2000/02/18 09:29:37 inoue Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.22 2000/02/25 02:58:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "optimizer/planmain.h"
 #include "optimizer/prep.h"
 #include "parser/parsetree.h"
+#include "parser/parse_func.h"
 #include "utils/builtins.h"
 #include "utils/syscache.h"
 #include "miscadmin.h" /* ReindexDatabase() */
 #include "utils/portal.h" /* ReindexDatabase() */
 #include "catalog/catalog.h" /* ReindexDatabase() */
 
-#define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args!=NULL)
+#define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args != NIL)
 
 /* non-export function prototypes */
 static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
-static void CheckPredExpr(Node *predicate, List *rangeTable,
-                         Oid baseRelOid);
-static void
-                       CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid);
-static void FuncIndexArgs(IndexElem *funcIndex, AttrNumber *attNumP,
-                         Oid *argTypes, Oid *opOidP, Oid relId);
+static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid);
+static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid);
+static void FuncIndexArgs(IndexElem *funcIndex, FuncIndexInfo *funcInfo,
+                                                 AttrNumber *attNumP, Oid *opOidP, Oid relId);
 static void NormIndexAttrs(List *attList, AttrNumber *attNumP,
-                          Oid *opOidP, Oid relId);
+                                                  Oid *opOidP, Oid relId);
+static void ProcessAttrTypename(IndexElem *attribute,
+                                                               Oid defType, int32 defTypmod);
+static Oid     GetAttrOpClass(IndexElem *attribute, Oid attrType);
 static char *GetDefaultOpClass(Oid atttypid);
 
 /*
@@ -169,30 +171,30 @@ DefineIndex(char *heapRelationName,
 
                FIsetnArgs(&fInfo, nargs);
 
-               strcpy(FIgetname(&fInfo), funcIndex->name);
-
-               attributeNumberA = (AttrNumber *) palloc(nargs * sizeof attributeNumberA[0]);
+               namestrcpy(&fInfo.funcName, funcIndex->name);
 
-               classObjectId = (Oid *) palloc(sizeof classObjectId[0]);
+               attributeNumberA = (AttrNumber *) palloc(nargs *
+                                                                                                sizeof attributeNumberA[0]);
 
+               classObjectId = (Oid *) palloc(sizeof(Oid));
 
-               FuncIndexArgs(funcIndex, attributeNumberA,
-                                         &(FIgetArg(&fInfo, 0)),
+               FuncIndexArgs(funcIndex, &fInfo, attributeNumberA,
                                          classObjectId, relationId);
 
                index_create(heapRelationName,
                                         indexRelationName,
                                         &fInfo, NULL, accessMethodId,
                                         numberOfAttributes, attributeNumberA,
-                        classObjectId, parameterCount, parameterA, (Node *) cnfPred,
+                                        classObjectId, parameterCount, parameterA,
+                                        (Node *) cnfPred,
                                         lossy, unique, primary);
        }
        else
        {
                attributeNumberA = (AttrNumber *) palloc(numberOfAttributes *
-                                                                                        sizeof attributeNumberA[0]);
+                                                                                                sizeof attributeNumberA[0]);
 
-               classObjectId = (Oid *) palloc(numberOfAttributes * sizeof classObjectId[0]);
+               classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
 
                NormIndexAttrs(attributeList, attributeNumberA,
                                           classObjectId, relationId);
@@ -200,9 +202,11 @@ DefineIndex(char *heapRelationName,
                index_create(heapRelationName, indexRelationName, NULL,
                                         attributeList,
                                         accessMethodId, numberOfAttributes, attributeNumberA,
-                        classObjectId, parameterCount, parameterA, (Node *) cnfPred,
+                                        classObjectId, parameterCount, parameterA,
+                                        (Node *) cnfPred,
                                         lossy, unique, primary);
        }
+
        setRelhasindexInplace(relationId, true, false);
 }
 
@@ -320,7 +324,6 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
        if (indproc != InvalidOid)
        {
                funcInfo = &fInfo;
-/*             FIgetnArgs(funcInfo) = numberOfAttributes; */
                FIsetnArgs(funcInfo, numberOfAttributes);
 
                tuple = SearchSysCacheTuple(PROCOID,
@@ -407,51 +410,62 @@ CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid)
 
 static void
 FuncIndexArgs(IndexElem *funcIndex,
+                         FuncIndexInfo *funcInfo,
                          AttrNumber *attNumP,
-                         Oid *argTypes,
                          Oid *opOidP,
                          Oid relId)
 {
        List       *rest;
        HeapTuple       tuple;
-       Form_pg_attribute att;
-
-       tuple = SearchSysCacheTuple(CLANAME,
-                                                               PointerGetDatum(funcIndex->class),
-                                                               0, 0, 0);
-
-       if (!HeapTupleIsValid(tuple))
-       {
-               elog(ERROR, "DefineIndex: %s class not found",
-                        funcIndex->class);
-       }
-       *opOidP = tuple->t_data->t_oid;
-
-       MemSet(argTypes, 0, FUNC_MAX_ARGS * sizeof(Oid));
+       Oid                     retType;
+       int                     argn = 0;
 
        /*
-        * process the function arguments
+        * process the function arguments, which are a list of T_String
+        * (someday ought to allow more general expressions?)
         */
-       for (rest = funcIndex->args; rest != NIL; rest = lnext(rest))
-       {
-               char       *arg;
+       MemSet(funcInfo->arglist, 0, FUNC_MAX_ARGS * sizeof(Oid));
 
-               arg = strVal(lfirst(rest));
+       foreach(rest, funcIndex->args)
+       {
+               char       *arg = strVal(lfirst(rest));
+               Form_pg_attribute att;
 
                tuple = SearchSysCacheTuple(ATTNAME,
                                                                        ObjectIdGetDatum(relId),
                                                                        PointerGetDatum(arg), 0, 0);
 
                if (!HeapTupleIsValid(tuple))
-               {
-                       elog(ERROR,
-                                "DefineIndex: attribute \"%s\" not found",
-                                arg);
-               }
+                       elog(ERROR, "DefineIndex: attribute \"%s\" not found", arg);
                att = (Form_pg_attribute) GETSTRUCT(tuple);
                *attNumP++ = att->attnum;
-               *argTypes++ = att->atttypid;
+               funcInfo->arglist[argn++] = att->atttypid;
+       }
+
+       /* ----------------
+        * Lookup the function procedure to get its OID and result type.
+        * ----------------
+        */
+       tuple = SearchSysCacheTuple(PROCNAME,
+                                                               PointerGetDatum(FIgetname(funcInfo)),
+                                                               Int32GetDatum(FIgetnArgs(funcInfo)),
+                                                               PointerGetDatum(FIgetArglist(funcInfo)),
+                                                               0);
+
+       if (!HeapTupleIsValid(tuple))
+       {
+               func_error("DefineIndex", FIgetname(funcInfo),
+                                  FIgetnArgs(funcInfo), FIgetArglist(funcInfo), NULL);
        }
+
+       FIsetProcOid(funcInfo, tuple->t_data->t_oid);
+       retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype;
+
+       /* Process type and opclass, using func return type as default */
+
+       ProcessAttrTypename(funcIndex, retType, -1);
+
+       *opOidP = GetAttrOpClass(funcIndex, retType);
 }
 
 static void
@@ -461,80 +475,85 @@ NormIndexAttrs(List *attList,     /* list of IndexElem's */
                           Oid relId)
 {
        List       *rest;
-       HeapTuple       atttuple,
-                               tuple;
 
        /*
         * process attributeList
         */
-
-       for (rest = attList; rest != NIL; rest = lnext(rest))
+       foreach(rest, attList)
        {
-               IndexElem  *attribute;
+               IndexElem  *attribute = lfirst(rest);
+               HeapTuple       atttuple;
                Form_pg_attribute attform;
 
-               attribute = lfirst(rest);
-
                if (attribute->name == NULL)
                        elog(ERROR, "missing attribute for define index");
 
                atttuple = SearchSysCacheTupleCopy(ATTNAME,
                                                                                   ObjectIdGetDatum(relId),
-                                                                               PointerGetDatum(attribute->name),
+                                                                                  PointerGetDatum(attribute->name),
                                                                                   0, 0);
                if (!HeapTupleIsValid(atttuple))
-               {
-                       elog(ERROR,
-                                "DefineIndex: attribute \"%s\" not found",
+                       elog(ERROR, "DefineIndex: attribute \"%s\" not found",
                                 attribute->name);
-               }
-
                attform = (Form_pg_attribute) GETSTRUCT(atttuple);
+
                *attNumP++ = attform->attnum;
 
-               /* we want the type so we can set the proper alignment, etc. */
-               if (attribute->typename == NULL)
-               {
-                       tuple = SearchSysCacheTuple(TYPEOID,
-                                                                        ObjectIdGetDatum(attform->atttypid),
-                                                                               0, 0, 0);
-                       if (!HeapTupleIsValid(tuple))
-                               elog(ERROR, "create index: type for attribute '%s' undefined",
-                                        attribute->name);
-                       /* we just set the type name because that is all we need */
-                       attribute->typename = makeNode(TypeName);
-                       attribute->typename->name = nameout(&((Form_pg_type) GETSTRUCT(tuple))->typname);
-
-                       /* we all need the typmod for the char and varchar types. */
-                       attribute->typename->typmod = attform->atttypmod;
-               }
+               ProcessAttrTypename(attribute, attform->atttypid, attform->atttypmod);
 
-               if (attribute->class == NULL)
-               {
-                       /* no operator class specified, so find the default */
-                       attribute->class = GetDefaultOpClass(attform->atttypid);
-                       if (attribute->class == NULL)
-                       {
-                               elog(ERROR,
-                                        "Can't find a default operator class for type %u.",
-                                        attform->atttypid);
-                       }
-               }
+               *classOidP++ = GetAttrOpClass(attribute, attform->atttypid);
 
-               tuple = SearchSysCacheTuple(CLANAME,
-                                                                       PointerGetDatum(attribute->class),
-                                                                       0, 0, 0);
+               heap_freetuple(atttuple);
+       }
+}
 
+static void
+ProcessAttrTypename(IndexElem *attribute,
+                                       Oid defType, int32 defTypmod)
+{
+       HeapTuple       tuple;
+
+       /* build a type node so we can set the proper alignment, etc. */
+       if (attribute->typename == NULL)
+       {
+               tuple = SearchSysCacheTuple(TYPEOID,
+                                                                       ObjectIdGetDatum(defType),
+                                                                       0, 0, 0);
                if (!HeapTupleIsValid(tuple))
-               {
-                       elog(ERROR, "DefineIndex: %s class not found",
-                                attribute->class);
-               }
-               *classOidP++ = tuple->t_data->t_oid;
-               heap_freetuple(atttuple);
+                       elog(ERROR, "DefineIndex: type for attribute '%s' undefined",
+                                attribute->name);
+
+               attribute->typename = makeNode(TypeName);
+               attribute->typename->name = nameout(&((Form_pg_type) GETSTRUCT(tuple))->typname);
+               attribute->typename->typmod = defTypmod;
        }
 }
 
+static Oid
+GetAttrOpClass(IndexElem *attribute, Oid attrType)
+{
+       HeapTuple       tuple;
+
+       if (attribute->class == NULL)
+       {
+               /* no operator class specified, so find the default */
+               attribute->class = GetDefaultOpClass(attrType);
+               if (attribute->class == NULL)
+                       elog(ERROR, "Can't find a default operator class for type %u",
+                                attrType);
+       }
+
+       tuple = SearchSysCacheTuple(CLANAME,
+                                                               PointerGetDatum(attribute->class),
+                                                               0, 0, 0);
+
+       if (!HeapTupleIsValid(tuple))
+               elog(ERROR, "DefineIndex: %s opclass not found",
+                        attribute->class);
+
+       return tuple->t_data->t_oid;
+}
+
 static char *
 GetDefaultOpClass(Oid atttypid)
 {