|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.94 2000/11/1622: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 $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -759,14 +759,15 @@ func_select_candidate(int nargs,
|
759 | 759 | CandidateListcurrent_candidate;
|
760 | 760 | CandidateListlast_candidate;
|
761 | 761 | Oid*current_typeids;
|
| 762 | +Oidcurrent_type; |
762 | 763 | inti;
|
763 | 764 | intncandidates;
|
764 | 765 | intnbestMatch,
|
765 | 766 | nmatch;
|
766 |
| -CATEGORYslot_category, |
| 767 | +CATEGORYslot_category[FUNC_MAX_ARGS], |
767 | 768 | current_category;
|
768 |
| -Oidslot_type, |
769 |
| -current_type; |
| 769 | +boolslot_has_preferred_type[FUNC_MAX_ARGS]; |
| 770 | +boolresolved_unknowns; |
770 | 771 |
|
771 | 772 | /*
|
772 | 773 | * Run through all candidates and keep those with the most matches on
|
@@ -911,98 +912,133 @@ func_select_candidate(int nargs,
|
911 | 912 | * Still too many candidates? Try assigning types for the unknown
|
912 | 913 | * columns.
|
913 | 914 | *
|
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. |
919 | 922 | *
|
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. |
928 | 932 | */
|
| 933 | +resolved_unknowns= false; |
929 | 934 | for (i=0;i<nargs;i++)
|
930 | 935 | {
|
931 |
| -if (input_typeids[i]==UNKNOWNOID) |
| 936 | +boolhave_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) |
932 | 947 | {
|
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) |
939 | 952 | {
|
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 | +elseif (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) |
944 | 968 | {
|
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); |
948 | 973 | }
|
949 |
| -elseif (current_category!=slot_category) |
| 974 | +else |
950 | 975 | {
|
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 |
| -elseif (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; |
968 | 978 | }
|
969 |
| -elseif (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 | +boolkeepit= 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]) |
970 | 1008 | {
|
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 |
| -elseif (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; |
988 | 1011 | }
|
989 |
| -else |
| 1012 | +if (slot_has_preferred_type[i]&& |
| 1013 | +!IsPreferredType(current_category,current_type)) |
990 | 1014 | {
|
991 |
| -/* keep this candidate */ |
992 |
| -last_candidate=current_candidate; |
| 1015 | +keepit= false; |
| 1016 | +break; |
993 | 1017 | }
|
994 | 1018 | }
|
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 | +} |
997 | 1033 | }
|
| 1034 | +if (last_candidate)/* terminate rebuilt list */ |
| 1035 | +last_candidate->next=NULL; |
998 | 1036 | }
|
999 | 1037 |
|
1000 |
| -if (candidates==NULL) |
1001 |
| -returnNULL;/* no remaining candidates */ |
1002 |
| -if (candidates->next!=NULL) |
1003 |
| -returnNULL;/* more than one remaining candidate */ |
| 1038 | +if (ncandidates==1) |
| 1039 | +returncandidates->args; |
1004 | 1040 |
|
1005 |
| -returncandidates->args; |
| 1041 | +returnNULL;/* failed to determine a unique candidate */ |
1006 | 1042 | }/* func_select_candidate() */
|
1007 | 1043 |
|
1008 | 1044 |
|
|