|
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 toa 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 tooutside factors |
| 878 | + *such as a cursor. If the caller passed a value >= 0, believe |
| 879 | + *thatvalue, 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 | +doublelimit_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 | +int32count=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 | | -int32count=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 | +int32offset; |
| 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 | | -int32offset; |
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 | +elseif (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 | | -elseif (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 |
|
|