|
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