aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_func.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-04-06 06:59:25 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-04-06 06:59:25 +0000
commit0332d65ac4a1c843e1812755db1afc1b1109d0ea (patch)
tree7bf7644c1415b79c8c22d2c655af8bd605ff199f /src/backend/parser/parse_func.c
parent707cf12f1bd95b204c79a732db195782981959d2 (diff)
downloadpostgresql-0332d65ac4a1c843e1812755db1afc1b1109d0ea.tar.gz
postgresql-0332d65ac4a1c843e1812755db1afc1b1109d0ea.zip
Implement partial-key searching of syscaches, per recent suggestion
to pghackers. Use this to do searching for ambiguous functions --- it will get more uses soon.
Diffstat (limited to 'src/backend/parser/parse_func.c')
-rw-r--r--src/backend/parser/parse_func.c215
1 files changed, 76 insertions, 139 deletions
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index f3c8712abae..578402fd255 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.123 2002/04/05 00:31:27 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.124 2002/04/06 06:59:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,6 +18,7 @@
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
+#include "catalog/namespace.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_namespace.h"
@@ -40,7 +41,6 @@ static Node *ParseComplexProjection(ParseState *pstate,
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 Oid **gen_cross_product(InhPaths *arginh, int nargs);
static void make_arguments(ParseState *pstate,
int nargs,
@@ -48,14 +48,15 @@ static void make_arguments(ParseState *pstate,
Oid *input_typeids,
Oid *function_typeids);
static int match_argtypes(int nargs,
- Oid *input_typeids,
- CandidateList function_typeids,
- CandidateList *candidates);
+ Oid *input_typeids,
+ FuncCandidateList function_typeids,
+ FuncCandidateList *candidates);
static FieldSelect *setup_field_select(Node *input, char *attname, Oid relid);
-static Oid *func_select_candidate(int nargs, Oid *input_typeids,
- CandidateList candidates);
-static int agg_get_candidates(char *aggname, Oid typeId, CandidateList *candidates);
-static Oid agg_select_candidate(Oid typeid, CandidateList candidates);
+static FuncCandidateList func_select_candidate(int nargs, Oid *input_typeids,
+ FuncCandidateList candidates);
+static int agg_get_candidates(char *aggname, Oid typeId,
+ FuncCandidateList *candidates);
+static Oid agg_select_candidate(Oid typeid, FuncCandidateList candidates);
/*
@@ -170,7 +171,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
{
Oid basetype = exprType(lfirst(fargs));
int ncandidates;
- CandidateList candidates;
+ FuncCandidateList candidates;
/* try for exact match first... */
if (SearchSysCacheExists(AGGNAME,
@@ -374,7 +375,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
static int
agg_get_candidates(char *aggname,
Oid typeId,
- CandidateList *candidates)
+ FuncCandidateList *candidates)
{
Relation pg_aggregate_desc;
SysScanDesc pg_aggregate_scan;
@@ -398,11 +399,10 @@ agg_get_candidates(char *aggname,
while (HeapTupleIsValid(tup = systable_getnext(pg_aggregate_scan)))
{
Form_pg_aggregate agg = (Form_pg_aggregate) GETSTRUCT(tup);
- CandidateList current_candidate;
-
- current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList));
- current_candidate->args = (Oid *) palloc(sizeof(Oid));
+ FuncCandidateList current_candidate;
+ current_candidate = (FuncCandidateList)
+ palloc(sizeof(struct _FuncCandidateList));
current_candidate->args[0] = agg->aggbasetype;
current_candidate->next = *candidates;
*candidates = current_candidate;
@@ -422,10 +422,10 @@ agg_get_candidates(char *aggname,
* if successful, else InvalidOid.
*/
static Oid
-agg_select_candidate(Oid typeid, CandidateList candidates)
+agg_select_candidate(Oid typeid, FuncCandidateList candidates)
{
- CandidateList current_candidate;
- CandidateList last_candidate;
+ FuncCandidateList current_candidate;
+ FuncCandidateList last_candidate;
Oid current_typeid;
int ncandidates;
CATEGORY category,
@@ -498,91 +498,37 @@ agg_select_candidate(Oid typeid, CandidateList candidates)
} /* agg_select_candidate() */
-/* func_get_candidates()
- * get a list of all argument type vectors for which a function named
- * funcname taking nargs arguments exists
- */
-static CandidateList
-func_get_candidates(char *funcname, int nargs)
-{
- Relation heapRelation;
- ScanKeyData skey[2];
- HeapTuple tuple;
- SysScanDesc funcscan;
- CandidateList candidates = NULL;
- int i;
-
- heapRelation = heap_openr(ProcedureRelationName, AccessShareLock);
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) Anum_pg_proc_proname,
- (RegProcedure) F_NAMEEQ,
- PointerGetDatum(funcname));
- ScanKeyEntryInitialize(&skey[1],
- (bits16) 0x0,
- (AttrNumber) Anum_pg_proc_pronargs,
- (RegProcedure) F_INT2EQ,
- Int16GetDatum(nargs));
-
- funcscan = systable_beginscan(heapRelation, ProcedureNameNspIndex, true,
- SnapshotNow, 2, skey);
-
- while (HeapTupleIsValid(tuple = systable_getnext(funcscan)))
- {
- Form_pg_proc pgProcP = (Form_pg_proc) GETSTRUCT(tuple);
- CandidateList current_candidate;
-
- current_candidate = (CandidateList)
- palloc(sizeof(struct _CandidateList));
- current_candidate->args = (Oid *)
- palloc(FUNC_MAX_ARGS * sizeof(Oid));
- MemSet(current_candidate->args, 0, FUNC_MAX_ARGS * sizeof(Oid));
- for (i = 0; i < nargs; i++)
- current_candidate->args[i] = pgProcP->proargtypes[i];
-
- current_candidate->next = candidates;
- candidates = current_candidate;
- }
-
- systable_endscan(funcscan);
- heap_close(heapRelation, AccessShareLock);
-
- return candidates;
-}
-
-
/* match_argtypes()
+ *
* Given a list of possible typeid arrays to a function and an array of
* input typeids, produce a shortlist of those function typeid arrays
* that match the input typeids (either exactly or by coercion), and
- * return the number of such arrays
+ * return the number of such arrays.
+ *
+ * NB: okay to modify input list structure, as long as we find at least
+ * one match.
*/
static int
match_argtypes(int nargs,
Oid *input_typeids,
- CandidateList function_typeids,
- CandidateList *candidates) /* return value */
+ FuncCandidateList function_typeids,
+ FuncCandidateList *candidates) /* return value */
{
- CandidateList current_candidate;
- CandidateList matching_candidate;
- Oid *current_typeids;
+ FuncCandidateList current_candidate;
+ FuncCandidateList next_candidate;
int ncandidates = 0;
*candidates = NULL;
for (current_candidate = function_typeids;
current_candidate != NULL;
- current_candidate = current_candidate->next)
+ current_candidate = next_candidate)
{
- current_typeids = current_candidate->args;
- if (can_coerce_type(nargs, input_typeids, current_typeids))
+ next_candidate = current_candidate->next;
+ if (can_coerce_type(nargs, input_typeids, current_candidate->args))
{
- matching_candidate = (CandidateList)
- palloc(sizeof(struct _CandidateList));
- matching_candidate->args = current_typeids;
- matching_candidate->next = *candidates;
- *candidates = matching_candidate;
+ current_candidate->next = *candidates;
+ *candidates = current_candidate;
ncandidates++;
}
}
@@ -593,8 +539,8 @@ match_argtypes(int nargs,
/* func_select_candidate()
* Given the input argtype array and more than one candidate
- * for the function argtype array, attempt to resolve the conflict.
- * Returns the selected argtype array if the conflict can be resolved,
+ * for the function, attempt to resolve the conflict.
+ * Returns the selected candidate if the conflict can be resolved,
* otherwise returns NULL.
*
* By design, this is pretty similar to oper_select_candidate in parse_oper.c.
@@ -602,13 +548,13 @@ match_argtypes(int nargs,
* already pruned away "candidates" that aren't actually coercion-compatible
* with the input types, whereas oper_select_candidate must do that itself.
*/
-static Oid *
+static FuncCandidateList
func_select_candidate(int nargs,
Oid *input_typeids,
- CandidateList candidates)
+ FuncCandidateList candidates)
{
- CandidateList current_candidate;
- CandidateList last_candidate;
+ FuncCandidateList current_candidate;
+ FuncCandidateList last_candidate;
Oid *current_typeids;
Oid current_type;
int i;
@@ -662,7 +608,7 @@ func_select_candidate(int nargs,
last_candidate->next = NULL;
if (ncandidates == 1)
- return candidates->args;
+ return candidates;
/*
* Still too many candidates? Run through all candidates and keep
@@ -709,7 +655,7 @@ func_select_candidate(int nargs,
last_candidate->next = NULL;
if (ncandidates == 1)
- return candidates->args;
+ return candidates;
/*
* Still too many candidates? Now look for candidates which are
@@ -755,7 +701,7 @@ func_select_candidate(int nargs,
last_candidate->next = NULL;
if (ncandidates == 1)
- return candidates->args;
+ return candidates;
/*
* Still too many candidates? Try assigning types for the unknown
@@ -888,7 +834,7 @@ func_select_candidate(int nargs,
}
if (ncandidates == 1)
- return candidates->args;
+ return candidates;
return NULL; /* failed to determine a unique candidate */
} /* func_select_candidate() */
@@ -925,22 +871,24 @@ func_get_detail(char *funcname,
bool *retset, /* return value */
Oid **true_typeids) /* return value */
{
- HeapTuple ftup;
- CandidateList function_typeids;
+ FuncCandidateList function_typeids;
+ FuncCandidateList best_candidate;
- /* attempt to find with arguments exactly as specified... */
- ftup = SearchSysCache(PROCNAME,
- PointerGetDatum(funcname),
- Int32GetDatum(nargs),
- PointerGetDatum(argtypes),
- 0);
+ /* Get list of possible candidates from namespace search */
+ function_typeids = FuncnameGetCandidates(makeList1(makeString(funcname)), nargs);
- if (HeapTupleIsValid(ftup))
+ /*
+ * See if there is an exact match
+ */
+ for (best_candidate = function_typeids;
+ best_candidate != NULL;
+ best_candidate = best_candidate->next)
{
- /* given argument types are the right ones */
- *true_typeids = argtypes;
+ if (memcmp(argtypes, best_candidate->args, nargs * sizeof(Oid)) == 0)
+ break;
}
- else
+
+ if (best_candidate == NULL)
{
/*
* If we didn't find an exact match, next consider the possibility
@@ -1001,10 +949,6 @@ func_get_detail(char *funcname,
* didn't find an exact match, so now try to match up
* candidates...
*/
-
- function_typeids = func_get_candidates(funcname, nargs);
-
- /* found something, so let's look through them... */
if (function_typeids != NULL)
{
Oid **input_typeid_vector = NULL;
@@ -1019,7 +963,7 @@ func_get_detail(char *funcname,
do
{
- CandidateList current_function_typeids;
+ FuncCandidateList current_function_typeids;
int ncandidates;
ncandidates = match_argtypes(nargs, current_input_typeids,
@@ -1029,13 +973,7 @@ func_get_detail(char *funcname,
/* one match only? then run with it... */
if (ncandidates == 1)
{
- *true_typeids = current_function_typeids->args;
- ftup = SearchSysCache(PROCNAME,
- PointerGetDatum(funcname),
- Int32GetDatum(nargs),
- PointerGetDatum(*true_typeids),
- 0);
- Assert(HeapTupleIsValid(ftup));
+ best_candidate = current_function_typeids;
break;
}
@@ -1045,25 +983,15 @@ func_get_detail(char *funcname,
*/
if (ncandidates > 1)
{
- *true_typeids = func_select_candidate(nargs,
+ best_candidate = func_select_candidate(nargs,
current_input_typeids,
current_function_typeids);
- if (*true_typeids != NULL)
- {
- /* was able to choose a best candidate */
- ftup = SearchSysCache(PROCNAME,
- PointerGetDatum(funcname),
- Int32GetDatum(nargs),
- PointerGetDatum(*true_typeids),
- 0);
- Assert(HeapTupleIsValid(ftup));
- break;
- }
-
/*
- * otherwise, ambiguous function call, so fail by
- * exiting loop with ftup still NULL.
+ * If we were able to choose a best candidate, we're
+ * done. Otherwise, ambiguous function call, so fail
+ * by exiting loop with best_candidate still NULL.
+ * Either way, we're outta here.
*/
break;
}
@@ -1082,11 +1010,20 @@ func_get_detail(char *funcname,
}
}
- if (HeapTupleIsValid(ftup))
+ if (best_candidate)
{
- Form_pg_proc pform = (Form_pg_proc) GETSTRUCT(ftup);
-
- *funcid = ftup->t_data->t_oid;
+ HeapTuple ftup;
+ Form_pg_proc pform;
+
+ *funcid = best_candidate->oid;
+ *true_typeids = best_candidate->args;
+
+ ftup = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(best_candidate->oid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(ftup)) /* should not happen */
+ elog(ERROR, "function %u not found", best_candidate->oid);
+ pform = (Form_pg_proc) GETSTRUCT(ftup);
*rettype = pform->prorettype;
*retset = pform->proretset;
ReleaseSysCache(ftup);