diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 3d33d46..c18c92d 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -996,10 +996,20 @@ inheritance_planner(PlannerInfo *root)
 	RelOptInfo *final_rel;
 	ListCell   *lc;
 	Index		rti;
+	RangeTblEntry *parent_rte;
 
 	Assert(parse->commandType != CMD_INSERT);
 
 	/*
+	 * If the parent RTE is a partitioned table, we should use that as the
+	 * nominal relation, because we do not have the duplicate parent RTE,
+	 * unlike in the case of a non-partitioned inheritance parent.
+	 */
+	parent_rte = rt_fetch(parentRTindex, root->parse->rtable);
+	if (parent_rte->relkind == RELKIND_PARTITIONED_TABLE)
+		nominalRelation = parentRTindex;
+
+	/*
 	 * We generate a modified instance of the original Query for each target
 	 * relation, plan that, and put all the plans into a list that will be
 	 * controlled by a single ModifyTable node.  All the instances share the
@@ -1214,6 +1224,11 @@ inheritance_planner(PlannerInfo *root)
 		 * will not be otherwise referenced in the plan, doing so would give
 		 * rise to confusing use of multiple aliases in EXPLAIN output for
 		 * what the user will think is the "same" table.)
+		 *
+		 * If the parent is a partitioned table, we do not have a separate RTE
+		 * representing it as a member of the inheritance set, because we do
+		 * not create a scan plan for it.  As mentioned at the top of this
+		 * function, we make the parent RTE itself the nominal relation.
 		 */
 		if (nominalRelation < 0)
 			nominalRelation = appinfo->child_relid;
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 06e843d..10f7494 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -1374,9 +1374,17 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
 		Assert(rte->rtekind == RTE_SUBQUERY);
 		return;
 	}
-	/* Fast path for common case of childless table */
+	/*
+	 * Fast path for common case of childless table.  However, a partitioned
+	 * table RTE should *always* be processed by the later code as an
+	 * inheritance set, possibly an empty one in the absence of any leaf
+	 * partitions.  It is wrong for the later phases to try to create a scan
+	 * plan for a partitioned table, which would be the case if we turn off
+	 * the inh flag here.
+	 */
 	parentOID = rte->relid;
