diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index 510145e3c0..5b138e1c12 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -122,6 +122,7 @@ typedef struct GeneratePruningStepsContext
 	bool		contradictory;	/* clauses were proven self-contradictory */
 	/* Working state: */
 	int			next_step_id;
+	bool		has_is_not_op;
 } GeneratePruningStepsContext;
 
 /* The result of performing one PartitionPruneStep */
@@ -201,7 +202,8 @@ static PruneStepResult *perform_pruning_combine_step(PartitionPruneContext *cont
 static PartClauseMatchStatus match_boolean_partition_clause(Oid partopfamily,
 															Expr *clause,
 															Expr *partkey,
-															Expr **outconst);
+															Expr **outconst,
+															bool *has_is_not_op);
 static void partkey_datum_from_expr(PartitionPruneContext *context,
 									Expr *expr, int stateidx,
 									Datum *value, bool *isnull);
@@ -776,6 +778,8 @@ prune_append_rel_partitions(RelOptInfo *rel)
 	if (!enable_partition_pruning || clauses == NIL)
 		return bms_add_range(NULL, 0, rel->nparts - 1);
 
+	gcontext.has_is_not_op = false;
+
 	/*
 	 * Process clauses to extract pruning steps that are usable at plan time.
 	 * If the clauses are found to be contradictory, we can return the empty
@@ -807,6 +811,7 @@ prune_append_rel_partitions(RelOptInfo *rel)
 	context.planstate = NULL;
 	context.exprcontext = NULL;
 	context.exprstates = NULL;
+	context.has_is_not_op = gcontext.has_is_not_op;
 
 	/* Actual pruning happens here. */
 	return get_matching_partitions(&context, pruning_steps);
@@ -910,6 +915,10 @@ get_matching_partitions(PartitionPruneContext *context, List *pruning_steps)
 
 		result = bms_add_member(result, partindex);
 	}
+	if (context->has_is_not_op && context->boundinfo->null_index != -1)
+		result = bms_add_member(result, context->boundinfo->null_index);
+	else if (context->has_is_not_op)
+		scan_default |= partition_bound_has_default(context->boundinfo);
 
 	/* Add the null and/or default partition if needed and present. */
 	if (final_result->scan_null)
@@ -1814,7 +1823,7 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
 	 * Recognize specially shaped clauses that match a Boolean partition key.
 	 */
 	boolmatchstatus = match_boolean_partition_clause(partopfamily, clause,
-													 partkey, &expr);
+													 partkey, &expr, &context->has_is_not_op);
 
 	if (boolmatchstatus == PARTCLAUSE_MATCH_CLAUSE)
 	{
@@ -3596,7 +3605,7 @@ perform_pruning_combine_step(PartitionPruneContext *context,
  */
 static PartClauseMatchStatus
 match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
-							   Expr **outconst)
+							   Expr **outconst, bool *has_is_not_op)
 {
 	Expr	   *leftop;
 
@@ -3618,6 +3627,10 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
 			btest->booltesttype == IS_NOT_UNKNOWN)
 			return PARTCLAUSE_UNSUPPORTED;
 
+		if (btest->booltesttype == IS_NOT_TRUE ||
+			btest->booltesttype == IS_NOT_FALSE)
+			*has_is_not_op = true;
+
 		leftop = btest->arg;
 		if (IsA(leftop, RelabelType))
 			leftop = ((RelabelType *) leftop)->arg;
diff --git a/src/include/partitioning/partprune.h b/src/include/partitioning/partprune.h
index c0d6889d47..d8f72a0146 100644
--- a/src/include/partitioning/partprune.h
+++ b/src/include/partitioning/partprune.h
@@ -59,6 +59,7 @@ typedef struct PartitionPruneContext
 	PlanState  *planstate;
 	ExprContext *exprcontext;
 	ExprState **exprstates;
+	bool		has_is_not_op;
 } PartitionPruneContext;
 
 /*
@@ -70,10 +71,10 @@ typedef struct PartitionPruneContext
 #define PruneCxtStateIdx(partnatts, step_id, keyno) \
 	((partnatts) * (step_id) + (keyno))
 
-extern int make_partition_pruneinfo(struct PlannerInfo *root,
-									struct RelOptInfo *parentrel,
-									List *subpaths,
-									List *prunequal);
+extern int	make_partition_pruneinfo(struct PlannerInfo *root,
+									 struct RelOptInfo *parentrel,
+									 List *subpaths,
+									 List *prunequal);
 extern Bitmapset *prune_append_rel_partitions(struct RelOptInfo *rel);
 extern Bitmapset *get_matching_partitions(PartitionPruneContext *context,
 										  List *pruning_steps);
diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out
index d700c00629..55cc528e55 100644
--- a/src/test/regress/expected/partition_prune.out
+++ b/src/test/regress/expected/partition_prune.out
@@ -1070,20 +1070,25 @@ explain (costs off) select * from boolpart where a is true or a is not true;
          Filter: ((a IS TRUE) OR (a IS NOT TRUE))
    ->  Seq Scan on boolpart_t boolpart_2
          Filter: ((a IS TRUE) OR (a IS NOT TRUE))
-(5 rows)
+   ->  Seq Scan on boolpart_default boolpart_3
+         Filter: ((a IS TRUE) OR (a IS NOT TRUE))
+(7 rows)
 
 explain (costs off) select * from boolpart where a is not true;
-           QUERY PLAN            
----------------------------------
- Seq Scan on boolpart_f boolpart
-   Filter: (a IS NOT TRUE)
-(2 rows)
+                  QUERY PLAN                   
+-----------------------------------------------
+ Append
+   ->  Seq Scan on boolpart_f boolpart_1
+         Filter: (a IS NOT TRUE)
+   ->  Seq Scan on boolpart_default boolpart_2
+         Filter: (a IS NOT TRUE)
+(5 rows)
 
 explain (costs off) select * from boolpart where a is not true and a is not false;
-        QUERY PLAN        
---------------------------
- Result
-   One-Time Filter: false
+                    QUERY PLAN                    
+--------------------------------------------------
+ Seq Scan on boolpart_default boolpart
+   Filter: ((a IS NOT TRUE) AND (a IS NOT FALSE))
 (2 rows)
 
 explain (costs off) select * from boolpart where a is unknown;
