|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.188 2005/06/05 22:32:56 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.189 2005/06/10 02:21:04 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -58,6 +58,8 @@ static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
|
58 | 58 | staticvoidpreprocess_qual_conditions(PlannerInfo*root,Node*jtnode);
|
59 | 59 | staticPlan*inheritance_planner(PlannerInfo*root,List*inheritlist);
|
60 | 60 | staticPlan*grouping_planner(PlannerInfo*root,doubletuple_fraction);
|
| 61 | +staticdoubleadjust_tuple_fraction_for_limit(PlannerInfo*root, |
| 62 | +doubletuple_fraction); |
61 | 63 | staticboolchoose_hashed_grouping(PlannerInfo*root,doubletuple_fraction,
|
62 | 64 | Path*cheapest_path,Path*sorted_path,
|
63 | 65 | List*sort_pathkeys,List*group_pathkeys,
|
@@ -648,15 +650,30 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
|
648 | 650 | List*current_pathkeys;
|
649 | 651 | List*sort_pathkeys;
|
650 | 652 |
|
| 653 | +/* Tweak caller-supplied tuple_fraction if have LIMIT */ |
| 654 | +if (parse->limitCount!=NULL) |
| 655 | +tuple_fraction=adjust_tuple_fraction_for_limit(root,tuple_fraction); |
| 656 | + |
651 | 657 | if (parse->setOperations)
|
652 | 658 | {
|
653 | 659 | List*set_sortclauses;
|
654 | 660 |
|
| 661 | +/* |
| 662 | + * If there's a top-level ORDER BY, assume we have to fetch all |
| 663 | + * the tuples. This might seem too simplistic given all the |
| 664 | + * hackery below to possibly avoid the sort ... but a nonzero |
| 665 | + * tuple_fraction is only of use to plan_set_operations() when |
| 666 | + * the setop is UNION ALL, and the result of UNION ALL is always |
| 667 | + * unsorted. |
| 668 | + */ |
| 669 | +if (parse->sortClause) |
| 670 | +tuple_fraction=0.0; |
| 671 | + |
655 | 672 | /*
|
656 | 673 | * Construct the plan for set operations. The result will not
|
657 | 674 | * need any work except perhaps a top-level sort and/or LIMIT.
|
658 | 675 | */
|
659 |
| -result_plan=plan_set_operations(root, |
| 676 | +result_plan=plan_set_operations(root,tuple_fraction, |
660 | 677 | &set_sortclauses);
|
661 | 678 |
|
662 | 679 | /*
|
@@ -769,108 +786,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
|
769 | 786 | else
|
770 | 787 | root->query_pathkeys=NIL;
|
771 | 788 |
|
772 |
| -/* |
773 |
| - * Adjust tuple_fraction if we see that we are going to apply |
774 |
| - * limiting/grouping/aggregation/etc. This is not overridable by |
775 |
| - * the caller, since it reflects plan actions that this routine |
776 |
| - * will certainly take, not assumptions about context. |
777 |
| - */ |
778 |
| -if (parse->limitCount!=NULL) |
779 |
| -{ |
780 |
| -/* |
781 |
| - * A LIMIT clause limits the absolute number of tuples |
782 |
| - * returned. However, if it's not a constant LIMIT then we |
783 |
| - * have to punt; for lack of a better idea, assume 10% of the |
784 |
| - * plan's result is wanted. |
785 |
| - */ |
786 |
| -doublelimit_fraction=0.0; |
787 |
| - |
788 |
| -if (IsA(parse->limitCount,Const)) |
789 |
| -{ |
790 |
| -Const*limitc= (Const*)parse->limitCount; |
791 |
| -int32count=DatumGetInt32(limitc->constvalue); |
792 |
| - |
793 |
| -/* |
794 |
| - * A NULL-constant LIMIT represents "LIMIT ALL", which we |
795 |
| - * treat the same as no limit (ie, expect to retrieve all |
796 |
| - * the tuples). |
797 |
| - */ |
798 |
| -if (!limitc->constisnull&&count>0) |
799 |
| -{ |
800 |
| -limit_fraction= (double)count; |
801 |
| -/* We must also consider the OFFSET, if present */ |
802 |
| -if (parse->limitOffset!=NULL) |
803 |
| -{ |
804 |
| -if (IsA(parse->limitOffset,Const)) |
805 |
| -{ |
806 |
| -int32offset; |
807 |
| - |
808 |
| -limitc= (Const*)parse->limitOffset; |
809 |
| -offset=DatumGetInt32(limitc->constvalue); |
810 |
| -if (!limitc->constisnull&&offset>0) |
811 |
| -limit_fraction+= (double)offset; |
812 |
| -} |
813 |
| -else |
814 |
| -{ |
815 |
| -/* OFFSET is an expression ... punt ... */ |
816 |
| -limit_fraction=0.10; |
817 |
| -} |
818 |
| -} |
819 |
| -} |
820 |
| -} |
821 |
| -else |
822 |
| -{ |
823 |
| -/* LIMIT is an expression ... punt ... */ |
824 |
| -limit_fraction=0.10; |
825 |
| -} |
826 |
| - |
827 |
| -if (limit_fraction>0.0) |
828 |
| -{ |
829 |
| -/* |
830 |
| - * If we have absolute limits from both caller and LIMIT, |
831 |
| - * use the smaller value; if one is fractional and the |
832 |
| - * other absolute, treat the fraction as a fraction of the |
833 |
| - * absolute value; else we can multiply the two fractions |
834 |
| - * together. |
835 |
| - */ |
836 |
| -if (tuple_fraction >=1.0) |
837 |
| -{ |
838 |
| -if (limit_fraction >=1.0) |
839 |
| -{ |
840 |
| -/* both absolute */ |
841 |
| -tuple_fraction=Min(tuple_fraction,limit_fraction); |
842 |
| -} |
843 |
| -else |
844 |
| -{ |
845 |
| -/* caller absolute, limit fractional */ |
846 |
| -tuple_fraction *=limit_fraction; |
847 |
| -if (tuple_fraction<1.0) |
848 |
| -tuple_fraction=1.0; |
849 |
| -} |
850 |
| -} |
851 |
| -elseif (tuple_fraction>0.0) |
852 |
| -{ |
853 |
| -if (limit_fraction >=1.0) |
854 |
| -{ |
855 |
| -/* caller fractional, limit absolute */ |
856 |
| -tuple_fraction *=limit_fraction; |
857 |
| -if (tuple_fraction<1.0) |
858 |
| -tuple_fraction=1.0; |
859 |
| -} |
860 |
| -else |
861 |
| -{ |
862 |
| -/* both fractional */ |
863 |
| -tuple_fraction *=limit_fraction; |
864 |
| -} |
865 |
| -} |
866 |
| -else |
867 |
| -{ |
868 |
| -/* no info from caller, just use limit */ |
869 |
| -tuple_fraction=limit_fraction; |
870 |
| -} |
871 |
| -} |
872 |
| -} |
873 |
| - |
874 | 789 | /*
|
875 | 790 | * With grouping or aggregation, the tuple fraction to pass to
|
876 | 791 | * query_planner() may be different from what it is at top level.
|
@@ -1242,6 +1157,114 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
|
1242 | 1157 | returnresult_plan;
|
1243 | 1158 | }
|
1244 | 1159 |
|
| 1160 | +/* |
| 1161 | + * adjust_tuple_fraction_for_limit - adjust tuple fraction for LIMIT |
| 1162 | + * |
| 1163 | + * If the query contains LIMIT, we adjust the caller-supplied tuple_fraction |
| 1164 | + * accordingly. This is not overridable by the caller, since it reflects plan |
| 1165 | + * actions that grouping_planner() will certainly take, not assumptions about |
| 1166 | + * context. |
| 1167 | + */ |
| 1168 | +staticdouble |
| 1169 | +adjust_tuple_fraction_for_limit(PlannerInfo*root,doubletuple_fraction) |
| 1170 | +{ |
| 1171 | +Query*parse=root->parse; |
| 1172 | +doublelimit_fraction=0.0; |
| 1173 | + |
| 1174 | +/* Should not be called unless LIMIT */ |
| 1175 | +Assert(parse->limitCount!=NULL); |
| 1176 | + |
| 1177 | +/* |
| 1178 | + * A LIMIT clause limits the absolute number of tuples returned. However, |
| 1179 | + * if it's not a constant LIMIT then we have to punt; for lack of a better |
| 1180 | + * idea, assume 10% of the plan's result is wanted. |
| 1181 | + */ |
| 1182 | +if (IsA(parse->limitCount,Const)) |
| 1183 | +{ |
| 1184 | +Const*limitc= (Const*)parse->limitCount; |
| 1185 | +int32count=DatumGetInt32(limitc->constvalue); |
| 1186 | + |
| 1187 | +/* |
| 1188 | + * A NULL-constant LIMIT represents "LIMIT ALL", which we treat the |
| 1189 | + * same as no limit (ie, expect to retrieve all the tuples). |
| 1190 | + */ |
| 1191 | +if (!limitc->constisnull&&count>0) |
| 1192 | +{ |
| 1193 | +limit_fraction= (double)count; |
| 1194 | +/* We must also consider the OFFSET, if present */ |
| 1195 | +if (parse->limitOffset!=NULL) |
| 1196 | +{ |
| 1197 | +if (IsA(parse->limitOffset,Const)) |
| 1198 | +{ |
| 1199 | +int32offset; |
| 1200 | + |
| 1201 | +limitc= (Const*)parse->limitOffset; |
| 1202 | +offset=DatumGetInt32(limitc->constvalue); |
| 1203 | +if (!limitc->constisnull&&offset>0) |
| 1204 | +limit_fraction+= (double)offset; |
| 1205 | +} |
| 1206 | +else |
| 1207 | +{ |
| 1208 | +/* OFFSET is an expression ... punt ... */ |
| 1209 | +limit_fraction=0.10; |
| 1210 | +} |
| 1211 | +} |
| 1212 | +} |
| 1213 | +} |
| 1214 | +else |
| 1215 | +{ |
| 1216 | +/* LIMIT is an expression ... punt ... */ |
| 1217 | +limit_fraction=0.10; |
| 1218 | +} |
| 1219 | + |
| 1220 | +if (limit_fraction>0.0) |
| 1221 | +{ |
| 1222 | +/* |
| 1223 | + * If we have absolute limits from both caller and LIMIT, use the |
| 1224 | + * smaller value; if one is fractional and the other absolute, |
| 1225 | + * treat the fraction as a fraction of the absolute value; |
| 1226 | + * else we can multiply the two fractions together. |
| 1227 | + */ |
| 1228 | +if (tuple_fraction >=1.0) |
| 1229 | +{ |
| 1230 | +if (limit_fraction >=1.0) |
| 1231 | +{ |
| 1232 | +/* both absolute */ |
| 1233 | +tuple_fraction=Min(tuple_fraction,limit_fraction); |
| 1234 | +} |
| 1235 | +else |
| 1236 | +{ |
| 1237 | +/* caller absolute, limit fractional */ |
| 1238 | +tuple_fraction *=limit_fraction; |
| 1239 | +if (tuple_fraction<1.0) |
| 1240 | +tuple_fraction=1.0; |
| 1241 | +} |
| 1242 | +} |
| 1243 | +elseif (tuple_fraction>0.0) |
| 1244 | +{ |
| 1245 | +if (limit_fraction >=1.0) |
| 1246 | +{ |
| 1247 | +/* caller fractional, limit absolute */ |
| 1248 | +tuple_fraction *=limit_fraction; |
| 1249 | +if (tuple_fraction<1.0) |
| 1250 | +tuple_fraction=1.0; |
| 1251 | +} |
| 1252 | +else |
| 1253 | +{ |
| 1254 | +/* both fractional */ |
| 1255 | +tuple_fraction *=limit_fraction; |
| 1256 | +} |
| 1257 | +} |
| 1258 | +else |
| 1259 | +{ |
| 1260 | +/* no info from caller, just use limit */ |
| 1261 | +tuple_fraction=limit_fraction; |
| 1262 | +} |
| 1263 | +} |
| 1264 | + |
| 1265 | +returntuple_fraction; |
| 1266 | +} |
| 1267 | + |
1245 | 1268 | /*
|
1246 | 1269 | * choose_hashed_grouping - should we use hashed grouping?
|
1247 | 1270 | */
|
|