-	if (!has_subclass(parentOID))
+	if (rte->relkind != RELKIND_PARTITIONED_TABLE &&
+		!has_subclass(parentOID))
 	{
 		/* Clear flag before returning */
 		rte->inh = false;
@@ -1410,9 +1418,11 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
 	/*
 	 * Check that there's at least one descendant, else treat as no-child
 	 * case.  This could happen despite above has_subclass() check, if table
-	 * once had a child but no longer does.
+	 * once had a child but no longer does.  Again, do not disable inheritance
+	 * for a partitioned table as described above.
 	 */
-	if (list_length(inhOIDs) < 2)
+	if (rte->relkind != RELKIND_PARTITIONED_TABLE &&
+		list_length(inhOIDs) < 2)
 	{
 		/* Clear flag before returning */
 		rte->inh = false;
@@ -1450,6 +1460,18 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
 			newrelation = oldrelation;
 
 		/*
+		 * Ignore partitioned tables here, because we do not want them to
+		 * be considered as child tables in the inheritance set.  No scan
+		 * plans will be created for them.
+		 */
+		if (newrelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+		{
+			if (newrelation != oldrelation)
+				heap_close(newrelation, lockmode);
+			continue;
+		}
+
+		/*
 		 * It is possible that the parent table has children that are temp
 		 * tables of other backends.  We cannot safely access such tables
 		 * (because of buffering issues), and the best thing to do seems to be
@@ -1548,9 +1570,11 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
 	 * If all the children were temp tables, pretend it's a non-inheritance
 	 * situation.  The duplicate RTE we added for the parent table is
 	 * harmless, so we don't bother to get rid of it; ditto for the useless
-	 * PlanRowMark node.
+	 * PlanRowMark node.  Do not disable inheritance for partitioned tables
+	 * as described above.
 	 */
-	if (list_length(appinfos) < 2)
+	if (rte->relkind != RELKIND_PARTITIONED_TABLE &&
+		list_length(appinfos) < 2)
 	{
 		/* Clear flag before returning */
 		rte->inh = false;
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index a8c8b28..7215f03 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -1598,6 +1598,14 @@ reset enable_bitmapscan;
 create table list_parted (
 	a	varchar
 ) partition by list (a);
+-- test scanning partitioned table without any partitions
+explain (costs off) select * from list_parted;
+        QUERY PLAN        
+--------------------------
+ Result
+   One-Time Filter: false
+(2 rows)
+
 create table part_ab_cd partition of list_parted for values in ('ab', 'cd');
 create table part_ef_gh partition of list_parted for values in ('ef', 'gh');
 create table part_null_xy partition of list_parted for values in (null, 'xy');
@@ -1605,77 +1613,74 @@ explain (costs off) select * from list_parted;
            QUERY PLAN           
 --------------------------------
  Append
-   ->  Seq Scan on list_parted
    ->  Seq Scan on part_ab_cd
    ->  Seq Scan on part_ef_gh
    ->  Seq Scan on part_null_xy
-(5 rows)
+(4 rows)
 
 explain (costs off) select * from list_parted where a is null;
            QUERY PLAN           
 --------------------------------
  Append
-   ->  Seq Scan on list_parted
-         Filter: (a IS NULL)
    ->  Seq Scan on part_null_xy
          Filter: (a IS NULL)
-(5 rows)
+(3 rows)
 
 explain (costs off) select * from list_parted where a is not null;
            QUERY PLAN            
 ---------------------------------
  Append
-   ->  Seq Scan on list_parted
-         Filter: (a IS NOT NULL)
    ->  Seq Scan on part_ab_cd
          Filter: (a IS NOT NULL)
    ->  Seq Scan on part_ef_gh
          Filter: (a IS NOT NULL)
    ->  Seq Scan on part_null_xy
          Filter: (a IS NOT NULL)
-(9 rows)
+(7 rows)
 
 explain (costs off) select * from list_parted where a in ('ab', 'cd', 'ef');
                         QUERY PLAN                        
 ----------------------------------------------------------
  Append
-   ->  Seq Scan on list_parted
-         Filter: ((a)::text = ANY ('{ab,cd,ef}'::text[]))
    ->  Seq Scan on part_ab_cd
          Filter: ((a)::text = ANY ('{ab,cd,ef}'::text[]))
    ->  Seq Scan on part_ef_gh
          Filter: ((a)::text = ANY ('{ab,cd,ef}'::text[]))
-(7 rows)
+(5 rows)
 
 explain (costs off) select * from list_parted where a = 'ab' or a in (null, 'cd');
                                       QUERY PLAN                                       
 ---------------------------------------------------------------------------------------
  Append
-   ->  Seq Scan on list_parted
-         Filter: (((a)::text = 'ab'::text) OR ((a)::text = ANY ('{NULL,cd}'::text[])))
    ->  Seq Scan on part_ab_cd
          Filter: (((a)::text = 'ab'::text) OR ((a)::text = ANY ('{NULL,cd}'::text[])))
    ->  Seq Scan on part_ef_gh
          Filter: (((a)::text = 'ab'::text) OR ((a)::text = ANY ('{NULL,cd}'::text[])))
    ->  Seq Scan on part_null_xy
          Filter: (((a)::text = 'ab'::text) OR ((a)::text = ANY ('{NULL,cd}'::text[])))
-(9 rows)
+(7 rows)
 
 explain (costs off) select * from list_parted where a = 'ab';
                 QUERY PLAN                
 ------------------------------------------
  Append
-   ->  Seq Scan on list_parted
-         Filter: ((a)::text = 'ab'::text)
    ->  Seq Scan on part_ab_cd
          Filter: ((a)::text = 'ab'::text)
-(5 rows)
+(3 rows)
 
 create table range_list_parted (
 	a	int,
 	b	char(2)
 ) partition by range (a);
 create table part_1_10 partition of range_list_parted for values from (1) to (10) partition by list (b);
+-- test scanning partitioned table without any partitions
+explain (costs off) select * from range_list_parted;
+        QUERY PLAN        
+--------------------------
+ Result
+   One-Time Filter: false
+(2 rows)
+
 create table part_1_10_ab partition of part_1_10 for values in ('ab');
 create table part_1_10_cd partition of part_1_10 for values in ('cd');
 create table part_10_20 partition of range_list_parted for values from (10) to (20) partition by list (b);
@@ -1689,14 +1694,9 @@ create table part_40_inf_ab partition of part_40_inf for values in ('ab');
 create table part_40_inf_cd partition of part_40_inf for values in ('cd');
 create table part_40_inf_null partition of part_40_inf for values in (null);
 explain (costs off) select * from range_list_parted;
-             QUERY PLAN              
--------------------------------------
+             QUERY PLAN             
+------------------------------------
  Append
-   ->  Seq Scan on range_list_parted
-   ->  Seq Scan on part_1_10
-   ->  Seq Scan on part_10_20
-   ->  Seq Scan on part_21_30
-   ->  Seq Scan on part_40_inf
    ->  Seq Scan on part_1_10_ab
    ->  Seq Scan on part_1_10_cd
    ->  Seq Scan on part_10_20_ab
@@ -1706,36 +1706,22 @@ explain (costs off) select * from range_list_parted;
    ->  Seq Scan on part_40_inf_ab
    ->  Seq Scan on part_40_inf_cd
    ->  Seq Scan on part_40_inf_null
-(15 rows)
+(10 rows)
 
 explain (costs off) select * from range_list_parted where a = 5;
-             QUERY PLAN              
--------------------------------------
+           QUERY PLAN           
+--------------------------------
  Append
-   ->  Seq Scan on range_list_parted
-         Filter: (a = 5)
-   ->  Seq Scan on part_1_10
-         Filter: (a = 5)
    ->  Seq Scan on part_1_10_ab
          Filter: (a = 5)
    ->  Seq Scan on part_1_10_cd
          Filter: (a = 5)
-(9 rows)
+(5 rows)
 
 explain (costs off) select * from range_list_parted where b = 'ab';
-             QUERY PLAN              
--------------------------------------
+             QUERY PLAN             
+------------------------------------
  Append
-   ->  Seq Scan on range_list_parted
-         Filter: (b = 'ab'::bpchar)
-   ->  Seq Scan on part_1_10
-         Filter: (b = 'ab'::bpchar)
-   ->  Seq Scan on part_10_20
-         Filter: (b = 'ab'::bpchar)
-   ->  Seq Scan on part_21_30
-         Filter: (b = 'ab'::bpchar)
-   ->  Seq Scan on part_40_inf
-         Filter: (b = 'ab'::bpchar)
    ->  Seq Scan on part_1_10_ab
          Filter: (b = 'ab'::bpchar)
    ->  Seq Scan on part_10_20_ab
@@ -1744,27 +1730,19 @@ explain (costs off) select * from range_list_parted where b = 'ab';
          Filter: (b = 'ab'::bpchar)
    ->  Seq Scan on part_40_inf_ab
          Filter: (b = 'ab'::bpchar)
-(19 rows)
+(9 rows)
 
 explain (costs off) select * from range_list_parted where a between 3 and 23 and b in ('ab');
                            QUERY PLAN                            
 -----------------------------------------------------------------
  Append
-   ->  Seq Scan on range_list_parted
-         Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar))
-   ->  Seq Scan on part_1_10
-         Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar))
-   ->  Seq Scan on part_10_20
-         Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar))
-   ->  Seq Scan on part_21_30
-         Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar))
    ->  Seq Scan on part_1_10_ab
          Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar))
    ->  Seq Scan on part_10_20_ab
          Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar))
    ->  Seq Scan on part_21_30_ab
          Filter: ((a >= 3) AND (a <= 23) AND (b = 'ab'::bpchar))
-(15 rows)
+(7 rows)
 
 /* Should select no rows because range partition key cannot be null */
 explain (costs off) select * from range_list_parted where a is null;
@@ -1776,37 +1754,17 @@ explain (costs off) select * from range_list_parted where a is null;
 
 /* Should only select rows from the null-accepting partition */
 explain (costs off) select * from range_list_parted where b is null;
-             QUERY PLAN              
--------------------------------------
+             QUERY PLAN             
+------------------------------------
  Append
-   ->  Seq Scan on range_list_parted
-         Filter: (b IS NULL)
-   ->  Seq Scan on part_1_10
-         Filter: (b IS NULL)
-   ->  Seq Scan on part_10_20
-         Filter: (b IS NULL)
-   ->  Seq Scan on part_21_30
-         Filter: (b IS NULL)
-   ->  Seq Scan on part_40_inf
-         Filter: (b IS NULL)
    ->  Seq Scan on part_40_inf_null
          Filter: (b IS NULL)
-(13 rows)
+(3 rows)
 
 explain (costs off) select * from range_list_parted where a is not null and a < 67;
                    QUERY PLAN                   
 ------------------------------------------------
  Append
-   ->  Seq Scan on range_list_parted
-         Filter: ((a IS NOT NULL) AND (a < 67))
-   ->  Seq Scan on part_1_10
-         Filter: ((a IS NOT NULL) AND (a < 67))
-   ->  Seq Scan on part_10_20
-         Filter: ((a IS NOT NULL) AND (a < 67))
-   ->  Seq Scan on part_21_30
-         Filter: ((a IS NOT NULL) AND (a < 67))
-   ->  Seq Scan on part_40_inf
-         Filter: ((a IS NOT NULL) AND (a < 67))
    ->  Seq Scan on part_1_10_ab
          Filter: ((a IS NOT NULL) AND (a < 67))
    ->  Seq Scan on part_1_10_cd
