Commit 4b8f1bcb authored by Tom Lane's avatar Tom Lane

Make functional indexes accept binary-compatible functions, for example

CREATE INDEX fooi ON foo (lower(f1)) where f1 is varchar rather than text.
parent 5cfbf3ab
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -370,9 +370,12 @@ FuncIndexArgs(IndexInfo *indexInfo,
{ {
Oid argTypes[FUNC_MAX_ARGS]; Oid argTypes[FUNC_MAX_ARGS];
List *arglist; List *arglist;
HeapTuple tuple; int nargs = 0;
Oid retType; int i;
int argn = 0; Oid funcid;
Oid rettype;
bool retset;
Oid *true_typeids;
/* /*
* process the function arguments, which are a list of T_String * process the function arguments, which are a list of T_String
...@@ -385,6 +388,7 @@ FuncIndexArgs(IndexInfo *indexInfo, ...@@ -385,6 +388,7 @@ FuncIndexArgs(IndexInfo *indexInfo,
foreach(arglist, funcIndex->args) foreach(arglist, funcIndex->args)
{ {
char *arg = strVal(lfirst(arglist)); char *arg = strVal(lfirst(arglist));
HeapTuple tuple;
Form_pg_attribute att; Form_pg_attribute att;
tuple = SearchSysCacheTuple(ATTNAME, tuple = SearchSysCacheTuple(ATTNAME,
...@@ -395,40 +399,47 @@ FuncIndexArgs(IndexInfo *indexInfo, ...@@ -395,40 +399,47 @@ FuncIndexArgs(IndexInfo *indexInfo,
elog(ERROR, "DefineIndex: attribute \"%s\" not found", arg); elog(ERROR, "DefineIndex: attribute \"%s\" not found", arg);
att = (Form_pg_attribute) GETSTRUCT(tuple); att = (Form_pg_attribute) GETSTRUCT(tuple);
indexInfo->ii_KeyAttrNumbers[argn] = att->attnum; indexInfo->ii_KeyAttrNumbers[nargs] = att->attnum;
argTypes[argn] = att->atttypid; argTypes[nargs] = att->atttypid;
argn++; nargs++;
} }
/* ---------------- /* ----------------
* Lookup the function procedure to get its OID and result type. * Lookup the function procedure to get its OID and result type.
* *
* XXX need to accept binary-compatible functions here, not just * We rely on parse_func.c to find the correct function in the
* an exact match. * 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, if (! func_get_detail(funcIndex->name, nargs, argTypes,
PointerGetDatum(funcIndex->name), &funcid, &rettype, &retset, &true_typeids))
Int32GetDatum(indexInfo->ii_NumKeyAttrs), func_error("DefineIndex", funcIndex->name, nargs, argTypes, NULL);
PointerGetDatum(argTypes),
0); if (retset)
if (!HeapTupleIsValid(tuple)) elog(ERROR, "DefineIndex: cannot index on a function returning a set");
for (i = 0; i < nargs; i++)
{ {
func_error("DefineIndex", funcIndex->name, if (argTypes[i] != true_typeids[i] &&
indexInfo->ii_NumKeyAttrs, argTypes, NULL); ! 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 */ /* Process opclass, using func return type as default type */
classOidP[0] = GetAttrOpClass(funcIndex, retType, classOidP[0] = GetAttrOpClass(funcIndex, rettype,
accessMethodName, accessMethodId); 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 static void
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -37,18 +37,10 @@ static Node *ParseComplexProjection(ParseState *pstate,
char *funcname, char *funcname,
Node *first_arg, Node *first_arg,
bool *attisset); 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 int find_inheritors(Oid relid, Oid **supervec);
static CandidateList func_get_candidates(char *funcname, int nargs); 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 Oid **gen_cross_product(InhPaths *arginh, int nargs);
static void make_arguments(ParseState *pstate, static void make_arguments(ParseState *pstate,
int nargs, int nargs,
...@@ -1097,10 +1089,10 @@ func_select_candidate(int nargs, ...@@ -1097,10 +1089,10 @@ func_select_candidate(int nargs,
* c) if the answer is more than one, attempt to resolve the conflict * 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 * d) if the answer is zero, try the next array from vector #1
*/ */
static bool bool
func_get_detail(char *funcname, func_get_detail(char *funcname,
int nargs, int nargs,
Oid *oid_array, Oid *argtypes,
Oid *funcid, /* return value */ Oid *funcid, /* return value */
Oid *rettype, /* return value */ Oid *rettype, /* return value */
bool *retset, /* return value */ bool *retset, /* return value */
...@@ -1112,13 +1104,13 @@ func_get_detail(char *funcname, ...@@ -1112,13 +1104,13 @@ func_get_detail(char *funcname,
ftup = SearchSysCacheTuple(PROCNAME, ftup = SearchSysCacheTuple(PROCNAME,
PointerGetDatum(funcname), PointerGetDatum(funcname),
Int32GetDatum(nargs), Int32GetDatum(nargs),
PointerGetDatum(oid_array), PointerGetDatum(argtypes),
0); 0);
if (HeapTupleIsValid(ftup)) if (HeapTupleIsValid(ftup))
{ {
/* given argument types are the right ones */ /* given argument types are the right ones */
*true_typeids = oid_array; *true_typeids = argtypes;
} }
else else
{ {
...@@ -1138,11 +1130,11 @@ func_get_detail(char *funcname, ...@@ -1138,11 +1130,11 @@ func_get_detail(char *funcname,
Oid *current_input_typeids; 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 * variants based on replacing complex types with their
* inheritance ancestors. Stop as soon as any match is found. * inheritance ancestors. Stop as soon as any match is found.
*/ */
current_input_typeids = oid_array; current_input_typeids = argtypes;
do do
{ {
...@@ -1200,7 +1192,7 @@ func_get_detail(char *funcname, ...@@ -1200,7 +1192,7 @@ func_get_detail(char *funcname,
* vectors. * vectors.
*/ */
if (input_typeid_vector == NULL) 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++; current_input_typeids = *input_typeid_vector++;
} }
...@@ -1243,7 +1235,7 @@ func_get_detail(char *funcname, ...@@ -1243,7 +1235,7 @@ func_get_detail(char *funcname,
* catalogs. * catalogs.
*/ */
static Oid ** static Oid **
argtype_inherit(int nargs, Oid *oid_array) argtype_inherit(int nargs, Oid *argtypes)
{ {
Oid relid; Oid relid;
int i; int i;
...@@ -1253,8 +1245,8 @@ argtype_inherit(int nargs, Oid *oid_array) ...@@ -1253,8 +1245,8 @@ argtype_inherit(int nargs, Oid *oid_array)
{ {
if (i < nargs) if (i < nargs)
{ {
arginh[i].self = oid_array[i]; arginh[i].self = argtypes[i];
if ((relid = typeidTypeRelid(oid_array[i])) != InvalidOid) if ((relid = typeidTypeRelid(argtypes[i])) != InvalidOid)
arginh[i].nsupers = find_inheritors(relid, &(arginh[i].supervec)); arginh[i].nsupers = find_inheritors(relid, &(arginh[i].supervec));
else else
{ {
...@@ -1467,16 +1459,6 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId) ...@@ -1467,16 +1459,6 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId)
/* make_arguments() /* make_arguments()
* Given the number and types of arguments to a function, and the * Given the number and types of arguments to a function, and the
* actual arguments and argument types, do the necessary typecasting. * 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 static void
make_arguments(ParseState *pstate, make_arguments(ParseState *pstate,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * 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, ...@@ -45,6 +45,10 @@ extern Node *ParseFuncOrColumn(ParseState *pstate,
bool agg_star, bool agg_distinct, bool agg_star, bool agg_distinct,
int *curr_resno, int precedence); 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 bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId);
extern void func_error(char *caller, char *funcname, extern void func_error(char *caller, char *funcname,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment