CREATE INDEX fooi ON foo (lower(f1)) where f1 is varchar rather than text.
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{
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
foreach(arglist, funcIndex->args)
{
char *arg = strVal(lfirst(arglist));
+ HeapTuple tuple;
Form_pg_attribute att;
tuple = SearchSysCacheTuple(ATTNAME,
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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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,
* 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 */
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
{
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
{
* 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++;
}
* catalogs.
*/
static Oid **
-argtype_inherit(int nargs, Oid *oid_array)
+argtype_inherit(int nargs, Oid *argtypes)
{
Oid relid;
int i;
{
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
{
/* 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,
* 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 $
*
*-------------------------------------------------------------------------
*/
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,