Skip to content

Commit 7d6af50

Browse files
committed
Make algorithm for resolving UNKNOWN function/operator inputs be
insensitive to the order of arguments. Per pghackers discussion 12/10/00.
1 parent ff783fb commit 7d6af50

File tree

2 files changed

+229
-151
lines changed

2 files changed

+229
-151
lines changed

src/backend/parser/parse_func.c

Lines changed: 113 additions & 77 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.94 2000/11/16 22:30:28 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.95 2000/12/15 19:22:03 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -759,14 +759,15 @@ func_select_candidate(int nargs,
759759
CandidateList current_candidate;
760760
CandidateList last_candidate;
761761
Oid *current_typeids;
762+
Oid current_type;
762763
int i;
763764
int ncandidates;
764765
int nbestMatch,
765766
nmatch;
766-
CATEGORY slot_category,
767+
CATEGORY slot_category[FUNC_MAX_ARGS],
767768
current_category;
768-
Oid slot_type,
769-
current_type;
769+
bool slot_has_preferred_type[FUNC_MAX_ARGS];
770+
bool resolved_unknowns;
770771

771772
/*
772773
* Run through all candidates and keep those with the most matches on
@@ -911,98 +912,133 @@ func_select_candidate(int nargs,
911912
* Still too many candidates? Try assigning types for the unknown
912913
* columns.
913914
*
914-
* We do this by examining each unknown argument position to see if all
915-
* the candidates agree on the type category of that slot. If so, and
916-
* if some candidates accept the preferred type in that category,
917-
* eliminate the candidates with other input types. If we are down to
918-
* one candidate at the end, we win.
915+
* We do this by examining each unknown argument position to see if we
916+
* can determine a "type category" for it. If any candidate has an
917+
* input datatype of STRING category, use STRING category (this bias
918+
* towards STRING is appropriate since unknown-type literals look like
919+
* strings). Otherwise, if all the candidates agree on the type
920+
* category of this argument position, use that category. Otherwise,
921+
* fail because we cannot determine a category.
919922
*
920-
* XXX It's kinda bogus to do this left-to-right, isn't it? If we
921-
* eliminate some candidates because they are non-preferred at the
922-
* first slot, we won't notice that they didn't have the same type
923-
* category for a later slot.
924-
* XXX Hmm. How else would you do this? These candidates are here because
925-
* they all have the same number of matches on arguments with explicit
926-
* types, so from here on left-to-right resolution is as good as any.
927-
* Need a counterexample to see otherwise...
923+
* If we are able to determine a type category, also notice whether
924+
* any of the candidates takes a preferred datatype within the category.
925+
*
926+
* Having completed this examination, remove candidates that accept
927+
* the wrong category at any unknown position. Also, if at least one
928+
* candidate accepted a preferred type at a position, remove candidates
929+
* that accept non-preferred types.
930+
*
931+
* If we are down to one candidate at the end, we win.
928932
*/
933+
resolved_unknowns = false;
929934
for (i = 0; i < nargs; i++)
930935
{
931-
if (input_typeids[i] == UNKNOWNOID)
936+
bool have_conflict;
937+
938+
if (input_typeids[i] != UNKNOWNOID)
939+
continue;
940+
resolved_unknowns = true; /* assume we can do it */
941+
slot_category[i] = INVALID_TYPE;
942+
slot_has_preferred_type[i] = false;
943+
have_conflict = false;
944+
for (current_candidate = candidates;
945+
current_candidate != NULL;
946+
current_candidate = current_candidate->next)
932947
{
933-
slot_category = INVALID_TYPE;
934-
slot_type = InvalidOid;
935-
last_candidate = NULL;
936-
for (current_candidate = candidates;
937-
current_candidate != NULL;
938-
current_candidate = current_candidate->next)
948+
current_typeids = current_candidate->args;
949+
current_type = current_typeids[i];
950+
current_category = TypeCategory(current_type);
951+
if (slot_category[i] == INVALID_TYPE)
939952
{
940-
current_typeids = current_candidate->args;
941-
current_type = current_typeids[i];
942-
current_category = TypeCategory(current_type);
943-
if (slot_category == INVALID_TYPE)
953+
/* first candidate */
954+
slot_category[i] = current_category;
955+
slot_has_preferred_type[i] =
956+
IsPreferredType(current_category, current_type);
957+
}
958+
else if (current_category == slot_category[i])
959+
{
960+
/* more candidates in same category */
961+
slot_has_preferred_type[i] |=
962+
IsPreferredType(current_category, current_type);
963+
}
964+
else
965+
{
966+
/* category conflict! */
967+
if (current_category == STRING_TYPE)
944968
{
945-
slot_category = current_category;
946-
slot_type = current_type;
947-
last_candidate = current_candidate;
969+
/* STRING always wins if available */
970+
slot_category[i] = current_category;
971+
slot_has_preferred_type[i] =
972+
IsPreferredType(current_category, current_type);
948973
}
949-
else if (current_category != slot_category)
974+
else
950975
{
951-
/* started out as unknown type, so give preference to string type, if available */
952-
if (current_category == STRING_TYPE)
953-
{
954-
slot_category = current_category;
955-
slot_type = current_type;
956-
/* forget all previous candidates */
957-
candidates = current_candidate;
958-
last_candidate = current_candidate;
959-
}
960-
else if (slot_category == STRING_TYPE)
961-
{
962-
/* forget this candidate */
963-
if (last_candidate)
964-
last_candidate->next = current_candidate->next;
965-
else
966-
candidates = current_candidate->next;
967-
}
976+
/* Remember conflict, but keep going (might find STRING) */
977+
have_conflict = true;
968978
}
969-
else if (current_type != slot_type)
979+
}
980+
}
981+
if (have_conflict && slot_category[i] != STRING_TYPE)
982+
{
983+
/* Failed to resolve category conflict at this position */
984+
resolved_unknowns = false;
985+
break;
986+
}
987+
}
988+
989+
if (resolved_unknowns)
990+
{
991+
/* Strip non-matching candidates */
992+
ncandidates = 0;
993+
last_candidate = NULL;
994+
for (current_candidate = candidates;
995+
current_candidate != NULL;
996+
current_candidate = current_candidate->next)
997+
{
998+
bool keepit = true;
999+
1000+
current_typeids = current_candidate->args;
1001+
for (i = 0; i < nargs; i++)
1002+
{
1003+
if (input_typeids[i] != UNKNOWNOID)
1004+
continue;
1005+
current_type = current_typeids[i];
1006+
current_category = TypeCategory(current_type);
1007+
if (current_category != slot_category[i])
9701008
{
971-
if (IsPreferredType(slot_category, current_type))
972-
{
973-
slot_type = current_type;
974-
/* forget all previous candidates */
975-
candidates = current_candidate;
976-
last_candidate = current_candidate;
977-
}
978-
else if (IsPreferredType(slot_category, slot_type))
979-
{
980-
/* forget this candidate */
981-
if (last_candidate)
982-
last_candidate->next = current_candidate->next;
983-
else
984-
candidates = current_candidate->next;
985-
}
986-
else
987-
last_candidate = current_candidate;
1009+
keepit = false;
1010+
break;
9881011
}
989-
else
1012+
if (slot_has_preferred_type[i] &&
1013+
!IsPreferredType(current_category, current_type))
9901014
{
991-
/* keep this candidate */
992-
last_candidate = current_candidate;
1015+
keepit = false;
1016+
break;
9931017
}
9941018
}
995-
if (last_candidate) /* terminate rebuilt list */
996-
last_candidate->next = NULL;
1019+
if (keepit)
1020+
{
1021+
/* keep this candidate */
1022+
last_candidate = current_candidate;
1023+
ncandidates++;
1024+
}
1025+
else
1026+
{
1027+
/* forget this candidate */
1028+
if (last_candidate)
1029+
last_candidate->next = current_candidate->next;
1030+
else
1031+
candidates = current_candidate->next;
1032+
}
9971033
}
1034+
if (last_candidate) /* terminate rebuilt list */
1035+
last_candidate->next = NULL;
9981036
}
9991037

1000-
if (candidates == NULL)
1001-
return NULL; /* no remaining candidates */
1002-
if (candidates->next != NULL)
1003-
return NULL; /* more than one remaining candidate */
1038+
if (ncandidates == 1)
1039+
return candidates->args;
10041040

1005-
return candidates->args;
1041+
return NULL; /* failed to determine a unique candidate */
10061042
} /* func_select_candidate() */
10071043

10081044

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