@@ -1825,23 +1783,19 @@ explain (costs off) select * from range_list_parted where a is not null and a <
          Filter: ((a IS NOT NULL) AND (a < 67))
    ->  Seq Scan on part_40_inf_null
          Filter: ((a IS NOT NULL) AND (a < 67))
-(29 rows)
+(19 rows)
 
 explain (costs off) select * from range_list_parted where a >= 30;
-             QUERY PLAN              
--------------------------------------
+             QUERY PLAN             
+------------------------------------
  Append
-   ->  Seq Scan on range_list_parted
-         Filter: (a >= 30)
-   ->  Seq Scan on part_40_inf
-         Filter: (a >= 30)
    ->  Seq Scan on part_40_inf_ab
          Filter: (a >= 30)
    ->  Seq Scan on part_40_inf_cd
          Filter: (a >= 30)
    ->  Seq Scan on part_40_inf_null
          Filter: (a >= 30)
-(11 rows)
+(7 rows)
 
 drop table list_parted cascade;
 NOTICE:  drop cascades to 3 other objects
diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql
index a8b7eb1..fa0bb47 100644
--- a/src/test/regress/sql/inherit.sql
+++ b/src/test/regress/sql/inherit.sql
@@ -570,6 +570,10 @@ reset enable_bitmapscan;
 create table list_parted (
 	a	varchar
 ) partition by list (a);
+
+-- test scanning partitioned table without any partitions
+explain (costs off) select * from list_parted;
+
 create table part_ab_cd partition of list_parted for values in ('ab', 'cd');
 create table part_ef_gh partition of list_parted for values in ('ef', 'gh');
 create table part_null_xy partition of list_parted for values in (null, 'xy');
@@ -586,6 +590,10 @@ create table range_list_parted (
 	b	char(2)
 ) partition by range (a);
 create table part_1_10 partition of range_list_parted for values from (1) to (10) partition by list (b);
+
+-- test scanning partitioned table without any partitions
+explain (costs off) select * from range_list_parted;
+
 create table part_1_10_ab partition of part_1_10 for values in ('ab');
 create table part_1_10_cd partition of part_1_10 for values in ('cd');
 create table part_10_20 partition of range_list_parted for values from (10) to (20) partition by list (b);
