Skip to content

Commit 5253c51

Browse files
committed
Fix broken list-slinging logic in func_select_candidate and
agg_select_candidate, which could cause them to keep more candidates than they should and thus fail to select a single match. I had previously fixed the identical bug in oper_select_candidate, but didn't realize that the same error was repeated over here. Also, repair func_select_candidate's curious notion that it could scribble on the input type-OID vector. That was causing failure to apply necessary type coercion later on, leading to malfunction of examples such as select date('now').
1 parent f4d108a commit 5253c51

File tree

1 file changed

+42
-24
lines changed

1 file changed

+42
-24
lines changed

src/backend/parser/parse_func.c

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.69 2000/02/15 03:37:47 thomas Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.70 2000/02/20 06:35:08 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -45,14 +45,13 @@ static Oid **argtype_inherit(int nargs, Oid *oid_array);
4545

4646
static int find_inheritors(Oid relid, Oid **supervec);
4747
static CandidateList func_get_candidates(char *funcname, int nargs);
48-
static bool
49-
func_get_detail(char *funcname,
50-
int nargs,
51-
Oid *oid_array,
52-
Oid *funcid, /* return value */
53-
Oid *rettype, /* return value */
54-
bool *retset, /* return value */
55-
Oid **true_typeids);
48+
static bool func_get_detail(char *funcname,
49+
int nargs,
50+
Oid *oid_array,
51+
Oid *funcid, /* return value */
52+
Oid *rettype, /* return value */
53+
bool *retset, /* return value */
54+
Oid **true_typeids);
5655
static Oid **gen_cross_product(InhPaths *arginh, int nargs);
5756
static void make_arguments(ParseState *pstate,
5857
int nargs,
@@ -228,10 +227,11 @@ agg_select_candidate(Oid typeid, CandidateList candidates)
228227
}
229228
}
230229
/* otherwise, don't bother keeping this one around... */
231-
else if (last_candidate != NULL)
232-
last_candidate->next = NULL;
233230
}
234231

232+
if (last_candidate) /* terminate rebuilt list */
233+
last_candidate->next = NULL;
234+
235235
return ((ncandidates == 1) ? candidates->args[0] : 0);
236236
} /* agg_select_candidate() */
237237

@@ -559,8 +559,8 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
559559
}
560560

561561
/* Most of the rest of the parser just assumes that functions do not
562-
* have more than FUNC_MAX_ARGS parameters. We have to test here to protect
563-
* against array overruns, etc.
562+
* have more than FUNC_MAX_ARGS parameters. We have to test here
563+
* to protect against array overruns, etc.
564564
*/
565565
if (nargs >= FUNC_MAX_ARGS)
566566
elog(ERROR, "Cannot pass more than %d arguments to a function",
@@ -892,23 +892,27 @@ func_select_candidate(int nargs,
892892
if ((nmatch + nident) == nargs)
893893
return current_candidate->args;
894894

895+
/* take this one as the best choice so far? */
895896
if ((nmatch > nbestMatch) || (last_candidate == NULL))
896897
{
897898
nbestMatch = nmatch;
898899
candidates = current_candidate;
899900
last_candidate = current_candidate;
900901
ncandidates = 1;
901902
}
903+
/* no worse than the last choice, so keep this one too? */
902904
else if (nmatch == nbestMatch)
903905
{
904906
last_candidate->next = current_candidate;
905907
last_candidate = current_candidate;
906908
ncandidates++;
907909
}
908-
else
909-
last_candidate->next = NULL;
910+
/* otherwise, don't bother keeping this one... */
910911
}
911912

913+
if (last_candidate) /* terminate rebuilt list */
914+
last_candidate->next = NULL;
915+
912916
if (ncandidates == 1)
913917
return candidates->args;
914918

@@ -922,6 +926,7 @@ func_select_candidate(int nargs,
922926
{
923927
slot_category = INVALID_TYPE;
924928
slot_type = InvalidOid;
929+
last_candidate = NULL;
925930
for (current_candidate = candidates;
926931
current_candidate != NULL;
927932
current_candidate = current_candidate->next)
@@ -935,26 +940,39 @@ func_select_candidate(int nargs,
935940
slot_category = current_category;
936941
slot_type = current_type;
937942
}
938-
else if ((current_category != slot_category)
939-
&& IS_BUILTIN_TYPE(current_type))
943+
else if (current_category != slot_category)
944+
{
945+
/* punt if more than one category for this slot */
940946
return NULL;
947+
}
941948
else if (current_type != slot_type)
942949
{
943950
if (IsPreferredType(slot_category, current_type))
944951
{
945952
slot_type = current_type;
953+
/* forget all previous candidates */
946954
candidates = current_candidate;
955+
last_candidate = current_candidate;
947956
}
948957
else if (IsPreferredType(slot_category, slot_type))
949-
candidates->next = current_candidate->next;
958+
{
959+
/* forget this candidate */
960+
if (last_candidate)
961+
last_candidate->next = current_candidate->next;
962+
else
963+
candidates = current_candidate->next;
964+
}
965+
else
966+
last_candidate = current_candidate;
967+
}
968+
else
969+
{
970+
/* keep this candidate */
971+
last_candidate = current_candidate;
950972
}
951973
}
952-
953-
if (slot_type != InvalidOid)
954-
input_typeids[i] = slot_type;
955-
}
956-
else
957-
{
974+
if (last_candidate) /* terminate rebuilt list */
975+
last_candidate->next = NULL;
958976
}
959977
}
960978

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy