|
8 | 8 | * |
9 | 9 | * |
10 | 10 | * IDENTIFICATION |
11 | | - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.102 2001/03/22 03:59:37 momjian Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.103 2001/04/01 22:37:19 tgl Exp $ |
12 | 12 | * |
13 | 13 | *------------------------------------------------------------------------- |
14 | 14 | */ |
@@ -874,84 +874,128 @@ grouping_planner(Query *parse, double tuple_fraction) |
874 | 874 |
|
875 | 875 | /* |
876 | 876 | * Figure out whether we expect to retrieve all the tuples that |
877 | | - * the plan can generate, or to stop early due to a LIMIT or other |
878 | | - * factors. If the caller passed a value >= 0, believe that |
879 | | - * value, else do our own examination of the query context. |
| 877 | + * the plan can generate, or to stop early due to outside factors |
| 878 | + * such as a cursor. If the caller passed a value >= 0, believe |
| 879 | + * that value, else do our own examination of the query context. |
880 | 880 | */ |
881 | 881 | if (tuple_fraction < 0.0) |
882 | 882 | { |
883 | 883 | /* Initial assumption is we need all the tuples */ |
884 | 884 | tuple_fraction = 0.0; |
885 | 885 |
|
886 | 886 | /* |
887 | | - * Check for a LIMIT clause. |
| 887 | + * Check for retrieve-into-portal, ie DECLARE CURSOR. |
| 888 | + * |
| 889 | + * We have no real idea how many tuples the user will ultimately |
| 890 | + * FETCH from a cursor, but it seems a good bet that he |
| 891 | + * doesn't want 'em all. Optimize for 10% retrieval (you |
| 892 | + * gotta better number? Should this be a SETtable parameter?) |
| 893 | + */ |
| 894 | + if (parse->isPortal) |
| 895 | + tuple_fraction = 0.10; |
| 896 | + } |
| 897 | + |
| 898 | + /* |
| 899 | + * Adjust tuple_fraction if we see that we are going to apply |
| 900 | + * limiting/grouping/aggregation/etc. This is not overridable by |
| 901 | + * the caller, since it reflects plan actions that this routine |
| 902 | + * will certainly take, not assumptions about context. |
| 903 | + */ |
| 904 | + if (parse->limitCount != NULL) |
| 905 | + { |
| 906 | + /* |
| 907 | + * A LIMIT clause limits the absolute number of tuples returned. |
| 908 | + * However, if it's not a constant LIMIT then we have to punt; |
| 909 | + * for lack of a better idea, assume 10% of the plan's result |
| 910 | + * is wanted. |
888 | 911 | */ |
889 | | - if (parse->limitCount != NULL) |
| 912 | + double limit_fraction = 0.0; |
| 913 | + |
| 914 | + if (IsA(parse->limitCount, Const)) |
890 | 915 | { |
891 | | - if (IsA(parse->limitCount, Const)) |
| 916 | + Const *limitc = (Const *) parse->limitCount; |
| 917 | + int32 count = DatumGetInt32(limitc->constvalue); |
| 918 | + |
| 919 | + /* |
| 920 | + * A NULL-constant LIMIT represents "LIMIT ALL", which |
| 921 | + * we treat the same as no limit (ie, expect to |
| 922 | + * retrieve all the tuples). |
| 923 | + */ |
| 924 | + if (!limitc->constisnull && count > 0) |
892 | 925 | { |
893 | | - Const *limitc = (Const *) parse->limitCount; |
894 | | - int32 count = DatumGetInt32(limitc->constvalue); |
895 | | - |
896 | | - /* |
897 | | - * A NULL-constant LIMIT represents "LIMIT ALL", which |
898 | | - * we treat the same as no limit (ie, expect to |
899 | | - * retrieve all the tuples). |
900 | | - */ |
901 | | - if (!limitc->constisnull && count > 0) |
| 926 | + limit_fraction = (double) count; |
| 927 | + /* We must also consider the OFFSET, if present */ |
| 928 | + if (parse->limitOffset != NULL) |
902 | 929 | { |
903 | | - tuple_fraction = (double) count; |
904 | | - /* We must also consider the OFFSET, if present */ |
905 | | - if (parse->limitOffset != NULL) |
| 930 | + if (IsA(parse->limitOffset, Const)) |
| 931 | + { |
| 932 | + int32 offset; |
| 933 | + |
| 934 | + limitc = (Const *) parse->limitOffset; |
| 935 | + offset = DatumGetInt32(limitc->constvalue); |
| 936 | + if (!limitc->constisnull && offset > 0) |
| 937 | + limit_fraction += (double) offset; |
| 938 | + } |
| 939 | + else |
906 | 940 | { |
907 | | - if (IsA(parse->limitOffset, Const)) |
908 | | - { |
909 | | - int32 offset; |
910 | | - |
911 | | - limitc = (Const *) parse->limitOffset; |
912 | | - offset = DatumGetInt32(limitc->constvalue); |
913 | | - if (!limitc->constisnull && offset > 0) |
914 | | - tuple_fraction += (double) offset; |
915 | | - } |
916 | | - else |
917 | | - { |
918 | | - /* It's an expression ... punt ... */ |
919 | | - tuple_fraction = 0.10; |
920 | | - } |
| 941 | + /* OFFSET is an expression ... punt ... */ |
| 942 | + limit_fraction = 0.10; |
921 | 943 | } |
922 | 944 | } |
923 | 945 | } |
| 946 | + } |
| 947 | + else |
| 948 | + { |
| 949 | + /* LIMIT is an expression ... punt ... */ |
| 950 | + limit_fraction = 0.10; |
| 951 | + } |
| 952 | + |
| 953 | + if (limit_fraction > 0.0) |
| 954 | + { |
| 955 | + /* |
| 956 | + * If we have absolute limits from both caller and LIMIT, |
| 957 | + * use the smaller value; if one is fractional and the other |
| 958 | + * absolute, treat the fraction as a fraction of the absolute |
| 959 | + * value; else we can multiply the two fractions together. |
| 960 | + */ |
| 961 | + if (tuple_fraction >= 1.0) |
| 962 | + { |
| 963 | + if (limit_fraction >= 1.0) |
| 964 | + { |
| 965 | + /* both absolute */ |
| 966 | + tuple_fraction = Min(tuple_fraction, limit_fraction); |
| 967 | + } |
| 968 | + else |
| 969 | + { |
| 970 | + /* caller absolute, limit fractional */ |
| 971 | + tuple_fraction *= limit_fraction; |
| 972 | + if (tuple_fraction < 1.0) |
| 973 | + tuple_fraction = 1.0; |
| 974 | + } |
| 975 | + } |
| 976 | + else if (tuple_fraction > 0.0) |
| 977 | + { |
| 978 | + if (limit_fraction >= 1.0) |
| 979 | + { |
| 980 | + /* caller fractional, limit absolute */ |
| 981 | + tuple_fraction *= limit_fraction; |
| 982 | + if (tuple_fraction < 1.0) |
| 983 | + tuple_fraction = 1.0; |
| 984 | + } |
| 985 | + else |
| 986 | + { |
| 987 | + /* both fractional */ |
| 988 | + tuple_fraction *= limit_fraction; |
| 989 | + } |
| 990 | + } |
924 | 991 | else |
925 | 992 | { |
926 | | - |
927 | | - /* |
928 | | - * COUNT is an expression ... don't know exactly what |
929 | | - * the limit will be, but for lack of a better idea |
930 | | - * assume 10% of the plan's result is wanted. |
931 | | - */ |
932 | | - tuple_fraction = 0.10; |
| 993 | + /* no info from caller, just use limit */ |
| 994 | + tuple_fraction = limit_fraction; |
933 | 995 | } |
934 | 996 | } |
935 | | - |
936 | | - /* |
937 | | - * If no LIMIT, check for retrieve-into-portal, ie DECLARE |
938 | | - * CURSOR. |
939 | | - * |
940 | | - * We have no real idea how many tuples the user will ultimately |
941 | | - * FETCH from a cursor, but it seems a good bet that he |
942 | | - * doesn't want 'em all. Optimize for 10% retrieval (you |
943 | | - * gotta better number?) |
944 | | - */ |
945 | | - else if (parse->isPortal) |
946 | | - tuple_fraction = 0.10; |
947 | 997 | } |
948 | 998 |
|
949 | | - /* |
950 | | - * Adjust tuple_fraction if we see that we are going to apply |
951 | | - * grouping/aggregation/etc. This is not overridable by the |
952 | | - * caller, since it reflects plan actions that this routine will |
953 | | - * certainly take, not assumptions about context. |
954 | | - */ |
955 | 999 | if (parse->groupClause) |
956 | 1000 | { |
957 | 1001 |
|
|
0 commit comments