|
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 | static Node *ParseComplexProjection(ParseState *pstate, char *funcname, |
36 | 36 | Node *first_arg); |
37 | | -static Oid **argtype_inherit(int nargs, Oid *argtypes); |
38 | | - |
39 | | -static int find_inheritors(Oid relid, Oid **supervec); |
40 | | -static Oid **gen_cross_product(InhPaths *arginh, int nargs); |
41 | 37 | static void unknown_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 | + FuncCandidateList current_candidates; |
| 754 | + int ncandidates; |
| 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 | + else if (ncandidates > 1) |
768 | 769 | { |
769 | | - FuncCandidateList current_candidates; |
770 | | - int ncandidates; |
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 | return FUNCDETAIL_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 | return FUNCDETAIL_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 | | -static Oid ** |
872 | | -argtype_inherit(int nargs, Oid *argtypes) |
873 | | -{ |
874 | | - Oid **result; |
875 | | - Oid relid; |
876 | | - int i; |
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 | | - return result; |
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 | | -static int |
910 | | -find_inheritors(Oid relid, Oid **supervec) |
| 815 | +bool |
| 816 | +typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId) |
911 | 817 | { |
| 818 | + bool result = false; |
| 819 | + Oid relid; |
912 | 820 | Relation inhrel; |
913 | | - int nvisited; |
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_inherits inh = (Form_pg_inherits) GETSTRUCT(inhtup); |
| 876 | + Oid inhparent = 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 | | - return nvisited; |
994 | | -} |
995 | | - |
996 | | -/* |
997 | | - * Generate the ordered list of substitute argtype vectors to try. |
998 | | - * |
999 | | - * See comments for argtype_inherit. |
1000 | | - */ |
1001 | | -static Oid ** |
1002 | | -gen_cross_product(InhPaths *arginh, int nargs) |
1003 | | -{ |
1004 | | - int nanswers; |
1005 | | - Oid **result; |
1006 | | - Oid *oneres; |
1007 | | - int i, |
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 | | - return result; |
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(Oid subclassTypeId, Oid superclassTypeId) |
1082 | | -{ |
1083 | | - Oid relid; |
1084 | | - Oid *supervec; |
1085 | | - int nsupers, |
1086 | | - i; |
1087 | | - bool result; |
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 | return result; |
1107 | 901 | } |
1108 | 902 |
|
|
0 commit comments