|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.178 2005/04/14 20:03:25 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.179 2005/04/23 22:09:58 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
|
34 | 34 |
|
35 | 35 | staticNode*ParseComplexProjection(ParseState*pstate,char*funcname,
|
36 | 36 | Node*first_arg);
|
37 |
| -staticOid**argtype_inherit(intnargs,Oid*argtypes); |
38 |
| - |
39 |
| -staticintfind_inheritors(Oidrelid,Oid**supervec); |
40 |
| -staticOid**gen_cross_product(InhPaths*arginh,intnargs); |
41 | 37 | staticvoidunknown_attribute(ParseState*pstate,Node*relref,char*attname);
|
42 | 38 |
|
43 | 39 |
|
@@ -754,63 +750,34 @@ func_get_detail(List *funcname,
|
754 | 750 | */
|
755 | 751 | if (raw_candidates!=NULL)
|
756 | 752 | {
|
757 |
| -Oid**input_typeid_vector=NULL; |
758 |
| -Oid*current_input_typeids; |
| 753 | +FuncCandidateListcurrent_candidates; |
| 754 | +intncandidates; |
| 755 | + |
| 756 | +ncandidates=func_match_argtypes(nargs, |
| 757 | +argtypes, |
| 758 | +raw_candidates, |
| 759 | +¤t_candidates); |
| 760 | + |
| 761 | +/* one match only? then run with it... */ |
| 762 | +if (ncandidates==1) |
| 763 | +best_candidate=current_candidates; |
759 | 764 |
|
760 | 765 | /*
|
761 |
| - * First we will search with the given argtypes, then with |
762 |
| - * variants based on replacing complex types with their |
763 |
| - * inheritance ancestors. Stop as soon as any match is found. |
| 766 | + * multiple candidates? then better decide or throw an error... |
764 | 767 | */
|
765 |
| -current_input_typeids=argtypes; |
766 |
| - |
767 |
| -do |
| 768 | +elseif (ncandidates>1) |
768 | 769 | {
|
769 |
| -FuncCandidateListcurrent_candidates; |
770 |
| -intncandidates; |
771 |
| - |
772 |
| -ncandidates=func_match_argtypes(nargs, |
773 |
| -current_input_typeids, |
774 |
| -raw_candidates, |
775 |
| -¤t_candidates); |
776 |
| - |
777 |
| -/* one match only? then run with it... */ |
778 |
| -if (ncandidates==1) |
779 |
| -{ |
780 |
| -best_candidate=current_candidates; |
781 |
| -break; |
782 |
| -} |
| 770 | +best_candidate=func_select_candidate(nargs, |
| 771 | +argtypes, |
| 772 | +current_candidates); |
783 | 773 |
|
784 | 774 | /*
|
785 |
| - *multiple candidates? then better decide or throw an |
786 |
| - *error... |
| 775 | + *If we were able to choose a best candidate, we're |
| 776 | + *done. Otherwise, ambiguous function call. |
787 | 777 | */
|
788 |
| -if (ncandidates>1) |
789 |
| -{ |
790 |
| -best_candidate=func_select_candidate(nargs, |
791 |
| -current_input_typeids, |
792 |
| -current_candidates); |
793 |
| - |
794 |
| -/* |
795 |
| - * If we were able to choose a best candidate, we're |
796 |
| - * done. Otherwise, ambiguous function call. |
797 |
| - */ |
798 |
| -if (best_candidate) |
799 |
| -break; |
| 778 | +if (!best_candidate) |
800 | 779 | returnFUNCDETAIL_MULTIPLE;
|
801 |
| -} |
802 |
| - |
803 |
| -/* |
804 |
| - * No match here, so try the next inherited type vector. |
805 |
| - * First time through, we need to compute the list of |
806 |
| - * vectors. |
807 |
| - */ |
808 |
| -if (input_typeid_vector==NULL) |
809 |
| -input_typeid_vector=argtype_inherit(nargs,argtypes); |
810 |
| - |
811 |
| -current_input_typeids=*input_typeid_vector++; |
812 | 780 | }
|
813 |
| -while (current_input_typeids!=NULL); |
814 | 781 | }
|
815 | 782 | }
|
816 | 783 |
|
@@ -840,81 +807,27 @@ func_get_detail(List *funcname,
|
840 | 807 | returnFUNCDETAIL_NOTFOUND;
|
841 | 808 | }
|
842 | 809 |
|
843 |
| -/* |
844 |
| - *argtype_inherit() -- Construct an argtype vector reflecting the |
845 |
| - * inheritance properties of the supplied argv. |
846 |
| - * |
847 |
| - *This function is used to handle resolution of function calls when |
848 |
| - *there is no match to the given argument types, but there might be |
849 |
| - *matches based on considering complex types as members of their |
850 |
| - *superclass types (parent classes). |
851 |
| - * |
852 |
| - *It takes an array of input type ids. For each type id in the array |
853 |
| - *that's a complex type (a class), it walks up the inheritance tree, |
854 |
| - *finding all superclasses of that type. A vector of new Oid type |
855 |
| - *arrays is returned to the caller, listing possible alternative |
856 |
| - *interpretations of the input typeids as members of their superclasses |
857 |
| - *rather than the actually given argument types.The vector is |
858 |
| - *terminated by a NULL pointer. |
859 |
| - * |
860 |
| - *The order of this vector is as follows: all superclasses of the |
861 |
| - *rightmost complex class are explored first. The exploration |
862 |
| - *continues from right to left. This policy means that we favor |
863 |
| - *keeping the leftmost argument type as low in the inheritance tree |
864 |
| - *as possible. This is intentional; it is exactly what we need to |
865 |
| - *do for method dispatch. |
866 |
| - * |
867 |
| - *The vector does not include the case where no complex classes have |
868 |
| - *been promoted, since that was already tried before this routine |
869 |
| - *got called. |
870 |
| - */ |
871 |
| -staticOid** |
872 |
| -argtype_inherit(intnargs,Oid*argtypes) |
873 |
| -{ |
874 |
| -Oid**result; |
875 |
| -Oidrelid; |
876 |
| -inti; |
877 |
| -InhPaths*arginh; |
878 |
| - |
879 |
| -/* Set up the vector of superclass information */ |
880 |
| -arginh= (InhPaths*)palloc(nargs*sizeof(InhPaths)); |
881 |
| - |
882 |
| -for (i=0;i<nargs;i++) |
883 |
| -{ |
884 |
| -arginh[i].self=argtypes[i]; |
885 |
| -if ((relid=typeidTypeRelid(argtypes[i]))!=InvalidOid) |
886 |
| -arginh[i].nsupers=find_inheritors(relid,&(arginh[i].supervec)); |
887 |
| -else |
888 |
| -{ |
889 |
| -arginh[i].nsupers=0; |
890 |
| -arginh[i].supervec=NULL; |
891 |
| -} |
892 |
| -} |
893 |
| - |
894 |
| -/* Compute an ordered cross-product of the classes involved */ |
895 |
| -result=gen_cross_product(arginh,nargs); |
896 |
| - |
897 |
| -pfree(arginh); |
898 |
| - |
899 |
| -returnresult; |
900 |
| -} |
901 | 810 |
|
902 | 811 | /*
|
903 |
| - * Look up the parent superclass(es) of the given relation. |
904 |
| - * |
905 |
| - * *supervec is set to an array of the type OIDs (not the relation OIDs) |
906 |
| - * of the parents, with nearest ancestors listed first. It's set to NULL |
907 |
| - * if there are no parents. The return value is the number of parents. |
| 812 | + * Given two type OIDs, determine whether the first is a complex type |
| 813 | + * (class type) that inherits from the second. |
908 | 814 | */
|
909 |
| -staticint |
910 |
| -find_inheritors(Oidrelid,Oid**supervec) |
| 815 | +bool |
| 816 | +typeInheritsFrom(OidsubclassTypeId,OidsuperclassTypeId) |
911 | 817 | {
|
| 818 | +boolresult= false; |
| 819 | +Oidrelid; |
912 | 820 | Relationinhrel;
|
913 |
| -intnvisited; |
914 | 821 | List*visited,
|
915 | 822 | *queue;
|
916 | 823 | ListCell*queue_item;
|
917 | 824 |
|
| 825 | +if (!ISCOMPLEX(subclassTypeId)|| !ISCOMPLEX(superclassTypeId)) |
| 826 | +return false; |
| 827 | +relid=typeidTypeRelid(subclassTypeId); |
| 828 | +if (relid==InvalidOid) |
| 829 | +return false; |
| 830 | + |
918 | 831 | /*
|
919 | 832 | * Begin the search at the relation itself, so add relid to the queue.
|
920 | 833 | */
|
@@ -960,149 +873,30 @@ find_inheritors(Oid relid, Oid **supervec)
|
960 | 873 | while ((inhtup=heap_getnext(inhscan,ForwardScanDirection))!=NULL)
|
961 | 874 | {
|
962 | 875 | Form_pg_inheritsinh= (Form_pg_inherits)GETSTRUCT(inhtup);
|
| 876 | +Oidinhparent=inh->inhparent; |
| 877 | + |
| 878 | +/* If this is the target superclass, we're done */ |
| 879 | +if (get_rel_type_id(inhparent)==superclassTypeId) |
| 880 | +{ |
| 881 | +result= true; |
| 882 | +break; |
| 883 | +} |
963 | 884 |
|
964 |
| -queue=lappend_oid(queue,inh->inhparent); |
| 885 | +/* Else add to queue */ |
| 886 | +queue=lappend_oid(queue,inhparent); |
965 | 887 | }
|
966 | 888 |
|
967 | 889 | heap_endscan(inhscan);
|
| 890 | + |
| 891 | +if (result) |
| 892 | +break; |
968 | 893 | }
|
969 | 894 |
|
970 | 895 | heap_close(inhrel,AccessShareLock);
|
971 | 896 |
|
972 |
| -nvisited=list_length(visited); |
973 |
| -if (nvisited>0) |
974 |
| -{ |
975 |
| -Oid*relidvec; |
976 |
| -ListCell*l; |
977 |
| - |
978 |
| -relidvec= (Oid*)palloc(nvisited*sizeof(*relidvec)); |
979 |
| -*supervec=relidvec; |
980 |
| - |
981 |
| -foreach(l,visited) |
982 |
| -{ |
983 |
| -/* return the type id, rather than the relation id */ |
984 |
| -*relidvec++=get_rel_type_id(lfirst_oid(l)); |
985 |
| -} |
986 |
| -} |
987 |
| -else |
988 |
| -*supervec=NULL; |
989 |
| - |
990 | 897 | list_free(visited);
|
991 | 898 | list_free(queue);
|
992 | 899 |
|
993 |
| -returnnvisited; |
994 |
| -} |
995 |
| - |
996 |
| -/* |
997 |
| - * Generate the ordered list of substitute argtype vectors to try. |
998 |
| - * |
999 |
| - * See comments for argtype_inherit. |
1000 |
| - */ |
1001 |
| -staticOid** |
1002 |
| -gen_cross_product(InhPaths*arginh,intnargs) |
1003 |
| -{ |
1004 |
| -intnanswers; |
1005 |
| -Oid**result; |
1006 |
| -Oid*oneres; |
1007 |
| -inti, |
1008 |
| -j; |
1009 |
| -int*cur; |
1010 |
| - |
1011 |
| -/* |
1012 |
| - * At each position we want to try the original datatype, plus each |
1013 |
| - * supertype. So the number of possible combinations is this: |
1014 |
| - */ |
1015 |
| -nanswers=1; |
1016 |
| -for (i=0;i<nargs;i++) |
1017 |
| -nanswers *= (arginh[i].nsupers+1); |
1018 |
| - |
1019 |
| -/* |
1020 |
| - * We also need an extra slot for the terminating NULL in the result |
1021 |
| - * array, but that cancels out with the fact that we don't want to |
1022 |
| - * generate the zero-changes case.So we need exactly nanswers slots. |
1023 |
| - */ |
1024 |
| -result= (Oid**)palloc(sizeof(Oid*)*nanswers); |
1025 |
| -j=0; |
1026 |
| - |
1027 |
| -/* |
1028 |
| - * Compute the cross product from right to left. When cur[i] == 0, |
1029 |
| - * generate the original input type at position i.When cur[i] == k |
1030 |
| - * for k > 0, generate its k'th supertype. |
1031 |
| - */ |
1032 |
| -cur= (int*)palloc0(nargs*sizeof(int)); |
1033 |
| - |
1034 |
| -for (;;) |
1035 |
| -{ |
1036 |
| -/* |
1037 |
| - * Find a column we can increment.All the columns after it get |
1038 |
| - * reset to zero. (Essentially, we're adding one to the multi- |
1039 |
| - * digit number represented by cur[].) |
1040 |
| - */ |
1041 |
| -for (i=nargs-1;i >=0&&cur[i] >=arginh[i].nsupers;i--) |
1042 |
| -cur[i]=0; |
1043 |
| - |
1044 |
| -/* if none, we're done */ |
1045 |
| -if (i<0) |
1046 |
| -break; |
1047 |
| - |
1048 |
| -/* increment this column */ |
1049 |
| -cur[i]+=1; |
1050 |
| - |
1051 |
| -/* Generate the proper output type-OID vector */ |
1052 |
| -oneres= (Oid*)palloc(nargs*sizeof(Oid)); |
1053 |
| - |
1054 |
| -for (i=0;i<nargs;i++) |
1055 |
| -{ |
1056 |
| -if (cur[i]==0) |
1057 |
| -oneres[i]=arginh[i].self; |
1058 |
| -else |
1059 |
| -oneres[i]=arginh[i].supervec[cur[i]-1]; |
1060 |
| -} |
1061 |
| - |
1062 |
| -result[j++]=oneres; |
1063 |
| -} |
1064 |
| - |
1065 |
| -/* terminate result vector with NULL pointer */ |
1066 |
| -result[j++]=NULL; |
1067 |
| - |
1068 |
| -Assert(j==nanswers); |
1069 |
| - |
1070 |
| -pfree(cur); |
1071 |
| - |
1072 |
| -returnresult; |
1073 |
| -} |
1074 |
| - |
1075 |
| - |
1076 |
| -/* |
1077 |
| - * Given two type OIDs, determine whether the first is a complex type |
1078 |
| - * (class type) that inherits from the second. |
1079 |
| - */ |
1080 |
| -bool |
1081 |
| -typeInheritsFrom(OidsubclassTypeId,OidsuperclassTypeId) |
1082 |
| -{ |
1083 |
| -Oidrelid; |
1084 |
| -Oid*supervec; |
1085 |
| -intnsupers, |
1086 |
| -i; |
1087 |
| -boolresult; |
1088 |
| - |
1089 |
| -if (!ISCOMPLEX(subclassTypeId)|| !ISCOMPLEX(superclassTypeId)) |
1090 |
| -return false; |
1091 |
| -relid=typeidTypeRelid(subclassTypeId); |
1092 |
| -if (relid==InvalidOid) |
1093 |
| -return false; |
1094 |
| -nsupers=find_inheritors(relid,&supervec); |
1095 |
| -result= false; |
1096 |
| -for (i=0;i<nsupers;i++) |
1097 |
| -{ |
1098 |
| -if (supervec[i]==superclassTypeId) |
1099 |
| -{ |
1100 |
| -result= true; |
1101 |
| -break; |
1102 |
| -} |
1103 |
| -} |
1104 |
| -if (supervec) |
1105 |
| -pfree(supervec); |
1106 | 900 | returnresult;
|
1107 | 901 | }
|
1108 | 902 |
|
|