|
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 |
|
|