diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index b375902..0c839b9 100644
*** a/src/backend/optimizer/path/allpaths.c
--- b/src/backend/optimizer/path/allpaths.c
***************
*** 27,32 ****
--- 27,33 ----
  #include "optimizer/pathnode.h"
  #include "optimizer/paths.h"
  #include "optimizer/plancat.h"
+ #include "optimizer/planmain.h"
  #include "optimizer/planner.h"
  #include "optimizer/prep.h"
  #include "optimizer/restrictinfo.h"
*************** set_append_rel_pathlist(PlannerInfo *roo
*** 289,294 ****
--- 290,296 ----
  	double	   *parent_attrsizes;
  	int			nattrs;
  	ListCell   *l;
+ 	bool		can_optimize_minmax;
  
  	/*
  	 * Initialize to compute size estimates for whole append relation.
*************** set_append_rel_pathlist(PlannerInfo *roo
*** 309,314 ****
--- 311,319 ----
  	nattrs = rel->max_attr - rel->min_attr + 1;
  	parent_attrsizes = (double *) palloc0(nattrs * sizeof(double));
  
+ 
+ 	can_optimize_minmax = can_optimize_append_minmax(root);
+ 
  	/*
  	 * Generate access paths for each member relation, and pick the cheapest
  	 * path for each one.
*************** set_append_rel_pathlist(PlannerInfo *roo
*** 427,433 ****
--- 432,454 ----
  			subpaths = list_concat(subpaths,
  								   ((AppendPath *) childpath)->subpaths);
  		else
+ 		{
+ 			if (can_optimize_minmax)
+ 			{
+ 				Path *minmax_path;
+ 				List *targetlist = (List *)
+ 					adjust_appendrel_attrs((Node *) root->parse->targetList,
+ 													appinfo);
+ 				
+ 				minmax_path = optimize_append_minmax(root, targetlist, childrel,
+ 													 childpath);
+ 
+ 				if (minmax_path)
+ 					childpath = minmax_path;
+ 			}
+ 
  			subpaths = lappend(subpaths, childpath);
+ 		}
  
  		/*
  		 * Accumulate size information from each child.
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 6e5c251..6643486 100644
*** a/src/backend/optimizer/plan/createplan.c
--- b/src/backend/optimizer/plan/createplan.c
***************
*** 20,25 ****
--- 20,26 ----
  #include <math.h>
  
  #include "access/skey.h"
+ #include "catalog/pg_type.h"
  #include "nodes/makefuncs.h"
  #include "nodes/nodeFuncs.h"
  #include "optimizer/clauses.h"
*************** create_append_plan(PlannerInfo *root, Ap
*** 546,551 ****
--- 547,554 ----
  	List	   *tlist = build_relation_tlist(best_path->path.parent);
  	List	   *subplans = NIL;
  	ListCell   *subpaths;
+ 	bool	    can_optimize_minmax;
+ 	Node	   *limitCount;
  
  	/*
  	 * It is possible for the subplans list to contain only one entry, or even
*************** create_append_plan(PlannerInfo *root, Ap
*** 566,577 ****
  									NULL);
  	}
  
  	/* Normal case with multiple subpaths */
  	foreach(subpaths, best_path->subpaths)
  	{
  		Path	   *subpath = (Path *) lfirst(subpaths);
  
! 		subplans = lappend(subplans, create_plan(root, subpath));
  	}
  
  	plan = make_append(subplans, false, tlist);
--- 569,591 ----
  									NULL);
  	}
  
+ 	can_optimize_minmax = can_optimize_append_minmax(root);
+ 	if (can_optimize_minmax)
+ 		limitCount = (Node *) makeConst(INT8OID, -1, sizeof(int64),
+ 										Int64GetDatum(1), false,
+ 										FLOAT8PASSBYVAL);
+ 
  	/* Normal case with multiple subpaths */
  	foreach(subpaths, best_path->subpaths)
  	{
  		Path	   *subpath = (Path *) lfirst(subpaths);
+ 		Plan	   *subplan = create_plan(root, subpath);
  
! 		/* apply the LIMIT 1 on top of the index scan */
! 		if (can_optimize_minmax && IsA(subplan, IndexScan))
! 			subplan = (Plan *) make_limit(subplan, NULL, limitCount, 0, 1);
! 
! 		subplans = lappend(subplans, subplan);
  	}
  
  	plan = make_append(subplans, false, tlist);
diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c
index 34e9617..f7cdc5e 100644
*** a/src/backend/optimizer/plan/planagg.c
--- b/src/backend/optimizer/plan/planagg.c
*************** optimize_minmax_aggregates(PlannerInfo *
*** 214,219 ****
--- 214,320 ----
  }
  
  /*
+  * can_optimize_append_minmax - check whether optimizing MIN/MAX via indexes
+  * can potentially be pushed down to child relations.
+  *
+  * This checks whether the query is of the form:
+  * 	1. SELECT MAX(col) FROM tab WHERE ...;
+  * 	2. SELECT MIN(col) FROM tab WHERE ...;
+  */
+ bool
+ can_optimize_append_minmax(PlannerInfo *root)
+ {
+ 	Query	   *parse = root->parse;
+ 	List	   *tlist = parse->targetList;
+ 	List	   *aggs_list;
+ 
+ 	/* Nothing to do if query has no aggregates */
+ 	if (!parse->hasAggs)
+ 		return false;
+ 
+ 	Assert(!parse->setOperations);		/* shouldn't get here if a setop */
+ 	Assert(parse->rowMarks == NIL);		/* nor if FOR UPDATE */
+ 
+ 	/*
+ 	 * Reject unoptimizable cases.
+ 	 *
+ 	 * We don't handle GROUP BY or windowing, because our current
+ 	 * implementations of grouping require looking at all the rows anyway, and
+ 	 * so there's not much point in optimizing MIN/MAX.
+ 	 */
+ 	if (parse->groupClause || parse->hasWindowFuncs)
+ 		return false;
+ 
+ 	/* We're only supporting a single MIN/MAX in the targetlist. */
+ 	if (list_length(tlist) > 1 || parse->havingQual)
+ 		return false;
+ 
+ 	aggs_list = NIL;
+ 	if (find_minmax_aggs_walker((Node *) tlist, &aggs_list))
+ 		return false;
+ 
+ 	if (list_length(aggs_list) > 1)
+ 		return false;
+ 
+ 	return true;
+ }
+ 
+ /*
+  * optimize_append_minmax - returns the IndexPath for a child relation as an
+  * optimization for MIN/MAX.  See can_optimize_append_minmax() above.  Returns
+  * NULL if no IndexPath is available or it is not profitable compared to the
+  * existing best_path.
+  */
+ Path *
+ optimize_append_minmax(PlannerInfo *root, List *tlist, RelOptInfo *rel,
+ 					   Path *best_path)
+ {
+ 	List	   *aggs_list;
+ 	Cost		total_cost;
+ 	MinMaxAggInfo *info;
+ 	Path		agg_p;
+ 	Path		minmax_agg_p;
+ 
+ 	/* Pass 1: Get the one MIN/MAX from the targetlist */
+ 	aggs_list = NIL;
+ 	if (find_minmax_aggs_walker((Node *) tlist, &aggs_list))
+ 		return NULL;
+ 
+ 	Assert(list_length(aggs_list) == 1);
+ 
+ 	/* Pass 2: see if MIN/MAX is optimizable */
+ 	info = (MinMaxAggInfo *) linitial(aggs_list);
+ 	if (!build_minmax_path(root, rel, info))
+ 		return NULL;
+ 	total_cost = info->pathcost;
+ 
+ 	/*
+ 	 * Make the cost comparison.
+ 	 *
+ 	 * We are comparing the cost of the best_path that has to pass all of its
+ 	 * output as input to the aggregate node against the one output tuple in
+ 	 * the optimized path.
+ 	 *
+ 	 * Note that we don't include evaluation cost of the tlist here; this is
+ 	 * OK since it isn't included in best_path's cost either, and should be
+ 	 * the same in either case.
+ 	 */
+ 	cost_agg(&agg_p, root, AGG_PLAIN, list_length(aggs_list),
+ 			 0, 0,
+ 			 best_path->startup_cost, best_path->total_cost,
+ 			 best_path->parent->rows);
+ 
+ 	/* only one input tuple expected from the minmax index path */
+ 	cost_agg(&minmax_agg_p, root, AGG_PLAIN, list_length(aggs_list),
+ 			 0, 0, 0, total_cost, 1);
+ 
+ 	if (minmax_agg_p.total_cost > agg_p.total_cost)
+ 		return NULL;			/* too expensive */
+ 
+ 	return (Path *) info->path;
+ }
+ 
+ /*
   * find_minmax_aggs_walker
   *		Recursively scan the Aggref nodes in an expression tree, and check
   *		that each one is a MIN/MAX aggregate.  If so, build a list of the
diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h
index 0dd2bcc..61dd0a5 100644
*** a/src/include/optimizer/planmain.h
--- b/src/include/optimizer/planmain.h
*************** extern void query_planner(PlannerInfo *r
*** 34,39 ****
--- 34,42 ----
   */
  extern Plan *optimize_minmax_aggregates(PlannerInfo *root, List *tlist,
  						   Path *best_path);
+ extern bool can_optimize_append_minmax(PlannerInfo *root);
+ extern Path *optimize_append_minmax(PlannerInfo *root, List *tlist,
+ 									RelOptInfo *rel, Path *best_path);
  
  /*
   * prototypes for plan/createplan.c
