]> granicus.if.org Git - postgresql/commitdiff
Make functional indexes accept binary-compatible functions, for example
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 20 Aug 2000 00:44:19 +0000 (00:44 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 20 Aug 2000 00:44:19 +0000 (00:44 +0000)
CREATE INDEX fooi ON foo (lower(f1)) where f1 is varchar rather than text.

src/backend/commands/indexcmds.c
src/backend/parser/parse_func.c
src/include/parser/parse_func.h

index 85de47a67660980a6b1a2326aa163f58d475f3c1..0fb1129f7318ed1a7eb7fba3c971099f674321ba 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.36 2000/08/03 16:34:01 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.37 2000/08/20 00:44:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -370,9 +370,12 @@ FuncIndexArgs(IndexInfo *indexInfo,
 {
        Oid                     argTypes[FUNC_MAX_ARGS];
        List       *arglist;
-       HeapTuple       tuple;
-       Oid                     retType;
-       int                     argn = 0;
+       int                     nargs = 0;
+       int                     i;
+       Oid                     funcid;
+       Oid                     rettype;
+       bool            retset;
+       Oid                *true_typeids;
 
        /*
         * process the function arguments, which are a list of T_String
@@ -385,6 +388,7 @@ FuncIndexArgs(IndexInfo *indexInfo,
        foreach(arglist, funcIndex->args)
        {
                char       *arg = strVal(lfirst(arglist));
+               HeapTuple       tuple;
                Form_pg_attribute att;
 
                tuple = SearchSysCacheTuple(ATTNAME,
@@ -395,40 +399,47 @@ FuncIndexArgs(IndexInfo *indexInfo,
                        elog(ERROR, "DefineIndex: attribute \"%s\" not found", arg);
                att = (Form_pg_attribute) GETSTRUCT(tuple);
 
-               indexInfo->ii_KeyAttrNumbers[argn] = att->attnum;
-               argTypes[argn] = att->atttypid;
-               argn++;
+               indexInfo->ii_KeyAttrNumbers[nargs] = att->attnum;
+               argTypes[nargs] = att->atttypid;
+               nargs++;
        }
 
        /* ----------------
         * Lookup the function procedure to get its OID and result type.
         *
-        * XXX need to accept binary-compatible functions here, not just
-        * an exact match.
+        * We rely on parse_func.c to find the correct function in the
+        * possible presence of binary-compatible types.  However, parse_func
+        * may do too much: it will accept a function that requires run-time
+        * coercion of input types, and the executor is not currently set up
+        * to support that.  So, check to make sure that the selected function
+        * has exact-match or binary-compatible input types.
         * ----------------
         */
-       tuple = SearchSysCacheTuple(PROCNAME,
-                                                               PointerGetDatum(funcIndex->name),
-                                                               Int32GetDatum(indexInfo->ii_NumKeyAttrs),
-                                                               PointerGetDatum(argTypes),
-                                                               0);
-       if (!HeapTupleIsValid(tuple))
+       if (! func_get_detail(funcIndex->name, nargs, argTypes,
+                                                 &funcid, &rettype, &retset, &true_typeids))
+               func_error("DefineIndex", funcIndex->name, nargs, argTypes, NULL);
+
+       if (retset)
+               elog(ERROR, "DefineIndex: cannot index on a function returning a set");
+
+       for (i = 0; i < nargs; i++)
        {
-               func_error("DefineIndex", funcIndex->name,
-                                  indexInfo->ii_NumKeyAttrs, argTypes, NULL);
+               if (argTypes[i] != true_typeids[i] &&
+                       ! IS_BINARY_COMPATIBLE(argTypes[i], true_typeids[i]))
+                       func_error("DefineIndex", funcIndex->name, nargs, argTypes,
+                                          "Index function must be binary-compatible with table datatype");
        }
 
-       indexInfo->ii_FuncOid = tuple->t_data->t_oid;
-       retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype;
-
        /* Process opclass, using func return type as default type */
 
-       classOidP[0] = GetAttrOpClass(funcIndex, retType,
+       classOidP[0] = GetAttrOpClass(funcIndex, rettype,
                                                                  accessMethodName, accessMethodId);
 
-       /* Need to do the fmgr function lookup now, too */
+       /* OK, return results */
 
-       fmgr_info(indexInfo->ii_FuncOid, & indexInfo->ii_FuncInfo);
+       indexInfo->ii_FuncOid = funcid;
+       /* Need to do the fmgr function lookup now, too */
+       fmgr_info(funcid, & indexInfo->ii_FuncInfo);
 }
 
 static void
index 44a750c166e38756934b8766a8bd720e367d2fed..551e7d2b585510092c12ba8fd244f620c0d7162f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.87 2000/08/08 15:42:04 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.88 2000/08/20 00:44:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -37,18 +37,10 @@ static Node *ParseComplexProjection(ParseState *pstate,
                                           char *funcname,
                                           Node *first_arg,
                                           bool *attisset);
-static Oid **argtype_inherit(int nargs, Oid *oid_array);
+static Oid **argtype_inherit(int nargs, Oid *argtypes);
 
 static int     find_inheritors(Oid relid, Oid **supervec);
 static CandidateList func_get_candidates(char *funcname, int nargs);
-static bool
-func_get_detail(char *funcname,
-                               int nargs,
-                               Oid *oid_array,
-                               Oid *funcid,    /* return value */
-                               Oid *rettype,   /* return value */
-                               bool *retset,   /* return value */
-                               Oid **true_typeids);
 static Oid **gen_cross_product(InhPaths *arginh, int nargs);
 static void make_arguments(ParseState *pstate,
                           int nargs,
@@ -1097,10 +1089,10 @@ func_select_candidate(int nargs,
  *      c) if the answer is more than one, attempt to resolve the conflict
  *      d) if the answer is zero, try the next array from vector #1
  */
-static bool
+bool
 func_get_detail(char *funcname,
                                int nargs,
-                               Oid *oid_array,
+                               Oid *argtypes,
                                Oid *funcid,    /* return value */
                                Oid *rettype,   /* return value */
                                bool *retset,   /* return value */
@@ -1112,13 +1104,13 @@ func_get_detail(char *funcname,
        ftup = SearchSysCacheTuple(PROCNAME,
                                                           PointerGetDatum(funcname),
                                                           Int32GetDatum(nargs),
-                                                          PointerGetDatum(oid_array),
+                                                          PointerGetDatum(argtypes),
                                                           0);
 
        if (HeapTupleIsValid(ftup))
        {
                /* given argument types are the right ones */
-               *true_typeids = oid_array;
+               *true_typeids = argtypes;
        }
        else
        {
@@ -1138,11 +1130,11 @@ func_get_detail(char *funcname,
                        Oid                *current_input_typeids;
 
                        /*
-                        * First we will search with the given oid_array, then with
+                        * First we will search with the given argtypes, then with
                         * variants based on replacing complex types with their
                         * inheritance ancestors.  Stop as soon as any match is found.
                         */
-                       current_input_typeids = oid_array;
+                       current_input_typeids = argtypes;
 
                        do
                        {
@@ -1200,7 +1192,7 @@ func_get_detail(char *funcname,
                                 * vectors.
                                 */
                                if (input_typeid_vector == NULL)
-                                       input_typeid_vector = argtype_inherit(nargs, oid_array);
+                                       input_typeid_vector = argtype_inherit(nargs, argtypes);
 
                                current_input_typeids = *input_typeid_vector++;
                        }
@@ -1243,7 +1235,7 @@ func_get_detail(char *funcname,
  *             catalogs.
  */
 static Oid **
-argtype_inherit(int nargs, Oid *oid_array)
+argtype_inherit(int nargs, Oid *argtypes)
 {
        Oid                     relid;
        int                     i;
@@ -1253,8 +1245,8 @@ argtype_inherit(int nargs, Oid *oid_array)
        {
                if (i < nargs)
                {
-                       arginh[i].self = oid_array[i];
-                       if ((relid = typeidTypeRelid(oid_array[i])) != InvalidOid)
+                       arginh[i].self = argtypes[i];
+                       if ((relid = typeidTypeRelid(argtypes[i])) != InvalidOid)
                                arginh[i].nsupers = find_inheritors(relid, &(arginh[i].supervec));
                        else
                        {
@@ -1467,16 +1459,6 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
 /* make_arguments()
  * Given the number and types of arguments to a function, and the
  *     actual arguments and argument types, do the necessary typecasting.
- *
- * There are two ways an input typeid can differ from a function typeid:
- *     1) the input type inherits the function type, so no typecasting required
- *     2) the input type can be typecast into the function type
- * Right now, we only typecast unknowns, and that is all we check for.
- *
- * func_get_detail() now can find coercions for function arguments which
- *     will make this function executable. So, we need to recover these
- *     results here too.
- * - thomas 1998-03-25
  */
 static void
 make_arguments(ParseState *pstate,
index 79b193a2b5117e63d1456c07ba45b099a9df4dd1..be96652cfb21810e4a89ff3b6d6f9261922dc39d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parse_func.h,v 1.25 2000/08/08 15:42:59 tgl Exp $
+ * $Id: parse_func.h,v 1.26 2000/08/20 00:44:17 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -45,6 +45,10 @@ extern Node *ParseFuncOrColumn(ParseState *pstate,
                                  bool agg_star, bool agg_distinct,
                                  int *curr_resno, int precedence);
 
+extern bool func_get_detail(char *funcname, int nargs, Oid *argtypes,
+                                                       Oid *funcid, Oid *rettype,
+                                                       bool *retset, Oid **true_typeids);
+
 extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId);
 
 extern void func_error(char *caller, char *funcname,