diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index b231058726078d21d68fba3f4b3426d1c0000a41..4c24d684991dd4e72321dc3834c3ef1cde78b0a8 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.106 2001/05/19 00:33:20 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.107 2001/05/19 00:37:45 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -104,136 +104,6 @@ ParseNestedFuncOrColumn(ParseState *pstate, Attr *attr, int precedence) return retval; } -static int -agg_get_candidates(char *aggname, - Oid typeId, - CandidateList *candidates) -{ - CandidateList current_candidate; - Relation pg_aggregate_desc; - HeapScanDesc pg_aggregate_scan; - HeapTuple tup; - Form_pg_aggregate agg; - int ncandidates = 0; - ScanKeyData aggKey[1]; - - *candidates = NULL; - - ScanKeyEntryInitialize(&aggKey[0], 0, - Anum_pg_aggregate_aggname, - F_NAMEEQ, - NameGetDatum(aggname)); - - pg_aggregate_desc = heap_openr(AggregateRelationName, AccessShareLock); - pg_aggregate_scan = heap_beginscan(pg_aggregate_desc, - 0, - SnapshotSelf, /* ??? */ - 1, - aggKey); - - while (HeapTupleIsValid(tup = heap_getnext(pg_aggregate_scan, 0))) - { - agg = (Form_pg_aggregate) GETSTRUCT(tup); - - current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList)); - current_candidate->args = (Oid *) palloc(sizeof(Oid)); - - current_candidate->args[0] = agg->aggbasetype; - current_candidate->next = *candidates; - *candidates = current_candidate; - ncandidates++; - } - - heap_endscan(pg_aggregate_scan); - heap_close(pg_aggregate_desc, AccessShareLock); - - return ncandidates; -} /* agg_get_candidates() */ - -/* agg_select_candidate() - * - * Try to choose only one candidate aggregate function from a list of - * possible matches. Return value is Oid of input type of aggregate - * if successful, else InvalidOid. - */ -static Oid -agg_select_candidate(Oid typeid, CandidateList candidates) -{ - CandidateList current_candidate; - CandidateList last_candidate; - Oid current_typeid; - int ncandidates; - CATEGORY category, - current_category; - - /* - * First look for exact matches or binary compatible matches. (Of - * course exact matches shouldn't even get here, but anyway.) - */ - ncandidates = 0; - last_candidate = NULL; - for (current_candidate = candidates; - current_candidate != NULL; - current_candidate = current_candidate->next) - { - current_typeid = current_candidate->args[0]; - - if (current_typeid == typeid - || IS_BINARY_COMPATIBLE(current_typeid, typeid)) - { - last_candidate = current_candidate; - ncandidates++; - } - } - if (ncandidates == 1) - return last_candidate->args[0]; - - /* - * If no luck that way, look for candidates which allow coercion and - * have a preferred type. Keep all candidates if none match. - */ - category = TypeCategory(typeid); - ncandidates = 0; - last_candidate = NULL; - for (current_candidate = candidates; - current_candidate != NULL; - current_candidate = current_candidate->next) - { - current_typeid = current_candidate->args[0]; - current_category = TypeCategory(current_typeid); - - if (current_category == category - && IsPreferredType(current_category, current_typeid) - && can_coerce_type(1, &typeid, ¤t_typeid)) - { - /* only one so far? then keep it... */ - if (last_candidate == NULL) - { - candidates = current_candidate; - last_candidate = current_candidate; - ncandidates = 1; - } - /* otherwise, keep this one too... */ - else - { - last_candidate->next = current_candidate; - last_candidate = current_candidate; - ncandidates++; - } - } - /* otherwise, don't bother keeping this one around... */ - } - - if (last_candidate) /* terminate rebuilt list */ - last_candidate->next = NULL; - - if (ncandidates == 1) - return candidates->args[0]; - - return InvalidOid; -} /* agg_select_candidate() */ - - /* * parse function * This code is confusing because the database can accept @@ -709,6 +579,136 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs, } +static int +agg_get_candidates(char *aggname, + Oid typeId, + CandidateList *candidates) +{ + CandidateList current_candidate; + Relation pg_aggregate_desc; + HeapScanDesc pg_aggregate_scan; + HeapTuple tup; + Form_pg_aggregate agg; + int ncandidates = 0; + ScanKeyData aggKey[1]; + + *candidates = NULL; + + ScanKeyEntryInitialize(&aggKey[0], 0, + Anum_pg_aggregate_aggname, + F_NAMEEQ, + NameGetDatum(aggname)); + + pg_aggregate_desc = heap_openr(AggregateRelationName, AccessShareLock); + pg_aggregate_scan = heap_beginscan(pg_aggregate_desc, + 0, + SnapshotSelf, /* ??? */ + 1, + aggKey); + + while (HeapTupleIsValid(tup = heap_getnext(pg_aggregate_scan, 0))) + { + agg = (Form_pg_aggregate) GETSTRUCT(tup); + + current_candidate = (CandidateList) palloc(sizeof(struct _CandidateList)); + current_candidate->args = (Oid *) palloc(sizeof(Oid)); + + current_candidate->args[0] = agg->aggbasetype; + current_candidate->next = *candidates; + *candidates = current_candidate; + ncandidates++; + } + + heap_endscan(pg_aggregate_scan); + heap_close(pg_aggregate_desc, AccessShareLock); + + return ncandidates; +} /* agg_get_candidates() */ + +/* agg_select_candidate() + * + * Try to choose only one candidate aggregate function from a list of + * possible matches. Return value is Oid of input type of aggregate + * if successful, else InvalidOid. + */ +static Oid +agg_select_candidate(Oid typeid, CandidateList candidates) +{ + CandidateList current_candidate; + CandidateList last_candidate; + Oid current_typeid; + int ncandidates; + CATEGORY category, + current_category; + + /* + * First look for exact matches or binary compatible matches. (Of + * course exact matches shouldn't even get here, but anyway.) + */ + ncandidates = 0; + last_candidate = NULL; + for (current_candidate = candidates; + current_candidate != NULL; + current_candidate = current_candidate->next) + { + current_typeid = current_candidate->args[0]; + + if (current_typeid == typeid + || IS_BINARY_COMPATIBLE(current_typeid, typeid)) + { + last_candidate = current_candidate; + ncandidates++; + } + } + if (ncandidates == 1) + return last_candidate->args[0]; + + /* + * If no luck that way, look for candidates which allow coercion and + * have a preferred type. Keep all candidates if none match. + */ + category = TypeCategory(typeid); + ncandidates = 0; + last_candidate = NULL; + for (current_candidate = candidates; + current_candidate != NULL; + current_candidate = current_candidate->next) + { + current_typeid = current_candidate->args[0]; + current_category = TypeCategory(current_typeid); + + if (current_category == category + && IsPreferredType(current_category, current_typeid) + && can_coerce_type(1, &typeid, ¤t_typeid)) + { + /* only one so far? then keep it... */ + if (last_candidate == NULL) + { + candidates = current_candidate; + last_candidate = current_candidate; + ncandidates = 1; + } + /* otherwise, keep this one too... */ + else + { + last_candidate->next = current_candidate; + last_candidate = current_candidate; + ncandidates++; + } + } + /* otherwise, don't bother keeping this one around... */ + } + + if (last_candidate) /* terminate rebuilt list */ + last_candidate->next = NULL; + + if (ncandidates == 1) + return candidates->args[0]; + + return InvalidOid; +} /* agg_select_candidate() */ + + /* func_get_candidates() * get a list of all argument type vectors for which a function named * funcname taking nargs arguments exists