mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-27 22:41:57 +02:00
Make functional indexes accept binary-compatible functions, for example
CREATE INDEX fooi ON foo (lower(f1)) where f1 is varchar rather than text.
This commit is contained in:
parent
5cfbf3aba2
commit
4b8f1bcb9c
@ -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))
|
||||
{
|
||||
func_error("DefineIndex", funcIndex->name,
|
||||
indexInfo->ii_NumKeyAttrs, argTypes, NULL);
|
||||
}
|
||||
if (! func_get_detail(funcIndex->name, nargs, argTypes,
|
||||
&funcid, &rettype, &retset, &true_typeids))
|
||||
func_error("DefineIndex", funcIndex->name, nargs, argTypes, NULL);
|
||||
|
||||
indexInfo->ii_FuncOid = tuple->t_data->t_oid;
|
||||
retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype;
|
||||
if (retset)
|
||||
elog(ERROR, "DefineIndex: cannot index on a function returning a set");
|
||||
|
||||
for (i = 0; i < nargs; i++)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user