From 78f5cc3649a4253c66a7146b2312f8005f8cee57 Mon Sep 17 00:00:00 2001
From: Masahiro Ikeda <Masahiro.Ikeda@nttdata.com>
Date: Fri, 21 Jun 2024 15:18:34 +0900
Subject: [PATCH] PoC: Add new information "Index Bound Cond" to EXPLAIN output

---
 .../postgres_fdw/expected/postgres_fdw.out    |  18 +-
 src/backend/commands/explain.c                |   6 +
 src/backend/optimizer/plan/createplan.c       | 109 +++++---
 src/backend/optimizer/plan/setrefs.c          |   9 +
 src/backend/optimizer/util/pathnode.c         |   1 +
 src/backend/utils/adt/selfuncs.c              |   6 +
 src/include/nodes/pathnodes.h                 |   4 +
 src/include/nodes/plannodes.h                 |  14 +
 src/test/regress/expected/aggregates.out      |  85 ++++--
 src/test/regress/expected/btree_index.out     |  69 +++--
 src/test/regress/expected/cluster.out         |  18 +-
 src/test/regress/expected/create_index.out    | 118 +++++----
 src/test/regress/expected/equivclass.out      | 116 +++++---
 src/test/regress/expected/explain.out         |   3 +-
 src/test/regress/expected/expressions.out     |   3 +-
 src/test/regress/expected/fast_default.out    |   7 +-
 src/test/regress/expected/foreign_key.out     |   4 +-
 src/test/regress/expected/generated.out       |  18 +-
 src/test/regress/expected/groupingsets.out    |   3 +-
 .../regress/expected/incremental_sort.out     |   6 +-
 src/test/regress/expected/index_including.out |  21 +-
 src/test/regress/expected/inet.out            |  28 +-
 src/test/regress/expected/inherit.out         |  89 +++++--
 src/test/regress/expected/insert_conflict.out |   3 +-
 src/test/regress/expected/join.out            | 248 ++++++++++++------
 src/test/regress/expected/memoize.out         |  44 +++-
 src/test/regress/expected/misc_functions.out  |   6 +-
 src/test/regress/expected/partition_join.out  |  71 +++--
 src/test/regress/expected/partition_prune.out | 135 ++++++++--
 src/test/regress/expected/plancache.out       |   6 +-
 src/test/regress/expected/portals.out         |   7 +-
 src/test/regress/expected/privileges.out      |  15 +-
 src/test/regress/expected/regex.out           |  41 +--
 src/test/regress/expected/rowsecurity.out     |  30 ++-
 src/test/regress/expected/rowtypes.out        |  38 +--
 src/test/regress/expected/select.out          |  29 +-
 src/test/regress/expected/select_parallel.out |  25 +-
 src/test/regress/expected/stats.out           |   9 +-
 src/test/regress/expected/subselect.out       |  18 +-
 src/test/regress/expected/union.out           |  24 +-
 src/test/regress/expected/updatable_views.out |  79 ++++--
 src/test/regress/expected/with.out            |   3 +-
 42 files changed, 1095 insertions(+), 491 deletions(-)

diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index ea566d5034..b3c5031d7e 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -739,10 +739,11 @@ EXPLAIN (VERBOSE, COSTS OFF)
    ->  Index Scan using t1_pkey on "S 1"."T 1" a
          Output: a."C 1", a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8
          Index Cond: (a."C 1" = 47)
+         Index Bound Cond: (a."C 1" = 47)
    ->  Foreign Scan on public.ft2 b
          Output: b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8
          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1::integer))
-(8 rows)
+(9 rows)
 
 SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2;
  C 1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  | c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
@@ -3734,6 +3735,7 @@ select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum fr
          ->  Index Scan using t1_pkey on "S 1"."T 1" t1
                Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
                Index Cond: (t1."C 1" < 100)
+               Index Bound Cond: (t1."C 1" < 100)
                Filter: (t1.c2 < 3)
          ->  Subquery Scan on qry
                Output: qry.sum, t2.c1
@@ -3742,7 +3744,7 @@ select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum fr
                      Output: (sum((t2.c1 + t1."C 1"))), t2.c1
                      Relations: Aggregate on (public.ft2 t2)
                      Remote SQL: SELECT sum(("C 1" + $1::integer)), "C 1" FROM "S 1"."T 1" GROUP BY 2
-(16 rows)
+(17 rows)
 
 select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 3 and t1."C 1" < 100 order by 1;
  c2 | sum 
@@ -3774,6 +3776,7 @@ ORDER BY ref_0."C 1";
          ->  Index Scan using t1_pkey on "S 1"."T 1" ref_0
                Output: ref_0."C 1", ref_0.c2, ref_0.c3, ref_0.c4, ref_0.c5, ref_0.c6, ref_0.c7, ref_0.c8
                Index Cond: (ref_0."C 1" < 10)
+               Index Bound Cond: (ref_0."C 1" < 10)
          ->  Foreign Scan on public.ft1 ref_1
                Output: ref_1.c3, ref_0.c2
                Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE ((c3 = '00001'))
@@ -3782,7 +3785,7 @@ ORDER BY ref_0."C 1";
          ->  Foreign Scan on public.ft2 ref_3
                Output: ref_3.c3
                Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE ((c3 = '00001'))
-(15 rows)
+(16 rows)
 
 SELECT ref_0.c2, subq_1.*
 FROM
@@ -4617,10 +4620,11 @@ explain (verbose, costs off) select * from ft3 f, loct3 l
    ->  Index Scan using loct3_f1_key on public.loct3 l
          Output: l.f1, l.f2, l.f3
          Index Cond: (l.f1 = 'foo'::text)
+         Index Bound Cond: (l.f1 = 'foo'::text)
    ->  Foreign Scan on public.ft3 f
          Output: f.f1, f.f2, f.f3
          Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f3 = $1::character varying(10)))
-(8 rows)
+(9 rows)
 
 -- can't be sent to remote
 explain (verbose, costs off) select * from ft3 where f1 COLLATE "POSIX" = 'foo';
@@ -4675,7 +4679,8 @@ explain (verbose, costs off) select * from ft3 f, loct3 l
          ->  Index Scan using loct3_f1_key on public.loct3 l
                Output: l.f1, l.f2, l.f3
                Index Cond: (l.f1 = 'foo'::text)
-(12 rows)
+               Index Bound Cond: (l.f1 = 'foo'::text)
+(13 rows)
 
 -- ===================================================================
 -- test SEMI-JOIN pushdown
@@ -8482,9 +8487,10 @@ delete from foo where f1 < 5 returning *;
          ->  Index Scan using i_foo_f1 on public.foo foo_1
                Output: foo_1.tableoid, foo_1.ctid
                Index Cond: (foo_1.f1 < 5)
+               Index Bound Cond: (foo_1.f1 < 5)
          ->  Foreign Delete on public.foo2 foo_2
                Remote SQL: DELETE FROM public.loct1 WHERE ((f1 < 5)) RETURNING f1, f2
-(10 rows)
+(11 rows)
 
 delete from foo where f1 < 5 returning *;
  f1 | f2 
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 94511a5a02..f071c30048 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -1966,6 +1966,8 @@ ExplainNode(PlanState *planstate, List *ancestors,
 		case T_IndexScan:
 			show_scan_qual(((IndexScan *) plan)->indexqualorig,
 						   "Index Cond", planstate, ancestors, es);
+			show_scan_qual(((IndexScan *) plan)->indexboundqualorig,
+						   "Index Bound Cond", planstate, ancestors, es);
 			if (((IndexScan *) plan)->indexqualorig)
 				show_instrumentation_count("Rows Removed by Index Recheck", 2,
 										   planstate, es);
@@ -1979,6 +1981,8 @@ ExplainNode(PlanState *planstate, List *ancestors,
 		case T_IndexOnlyScan:
 			show_scan_qual(((IndexOnlyScan *) plan)->indexqual,
 						   "Index Cond", planstate, ancestors, es);
+			show_scan_qual(((IndexOnlyScan *) plan)->indexboundqual,
+						   "Index Bound Cond", planstate, ancestors, es);
 			if (((IndexOnlyScan *) plan)->recheckqual)
 				show_instrumentation_count("Rows Removed by Index Recheck", 2,
 										   planstate, es);
@@ -1995,6 +1999,8 @@ ExplainNode(PlanState *planstate, List *ancestors,
 		case T_BitmapIndexScan:
 			show_scan_qual(((BitmapIndexScan *) plan)->indexqualorig,
 						   "Index Cond", planstate, ancestors, es);
+			show_scan_qual(((BitmapIndexScan *) plan)->indexboundqualorig,
+						   "Index Bound Cond", planstate, ancestors, es);
 			break;
 		case T_BitmapHeapScan:
 			show_scan_qual(((BitmapHeapScan *) plan)->bitmapqualorig,
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 6b64c4a362..92a33e79c0 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -166,7 +166,9 @@ static Node *replace_nestloop_params(PlannerInfo *root, Node *expr);
 static Node *replace_nestloop_params_mutator(Node *node, PlannerInfo *root);
 static void fix_indexqual_references(PlannerInfo *root, IndexPath *index_path,
 									 List **stripped_indexquals_p,
-									 List **fixed_indexquals_p);
+									 List **fixed_indexquals_p,
+									 List **stripped_indexboundquals_p,
+									 List **fixed_indexboundquals_p);
 static List *fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path);
 static Node *fix_indexqual_clause(PlannerInfo *root,
 								  IndexOptInfo *index, int indexcol,
@@ -183,18 +185,22 @@ static SampleScan *make_samplescan(List *qptlist, List *qpqual, Index scanrelid,
 								   TableSampleClause *tsc);
 static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
 								 Oid indexid, List *indexqual, List *indexqualorig,
+								 List *indexboundqualorig,
 								 List *indexorderby, List *indexorderbyorig,
 								 List *indexorderbyops,
 								 ScanDirection indexscandir);
 static IndexOnlyScan *make_indexonlyscan(List *qptlist, List *qpqual,
 										 Index scanrelid, Oid indexid,
-										 List *indexqual, List *recheckqual,
+										 List *indexqual,
+										 List *indexboundqual,
+										 List *recheckqual,
 										 List *indexorderby,
 										 List *indextlist,
 										 ScanDirection indexscandir);
 static BitmapIndexScan *make_bitmap_indexscan(Index scanrelid, Oid indexid,
 											  List *indexqual,
-											  List *indexqualorig);
+											  List *indexqualorig,
+											  List *indexboundqualorig);
 static BitmapHeapScan *make_bitmap_heapscan(List *qptlist,
 											List *qpqual,
 											Plan *lefttree,
@@ -3017,6 +3023,8 @@ create_indexscan_plan(PlannerInfo *root,
 	List	   *qpqual;
 	List	   *stripped_indexquals;
 	List	   *fixed_indexquals;
+	List	   *stripped_indexboundquals;
+	List	   *fixed_indexboundquals;
 	List	   *fixed_indexorderbys;
 	List	   *indexorderbyops = NIL;
 	ListCell   *l;
@@ -3036,7 +3044,9 @@ create_indexscan_plan(PlannerInfo *root,
 	 */
 	fix_indexqual_references(root, best_path,
 							 &stripped_indexquals,
-							 &fixed_indexquals);
+							 &fixed_indexquals,
+							 &stripped_indexboundquals,
+							 &fixed_indexboundquals);
 
 	/*
 	 * Likewise fix up index attr references in the ORDER BY expressions.
@@ -3106,6 +3116,8 @@ create_indexscan_plan(PlannerInfo *root,
 	{
 		stripped_indexquals = (List *)
 			replace_nestloop_params(root, (Node *) stripped_indexquals);
+		stripped_indexboundquals = (List *)
+			replace_nestloop_params(root, (Node *) stripped_indexboundquals);
 		qpqual = (List *)
 			replace_nestloop_params(root, (Node *) qpqual);
 		indexorderbys = (List *)
@@ -3171,6 +3183,7 @@ create_indexscan_plan(PlannerInfo *root,
 												baserelid,
 												indexoid,
 												fixed_indexquals,
+												fixed_indexboundquals,
 												stripped_indexquals,
 												fixed_indexorderbys,
 												indexinfo->indextlist,
@@ -3182,6 +3195,7 @@ create_indexscan_plan(PlannerInfo *root,
 											indexoid,
 											fixed_indexquals,
 											stripped_indexquals,
+											stripped_indexboundquals,
 											fixed_indexorderbys,
 											indexorderbys,
 											indexorderbyops,
@@ -3475,7 +3489,8 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
 		plan = (Plan *) make_bitmap_indexscan(iscan->scan.scanrelid,
 											  iscan->indexid,
 											  iscan->indexqual,
-											  iscan->indexqualorig);
+											  iscan->indexqualorig,
+											  iscan->indexboundqualorig);
 		/* and set its cost/width fields appropriately */
 		plan->startup_cost = 0.0;
 		plan->total_cost = ipath->indextotalcost;
@@ -4998,6 +5013,39 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
 								   (void *) root);
 }
 
+static void
+fix_indexqual_references_clauses(PlannerInfo *root, IndexOptInfo *index,
+								 List *indexclauses, List **stripped_quals_p,
+								 List **fixed_quals_p)
+{
+	List	   *stripped_quals;
+	List	   *fixed_quals;
+	ListCell   *lc;
+
+	stripped_quals = fixed_quals = NIL;
+
+	foreach(lc, indexclauses)
+	{
+		IndexClause *iclause = lfirst_node(IndexClause, lc);
+		int			indexcol = iclause->indexcol;
+		ListCell   *lc2;
+
+		foreach(lc2, iclause->indexquals)
+		{
+			RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
+			Node	   *clause = (Node *) rinfo->clause;
+
+			stripped_quals = lappend(stripped_quals, clause);
+			clause = fix_indexqual_clause(root, index, indexcol,
+										  clause, iclause->indexcols);
+			fixed_quals = lappend(fixed_quals, clause);
+		}
+	}
+
+	*stripped_quals_p = stripped_quals;
+	*fixed_quals_p = fixed_quals;
+}
+
 /*
  * fix_indexqual_references
  *	  Adjust indexqual clauses to the form the executor's indexqual
@@ -5017,38 +5065,25 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
  * that shares no substructure with the original; this is needed in case there
  * are subplans in it (we need two separate copies of the subplan tree, or
  * things will go awry).
+ * 
+ * *stripped_indexboundquals_p and *fixed_indexboundquals_p are the same as above
+ * except that they store only the quals used to scan index efficiently.
+ * 
  */
 static void
 fix_indexqual_references(PlannerInfo *root, IndexPath *index_path,
-						 List **stripped_indexquals_p, List **fixed_indexquals_p)
+						 List **stripped_indexquals_p, List **fixed_indexquals_p,
+						 List **stripped_indexboundquals_p, List **fixed_indexboundquals_p)
 {
-	IndexOptInfo *index = index_path->indexinfo;
-	List	   *stripped_indexquals;
-	List	   *fixed_indexquals;
-	ListCell   *lc;
-
-	stripped_indexquals = fixed_indexquals = NIL;
-
-	foreach(lc, index_path->indexclauses)
-	{
-		IndexClause *iclause = lfirst_node(IndexClause, lc);
-		int			indexcol = iclause->indexcol;
-		ListCell   *lc2;
-
-		foreach(lc2, iclause->indexquals)
-		{
-			RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
-			Node	   *clause = (Node *) rinfo->clause;
-
-			stripped_indexquals = lappend(stripped_indexquals, clause);
-			clause = fix_indexqual_clause(root, index, indexcol,
-										  clause, iclause->indexcols);
-			fixed_indexquals = lappend(fixed_indexquals, clause);
-		}
-	}
-
-	*stripped_indexquals_p = stripped_indexquals;
-	*fixed_indexquals_p = fixed_indexquals;
+	fix_indexqual_references_clauses(root, index_path->indexinfo,
+									 index_path->indexclauses,
+									 stripped_indexquals_p,
+									 fixed_indexquals_p);
+
+	fix_indexqual_references_clauses(root, index_path->indexinfo,
+									 index_path->indexboundclauses,
+									 stripped_indexboundquals_p,
+									 fixed_indexboundquals_p);
 }
 
 /*
@@ -5547,6 +5582,7 @@ make_indexscan(List *qptlist,
 			   Oid indexid,
 			   List *indexqual,
 			   List *indexqualorig,
+			   List *indexboundqualorig,
 			   List *indexorderby,
 			   List *indexorderbyorig,
 			   List *indexorderbyops,
@@ -5563,6 +5599,7 @@ make_indexscan(List *qptlist,
 	node->indexid = indexid;
 	node->indexqual = indexqual;
 	node->indexqualorig = indexqualorig;
+	node->indexboundqualorig = indexboundqualorig;
 	node->indexorderby = indexorderby;
 	node->indexorderbyorig = indexorderbyorig;
 	node->indexorderbyops = indexorderbyops;
@@ -5577,6 +5614,7 @@ make_indexonlyscan(List *qptlist,
 				   Index scanrelid,
 				   Oid indexid,
 				   List *indexqual,
+				   List *indexboundqual,
 				   List *recheckqual,
 				   List *indexorderby,
 				   List *indextlist,
@@ -5592,6 +5630,7 @@ make_indexonlyscan(List *qptlist,
 	node->scan.scanrelid = scanrelid;
 	node->indexid = indexid;
 	node->indexqual = indexqual;
+	node->indexboundqual = indexboundqual;
 	node->recheckqual = recheckqual;
 	node->indexorderby = indexorderby;
 	node->indextlist = indextlist;
@@ -5604,7 +5643,8 @@ static BitmapIndexScan *
 make_bitmap_indexscan(Index scanrelid,
 					  Oid indexid,
 					  List *indexqual,
-					  List *indexqualorig)
+					  List *indexqualorig,
+					  List *indexboundqualorig)
 {
 	BitmapIndexScan *node = makeNode(BitmapIndexScan);
 	Plan	   *plan = &node->scan.plan;
@@ -5617,6 +5657,7 @@ make_bitmap_indexscan(Index scanrelid,
 	node->indexid = indexid;
 	node->indexqual = indexqual;
 	node->indexqualorig = indexqualorig;
+	node->indexboundqualorig = indexboundqualorig;
 
 	return node;
 }
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 7aed84584c..2125b12819 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -666,6 +666,9 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
 				splan->indexqualorig =
 					fix_scan_list(root, splan->indexqualorig,
 								  rtoffset, NUM_EXEC_QUAL(plan));
+				splan->indexboundqualorig =
+					fix_scan_list(root, splan->indexboundqualorig,
+								  rtoffset, NUM_EXEC_QUAL(plan));
 				splan->indexorderby =
 					fix_scan_list(root, splan->indexorderby,
 								  rtoffset, 1);
@@ -694,6 +697,9 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
 				splan->indexqualorig =
 					fix_scan_list(root, splan->indexqualorig,
 								  rtoffset, NUM_EXEC_QUAL(plan));
+				splan->indexboundqualorig =
+					fix_scan_list(root, splan->indexboundqualorig,
+								  rtoffset, NUM_EXEC_QUAL(plan));
 			}
 			break;
 		case T_BitmapHeapScan:
@@ -1372,6 +1378,9 @@ set_indexonlyscan_references(PlannerInfo *root,
 	/* indexqual is already transformed to reference index columns */
 	plan->indexqual = fix_scan_list(root, plan->indexqual,
 									rtoffset, 1);
+	/* indexboundqual is already transformed to reference index columns */
+	plan->indexboundqual = fix_scan_list(root, plan->indexboundqual,
+									rtoffset, 1);
 	/* indexorderby is already transformed to reference index columns */
 	plan->indexorderby = fix_scan_list(root, plan->indexorderby,
 									   rtoffset, 1);
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index c42742d2c7..a0e56a57c8 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -4190,6 +4190,7 @@ do { \
 
 				ADJUST_CHILD_ATTRS(ipath->indexinfo->indrestrictinfo);
 				ADJUST_CHILD_ATTRS(ipath->indexclauses);
+				ADJUST_CHILD_ATTRS(ipath->indexboundclauses);
 				new_path = (Path *) ipath;
 			}
 			break;
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 5f5d7959d8..21bada12fe 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -6798,6 +6798,7 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
 	double		numIndexTuples;
 	Cost		descentCost;
 	List	   *indexBoundQuals;
+	List	   *indexBoundClauses;
 	int			indexcol;
 	bool		eqQualHere;
 	bool		found_saop;
@@ -6823,6 +6824,7 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
 	 * operator can be considered to act the same as it normally does.
 	 */
 	indexBoundQuals = NIL;
+	indexBoundClauses = NIL;
 	indexcol = 0;
 	eqQualHere = false;
 	found_saop = false;
@@ -6844,6 +6846,9 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
 				break;			/* no quals at all for indexcol */
 		}
 
+		/* Store the clauses for EXPLAIN */
+		indexBoundClauses = lappend(indexBoundClauses, iclause);
+
 		/* Examine each indexqual associated with this index clause */
 		foreach(lc2, iclause->indexquals)
 		{
@@ -7125,6 +7130,7 @@ btcostestimate(PlannerInfo *root, IndexPath *path, double loop_count,
 	*indexSelectivity = costs.indexSelectivity;
 	*indexCorrelation = costs.indexCorrelation;
 	*indexPages = costs.numIndexPages;
+	path->indexboundclauses = indexBoundClauses;
 }
 
 void
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index 2ba297c117..1125d611cb 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -1681,6 +1681,9 @@ typedef struct Path
  * index-checkable restriction, with implicit AND semantics across the list.
  * An empty list implies a full index scan.
  *
+ * 'indexboundclauses' is used for EXPLAIN. It is a subset of 'indexclauses',
+ * storing only the quals used to scan index efficiently.
+ * 
  * 'indexorderbys', if not NIL, is a list of ORDER BY expressions that have
  * been found to be usable as ordering operators for an amcanorderbyop index.
  * The list must match the path's pathkeys, ie, one expression per pathkey
@@ -1709,6 +1712,7 @@ typedef struct IndexPath
 	Path		path;
 	IndexOptInfo *indexinfo;
 	List	   *indexclauses;
+	List	   *indexboundclauses;
 	List	   *indexorderbys;
 	List	   *indexorderbycols;
 	ScanDirection indexscandir;
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 1aeeaec95e..79e720fdeb 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -421,6 +421,9 @@ typedef struct SampleScan
  * column position (but items referencing the same index column can appear
  * in any order).  indexqualorig is used at runtime only if we have to recheck
  * a lossy indexqual.
+ * 
+ * indexboundqualorig is used for EXPLAIN. It is a subset of indexqualorig,
+ * storing only the quals used to scan index efficiently.
  *
  * indexqual has the same form, but the expressions have been commuted if
  * necessary to put the indexkeys on the left, and the indexkeys are replaced
@@ -452,6 +455,7 @@ typedef struct IndexScan
 	Oid			indexid;		/* OID of index to scan */
 	List	   *indexqual;		/* list of index quals (usually OpExprs) */
 	List	   *indexqualorig;	/* the same in original form */
+	List	   *indexboundqualorig; /* index quals to scan efficiently */
 	List	   *indexorderby;	/* list of index ORDER BY exprs */
 	List	   *indexorderbyorig;	/* the same in original form */
 	List	   *indexorderbyops;	/* OIDs of sort ops for ORDER BY exprs */
@@ -476,6 +480,10 @@ typedef struct IndexScan
  * an expression f(x) in a non-retrievable column "ind2", an indexable
  * query on f(x) will use "ind2" in indexqual and f(ind1) in recheckqual.
  * Without the "ind1" column, an index-only scan would be disallowed.)
+ * 
+ * indexboundqualorig is used for EXPLAIN. It is a subset of indexqual,
+ * storing only the quals used to scan index efficiently.
+ *
  *
  * We don't currently need a recheckable equivalent of indexorderby,
  * because we don't support lossy operators in index ORDER BY.
@@ -494,6 +502,7 @@ typedef struct IndexOnlyScan
 	Scan		scan;
 	Oid			indexid;		/* OID of index to scan */
 	List	   *indexqual;		/* list of index quals (usually OpExprs) */
+	List	   *indexboundqual; /* index quals to scan efficiently */
 	List	   *recheckqual;	/* index quals in recheckable form */
 	List	   *indexorderby;	/* list of index ORDER BY exprs */
 	List	   *indextlist;		/* TargetEntry list describing index's cols */
@@ -515,6 +524,10 @@ typedef struct IndexOnlyScan
  * In a BitmapIndexScan plan node, the targetlist and qual fields are
  * not used and are always NIL.  The indexqualorig field is unused at
  * run time too, but is saved for the benefit of EXPLAIN.
+ * 
+ * indexboundqualorig is used for EXPLAIN. It is a subset of indexqualorig,
+ * storing only the quals used to scan index efficiently.
+ *
  * ----------------
  */
 typedef struct BitmapIndexScan
@@ -524,6 +537,7 @@ typedef struct BitmapIndexScan
 	bool		isshared;		/* Create shared bitmap if set */
 	List	   *indexqual;		/* list of index quals (OpExprs) */
 	List	   *indexqualorig;	/* the same in original form */
+	List	   *indexboundqualorig;	/* index quals to scan efficiently */
 } BitmapIndexScan;
 
 /* ----------------
diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out
index 1c1ca7573a..f017131c8e 100644
--- a/src/test/regress/expected/aggregates.out
+++ b/src/test/regress/expected/aggregates.out
@@ -919,7 +919,8 @@ explain (costs off)
      ->  Limit
            ->  Index Only Scan using tenk1_unique1 on tenk1
                  Index Cond: (unique1 IS NOT NULL)
-(5 rows)
+                 Index Bound Cond: (unique1 IS NOT NULL)
+(6 rows)
 
 select min(unique1) from tenk1;
  min 
@@ -936,7 +937,8 @@ explain (costs off)
      ->  Limit
            ->  Index Only Scan Backward using tenk1_unique1 on tenk1
                  Index Cond: (unique1 IS NOT NULL)
-(5 rows)
+                 Index Bound Cond: (unique1 IS NOT NULL)
+(6 rows)
 
 select max(unique1) from tenk1;
  max  
@@ -946,14 +948,15 @@ select max(unique1) from tenk1;
 
 explain (costs off)
   select max(unique1) from tenk1 where unique1 < 42;
-                               QUERY PLAN                               
-------------------------------------------------------------------------
+                                  QUERY PLAN                                  
+------------------------------------------------------------------------------
  Result
    InitPlan 1
      ->  Limit
            ->  Index Only Scan Backward using tenk1_unique1 on tenk1
                  Index Cond: ((unique1 IS NOT NULL) AND (unique1 < 42))
-(5 rows)
+                 Index Bound Cond: ((unique1 IS NOT NULL) AND (unique1 < 42))
+(6 rows)
 
 select max(unique1) from tenk1 where unique1 < 42;
  max 
@@ -963,14 +966,15 @@ select max(unique1) from tenk1 where unique1 < 42;
 
 explain (costs off)
   select max(unique1) from tenk1 where unique1 > 42;
-                               QUERY PLAN                               
-------------------------------------------------------------------------
+                                  QUERY PLAN                                  
+------------------------------------------------------------------------------
  Result
    InitPlan 1
      ->  Limit
            ->  Index Only Scan Backward using tenk1_unique1 on tenk1
                  Index Cond: ((unique1 IS NOT NULL) AND (unique1 > 42))
-(5 rows)
+                 Index Bound Cond: ((unique1 IS NOT NULL) AND (unique1 > 42))
+(6 rows)
 
 select max(unique1) from tenk1 where unique1 > 42;
  max  
@@ -986,14 +990,15 @@ begin;
 set local max_parallel_workers_per_gather = 0;
 explain (costs off)
   select max(unique1) from tenk1 where unique1 > 42000;
-                                QUERY PLAN                                 
----------------------------------------------------------------------------
+                                   QUERY PLAN                                    
+---------------------------------------------------------------------------------
  Result
    InitPlan 1
      ->  Limit
            ->  Index Only Scan Backward using tenk1_unique1 on tenk1
                  Index Cond: ((unique1 IS NOT NULL) AND (unique1 > 42000))
-(5 rows)
+                 Index Bound Cond: ((unique1 IS NOT NULL) AND (unique1 > 42000))
+(6 rows)
 
 select max(unique1) from tenk1 where unique1 > 42000;
  max 
@@ -1005,14 +1010,15 @@ rollback;
 -- multi-column index (uses tenk1_thous_tenthous)
 explain (costs off)
   select max(tenthous) from tenk1 where thousand = 33;
-                                 QUERY PLAN                                 
-----------------------------------------------------------------------------
+                                   QUERY PLAN                                   
+--------------------------------------------------------------------------------
  Result
    InitPlan 1
      ->  Limit
            ->  Index Only Scan Backward using tenk1_thous_tenthous on tenk1
                  Index Cond: ((thousand = 33) AND (tenthous IS NOT NULL))
-(5 rows)
+                 Index Bound Cond: ((thousand = 33) AND (tenthous IS NOT NULL))
+(6 rows)
 
 select max(tenthous) from tenk1 where thousand = 33;
  max  
@@ -1022,14 +1028,15 @@ select max(tenthous) from tenk1 where thousand = 33;
 
 explain (costs off)
   select min(tenthous) from tenk1 where thousand = 33;
-                                QUERY PLAN                                
---------------------------------------------------------------------------
+                                   QUERY PLAN                                   
+--------------------------------------------------------------------------------
  Result
    InitPlan 1
      ->  Limit
            ->  Index Only Scan using tenk1_thous_tenthous on tenk1
                  Index Cond: ((thousand = 33) AND (tenthous IS NOT NULL))
-(5 rows)
+                 Index Bound Cond: ((thousand = 33) AND (tenthous IS NOT NULL))
+(6 rows)
 
 select min(tenthous) from tenk1 where thousand = 33;
  min 
@@ -1041,8 +1048,8 @@ select min(tenthous) from tenk1 where thousand = 33;
 explain (costs off)
   select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt
     from int4_tbl;
-                                       QUERY PLAN                                        
------------------------------------------------------------------------------------------
+                                          QUERY PLAN                                           
+-----------------------------------------------------------------------------------------------
  Seq Scan on int4_tbl
    SubPlan 2
      ->  Result
@@ -1050,7 +1057,8 @@ explain (costs off)
              ->  Limit
                    ->  Index Only Scan using tenk1_unique1 on tenk1
                          Index Cond: ((unique1 IS NOT NULL) AND (unique1 > int4_tbl.f1))
-(7 rows)
+                         Index Bound Cond: ((unique1 IS NOT NULL) AND (unique1 > int4_tbl.f1))
+(8 rows)
 
 select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt
   from int4_tbl;
@@ -1074,8 +1082,9 @@ explain (costs off)
      ->  Limit
            ->  Index Only Scan Backward using tenk1_unique2 on tenk1
                  Index Cond: (unique2 IS NOT NULL)
+                 Index Bound Cond: (unique2 IS NOT NULL)
    ->  Result
-(7 rows)
+(8 rows)
 
 select distinct max(unique2) from tenk1;
  max  
@@ -1093,8 +1102,9 @@ explain (costs off)
      ->  Limit
            ->  Index Only Scan Backward using tenk1_unique2 on tenk1
                  Index Cond: (unique2 IS NOT NULL)
+                 Index Bound Cond: (unique2 IS NOT NULL)
    ->  Result
-(7 rows)
+(8 rows)
 
 select max(unique2) from tenk1 order by 1;
  max  
@@ -1112,8 +1122,9 @@ explain (costs off)
      ->  Limit
            ->  Index Only Scan Backward using tenk1_unique2 on tenk1
                  Index Cond: (unique2 IS NOT NULL)
+                 Index Bound Cond: (unique2 IS NOT NULL)
    ->  Result
-(7 rows)
+(8 rows)
 
 select max(unique2) from tenk1 order by max(unique2);
  max  
@@ -1131,8 +1142,9 @@ explain (costs off)
      ->  Limit
            ->  Index Only Scan Backward using tenk1_unique2 on tenk1
                  Index Cond: (unique2 IS NOT NULL)
+                 Index Bound Cond: (unique2 IS NOT NULL)
    ->  Result
-(7 rows)
+(8 rows)
 
 select max(unique2) from tenk1 order by max(unique2)+1;
  max  
@@ -1150,9 +1162,10 @@ explain (costs off)
      ->  Limit
            ->  Index Only Scan Backward using tenk1_unique2 on tenk1
                  Index Cond: (unique2 IS NOT NULL)
+                 Index Bound Cond: (unique2 IS NOT NULL)
    ->  ProjectSet
          ->  Result
-(8 rows)
+(9 rows)
 
 select max(unique2), generate_series(1,3) as g from tenk1 order by g desc;
  max  | g 
@@ -1205,10 +1218,13 @@ explain (costs off)
                  Sort Key: minmaxtest.f1
                  ->  Index Only Scan using minmaxtesti on minmaxtest minmaxtest_1
                        Index Cond: (f1 IS NOT NULL)
+                       Index Bound Cond: (f1 IS NOT NULL)
                  ->  Index Only Scan using minmaxtest1i on minmaxtest1 minmaxtest_2
                        Index Cond: (f1 IS NOT NULL)
+                       Index Bound Cond: (f1 IS NOT NULL)
                  ->  Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_3
                        Index Cond: (f1 IS NOT NULL)
+                       Index Bound Cond: (f1 IS NOT NULL)
                  ->  Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_4
    InitPlan 2
      ->  Limit
@@ -1216,12 +1232,15 @@ explain (costs off)
                  Sort Key: minmaxtest_5.f1 DESC
                  ->  Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_6
                        Index Cond: (f1 IS NOT NULL)
+                       Index Bound Cond: (f1 IS NOT NULL)
                  ->  Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest_7
                        Index Cond: (f1 IS NOT NULL)
+                       Index Bound Cond: (f1 IS NOT NULL)
                  ->  Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest_8
                        Index Cond: (f1 IS NOT NULL)
+                       Index Bound Cond: (f1 IS NOT NULL)
                  ->  Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_9
-(23 rows)
+(29 rows)
 
 select min(f1), max(f1) from minmaxtest;
  min | max 
@@ -1241,10 +1260,13 @@ explain (costs off)
                  Sort Key: minmaxtest.f1
                  ->  Index Only Scan using minmaxtesti on minmaxtest minmaxtest_1
                        Index Cond: (f1 IS NOT NULL)
+                       Index Bound Cond: (f1 IS NOT NULL)
                  ->  Index Only Scan using minmaxtest1i on minmaxtest1 minmaxtest_2
                        Index Cond: (f1 IS NOT NULL)
+                       Index Bound Cond: (f1 IS NOT NULL)
                  ->  Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_3
                        Index Cond: (f1 IS NOT NULL)
+                       Index Bound Cond: (f1 IS NOT NULL)
                  ->  Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_4
    InitPlan 2
      ->  Limit
@@ -1252,15 +1274,18 @@ explain (costs off)
                  Sort Key: minmaxtest_5.f1 DESC
                  ->  Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_6
                        Index Cond: (f1 IS NOT NULL)
+                       Index Bound Cond: (f1 IS NOT NULL)
                  ->  Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest_7
                        Index Cond: (f1 IS NOT NULL)
+                       Index Bound Cond: (f1 IS NOT NULL)
                  ->  Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest_8
                        Index Cond: (f1 IS NOT NULL)
+                       Index Bound Cond: (f1 IS NOT NULL)
                  ->  Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_9
    ->  Sort
          Sort Key: ((InitPlan 1).col1), ((InitPlan 2).col1)
          ->  Result
-(26 rows)
+(32 rows)
 
 select distinct min(f1), max(f1) from minmaxtest;
  min | max 
@@ -2874,7 +2899,8 @@ SELECT y, x, array_agg(distinct w)
    ->  Index Only Scan using btg_y_x_w_idx on public.btg
          Output: y, x, w
          Index Cond: (btg.y < 0)
-(6 rows)
+         Index Bound Cond: (btg.y < 0)
+(7 rows)
 
 -- Ensure that we do not select the aggregate pathkeys instead of the grouping
 -- pathkeys
@@ -2986,7 +3012,8 @@ FROM agg_sort_order WHERE c2 < 100 GROUP BY c1 ORDER BY 2;
                Sort Key: c1, c2
                ->  Index Scan using agg_sort_order_c2_idx on agg_sort_order
                      Index Cond: (c2 < 100)
-(8 rows)
+                     Index Bound Cond: (c2 < 100)
+(9 rows)
 
 DROP TABLE agg_sort_order CASCADE;
 DROP TABLE btg;
diff --git a/src/test/regress/expected/btree_index.out b/src/test/regress/expected/btree_index.out
index 510646cbce..0a99ac1806 100644
--- a/src/test/regress/expected/btree_index.out
+++ b/src/test/regress/expected/btree_index.out
@@ -163,7 +163,8 @@ select hundred, twenty from tenk1 where hundred < 48 order by hundred desc limit
  Limit
    ->  Index Scan Backward using tenk1_hundred on tenk1
          Index Cond: (hundred < 48)
-(3 rows)
+         Index Bound Cond: (hundred < 48)
+(4 rows)
 
 select hundred, twenty from tenk1 where hundred < 48 order by hundred desc limit 1;
  hundred | twenty 
@@ -181,7 +182,8 @@ select hundred, twenty from tenk1 where hundred <= 48 order by hundred desc limi
  Limit
    ->  Index Scan Backward using tenk1_hundred on tenk1
          Index Cond: (hundred <= 48)
-(3 rows)
+         Index Bound Cond: (hundred <= 48)
+(4 rows)
 
 select hundred, twenty from tenk1 where hundred <= 48 order by hundred desc limit 1;
  hundred | twenty 
@@ -194,12 +196,13 @@ select hundred, twenty from tenk1 where hundred <= 48 order by hundred desc limi
 --
 explain (costs off)
 select distinct hundred from tenk1 where hundred in (47, 48, 72, 82);
-                            QUERY PLAN                            
-------------------------------------------------------------------
+                               QUERY PLAN                               
+------------------------------------------------------------------------
  Unique
    ->  Index Only Scan using tenk1_hundred on tenk1
          Index Cond: (hundred = ANY ('{47,48,72,82}'::integer[]))
-(3 rows)
+         Index Bound Cond: (hundred = ANY ('{47,48,72,82}'::integer[]))
+(4 rows)
 
 select distinct hundred from tenk1 where hundred in (47, 48, 72, 82);
  hundred 
@@ -212,12 +215,13 @@ select distinct hundred from tenk1 where hundred in (47, 48, 72, 82);
 
 explain (costs off)
 select distinct hundred from tenk1 where hundred in (47, 48, 72, 82) order by hundred desc;
-                            QUERY PLAN                            
-------------------------------------------------------------------
+                               QUERY PLAN                               
+------------------------------------------------------------------------
  Unique
    ->  Index Only Scan Backward using tenk1_hundred on tenk1
          Index Cond: (hundred = ANY ('{47,48,72,82}'::integer[]))
-(3 rows)
+         Index Bound Cond: (hundred = ANY ('{47,48,72,82}'::integer[]))
+(4 rows)
 
 select distinct hundred from tenk1 where hundred in (47, 48, 72, 82) order by hundred desc;
  hundred 
@@ -230,11 +234,12 @@ select distinct hundred from tenk1 where hundred in (47, 48, 72, 82) order by hu
 
 explain (costs off)
 select thousand from tenk1 where thousand in (364, 366,380) and tenthous = 200000;
-                                      QUERY PLAN                                       
----------------------------------------------------------------------------------------
+                                         QUERY PLAN                                          
+---------------------------------------------------------------------------------------------
  Index Only Scan using tenk1_thous_tenthous on tenk1
    Index Cond: ((thousand = ANY ('{364,366,380}'::integer[])) AND (tenthous = 200000))
-(2 rows)
+   Index Bound Cond: ((thousand = ANY ('{364,366,380}'::integer[])) AND (tenthous = 200000))
+(3 rows)
 
 select thousand from tenk1 where thousand in (364, 366,380) and tenthous = 200000;
  thousand 
@@ -250,12 +255,13 @@ set enable_indexscan to true;
 set enable_bitmapscan to false;
 explain (costs off)
 select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
-                                  QUERY PLAN                                  
-------------------------------------------------------------------------------
+                                     QUERY PLAN                                     
+------------------------------------------------------------------------------------
  Index Only Scan using pg_proc_proname_args_nsp_index on pg_proc
    Index Cond: ((proname >= 'RI_FKey'::text) AND (proname < 'RI_FKez'::text))
+   Index Bound Cond: ((proname >= 'RI_FKey'::text) AND (proname < 'RI_FKez'::text))
    Filter: (proname ~~ 'RI\_FKey%del'::text)
-(3 rows)
+(4 rows)
 
 select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
         proname         
@@ -269,12 +275,13 @@ select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
 
 explain (costs off)
 select proname from pg_proc where proname ilike '00%foo' order by 1;
-                             QUERY PLAN                             
---------------------------------------------------------------------
+                                QUERY PLAN                                
+--------------------------------------------------------------------------
  Index Only Scan using pg_proc_proname_args_nsp_index on pg_proc
    Index Cond: ((proname >= '00'::text) AND (proname < '01'::text))
+   Index Bound Cond: ((proname >= '00'::text) AND (proname < '01'::text))
    Filter: (proname ~~* '00%foo'::text)
-(3 rows)
+(4 rows)
 
 select proname from pg_proc where proname ilike '00%foo' order by 1;
  proname 
@@ -293,15 +300,16 @@ set enable_indexscan to false;
 set enable_bitmapscan to true;
 explain (costs off)
 select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
-                                        QUERY PLAN                                        
-------------------------------------------------------------------------------------------
+                                           QUERY PLAN                                           
+------------------------------------------------------------------------------------------------
  Sort
    Sort Key: proname
    ->  Bitmap Heap Scan on pg_proc
          Filter: (proname ~~ 'RI\_FKey%del'::text)
          ->  Bitmap Index Scan on pg_proc_proname_args_nsp_index
                Index Cond: ((proname >= 'RI_FKey'::text) AND (proname < 'RI_FKez'::text))
-(6 rows)
+               Index Bound Cond: ((proname >= 'RI_FKey'::text) AND (proname < 'RI_FKez'::text))
+(7 rows)
 
 select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
         proname         
@@ -315,15 +323,16 @@ select proname from pg_proc where proname like E'RI\\_FKey%del' order by 1;
 
 explain (costs off)
 select proname from pg_proc where proname ilike '00%foo' order by 1;
-                                   QUERY PLAN                                   
---------------------------------------------------------------------------------
+                                      QUERY PLAN                                      
+--------------------------------------------------------------------------------------
  Sort
    Sort Key: proname
    ->  Bitmap Heap Scan on pg_proc
          Filter: (proname ~~* '00%foo'::text)
          ->  Bitmap Index Scan on pg_proc_proname_args_nsp_index
                Index Cond: ((proname >= '00'::text) AND (proname < '01'::text))
-(6 rows)
+               Index Bound Cond: ((proname >= '00'::text) AND (proname < '01'::text))
+(7 rows)
 
 select proname from pg_proc where proname ilike '00%foo' order by 1;
  proname 
@@ -378,13 +387,14 @@ select * from btree_bpchar where f1 like 'foo%';
 -- these do match the index:
 explain (costs off)
 select * from btree_bpchar where f1::bpchar like 'foo';
-                     QUERY PLAN                     
-----------------------------------------------------
+                        QUERY PLAN                        
+----------------------------------------------------------
  Bitmap Heap Scan on btree_bpchar
    Filter: ((f1)::bpchar ~~ 'foo'::text)
    ->  Bitmap Index Scan on btree_bpchar_f1_idx
          Index Cond: ((f1)::bpchar = 'foo'::bpchar)
-(4 rows)
+         Index Bound Cond: ((f1)::bpchar = 'foo'::bpchar)
+(5 rows)
 
 select * from btree_bpchar where f1::bpchar like 'foo';
  f1  
@@ -394,13 +404,14 @@ select * from btree_bpchar where f1::bpchar like 'foo';
 
 explain (costs off)
 select * from btree_bpchar where f1::bpchar like 'foo%';
-                                        QUERY PLAN                                        
-------------------------------------------------------------------------------------------
+                                           QUERY PLAN                                           
+------------------------------------------------------------------------------------------------
  Bitmap Heap Scan on btree_bpchar
    Filter: ((f1)::bpchar ~~ 'foo%'::text)
    ->  Bitmap Index Scan on btree_bpchar_f1_idx
          Index Cond: (((f1)::bpchar >= 'foo'::bpchar) AND ((f1)::bpchar < 'fop'::bpchar))
-(4 rows)
+         Index Bound Cond: (((f1)::bpchar >= 'foo'::bpchar) AND ((f1)::bpchar < 'fop'::bpchar))
+(5 rows)
 
 select * from btree_bpchar where f1::bpchar like 'foo%';
   f1  
diff --git a/src/test/regress/expected/cluster.out b/src/test/regress/expected/cluster.out
index a13aafff0b..71804500ef 100644
--- a/src/test/regress/expected/cluster.out
+++ b/src/test/regress/expected/cluster.out
@@ -557,7 +557,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
 ---------------------------------------------------------------
  Index Scan using clstr_expression_upper_b on clstr_expression
    Index Cond: (upper(b) = 'PREFIX3'::text)
-(2 rows)
+   Index Bound Cond: (upper(b) = 'PREFIX3'::text)
+(3 rows)
 
 SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
  id | a |    b    
@@ -570,7 +571,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
 ---------------------------------------------------------------
  Index Scan using clstr_expression_minus_a on clstr_expression
    Index Cond: ((- a) = '-3'::integer)
-(2 rows)
+   Index Bound Cond: ((- a) = '-3'::integer)
+(3 rows)
 
 SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
  id  | a |     b     
@@ -598,7 +600,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
 ---------------------------------------------------------------
  Index Scan using clstr_expression_upper_b on clstr_expression
    Index Cond: (upper(b) = 'PREFIX3'::text)
-(2 rows)
+   Index Bound Cond: (upper(b) = 'PREFIX3'::text)
+(3 rows)
 
 SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
  id | a |    b    
@@ -611,7 +614,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
 ---------------------------------------------------------------
  Index Scan using clstr_expression_minus_a on clstr_expression
    Index Cond: ((- a) = '-3'::integer)
-(2 rows)
+   Index Bound Cond: ((- a) = '-3'::integer)
+(3 rows)
 
 SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
  id  | a |     b     
@@ -639,7 +643,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
 ---------------------------------------------------------------
  Index Scan using clstr_expression_upper_b on clstr_expression
    Index Cond: (upper(b) = 'PREFIX3'::text)
-(2 rows)
+   Index Bound Cond: (upper(b) = 'PREFIX3'::text)
+(3 rows)
 
 SELECT * FROM clstr_expression WHERE upper(b) = 'PREFIX3';
  id | a |    b    
@@ -652,7 +657,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
 ---------------------------------------------------------------
  Index Scan using clstr_expression_minus_a on clstr_expression
    Index Cond: ((- a) = '-3'::integer)
-(2 rows)
+   Index Bound Cond: ((- a) = '-3'::integer)
+(3 rows)
 
 SELECT * FROM clstr_expression WHERE -a = -3 ORDER BY -a, b;
  id  | a |     b     
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index cf6eac5734..c45a38e26e 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -1851,11 +1851,14 @@ SELECT * FROM tenk1
    ->  BitmapOr
          ->  Bitmap Index Scan on tenk1_thous_tenthous
                Index Cond: ((thousand = 42) AND (tenthous = 1))
+               Index Bound Cond: ((thousand = 42) AND (tenthous = 1))
          ->  Bitmap Index Scan on tenk1_thous_tenthous
                Index Cond: ((thousand = 42) AND (tenthous = 3))
+               Index Bound Cond: ((thousand = 42) AND (tenthous = 3))
          ->  Bitmap Index Scan on tenk1_thous_tenthous
                Index Cond: ((thousand = 42) AND (tenthous = 42))
-(9 rows)
+               Index Bound Cond: ((thousand = 42) AND (tenthous = 42))
+(12 rows)
 
 SELECT * FROM tenk1
   WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42);
@@ -1875,12 +1878,15 @@ SELECT count(*) FROM tenk1
          ->  BitmapAnd
                ->  Bitmap Index Scan on tenk1_hundred
                      Index Cond: (hundred = 42)
+                     Index Bound Cond: (hundred = 42)
                ->  BitmapOr
                      ->  Bitmap Index Scan on tenk1_thous_tenthous
                            Index Cond: (thousand = 42)
+                           Index Bound Cond: (thousand = 42)
                      ->  Bitmap Index Scan on tenk1_thous_tenthous
                            Index Cond: (thousand = 99)
-(11 rows)
+                           Index Bound Cond: (thousand = 99)
+(14 rows)
 
 SELECT count(*) FROM tenk1
   WHERE hundred = 42 AND (thousand = 42 OR thousand = 99);
@@ -1906,7 +1912,8 @@ EXPLAIN (COSTS OFF)
          Recheck Cond: ((f1 >= 'WA'::text) AND (f1 <= 'ZZZ'::text) AND (id < 1000) AND (f1 ~<~ 'YX'::text))
          ->  Bitmap Index Scan on dupindexcols_i
                Index Cond: ((f1 >= 'WA'::text) AND (f1 <= 'ZZZ'::text) AND (id < 1000) AND (f1 ~<~ 'YX'::text))
-(5 rows)
+               Index Bound Cond: ((f1 >= 'WA'::text) AND (f1 <= 'ZZZ'::text))
+(6 rows)
 
 SELECT count(*) FROM dupindexcols
   WHERE f1 BETWEEN 'WA' AND 'ZZZ' and id < 1000 and f1 ~<~ 'YX';
@@ -1922,11 +1929,12 @@ explain (costs off)
 SELECT unique1 FROM tenk1
 WHERE unique1 IN (1,42,7)
 ORDER BY unique1;
-                      QUERY PLAN                       
--------------------------------------------------------
+                         QUERY PLAN                          
+-------------------------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: (unique1 = ANY ('{1,42,7}'::integer[]))
-(2 rows)
+   Index Bound Cond: (unique1 = ANY ('{1,42,7}'::integer[]))
+(3 rows)
 
 SELECT unique1 FROM tenk1
 WHERE unique1 IN (1,42,7)
@@ -1947,7 +1955,8 @@ ORDER BY thousand;
 --------------------------------------------------------------------------------
  Index Only Scan using tenk1_thous_tenthous on tenk1
    Index Cond: ((thousand < 2) AND (tenthous = ANY ('{1001,3000}'::integer[])))
-(2 rows)
+   Index Bound Cond: (thousand < 2)
+(3 rows)
 
 SELECT thousand, tenthous FROM tenk1
 WHERE thousand < 2 AND tenthous IN (1001,3000)
@@ -1967,7 +1976,8 @@ ORDER BY thousand DESC, tenthous DESC;
 --------------------------------------------------------------------------------
  Index Only Scan Backward using tenk1_thous_tenthous on tenk1
    Index Cond: ((thousand < 2) AND (tenthous = ANY ('{1001,3000}'::integer[])))
-(2 rows)
+   Index Bound Cond: (thousand < 2)
+(3 rows)
 
 SELECT thousand, tenthous FROM tenk1
 WHERE thousand < 2 AND tenthous IN (1001,3000)
@@ -1983,11 +1993,12 @@ ORDER BY thousand DESC, tenthous DESC;
 --
 explain (costs off)
 SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 = ANY('{7, 8, 9}');
-                                             QUERY PLAN                                             
-----------------------------------------------------------------------------------------------------
+                                                QUERY PLAN                                                
+----------------------------------------------------------------------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: ((unique1 = ANY ('{1,42,7}'::integer[])) AND (unique1 = ANY ('{7,8,9}'::integer[])))
-(2 rows)
+   Index Bound Cond: ((unique1 = ANY ('{1,42,7}'::integer[])) AND (unique1 = ANY ('{7,8,9}'::integer[])))
+(3 rows)
 
 SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 = ANY('{7, 8, 9}');
  unique1 
@@ -1997,11 +2008,12 @@ SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 = ANY('{7, 8,
 
 explain (costs off)
 SELECT unique1 FROM tenk1 WHERE unique1 = ANY('{7, 14, 22}') and unique1 = ANY('{33, 44}'::bigint[]);
-                                             QUERY PLAN                                             
-----------------------------------------------------------------------------------------------------
+                                                QUERY PLAN                                                
+----------------------------------------------------------------------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: ((unique1 = ANY ('{7,14,22}'::integer[])) AND (unique1 = ANY ('{33,44}'::bigint[])))
-(2 rows)
+   Index Bound Cond: ((unique1 = ANY ('{7,14,22}'::integer[])) AND (unique1 = ANY ('{33,44}'::bigint[])))
+(3 rows)
 
 SELECT unique1 FROM tenk1 WHERE unique1 = ANY('{7, 14, 22}') and unique1 = ANY('{33, 44}'::bigint[]);
  unique1 
@@ -2010,11 +2022,12 @@ SELECT unique1 FROM tenk1 WHERE unique1 = ANY('{7, 14, 22}') and unique1 = ANY('
 
 explain (costs off)
 SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 = 1;
-                                QUERY PLAN                                 
----------------------------------------------------------------------------
+                                   QUERY PLAN                                    
+---------------------------------------------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: ((unique1 = ANY ('{1,42,7}'::integer[])) AND (unique1 = 1))
-(2 rows)
+   Index Bound Cond: ((unique1 = ANY ('{1,42,7}'::integer[])) AND (unique1 = 1))
+(3 rows)
 
 SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 = 1;
  unique1 
@@ -2024,11 +2037,12 @@ SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 = 1;
 
 explain (costs off)
 SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 = 12345;
-                                  QUERY PLAN                                   
--------------------------------------------------------------------------------
+                                     QUERY PLAN                                      
+-------------------------------------------------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: ((unique1 = ANY ('{1,42,7}'::integer[])) AND (unique1 = 12345))
-(2 rows)
+   Index Bound Cond: ((unique1 = ANY ('{1,42,7}'::integer[])) AND (unique1 = 12345))
+(3 rows)
 
 SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 = 12345;
  unique1 
@@ -2037,11 +2051,12 @@ SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 = 12345;
 
 explain (costs off)
 SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 >= 42;
-                                 QUERY PLAN                                  
------------------------------------------------------------------------------
+                                    QUERY PLAN                                     
+-----------------------------------------------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: ((unique1 = ANY ('{1,42,7}'::integer[])) AND (unique1 >= 42))
-(2 rows)
+   Index Bound Cond: ((unique1 = ANY ('{1,42,7}'::integer[])) AND (unique1 >= 42))
+(3 rows)
 
 SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 >= 42;
  unique1 
@@ -2051,11 +2066,12 @@ SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 >= 42;
 
 explain (costs off)
 SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 > 42;
-                                 QUERY PLAN                                 
-----------------------------------------------------------------------------
+                                    QUERY PLAN                                    
+----------------------------------------------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: ((unique1 = ANY ('{1,42,7}'::integer[])) AND (unique1 > 42))
-(2 rows)
+   Index Bound Cond: ((unique1 = ANY ('{1,42,7}'::integer[])) AND (unique1 > 42))
+(3 rows)
 
 SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 > 42;
  unique1 
@@ -2064,11 +2080,12 @@ SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 > 42;
 
 explain (costs off)
 SELECT unique1 FROM tenk1 WHERE unique1 > 9996 and unique1 >= 9999;
-                       QUERY PLAN                       
---------------------------------------------------------
+                          QUERY PLAN                          
+--------------------------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: ((unique1 > 9996) AND (unique1 >= 9999))
-(2 rows)
+   Index Bound Cond: ((unique1 > 9996) AND (unique1 >= 9999))
+(3 rows)
 
 SELECT unique1 FROM tenk1 WHERE unique1 > 9996 and unique1 >= 9999;
  unique1 
@@ -2078,11 +2095,12 @@ SELECT unique1 FROM tenk1 WHERE unique1 > 9996 and unique1 >= 9999;
 
 explain (costs off)
 SELECT unique1 FROM tenk1 WHERE unique1 < 3 and unique1 <= 3;
-                    QUERY PLAN                    
---------------------------------------------------
+                       QUERY PLAN                       
+--------------------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: ((unique1 < 3) AND (unique1 <= 3))
-(2 rows)
+   Index Bound Cond: ((unique1 < 3) AND (unique1 <= 3))
+(3 rows)
 
 SELECT unique1 FROM tenk1 WHERE unique1 < 3 and unique1 <= 3;
  unique1 
@@ -2094,11 +2112,12 @@ SELECT unique1 FROM tenk1 WHERE unique1 < 3 and unique1 <= 3;
 
 explain (costs off)
 SELECT unique1 FROM tenk1 WHERE unique1 < 3 and unique1 < (-1)::bigint;
-                         QUERY PLAN                         
-------------------------------------------------------------
+                            QUERY PLAN                            
+------------------------------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: ((unique1 < 3) AND (unique1 < '-1'::bigint))
-(2 rows)
+   Index Bound Cond: ((unique1 < 3) AND (unique1 < '-1'::bigint))
+(3 rows)
 
 SELECT unique1 FROM tenk1 WHERE unique1 < 3 and unique1 < (-1)::bigint;
  unique1 
@@ -2107,11 +2126,12 @@ SELECT unique1 FROM tenk1 WHERE unique1 < 3 and unique1 < (-1)::bigint;
 
 explain (costs off)
 SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 < (-1)::bigint;
-                                      QUERY PLAN                                      
---------------------------------------------------------------------------------------
+                                         QUERY PLAN                                         
+--------------------------------------------------------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: ((unique1 = ANY ('{1,42,7}'::integer[])) AND (unique1 < '-1'::bigint))
-(2 rows)
+   Index Bound Cond: ((unique1 = ANY ('{1,42,7}'::integer[])) AND (unique1 < '-1'::bigint))
+(3 rows)
 
 SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 < (-1)::bigint;
  unique1 
@@ -2123,11 +2143,12 @@ SELECT unique1 FROM tenk1 WHERE unique1 IN (1, 42, 7) and unique1 < (-1)::bigint
 --
 explain (costs off)
   select * from tenk1 where (thousand, tenthous) in ((1,1001), (null,null));
-                      QUERY PLAN                      
-------------------------------------------------------
+                         QUERY PLAN                         
+------------------------------------------------------------
  Index Scan using tenk1_thous_tenthous on tenk1
    Index Cond: ((thousand = 1) AND (tenthous = 1001))
-(2 rows)
+   Index Bound Cond: ((thousand = 1) AND (tenthous = 1001))
+(3 rows)
 
 --
 -- Check matching of boolean index columns to WHERE conditions and sort keys
@@ -2148,7 +2169,8 @@ explain (costs off)
  Limit
    ->  Index Scan using boolindex_b_i_key on boolindex
          Index Cond: (b = true)
-(3 rows)
+         Index Bound Cond: (b = true)
+(4 rows)
 
 explain (costs off)
   select * from boolindex where b = true order by i desc limit 10;
@@ -2157,7 +2179,8 @@ explain (costs off)
  Limit
    ->  Index Scan Backward using boolindex_b_i_key on boolindex
          Index Cond: (b = true)
-(3 rows)
+         Index Bound Cond: (b = true)
+(4 rows)
 
 explain (costs off)
   select * from boolindex where not b order by i limit 10;
@@ -2166,7 +2189,8 @@ explain (costs off)
  Limit
    ->  Index Scan using boolindex_b_i_key on boolindex
          Index Cond: (b = false)
-(3 rows)
+         Index Bound Cond: (b = false)
+(4 rows)
 
 explain (costs off)
   select * from boolindex where b is true order by i desc limit 10;
@@ -2175,7 +2199,8 @@ explain (costs off)
  Limit
    ->  Index Scan Backward using boolindex_b_i_key on boolindex
          Index Cond: (b = true)
-(3 rows)
+         Index Bound Cond: (b = true)
+(4 rows)
 
 explain (costs off)
   select * from boolindex where b is false order by i desc limit 10;
@@ -2184,7 +2209,8 @@ explain (costs off)
  Limit
    ->  Index Scan Backward using boolindex_b_i_key on boolindex
          Index Cond: (b = false)
-(3 rows)
+         Index Bound Cond: (b = false)
+(4 rows)
 
 --
 -- REINDEX (VERBOSE)
diff --git a/src/test/regress/expected/equivclass.out b/src/test/regress/expected/equivclass.out
index 126f7047fe..1deab4fe08 100644
--- a/src/test/regress/expected/equivclass.out
+++ b/src/test/regress/expected/equivclass.out
@@ -104,30 +104,33 @@ set enable_mergejoin = off;
 --
 explain (costs off)
   select * from ec0 where ff = f1 and f1 = '42'::int8;
-            QUERY PLAN             
------------------------------------
+               QUERY PLAN                
+-----------------------------------------
  Index Scan using ec0_pkey on ec0
    Index Cond: (ff = '42'::bigint)
+   Index Bound Cond: (ff = '42'::bigint)
    Filter: (f1 = '42'::bigint)
-(3 rows)
+(4 rows)
 
 explain (costs off)
   select * from ec0 where ff = f1 and f1 = '42'::int8alias1;
-              QUERY PLAN               
----------------------------------------
+                 QUERY PLAN                  
+---------------------------------------------
  Index Scan using ec0_pkey on ec0
    Index Cond: (ff = '42'::int8alias1)
+   Index Bound Cond: (ff = '42'::int8alias1)
    Filter: (f1 = '42'::int8alias1)
-(3 rows)
+(4 rows)
 
 explain (costs off)
   select * from ec1 where ff = f1 and f1 = '42'::int8alias1;
-              QUERY PLAN               
----------------------------------------
+                 QUERY PLAN                  
+---------------------------------------------
  Index Scan using ec1_pkey on ec1
    Index Cond: (ff = '42'::int8alias1)
+   Index Bound Cond: (ff = '42'::int8alias1)
    Filter: (f1 = '42'::int8alias1)
-(3 rows)
+(4 rows)
 
 explain (costs off)
   select * from ec1 where ff = f1 and f1 = '42'::int8alias2;
@@ -139,48 +142,52 @@ explain (costs off)
 
 explain (costs off)
   select * from ec1, ec2 where ff = x1 and ff = '42'::int8;
-                            QUERY PLAN                             
--------------------------------------------------------------------
+                               QUERY PLAN                                
+-------------------------------------------------------------------------
  Nested Loop
    Join Filter: (ec1.ff = ec2.x1)
    ->  Index Scan using ec1_pkey on ec1
          Index Cond: ((ff = '42'::bigint) AND (ff = '42'::bigint))
+         Index Bound Cond: ((ff = '42'::bigint) AND (ff = '42'::bigint))
    ->  Seq Scan on ec2
-(5 rows)
+(6 rows)
 
 explain (costs off)
   select * from ec1, ec2 where ff = x1 and ff = '42'::int8alias1;
-                 QUERY PLAN                  
----------------------------------------------
+                    QUERY PLAN                     
+---------------------------------------------------
  Nested Loop
    ->  Index Scan using ec1_pkey on ec1
          Index Cond: (ff = '42'::int8alias1)
+         Index Bound Cond: (ff = '42'::int8alias1)
    ->  Seq Scan on ec2
          Filter: (x1 = '42'::int8alias1)
-(5 rows)
+(6 rows)
 
 explain (costs off)
   select * from ec1, ec2 where ff = x1 and '42'::int8 = x1;
-               QUERY PLAN                
------------------------------------------
+                  QUERY PLAN                   
+-----------------------------------------------
  Nested Loop
    Join Filter: (ec1.ff = ec2.x1)
    ->  Index Scan using ec1_pkey on ec1
          Index Cond: (ff = '42'::bigint)
+         Index Bound Cond: (ff = '42'::bigint)
    ->  Seq Scan on ec2
          Filter: ('42'::bigint = x1)
-(6 rows)
+(7 rows)
 
 explain (costs off)
   select * from ec1, ec2 where ff = x1 and x1 = '42'::int8alias1;
-                 QUERY PLAN                  
----------------------------------------------
+                    QUERY PLAN                     
+---------------------------------------------------
  Nested Loop
    ->  Index Scan using ec1_pkey on ec1
          Index Cond: (ff = '42'::int8alias1)
+         Index Bound Cond: (ff = '42'::int8alias1)
    ->  Seq Scan on ec2
          Filter: (x1 = '42'::int8alias1)
-(5 rows)
+(6 rows)
 
 explain (costs off)
   select * from ec1, ec2 where ff = x1 and x1 = '42'::int8alias2;
@@ -191,7 +198,8 @@ explain (costs off)
          Filter: (x1 = '42'::int8alias2)
    ->  Index Scan using ec1_pkey on ec1
          Index Cond: (ff = ec2.x1)
-(5 rows)
+         Index Bound Cond: (ff = ec2.x1)
+(6 rows)
 
 create unique index ec1_expr1 on ec1((ff + 1));
 create unique index ec1_expr2 on ec1((ff + 2 + 1));
@@ -206,19 +214,23 @@ explain (costs off)
      union all
      select ff + 4 as x from ec1) as ss1
   where ss1.x = ec1.f1 and ec1.ff = 42::int8;
-                     QUERY PLAN                      
------------------------------------------------------
+                        QUERY PLAN                         
+-----------------------------------------------------------
  Nested Loop
    ->  Index Scan using ec1_pkey on ec1
          Index Cond: (ff = '42'::bigint)
+         Index Bound Cond: (ff = '42'::bigint)
    ->  Append
          ->  Index Scan using ec1_expr2 on ec1 ec1_1
                Index Cond: (((ff + 2) + 1) = ec1.f1)
+               Index Bound Cond: (((ff + 2) + 1) = ec1.f1)
          ->  Index Scan using ec1_expr3 on ec1 ec1_2
                Index Cond: (((ff + 3) + 1) = ec1.f1)
+               Index Bound Cond: (((ff + 3) + 1) = ec1.f1)
          ->  Index Scan using ec1_expr4 on ec1 ec1_3
                Index Cond: ((ff + 4) = ec1.f1)
-(10 rows)
+               Index Bound Cond: ((ff + 4) = ec1.f1)
+(14 rows)
 
 explain (costs off)
   select * from ec1,
@@ -229,21 +241,25 @@ explain (costs off)
      union all
      select ff + 4 as x from ec1) as ss1
   where ss1.x = ec1.f1 and ec1.ff = 42::int8 and ec1.ff = ec1.f1;
-                            QUERY PLAN                             
--------------------------------------------------------------------
+                               QUERY PLAN                                
+-------------------------------------------------------------------------
  Nested Loop
    Join Filter: ((((ec1_1.ff + 2) + 1)) = ec1.f1)
    ->  Index Scan using ec1_pkey on ec1
          Index Cond: ((ff = '42'::bigint) AND (ff = '42'::bigint))
+         Index Bound Cond: ((ff = '42'::bigint) AND (ff = '42'::bigint))
          Filter: (ff = f1)
    ->  Append
          ->  Index Scan using ec1_expr2 on ec1 ec1_1
                Index Cond: (((ff + 2) + 1) = '42'::bigint)
+               Index Bound Cond: (((ff + 2) + 1) = '42'::bigint)
          ->  Index Scan using ec1_expr3 on ec1 ec1_2
                Index Cond: (((ff + 3) + 1) = '42'::bigint)
+               Index Bound Cond: (((ff + 3) + 1) = '42'::bigint)
          ->  Index Scan using ec1_expr4 on ec1 ec1_3
                Index Cond: ((ff + 4) = '42'::bigint)
-(12 rows)
+               Index Bound Cond: ((ff + 4) = '42'::bigint)
+(16 rows)
 
 explain (costs off)
   select * from ec1,
@@ -260,27 +276,34 @@ explain (costs off)
      union all
      select ff + 4 as x from ec1) as ss2
   where ss1.x = ec1.f1 and ss1.x = ss2.x and ec1.ff = 42::int8;
-                             QUERY PLAN                              
----------------------------------------------------------------------
+                                QUERY PLAN                                 
+---------------------------------------------------------------------------
  Nested Loop
    ->  Nested Loop
          ->  Index Scan using ec1_pkey on ec1
                Index Cond: (ff = '42'::bigint)
+               Index Bound Cond: (ff = '42'::bigint)
          ->  Append
                ->  Index Scan using ec1_expr2 on ec1 ec1_1
                      Index Cond: (((ff + 2) + 1) = ec1.f1)
+                     Index Bound Cond: (((ff + 2) + 1) = ec1.f1)
                ->  Index Scan using ec1_expr3 on ec1 ec1_2
                      Index Cond: (((ff + 3) + 1) = ec1.f1)
+                     Index Bound Cond: (((ff + 3) + 1) = ec1.f1)
                ->  Index Scan using ec1_expr4 on ec1 ec1_3
                      Index Cond: ((ff + 4) = ec1.f1)
+                     Index Bound Cond: ((ff + 4) = ec1.f1)
    ->  Append
          ->  Index Scan using ec1_expr2 on ec1 ec1_4
                Index Cond: (((ff + 2) + 1) = (((ec1_1.ff + 2) + 1)))
+               Index Bound Cond: (((ff + 2) + 1) = (((ec1_1.ff + 2) + 1)))
          ->  Index Scan using ec1_expr3 on ec1 ec1_5
                Index Cond: (((ff + 3) + 1) = (((ec1_1.ff + 2) + 1)))
+               Index Bound Cond: (((ff + 3) + 1) = (((ec1_1.ff + 2) + 1)))
          ->  Index Scan using ec1_expr4 on ec1 ec1_6
                Index Cond: ((ff + 4) = (((ec1_1.ff + 2) + 1)))
-(18 rows)
+               Index Bound Cond: ((ff + 4) = (((ec1_1.ff + 2) + 1)))
+(25 rows)
 
 -- let's try that as a mergejoin
 set enable_mergejoin = on;
@@ -321,7 +344,8 @@ explain (costs off)
                      Sort Key: ec1.f1 USING <
                      ->  Index Scan using ec1_pkey on ec1
                            Index Cond: (ff = '42'::bigint)
-(19 rows)
+                           Index Bound Cond: (ff = '42'::bigint)
+(20 rows)
 
 -- check partially indexed scan
 set enable_nestloop = on;
@@ -336,19 +360,22 @@ explain (costs off)
      union all
      select ff + 4 as x from ec1) as ss1
   where ss1.x = ec1.f1 and ec1.ff = 42::int8;
-                     QUERY PLAN                      
------------------------------------------------------
+                        QUERY PLAN                         
+-----------------------------------------------------------
  Nested Loop
    ->  Index Scan using ec1_pkey on ec1
          Index Cond: (ff = '42'::bigint)
+         Index Bound Cond: (ff = '42'::bigint)
    ->  Append
          ->  Index Scan using ec1_expr2 on ec1 ec1_1
                Index Cond: (((ff + 2) + 1) = ec1.f1)
+               Index Bound Cond: (((ff + 2) + 1) = ec1.f1)
          ->  Seq Scan on ec1 ec1_2
                Filter: (((ff + 3) + 1) = ec1.f1)
          ->  Index Scan using ec1_expr4 on ec1 ec1_3
                Index Cond: ((ff + 4) = ec1.f1)
-(10 rows)
+               Index Bound Cond: ((ff + 4) = ec1.f1)
+(13 rows)
 
 -- let's try that as a mergejoin
 set enable_mergejoin = on;
@@ -377,7 +404,8 @@ explain (costs off)
          Sort Key: ec1.f1 USING <
          ->  Index Scan using ec1_pkey on ec1
                Index Cond: (ff = '42'::bigint)
-(13 rows)
+               Index Bound Cond: (ff = '42'::bigint)
+(14 rows)
 
 -- check effects of row-level security
 set enable_nestloop = on;
@@ -391,14 +419,16 @@ grant select on ec1 to regress_user_ectest;
 explain (costs off)
   select * from ec0 a, ec1 b
   where a.ff = b.ff and a.ff = 43::bigint::int8alias1;
-                 QUERY PLAN                  
----------------------------------------------
+                    QUERY PLAN                     
+---------------------------------------------------
  Nested Loop
    ->  Index Scan using ec0_pkey on ec0 a
          Index Cond: (ff = '43'::int8alias1)
+         Index Bound Cond: (ff = '43'::int8alias1)
    ->  Index Scan using ec1_pkey on ec1 b
          Index Cond: (ff = '43'::int8alias1)
-(5 rows)
+         Index Bound Cond: (ff = '43'::int8alias1)
+(7 rows)
 
 set session authorization regress_user_ectest;
 -- with RLS active, the non-leakproof a.ff = 43 clause is not treated
@@ -407,15 +437,17 @@ set session authorization regress_user_ectest;
 explain (costs off)
   select * from ec0 a, ec1 b
   where a.ff = b.ff and a.ff = 43::bigint::int8alias1;
-                 QUERY PLAN                  
----------------------------------------------
+                    QUERY PLAN                     
+---------------------------------------------------
  Nested Loop
    ->  Index Scan using ec0_pkey on ec0 a
          Index Cond: (ff = '43'::int8alias1)
+         Index Bound Cond: (ff = '43'::int8alias1)
    ->  Index Scan using ec1_pkey on ec1 b
          Index Cond: (ff = a.ff)
+         Index Bound Cond: (ff = a.ff)
          Filter: (f1 < '5'::int8alias1)
-(6 rows)
+(8 rows)
 
 reset session authorization;
 revoke select on ec0 from regress_user_ectest;
diff --git a/src/test/regress/expected/explain.out b/src/test/regress/expected/explain.out
index 6585c6a69e..e0c91f27f2 100644
--- a/src/test/regress/expected/explain.out
+++ b/src/test/regress/expected/explain.out
@@ -334,7 +334,8 @@ select explain_filter('explain (generic_plan) select unique1 from tenk1 where th
    Recheck Cond: (thousand = $N)
    ->  Bitmap Index Scan on tenk1_thous_tenthous  (cost=N.N..N.N rows=N width=N)
          Index Cond: (thousand = $N)
-(4 rows)
+         Index Bound Cond: (thousand = $N)
+(5 rows)
 
 -- should fail
 select explain_filter('explain (analyze, generic_plan) select unique1 from tenk1 where thousand = $1');
diff --git a/src/test/regress/expected/expressions.out b/src/test/regress/expected/expressions.out
index caeeb19674..d5ff3a2b31 100644
--- a/src/test/regress/expected/expressions.out
+++ b/src/test/regress/expected/expressions.out
@@ -186,7 +186,8 @@ explain (verbose, costs off) select * from bpchar_view
  Index Scan using bpchar_tbl_f1_key on public.bpchar_tbl
    Output: bpchar_tbl.f1, (bpchar_tbl.f1)::character(14), (bpchar_tbl.f1)::bpchar, bpchar_tbl.f2, (bpchar_tbl.f2)::character(14), bpchar_tbl.f2
    Index Cond: ((bpchar_tbl.f1)::bpchar = 'foo'::bpchar)
-(3 rows)
+   Index Bound Cond: ((bpchar_tbl.f1)::bpchar = 'foo'::bpchar)
+(4 rows)
 
 rollback;
 --
diff --git a/src/test/regress/expected/fast_default.out b/src/test/regress/expected/fast_default.out
index 59365dad96..19e1af3226 100644
--- a/src/test/regress/expected/fast_default.out
+++ b/src/test/regress/expected/fast_default.out
@@ -441,8 +441,8 @@ DELETE FROM T WHERE pk BETWEEN 10 AND 20 RETURNING *;
 
 EXPLAIN (VERBOSE TRUE, COSTS FALSE)
 DELETE FROM T WHERE pk BETWEEN 10 AND 20 RETURNING *;
-                        QUERY PLAN                         
------------------------------------------------------------
+                           QUERY PLAN                            
+-----------------------------------------------------------------
  Delete on fast_default.t
    Output: pk, c_bigint, c_text
    ->  Bitmap Heap Scan on fast_default.t
@@ -450,7 +450,8 @@ DELETE FROM T WHERE pk BETWEEN 10 AND 20 RETURNING *;
          Recheck Cond: ((t.pk >= 10) AND (t.pk <= 20))
          ->  Bitmap Index Scan on t_pkey
                Index Cond: ((t.pk >= 10) AND (t.pk <= 20))
-(7 rows)
+               Index Bound Cond: ((t.pk >= 10) AND (t.pk <= 20))
+(8 rows)
 
 -- UPDATE
 UPDATE T SET c_text = '"' || c_text || '"'  WHERE pk < 10;
diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out
index 46764bd9e3..a1d8c74612 100644
--- a/src/test/regress/expected/foreign_key.out
+++ b/src/test/regress/expected/foreign_key.out
@@ -1458,13 +1458,15 @@ explain (costs off) delete from t1 where a = 1;
    ->  Nested Loop
          ->  Index Scan using t1_pkey on t1
                Index Cond: (a = 1)
+               Index Bound Cond: (a = 1)
          ->  Seq Scan on t2
                Filter: (b = 1)
  
  Delete on t1
    ->  Index Scan using t1_pkey on t1
          Index Cond: (a = 1)
-(10 rows)
+         Index Bound Cond: (a = 1)
+(12 rows)
 
 delete from t1 where a = 1;
 -- Test a primary key with attributes located in later attnum positions
diff --git a/src/test/regress/expected/generated.out b/src/test/regress/expected/generated.out
index 44058db7c1..ea3452c946 100644
--- a/src/test/regress/expected/generated.out
+++ b/src/test/regress/expected/generated.out
@@ -640,7 +640,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b = 4;
 ---------------------------------------------
  Index Scan using gtest22c_b_idx on gtest22c
    Index Cond: (b = 4)
-(2 rows)
+   Index Bound Cond: (b = 4)
+(3 rows)
 
 SELECT * FROM gtest22c WHERE b = 4;
  a | b 
@@ -653,7 +654,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b * 3 = 6;
 ------------------------------------------------
  Index Scan using gtest22c_expr_idx on gtest22c
    Index Cond: ((b * 3) = 6)
-(2 rows)
+   Index Bound Cond: ((b * 3) = 6)
+(3 rows)
 
 SELECT * FROM gtest22c WHERE b * 3 = 6;
  a | b 
@@ -666,7 +668,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE a = 1 AND b > 0;
 ------------------------------------------------
  Index Scan using gtest22c_pred_idx on gtest22c
    Index Cond: (a = 1)
-(2 rows)
+   Index Bound Cond: (a = 1)
+(3 rows)
 
 SELECT * FROM gtest22c WHERE a = 1 AND b > 0;
  a | b 
@@ -681,7 +684,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b = 8;
 ---------------------------------------------
  Index Scan using gtest22c_b_idx on gtest22c
    Index Cond: (b = 8)
-(2 rows)
+   Index Bound Cond: (b = 8)
+(3 rows)
 
 SELECT * FROM gtest22c WHERE b = 8;
  a | b 
@@ -694,7 +698,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b * 3 = 12;
 ------------------------------------------------
  Index Scan using gtest22c_expr_idx on gtest22c
    Index Cond: ((b * 3) = 12)
-(2 rows)
+   Index Bound Cond: ((b * 3) = 12)
+(3 rows)
 
 SELECT * FROM gtest22c WHERE b * 3 = 12;
  a | b 
@@ -707,7 +712,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE a = 1 AND b > 0;
 ------------------------------------------------
  Index Scan using gtest22c_pred_idx on gtest22c
    Index Cond: (a = 1)
-(2 rows)
+   Index Bound Cond: (a = 1)
+(3 rows)
 
 SELECT * FROM gtest22c WHERE a = 1 AND b > 0;
  a | b 
diff --git a/src/test/regress/expected/groupingsets.out b/src/test/regress/expected/groupingsets.out
index e1f0660810..b265502135 100644
--- a/src/test/regress/expected/groupingsets.out
+++ b/src/test/regress/expected/groupingsets.out
@@ -563,7 +563,8 @@ explain (costs off)
      ->  Limit
            ->  Index Only Scan using tenk1_unique1 on tenk1
                  Index Cond: (unique1 IS NOT NULL)
-(5 rows)
+                 Index Bound Cond: (unique1 IS NOT NULL)
+(6 rows)
 
 -- Views with GROUPING SET queries
 CREATE VIEW gstest_view AS select a, b, grouping(a,b), sum(c), count(*), max(c)
diff --git a/src/test/regress/expected/incremental_sort.out b/src/test/regress/expected/incremental_sort.out
index 5fd54a10b1..2b2a9278fa 100644
--- a/src/test/regress/expected/incremental_sort.out
+++ b/src/test/regress/expected/incremental_sort.out
@@ -1615,7 +1615,8 @@ from tenk1 t, generate_series(1, 1000);
                SubPlan 1
                  ->  Index Only Scan using tenk1_unique1 on tenk1
                        Index Cond: (unique1 = t.unique1)
-(11 rows)
+                       Index Bound Cond: (unique1 = t.unique1)
+(12 rows)
 
 explain (costs off) select
   unique1,
@@ -1634,7 +1635,8 @@ order by 1, 2;
          SubPlan 1
            ->  Index Only Scan using tenk1_unique1 on tenk1
                  Index Cond: (unique1 = t.unique1)
-(10 rows)
+                 Index Bound Cond: (unique1 = t.unique1)
+(11 rows)
 
 -- Parallel sort but with expression not available until the upper rel.
 explain (costs off) select distinct sub.unique1, stringu1 || random()::text
diff --git a/src/test/regress/expected/index_including.out b/src/test/regress/expected/index_including.out
index ea8b2454bf..04a4333da8 100644
--- a/src/test/regress/expected/index_including.out
+++ b/src/test/regress/expected/index_including.out
@@ -129,13 +129,14 @@ DETAIL:  Failing row contains (1, null, 3, (4,4),(4,4)).
 INSERT INTO tbl SELECT x, 2*x, NULL, NULL FROM generate_series(1,300) AS x;
 explain (costs off)
 select * from tbl where (c1,c2,c3) < (2,5,1);
-                   QUERY PLAN                   
-------------------------------------------------
+                      QUERY PLAN                      
+------------------------------------------------------
  Bitmap Heap Scan on tbl
    Filter: (ROW(c1, c2, c3) < ROW(2, 5, 1))
    ->  Bitmap Index Scan on covering
          Index Cond: (ROW(c1, c2) <= ROW(2, 5))
-(4 rows)
+         Index Bound Cond: (ROW(c1, c2) <= ROW(2, 5))
+(5 rows)
 
 select * from tbl where (c1,c2,c3) < (2,5,1);
  c1 | c2 | c3 | c4 
@@ -148,13 +149,14 @@ select * from tbl where (c1,c2,c3) < (2,5,1);
 SET enable_seqscan = off;
 explain (costs off)
 select * from tbl where (c1,c2,c3) < (262,1,1) limit 1;
-                     QUERY PLAN                     
-----------------------------------------------------
+                       QUERY PLAN                       
+--------------------------------------------------------
  Limit
    ->  Index Only Scan using covering on tbl
          Index Cond: (ROW(c1, c2) <= ROW(262, 1))
+         Index Bound Cond: (ROW(c1, c2) <= ROW(262, 1))
          Filter: (ROW(c1, c2, c3) < ROW(262, 1, 1))
-(4 rows)
+(5 rows)
 
 select * from tbl where (c1,c2,c3) < (262,1,1) limit 1;
  c1 | c2 | c3 | c4 
@@ -408,11 +410,12 @@ VACUUM nametbl;
 SET enable_seqscan = 0;
 -- Ensure we get an index only scan plan
 EXPLAIN (COSTS OFF) SELECT c2, c1, c3 FROM nametbl WHERE c2 = 'two' AND c1 = 1;
-                     QUERY PLAN                     
-----------------------------------------------------
+                      QUERY PLAN                       
+-------------------------------------------------------
  Index Only Scan using nametbl_c1_c2_idx on nametbl
    Index Cond: ((c2 = 'two'::name) AND (c1 = 1))
-(2 rows)
+   Index Bound Cond: ((c2 = 'two'::name) AND (c1 = 1))
+(3 rows)
 
 -- Validate the results look sane
 SELECT c2, c1, c3 FROM nametbl WHERE c2 = 'two' AND c1 = 1;
diff --git a/src/test/regress/expected/inet.out b/src/test/regress/expected/inet.out
index b6895d9ced..e45a1aeb3d 100644
--- a/src/test/regress/expected/inet.out
+++ b/src/test/regress/expected/inet.out
@@ -266,12 +266,13 @@ CREATE INDEX inet_idx1 ON inet_tbl(i);
 SET enable_seqscan TO off;
 EXPLAIN (COSTS OFF)
 SELECT * FROM inet_tbl WHERE i<<'192.168.1.0/24'::cidr;
-                                  QUERY PLAN                                   
--------------------------------------------------------------------------------
+                                     QUERY PLAN                                      
+-------------------------------------------------------------------------------------
  Index Scan using inet_idx1 on inet_tbl
    Index Cond: ((i > '192.168.1.0/24'::inet) AND (i <= '192.168.1.255'::inet))
+   Index Bound Cond: ((i > '192.168.1.0/24'::inet) AND (i <= '192.168.1.255'::inet))
    Filter: (i << '192.168.1.0/24'::inet)
-(3 rows)
+(4 rows)
 
 SELECT * FROM inet_tbl WHERE i<<'192.168.1.0/24'::cidr;
        c        |        i         
@@ -283,12 +284,13 @@ SELECT * FROM inet_tbl WHERE i<<'192.168.1.0/24'::cidr;
 
 EXPLAIN (COSTS OFF)
 SELECT * FROM inet_tbl WHERE i<<='192.168.1.0/24'::cidr;
-                                   QUERY PLAN                                   
---------------------------------------------------------------------------------
+                                      QUERY PLAN                                      
+--------------------------------------------------------------------------------------
  Index Scan using inet_idx1 on inet_tbl
    Index Cond: ((i >= '192.168.1.0/24'::inet) AND (i <= '192.168.1.255'::inet))
+   Index Bound Cond: ((i >= '192.168.1.0/24'::inet) AND (i <= '192.168.1.255'::inet))
    Filter: (i <<= '192.168.1.0/24'::inet)
-(3 rows)
+(4 rows)
 
 SELECT * FROM inet_tbl WHERE i<<='192.168.1.0/24'::cidr;
        c        |        i         
@@ -303,12 +305,13 @@ SELECT * FROM inet_tbl WHERE i<<='192.168.1.0/24'::cidr;
 
 EXPLAIN (COSTS OFF)
 SELECT * FROM inet_tbl WHERE '192.168.1.0/24'::cidr >>= i;
-                                   QUERY PLAN                                   
---------------------------------------------------------------------------------
+                                      QUERY PLAN                                      
+--------------------------------------------------------------------------------------
  Index Scan using inet_idx1 on inet_tbl
    Index Cond: ((i >= '192.168.1.0/24'::inet) AND (i <= '192.168.1.255'::inet))
+   Index Bound Cond: ((i >= '192.168.1.0/24'::inet) AND (i <= '192.168.1.255'::inet))
    Filter: ('192.168.1.0/24'::inet >>= i)
-(3 rows)
+(4 rows)
 
 SELECT * FROM inet_tbl WHERE '192.168.1.0/24'::cidr >>= i;
        c        |        i         
@@ -323,12 +326,13 @@ SELECT * FROM inet_tbl WHERE '192.168.1.0/24'::cidr >>= i;
 
 EXPLAIN (COSTS OFF)
 SELECT * FROM inet_tbl WHERE '192.168.1.0/24'::cidr >> i;
-                                  QUERY PLAN                                   
--------------------------------------------------------------------------------
+                                     QUERY PLAN                                      
+-------------------------------------------------------------------------------------
  Index Scan using inet_idx1 on inet_tbl
    Index Cond: ((i > '192.168.1.0/24'::inet) AND (i <= '192.168.1.255'::inet))
+   Index Bound Cond: ((i > '192.168.1.0/24'::inet) AND (i <= '192.168.1.255'::inet))
    Filter: ('192.168.1.0/24'::inet >> i)
-(3 rows)
+(4 rows)
 
 SELECT * FROM inet_tbl WHERE '192.168.1.0/24'::cidr >> i;
        c        |        i         
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index ad73213414..6e7f9f1d2c 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -559,7 +559,8 @@ update some_tab set f3 = 11 where f1 = 12 and f2 = 13;
    ->  Result
          ->  Index Scan using some_tab_child_f1_f2_idx on some_tab_child some_tab_1
                Index Cond: ((f1 = 12) AND (f2 = 13))
-(5 rows)
+               Index Bound Cond: ((f1 = 12) AND (f2 = 13))
+(6 rows)
 
 update some_tab set f3 = 11 where f1 = 12 and f2 = 13;
 NOTICE:  updating some_tab
@@ -1491,11 +1492,14 @@ select * from patest0 join (select f1 from int4_tbl limit 1) ss on id = f1;
    ->  Append
          ->  Index Scan using patest0i on patest0 patest0_1
                Index Cond: (id = int4_tbl.f1)
+               Index Bound Cond: (id = int4_tbl.f1)
          ->  Index Scan using patest1i on patest1 patest0_2
                Index Cond: (id = int4_tbl.f1)
+               Index Bound Cond: (id = int4_tbl.f1)
          ->  Index Scan using patest2i on patest2 patest0_3
                Index Cond: (id = int4_tbl.f1)
-(10 rows)
+               Index Bound Cond: (id = int4_tbl.f1)
+(13 rows)
 
 select * from patest0 join (select f1 from int4_tbl limit 1) ss on id = f1;
  id | x | f1 
@@ -1516,11 +1520,13 @@ select * from patest0 join (select f1 from int4_tbl limit 1) ss on id = f1;
    ->  Append
          ->  Index Scan using patest0i on patest0 patest0_1
                Index Cond: (id = int4_tbl.f1)
+               Index Bound Cond: (id = int4_tbl.f1)
          ->  Index Scan using patest1i on patest1 patest0_2
                Index Cond: (id = int4_tbl.f1)
+               Index Bound Cond: (id = int4_tbl.f1)
          ->  Seq Scan on patest2 patest0_3
                Filter: (int4_tbl.f1 = id)
-(10 rows)
+(12 rows)
 
 select * from patest0 join (select f1 from int4_tbl limit 1) ss on id = f1;
  id | x | f1 
@@ -1654,9 +1660,11 @@ explain (verbose, costs off) select min(1-id) from matest0;
                        ->  Index Scan using matest0i on public.matest0 matest0_1
                              Output: matest0_1.id, (1 - matest0_1.id)
                              Index Cond: ((1 - matest0_1.id) IS NOT NULL)
+                             Index Bound Cond: ((1 - matest0_1.id) IS NOT NULL)
                        ->  Index Scan using matest1i on public.matest1 matest0_2
                              Output: matest0_2.id, (1 - matest0_2.id)
                              Index Cond: ((1 - matest0_2.id) IS NOT NULL)
+                             Index Bound Cond: ((1 - matest0_2.id) IS NOT NULL)
                        ->  Sort
                              Output: matest0_3.id, ((1 - matest0_3.id))
                              Sort Key: ((1 - matest0_3.id))
@@ -1667,7 +1675,8 @@ explain (verbose, costs off) select min(1-id) from matest0;
                        ->  Index Scan using matest3i on public.matest3 matest0_4
                              Output: matest0_4.id, (1 - matest0_4.id)
                              Index Cond: ((1 - matest0_4.id) IS NOT NULL)
-(25 rows)
+                             Index Bound Cond: ((1 - matest0_4.id) IS NOT NULL)
+(28 rows)
 
 select min(1-id) from matest0;
  min 
@@ -1731,11 +1740,12 @@ select * from matest0 where a < 100 order by a;
    Sort Key: matest0.a
    ->  Index Only Scan using matest0_pkey on matest0 matest0_1
          Index Cond: (a < 100)
+         Index Bound Cond: (a < 100)
    ->  Sort
          Sort Key: matest0_2.a
          ->  Seq Scan on matest1 matest0_2
                Filter: (a < 100)
-(8 rows)
+(9 rows)
 
 drop table matest0 cascade;
 NOTICE:  drop cascades to table matest1
@@ -1806,9 +1816,11 @@ SELECT min(x) FROM
                  Sort Key: a.unique1
                  ->  Index Only Scan using tenk1_unique1 on tenk1 a
                        Index Cond: (unique1 IS NOT NULL)
+                       Index Bound Cond: (unique1 IS NOT NULL)
                  ->  Index Only Scan using tenk1_unique2 on tenk1 b
                        Index Cond: (unique2 IS NOT NULL)
-(9 rows)
+                       Index Bound Cond: (unique2 IS NOT NULL)
+(11 rows)
 
 explain (costs off)
 SELECT min(y) FROM
@@ -1824,9 +1836,11 @@ SELECT min(y) FROM
                  Sort Key: a.unique1
                  ->  Index Only Scan using tenk1_unique1 on tenk1 a
                        Index Cond: (unique1 IS NOT NULL)
+                       Index Bound Cond: (unique1 IS NOT NULL)
                  ->  Index Only Scan using tenk1_unique2 on tenk1 b
                        Index Cond: (unique2 IS NOT NULL)
-(9 rows)
+                       Index Bound Cond: (unique2 IS NOT NULL)
+(11 rows)
 
 -- XXX planner doesn't recognize that index on unique2 is sufficiently sorted
 explain (costs off)
@@ -2375,11 +2389,13 @@ explain (costs off) select min(a), max(a) from parted_minmax where b = '12345';
      ->  Limit
            ->  Index Only Scan using parted_minmax1i on parted_minmax1 parted_minmax
                  Index Cond: ((a IS NOT NULL) AND (b = '12345'::text))
+                 Index Bound Cond: (a IS NOT NULL)
    InitPlan 2
      ->  Limit
            ->  Index Only Scan Backward using parted_minmax1i on parted_minmax1 parted_minmax_1
                  Index Cond: ((a IS NOT NULL) AND (b = '12345'::text))
-(9 rows)
+                 Index Bound Cond: (a IS NOT NULL)
+(11 rows)
 
 select min(a), max(a) from parted_minmax where b = '12345';
  min | max 
@@ -2479,13 +2495,17 @@ explain (costs off) select * from mcrparted where a < 20 order by a, abs(b), c;
  Append
    ->  Index Scan using mcrparted0_a_abs_c_idx on mcrparted0 mcrparted_1
          Index Cond: (a < 20)
+         Index Bound Cond: (a < 20)
    ->  Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
          Index Cond: (a < 20)
+         Index Bound Cond: (a < 20)
    ->  Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
          Index Cond: (a < 20)
+         Index Bound Cond: (a < 20)
    ->  Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
          Index Cond: (a < 20)
-(9 rows)
+         Index Bound Cond: (a < 20)
+(13 rows)
 
 set enable_bitmapscan to off;
 set enable_sort to off;
@@ -2524,9 +2544,11 @@ explain (costs off) select * from mclparted where a in(3,4,5) order by a;
    Sort Key: mclparted.a
    ->  Index Only Scan using mclparted3_5_a_idx on mclparted3_5 mclparted_1
          Index Cond: (a = ANY ('{3,4,5}'::integer[]))
+         Index Bound Cond: (a = ANY ('{3,4,5}'::integer[]))
    ->  Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_2
          Index Cond: (a = ANY ('{3,4,5}'::integer[]))
-(6 rows)
+         Index Bound Cond: (a = ANY ('{3,4,5}'::integer[]))
+(8 rows)
 
 -- Introduce a NULL and DEFAULT partition so we can test more complex cases
 create table mclparted_null partition of mclparted for values in(null);
@@ -2538,11 +2560,14 @@ explain (costs off) select * from mclparted where a in(1,2,4) order by a;
  Append
    ->  Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_1
          Index Cond: (a = ANY ('{1,2,4}'::integer[]))
+         Index Bound Cond: (a = ANY ('{1,2,4}'::integer[]))
    ->  Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_2
          Index Cond: (a = ANY ('{1,2,4}'::integer[]))
+         Index Bound Cond: (a = ANY ('{1,2,4}'::integer[]))
    ->  Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_3
          Index Cond: (a = ANY ('{1,2,4}'::integer[]))
-(7 rows)
+         Index Bound Cond: (a = ANY ('{1,2,4}'::integer[]))
+(10 rows)
 
 explain (costs off) select * from mclparted where a in(1,2,4) or a is null order by a;
                                    QUERY PLAN                                   
@@ -2584,13 +2609,17 @@ explain (costs off) select * from mclparted where a in(0,1,2,4) order by a;
    Sort Key: mclparted.a
    ->  Index Only Scan using mclparted_0_null_a_idx on mclparted_0_null mclparted_1
          Index Cond: (a = ANY ('{0,1,2,4}'::integer[]))
+         Index Bound Cond: (a = ANY ('{0,1,2,4}'::integer[]))
    ->  Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_2
          Index Cond: (a = ANY ('{0,1,2,4}'::integer[]))
+         Index Bound Cond: (a = ANY ('{0,1,2,4}'::integer[]))
    ->  Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_3
          Index Cond: (a = ANY ('{0,1,2,4}'::integer[]))
+         Index Bound Cond: (a = ANY ('{0,1,2,4}'::integer[]))
    ->  Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_4
          Index Cond: (a = ANY ('{0,1,2,4}'::integer[]))
-(10 rows)
+         Index Bound Cond: (a = ANY ('{0,1,2,4}'::integer[]))
+(14 rows)
 
 -- Ensure Append is used when the null partition is pruned
 explain (costs off) select * from mclparted where a in(1,2,4) order by a;
@@ -2599,11 +2628,14 @@ explain (costs off) select * from mclparted where a in(1,2,4) order by a;
  Append
    ->  Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_1
          Index Cond: (a = ANY ('{1,2,4}'::integer[]))
+         Index Bound Cond: (a = ANY ('{1,2,4}'::integer[]))
    ->  Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_2
          Index Cond: (a = ANY ('{1,2,4}'::integer[]))
+         Index Bound Cond: (a = ANY ('{1,2,4}'::integer[]))
    ->  Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_3
          Index Cond: (a = ANY ('{1,2,4}'::integer[]))
-(7 rows)
+         Index Bound Cond: (a = ANY ('{1,2,4}'::integer[]))
+(10 rows)
 
 -- Ensure MergeAppend is used when the default partition is not pruned
 explain (costs off) select * from mclparted where a in(1,2,4,100) order by a;
@@ -2613,13 +2645,17 @@ explain (costs off) select * from mclparted where a in(1,2,4,100) order by a;
    Sort Key: mclparted.a
    ->  Index Only Scan using mclparted1_a_idx on mclparted1 mclparted_1
          Index Cond: (a = ANY ('{1,2,4,100}'::integer[]))
+         Index Bound Cond: (a = ANY ('{1,2,4,100}'::integer[]))
    ->  Index Only Scan using mclparted2_a_idx on mclparted2 mclparted_2
          Index Cond: (a = ANY ('{1,2,4,100}'::integer[]))
+         Index Bound Cond: (a = ANY ('{1,2,4,100}'::integer[]))
    ->  Index Only Scan using mclparted4_a_idx on mclparted4 mclparted_3
          Index Cond: (a = ANY ('{1,2,4,100}'::integer[]))
+         Index Bound Cond: (a = ANY ('{1,2,4,100}'::integer[]))
    ->  Index Only Scan using mclparted_def_a_idx on mclparted_def mclparted_4
          Index Cond: (a = ANY ('{1,2,4,100}'::integer[]))
-(10 rows)
+         Index Bound Cond: (a = ANY ('{1,2,4,100}'::integer[]))
+(14 rows)
 
 drop table mclparted;
 reset enable_sort;
@@ -2642,11 +2678,14 @@ explain (costs off) select * from mcrparted where a < 20 order by a, abs(b), c l
                      Filter: (a < 20)
          ->  Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_2
                Index Cond: (a < 20)
+               Index Bound Cond: (a < 20)
          ->  Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_3
                Index Cond: (a < 20)
+               Index Bound Cond: (a < 20)
          ->  Index Scan using mcrparted3_a_abs_c_idx on mcrparted3 mcrparted_4
                Index Cond: (a < 20)
-(12 rows)
+               Index Bound Cond: (a < 20)
+(15 rows)
 
 set enable_bitmapscan = 0;
 -- Ensure Append node can be used when the partition is ordered by some
@@ -2657,9 +2696,11 @@ explain (costs off) select * from mcrparted where a = 10 order by a, abs(b), c;
  Append
    ->  Index Scan using mcrparted1_a_abs_c_idx on mcrparted1 mcrparted_1
          Index Cond: (a = 10)
+         Index Bound Cond: (a = 10)
    ->  Index Scan using mcrparted2_a_abs_c_idx on mcrparted2 mcrparted_2
          Index Cond: (a = 10)
-(5 rows)
+         Index Bound Cond: (a = 10)
+(7 rows)
 
 reset enable_bitmapscan;
 drop table mcrparted;
@@ -2690,9 +2731,11 @@ explain (costs off) select * from bool_rp where b = true order by b,a;
  Append
    ->  Index Only Scan using bool_rp_true_1k_b_a_idx on bool_rp_true_1k bool_rp_1
          Index Cond: (b = true)
+         Index Bound Cond: (b = true)
    ->  Index Only Scan using bool_rp_true_2k_b_a_idx on bool_rp_true_2k bool_rp_2
          Index Cond: (b = true)
-(5 rows)
+         Index Bound Cond: (b = true)
+(7 rows)
 
 explain (costs off) select * from bool_rp where b = false order by b,a;
                                      QUERY PLAN                                     
@@ -2700,9 +2743,11 @@ explain (costs off) select * from bool_rp where b = false order by b,a;
  Append
    ->  Index Only Scan using bool_rp_false_1k_b_a_idx on bool_rp_false_1k bool_rp_1
          Index Cond: (b = false)
+         Index Bound Cond: (b = false)
    ->  Index Only Scan using bool_rp_false_2k_b_a_idx on bool_rp_false_2k bool_rp_2
          Index Cond: (b = false)
-(5 rows)
+         Index Bound Cond: (b = false)
+(7 rows)
 
 explain (costs off) select * from bool_rp where b = true order by a;
                                     QUERY PLAN                                    
@@ -2710,9 +2755,11 @@ explain (costs off) select * from bool_rp where b = true order by a;
  Append
    ->  Index Only Scan using bool_rp_true_1k_b_a_idx on bool_rp_true_1k bool_rp_1
          Index Cond: (b = true)
+         Index Bound Cond: (b = true)
    ->  Index Only Scan using bool_rp_true_2k_b_a_idx on bool_rp_true_2k bool_rp_2
          Index Cond: (b = true)
-(5 rows)
+         Index Bound Cond: (b = true)
+(7 rows)
 
 explain (costs off) select * from bool_rp where b = false order by a;
                                      QUERY PLAN                                     
@@ -2720,9 +2767,11 @@ explain (costs off) select * from bool_rp where b = false order by a;
  Append
    ->  Index Only Scan using bool_rp_false_1k_b_a_idx on bool_rp_false_1k bool_rp_1
          Index Cond: (b = false)
+         Index Bound Cond: (b = false)
    ->  Index Only Scan using bool_rp_false_2k_b_a_idx on bool_rp_false_2k bool_rp_2
          Index Cond: (b = false)
-(5 rows)
+         Index Bound Cond: (b = false)
+(7 rows)
 
 drop table bool_rp;
 -- Ensure an Append scan is chosen when the partition order is a subset of
diff --git a/src/test/regress/expected/insert_conflict.out b/src/test/regress/expected/insert_conflict.out
index 5cb9cde030..aa93f6dbbd 100644
--- a/src/test/regress/expected/insert_conflict.out
+++ b/src/test/regress/expected/insert_conflict.out
@@ -66,7 +66,8 @@ explain (costs off) insert into insertconflicttest values(0, 'Crowberry') on con
    SubPlan 1
      ->  Index Only Scan using both_index_expr_key on insertconflicttest ii
            Index Cond: (key = excluded.key)
-(8 rows)
+           Index Bound Cond: (key = excluded.key)
+(9 rows)
 
 -- Neither collation nor operator class specifications are required --
 -- supplying them merely *limits* matches to indexes with matching opclasses
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 6b16c3a676..23f79f2974 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -2335,8 +2335,8 @@ select a.f1, b.f1, t.thousand, t.tenthous from
   (select sum(f1)+1 as f1 from int4_tbl i4a) a,
   (select sum(f1) as f1 from int4_tbl i4b) b
 where b.f1 = t.thousand and a.f1 = b.f1 and (a.f1+b.f1+999) = t.tenthous;
-                                                   QUERY PLAN                                                    
------------------------------------------------------------------------------------------------------------------
+                                                      QUERY PLAN                                                       
+-----------------------------------------------------------------------------------------------------------------------
  Nested Loop
    ->  Nested Loop
          Join Filter: ((sum(i4b.f1)) = ((sum(i4a.f1) + 1)))
@@ -2346,7 +2346,8 @@ where b.f1 = t.thousand and a.f1 = b.f1 and (a.f1+b.f1+999) = t.tenthous;
                ->  Seq Scan on int4_tbl i4b
    ->  Index Only Scan using tenk1_thous_tenthous on tenk1 t
          Index Cond: ((thousand = (sum(i4b.f1))) AND (tenthous = ((((sum(i4a.f1) + 1)) + (sum(i4b.f1))) + 999)))
-(9 rows)
+         Index Bound Cond: ((thousand = (sum(i4b.f1))) AND (tenthous = ((((sum(i4a.f1) + 1)) + (sum(i4b.f1))) + 999)))
+(10 rows)
 
 select a.f1, b.f1, t.thousand, t.tenthous from
   tenk1 t,
@@ -3256,7 +3257,8 @@ select a.idv, b.idv from tidv a, tidv b where a.idv = b.idv;
    ->  Seq Scan on tidv a
    ->  Index Only Scan using tidv_idv_idx on tidv b
          Index Cond: (idv = a.idv)
-(4 rows)
+         Index Bound Cond: (idv = a.idv)
+(5 rows)
 
 rollback;
 --
@@ -3406,8 +3408,8 @@ SELECT qq, unique1
   ( SELECT COALESCE(q2, -1) AS qq FROM int8_tbl b ) AS ss2
   USING (qq)
   INNER JOIN tenk1 c ON qq = unique2;
-                                               QUERY PLAN                                                
----------------------------------------------------------------------------------------------------------
+                                                  QUERY PLAN                                                   
+---------------------------------------------------------------------------------------------------------------
  Nested Loop
    ->  Hash Full Join
          Hash Cond: ((COALESCE(a.q1, '0'::bigint)) = (COALESCE(b.q2, '-1'::bigint)))
@@ -3416,7 +3418,8 @@ SELECT qq, unique1
                ->  Seq Scan on int8_tbl b
    ->  Index Scan using tenk1_unique2 on tenk1 c
          Index Cond: (unique2 = COALESCE((COALESCE(a.q1, '0'::bigint)), (COALESCE(b.q2, '-1'::bigint))))
-(8 rows)
+         Index Bound Cond: (unique2 = COALESCE((COALESCE(a.q1, '0'::bigint)), (COALESCE(b.q2, '-1'::bigint))))
+(9 rows)
 
 SELECT qq, unique1
   FROM
@@ -3474,18 +3477,21 @@ from nt3 as nt3
     ) as ss2
     on ss2.id = nt3.nt2_id
 where nt3.id = 1 and ss2.b3;
-                  QUERY PLAN                   
------------------------------------------------
+                    QUERY PLAN                     
+---------------------------------------------------
  Nested Loop
    ->  Nested Loop
          ->  Index Scan using nt3_pkey on nt3
                Index Cond: (id = 1)
+               Index Bound Cond: (id = 1)
          ->  Index Scan using nt2_pkey on nt2
                Index Cond: (id = nt3.nt2_id)
+               Index Bound Cond: (id = nt3.nt2_id)
    ->  Index Only Scan using nt1_pkey on nt1
          Index Cond: (id = nt2.nt1_id)
+         Index Bound Cond: (id = nt2.nt1_id)
          Filter: (nt2.b1 AND (id IS NOT NULL))
-(9 rows)
+(12 rows)
 
 select nt3.id
 from nt3 as nt3
@@ -3687,19 +3693,21 @@ where q1 = thousand or q2 = thousand;
                ->  BitmapOr
                      ->  Bitmap Index Scan on tenk1_thous_tenthous
                            Index Cond: (thousand = q1.q1)
+                           Index Bound Cond: (thousand = q1.q1)
                      ->  Bitmap Index Scan on tenk1_thous_tenthous
                            Index Cond: (thousand = q2.q2)
+                           Index Bound Cond: (thousand = q2.q2)
    ->  Hash
          ->  Seq Scan on int4_tbl
-(15 rows)
+(17 rows)
 
 explain (costs off)
 select * from
   tenk1 join int4_tbl on f1 = twothousand,
   q1, q2
 where thousand = (q1 + q2);
-                          QUERY PLAN                          
---------------------------------------------------------------
+                             QUERY PLAN                             
+--------------------------------------------------------------------
  Hash Join
    Hash Cond: (tenk1.twothousand = int4_tbl.f1)
    ->  Nested Loop
@@ -3710,9 +3718,10 @@ where thousand = (q1 + q2);
                Recheck Cond: (thousand = (q1.q1 + q2.q2))
                ->  Bitmap Index Scan on tenk1_thous_tenthous
                      Index Cond: (thousand = (q1.q1 + q2.q2))
+                     Index Bound Cond: (thousand = (q1.q1 + q2.q2))
    ->  Hash
          ->  Seq Scan on int4_tbl
-(12 rows)
+(13 rows)
 
 --
 -- test ability to generate a suitable plan for a star-schema query
@@ -3721,8 +3730,8 @@ explain (costs off)
 select * from
   tenk1, int8_tbl a, int8_tbl b
 where thousand = a.q1 and tenthous = b.q1 and a.q2 = 1 and b.q2 = 2;
-                             QUERY PLAN                              
----------------------------------------------------------------------
+                                QUERY PLAN                                 
+---------------------------------------------------------------------------
  Nested Loop
    ->  Seq Scan on int8_tbl b
          Filter: (q2 = 2)
@@ -3731,7 +3740,8 @@ where thousand = a.q1 and tenthous = b.q1 and a.q2 = 1 and b.q2 = 2;
                Filter: (q2 = 1)
          ->  Index Scan using tenk1_thous_tenthous on tenk1
                Index Cond: ((thousand = a.q1) AND (tenthous = b.q1))
-(8 rows)
+               Index Bound Cond: ((thousand = a.q1) AND (tenthous = b.q1))
+(9 rows)
 
 --
 -- test a corner case in which we shouldn't apply the star-schema optimization
@@ -3749,8 +3759,8 @@ select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from
   left join tenk1 t2
   on (subq1.y1 = t2.unique1)
 where t1.unique2 < 42 and t1.stringu1 > t2.stringu2;
-                              QUERY PLAN                               
------------------------------------------------------------------------
+                                 QUERY PLAN                                  
+-----------------------------------------------------------------------------
  Nested Loop
    ->  Nested Loop
          Join Filter: (t1.stringu1 > t2.stringu2)
@@ -3760,11 +3770,13 @@ where t1.unique2 < 42 and t1.stringu1 > t2.stringu2;
                      ->  Seq Scan on onerow onerow_1
                ->  Index Scan using tenk1_unique2 on tenk1 t1
                      Index Cond: ((unique2 = (11)) AND (unique2 < 42))
+                     Index Bound Cond: ((unique2 = (11)) AND (unique2 < 42))
          ->  Index Scan using tenk1_unique1 on tenk1 t2
                Index Cond: (unique1 = (3))
+               Index Bound Cond: (unique1 = (3))
    ->  Seq Scan on int4_tbl i1
          Filter: (f1 = 0)
-(13 rows)
+(15 rows)
 
 select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from
   tenk1 t1
@@ -3817,8 +3829,8 @@ select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from
   left join tenk1 t2
   on (subq1.y1 = t2.unique1)
 where t1.unique2 < 42 and t1.stringu1 > t2.stringu2;
-                           QUERY PLAN                            
------------------------------------------------------------------
+                              QUERY PLAN                               
+-----------------------------------------------------------------------
  Nested Loop
    Join Filter: (t1.stringu1 > t2.stringu2)
    ->  Nested Loop
@@ -3826,9 +3838,11 @@ where t1.unique2 < 42 and t1.stringu1 > t2.stringu2;
                Filter: (f1 = 0)
          ->  Index Scan using tenk1_unique2 on tenk1 t1
                Index Cond: ((unique2 = (11)) AND (unique2 < 42))
+               Index Bound Cond: ((unique2 = (11)) AND (unique2 < 42))
    ->  Index Scan using tenk1_unique1 on tenk1 t2
          Index Cond: (unique1 = (3))
-(9 rows)
+         Index Bound Cond: (unique1 = (3))
+(11 rows)
 
 select t1.unique2, t1.stringu1, t2.unique1, t2.stringu2 from
   tenk1 t1
@@ -3978,7 +3992,8 @@ where x = unique1;
 ----------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: (unique1 = 1)
-(2 rows)
+   Index Bound Cond: (unique1 = 1)
+(3 rows)
 
 explain (verbose, costs off)
 select unique1, x.*
@@ -3993,7 +4008,8 @@ where x = unique1;
    ->  Index Only Scan using tenk1_unique1 on public.tenk1
          Output: tenk1.unique1
          Index Cond: (tenk1.unique1 = (1))
-(7 rows)
+         Index Bound Cond: (tenk1.unique1 = (1))
+(8 rows)
 
 explain (costs off)
 select unique1 from tenk1, f_immutable_int4(1) x where x = unique1;
@@ -4001,7 +4017,8 @@ select unique1 from tenk1, f_immutable_int4(1) x where x = unique1;
 ----------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: (unique1 = 1)
-(2 rows)
+   Index Bound Cond: (unique1 = 1)
+(3 rows)
 
 explain (costs off)
 select unique1 from tenk1, lateral f_immutable_int4(1) x where x = unique1;
@@ -4009,7 +4026,8 @@ select unique1 from tenk1, lateral f_immutable_int4(1) x where x = unique1;
 ----------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: (unique1 = 1)
-(2 rows)
+   Index Bound Cond: (unique1 = 1)
+(3 rows)
 
 explain (costs off)
 select unique1 from tenk1, lateral f_immutable_int4(1) x where x in (select 17);
@@ -4025,7 +4043,8 @@ select unique1, x from tenk1 join f_immutable_int4(1) x on unique1 = x;
 ----------------------------------------------
  Index Only Scan using tenk1_unique1 on tenk1
    Index Cond: (unique1 = 1)
-(2 rows)
+   Index Bound Cond: (unique1 = 1)
+(3 rows)
 
 explain (costs off)
 select unique1, x from tenk1 left join f_immutable_int4(1) x on unique1 = x;
@@ -4046,7 +4065,8 @@ select unique1, x from tenk1 right join f_immutable_int4(1) x on unique1 = x;
    ->  Result
    ->  Index Only Scan using tenk1_unique1 on tenk1
          Index Cond: (unique1 = 1)
-(4 rows)
+         Index Bound Cond: (unique1 = 1)
+(5 rows)
 
 explain (costs off)
 select unique1, x from tenk1 full join f_immutable_int4(1) x on unique1 = x;
@@ -4082,18 +4102,20 @@ from nt3 as nt3
     ) as ss2
     on ss2.id = nt3.nt2_id
 where nt3.id = 1 and ss2.b3;
-                  QUERY PLAN                  
-----------------------------------------------
+                    QUERY PLAN                     
+---------------------------------------------------
  Nested Loop Left Join
    Filter: ((nt2.b1 OR ((0) = 42)))
    ->  Index Scan using nt3_pkey on nt3
          Index Cond: (id = 1)
+         Index Bound Cond: (id = 1)
    ->  Nested Loop Left Join
          Join Filter: (0 = nt2.nt1_id)
          ->  Index Scan using nt2_pkey on nt2
                Index Cond: (id = nt3.nt2_id)
+               Index Bound Cond: (id = nt3.nt2_id)
          ->  Result
-(9 rows)
+(11 rows)
 
 drop function f_immutable_int4(int);
 -- test inlining when function returns composite
@@ -4175,17 +4197,21 @@ select * from tenk1 a join tenk1 b on
          ->  BitmapOr
                ->  Bitmap Index Scan on tenk1_unique1
                      Index Cond: (unique1 = 2)
+                     Index Bound Cond: (unique1 = 2)
                ->  Bitmap Index Scan on tenk1_hundred
                      Index Cond: (hundred = 4)
+                     Index Bound Cond: (hundred = 4)
    ->  Materialize
          ->  Bitmap Heap Scan on tenk1 a
                Recheck Cond: ((unique1 = 1) OR (unique2 = 3))
                ->  BitmapOr
                      ->  Bitmap Index Scan on tenk1_unique1
                            Index Cond: (unique1 = 1)
+                           Index Bound Cond: (unique1 = 1)
                      ->  Bitmap Index Scan on tenk1_unique2
                            Index Cond: (unique2 = 3)
-(17 rows)
+                           Index Bound Cond: (unique2 = 3)
+(21 rows)
 
 explain (costs off)
 select * from tenk1 a join tenk1 b on
@@ -4202,9 +4228,11 @@ select * from tenk1 a join tenk1 b on
                ->  BitmapOr
                      ->  Bitmap Index Scan on tenk1_unique1
                            Index Cond: (unique1 = 1)
+                           Index Bound Cond: (unique1 = 1)
                      ->  Bitmap Index Scan on tenk1_unique2
                            Index Cond: (unique2 = 3)
-(12 rows)
+                           Index Bound Cond: (unique2 = 3)
+(14 rows)
 
 explain (costs off)
 select * from tenk1 a join tenk1 b on
@@ -4219,19 +4247,24 @@ select * from tenk1 a join tenk1 b on
          ->  BitmapOr
                ->  Bitmap Index Scan on tenk1_unique1
                      Index Cond: (unique1 = 2)
+                     Index Bound Cond: (unique1 = 2)
                ->  Bitmap Index Scan on tenk1_hundred
                      Index Cond: (hundred = 4)
+                     Index Bound Cond: (hundred = 4)
    ->  Materialize
          ->  Bitmap Heap Scan on tenk1 a
                Recheck Cond: ((unique1 = 1) OR (unique2 = 3) OR (unique2 = 7))
                ->  BitmapOr
                      ->  Bitmap Index Scan on tenk1_unique1
                            Index Cond: (unique1 = 1)
+                           Index Bound Cond: (unique1 = 1)
                      ->  Bitmap Index Scan on tenk1_unique2
                            Index Cond: (unique2 = 3)
+                           Index Bound Cond: (unique2 = 3)
                      ->  Bitmap Index Scan on tenk1_unique2
                            Index Cond: (unique2 = 7)
-(19 rows)
+                           Index Bound Cond: (unique2 = 7)
+(24 rows)
 
 --
 -- test placement of movable quals in a parameterized join tree
@@ -4241,48 +4274,54 @@ select * from tenk1 t1 left join
   (tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2)
   on t1.hundred = t2.hundred and t1.ten = t3.ten
 where t1.unique1 = 1;
-                       QUERY PLAN                       
---------------------------------------------------------
+                          QUERY PLAN                          
+--------------------------------------------------------------
  Nested Loop Left Join
    ->  Index Scan using tenk1_unique1 on tenk1 t1
          Index Cond: (unique1 = 1)
+         Index Bound Cond: (unique1 = 1)
    ->  Nested Loop
          Join Filter: (t1.ten = t3.ten)
          ->  Bitmap Heap Scan on tenk1 t2
                Recheck Cond: (t1.hundred = hundred)
                ->  Bitmap Index Scan on tenk1_hundred
                      Index Cond: (hundred = t1.hundred)
+                     Index Bound Cond: (hundred = t1.hundred)
          ->  Index Scan using tenk1_unique2 on tenk1 t3
                Index Cond: (unique2 = t2.thousand)
-(11 rows)
+               Index Bound Cond: (unique2 = t2.thousand)
+(14 rows)
 
 explain (costs off)
 select * from tenk1 t1 left join
   (tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2)
   on t1.hundred = t2.hundred and t1.ten + t2.ten = t3.ten
 where t1.unique1 = 1;
-                       QUERY PLAN                       
---------------------------------------------------------
+                          QUERY PLAN                          
+--------------------------------------------------------------
  Nested Loop Left Join
    ->  Index Scan using tenk1_unique1 on tenk1 t1
          Index Cond: (unique1 = 1)
+         Index Bound Cond: (unique1 = 1)
    ->  Nested Loop
          Join Filter: ((t1.ten + t2.ten) = t3.ten)
          ->  Bitmap Heap Scan on tenk1 t2
                Recheck Cond: (t1.hundred = hundred)
                ->  Bitmap Index Scan on tenk1_hundred
                      Index Cond: (hundred = t1.hundred)
+                     Index Bound Cond: (hundred = t1.hundred)
          ->  Index Scan using tenk1_unique2 on tenk1 t3
                Index Cond: (unique2 = t2.thousand)
-(11 rows)
+               Index Bound Cond: (unique2 = t2.thousand)
+(14 rows)
 
 explain (costs off)
 select count(*) from
   tenk1 a join tenk1 b on a.unique1 = b.unique2
   left join tenk1 c on a.unique2 = b.unique1 and c.thousand = a.thousand
   join int4_tbl on b.thousand = f1;
-                               QUERY PLAN                                
--------------------------------------------------------------------------
+                                 QUERY PLAN                                 
+----------------------------------------------------------------------------
  Aggregate
    ->  Nested Loop Left Join
          Join Filter: (a.unique2 = b.unique1)
@@ -4293,11 +4332,14 @@ select count(*) from
                            Recheck Cond: (thousand = int4_tbl.f1)
                            ->  Bitmap Index Scan on tenk1_thous_tenthous
                                  Index Cond: (thousand = int4_tbl.f1)
+                                 Index Bound Cond: (thousand = int4_tbl.f1)
                ->  Index Scan using tenk1_unique1 on tenk1 a
                      Index Cond: (unique1 = b.unique2)
+                     Index Bound Cond: (unique1 = b.unique2)
          ->  Index Only Scan using tenk1_thous_tenthous on tenk1 c
                Index Cond: (thousand = a.thousand)
-(14 rows)
+               Index Bound Cond: (thousand = a.thousand)
+(17 rows)
 
 select count(*) from
   tenk1 a join tenk1 b on a.unique1 = b.unique2
@@ -4315,8 +4357,8 @@ select b.unique1 from
   join int4_tbl i1 on b.thousand = f1
   right join int4_tbl i2 on i2.f1 = b.tenthous
   order by 1;
-                                       QUERY PLAN                                        
------------------------------------------------------------------------------------------
+                                          QUERY PLAN                                           
+-----------------------------------------------------------------------------------------------
  Sort
    Sort Key: b.unique1
    ->  Nested Loop Left Join
@@ -4328,11 +4370,14 @@ select b.unique1 from
                            ->  Seq Scan on int4_tbl i1
                            ->  Index Scan using tenk1_thous_tenthous on tenk1 b
                                  Index Cond: ((thousand = i1.f1) AND (tenthous = i2.f1))
+                                 Index Bound Cond: ((thousand = i1.f1) AND (tenthous = i2.f1))
                      ->  Index Scan using tenk1_unique1 on tenk1 a
                            Index Cond: (unique1 = b.unique2)
+                           Index Bound Cond: (unique1 = b.unique2)
                ->  Index Only Scan using tenk1_thous_tenthous on tenk1 c
                      Index Cond: (thousand = a.thousand)
-(15 rows)
+                     Index Bound Cond: (thousand = a.thousand)
+(18 rows)
 
 select b.unique1 from
   tenk1 a join tenk1 b on a.unique1 = b.unique2
@@ -4364,7 +4409,8 @@ order by fault;
    ->  Seq Scan on int8_tbl
    ->  Index Scan using tenk1_unique2 on tenk1
          Index Cond: (unique2 = int8_tbl.q2)
-(5 rows)
+         Index Bound Cond: (unique2 = int8_tbl.q2)
+(6 rows)
 
 select * from
 (
@@ -4419,7 +4465,8 @@ select q1, unique2, thousand, hundred
    ->  Seq Scan on int8_tbl a
    ->  Index Scan using tenk1_unique2 on tenk1 b
          Index Cond: (unique2 = a.q1)
-(5 rows)
+         Index Bound Cond: (unique2 = a.q1)
+(6 rows)
 
 select q1, unique2, thousand, hundred
   from int8_tbl a left join tenk1 b on q1 = unique2
@@ -4439,7 +4486,8 @@ select f1, unique2, case when unique2 is null then f1 else 0 end
    ->  Seq Scan on int4_tbl a
    ->  Index Only Scan using tenk1_unique2 on tenk1 b
          Index Cond: (unique2 = a.f1)
-(5 rows)
+         Index Bound Cond: (unique2 = a.f1)
+(6 rows)
 
 select f1, unique2, case when unique2 is null then f1 else 0 end
   from int4_tbl a left join tenk1 b on f1 = unique2
@@ -4463,13 +4511,16 @@ select a.unique1, b.unique1, c.unique1, coalesce(b.twothousand, a.twothousand)
          Filter: (COALESCE(b.twothousand, a.twothousand) = 44)
          ->  Index Scan using tenk1_unique2 on tenk1 a
                Index Cond: (unique2 < 10)
+               Index Bound Cond: (unique2 < 10)
          ->  Bitmap Heap Scan on tenk1 b
                Recheck Cond: (thousand = a.unique1)
                ->  Bitmap Index Scan on tenk1_thous_tenthous
                      Index Cond: (thousand = a.unique1)
+                     Index Bound Cond: (thousand = a.unique1)
    ->  Index Scan using tenk1_unique2 on tenk1 c
          Index Cond: (unique2 = 44)
-(11 rows)
+         Index Bound Cond: (unique2 = 44)
+(14 rows)
 
 select a.unique1, b.unique1, c.unique1, coalesce(b.twothousand, a.twothousand)
   from tenk1 a left join tenk1 b on b.thousand = a.unique1                        left join tenk1 c on c.unique2 = coalesce(b.twothousand, a.twothousand)
@@ -4542,7 +4593,8 @@ using (join_key);
                ->  Index Only Scan using tenk1_unique2 on public.tenk1 i2
                      Output: i2.unique2
                      Index Cond: (i2.unique2 = i1.f1)
-(14 rows)
+                     Index Bound Cond: (i2.unique2 = i1.f1)
+(15 rows)
 
 select foo1.join_key as foo1_id, foo3.join_key AS foo3_id, bug_field from
   (values (0),(1)) foo1(join_key)
@@ -5210,7 +5262,8 @@ explain (costs off)
          Filter: (f1 = 0)
    ->  Index Scan using tenk1_unique2 on tenk1 b
          Index Cond: (unique2 = 0)
-(5 rows)
+         Index Bound Cond: (unique2 = 0)
+(6 rows)
 
 explain (costs off)
   select * from tenk1 a full join tenk1 b using(unique2) where unique2 = 42;
@@ -5219,9 +5272,11 @@ explain (costs off)
  Merge Full Join
    ->  Index Scan using tenk1_unique2 on tenk1 a
          Index Cond: (unique2 = 42)
+         Index Bound Cond: (unique2 = 42)
    ->  Index Scan using tenk1_unique2 on tenk1 b
          Index Cond: (unique2 = 42)
-(5 rows)
+         Index Bound Cond: (unique2 = 42)
+(7 rows)
 
 --
 -- test that quals attached to an outer join have correct semantics,
@@ -5311,9 +5366,11 @@ select a.unique1, b.unique2
  Nested Loop Left Join
    ->  Index Only Scan using onek_unique1 on onek a
          Index Cond: (unique1 = 42)
+         Index Bound Cond: (unique1 = 42)
    ->  Index Only Scan using onek_unique2 on onek b
          Index Cond: (unique2 = 42)
-(5 rows)
+         Index Bound Cond: (unique2 = 42)
+(7 rows)
 
 select a.unique1, b.unique2
   from onek a full join onek b on a.unique1 = b.unique2
@@ -5332,9 +5389,11 @@ select a.unique1, b.unique2
  Nested Loop Left Join
    ->  Index Only Scan using onek_unique2 on onek b
          Index Cond: (unique2 = 43)
+         Index Bound Cond: (unique2 = 43)
    ->  Index Only Scan using onek_unique1 on onek a
          Index Cond: (unique1 = 43)
-(5 rows)
+         Index Bound Cond: (unique1 = 43)
+(7 rows)
 
 select a.unique1, b.unique2
   from onek a full join onek b on a.unique1 = b.unique2
@@ -5353,9 +5412,11 @@ select a.unique1, b.unique2
  Nested Loop
    ->  Index Only Scan using onek_unique1 on onek a
          Index Cond: (unique1 = 42)
+         Index Bound Cond: (unique1 = 42)
    ->  Index Only Scan using onek_unique2 on onek b
          Index Cond: (unique2 = 42)
-(5 rows)
+         Index Bound Cond: (unique2 = 42)
+(7 rows)
 
 select a.unique1, b.unique2
   from onek a full join onek b on a.unique1 = b.unique2
@@ -5697,8 +5758,9 @@ select 1 from a t1
                Join Filter: (t2.id = 1)
                ->  Index Only Scan using a_pkey on a t2
                      Index Cond: (id = 1)
+                     Index Bound Cond: (id = 1)
                ->  Seq Scan on a t3
-(8 rows)
+(9 rows)
 
 -- check join removal works when uniqueness of the join condition is enforced
 -- by a UNION
@@ -5888,7 +5950,8 @@ SELECT q2 FROM
    ->  Seq Scan on int8_tbl
    ->  Index Scan using innertab_pkey on innertab
          Index Cond: (id = int8_tbl.q2)
-(5 rows)
+         Index Bound Cond: (id = int8_tbl.q2)
+(6 rows)
 
 -- join removal bug #17773: otherwise-removable PHV appears in a qual condition
 EXPLAIN (VERBOSE, COSTS OFF)
@@ -5966,10 +6029,11 @@ where ss.stringu2 !~* ss.case1;
          ->  Seq Scan on int4_tbl i4
          ->  Index Scan using tenk1_unique2 on tenk1 t1
                Index Cond: (unique2 = i4.f1)
+               Index Bound Cond: (unique2 = i4.f1)
                Filter: (stringu2 !~* CASE ten WHEN 0 THEN 'doh!'::text ELSE NULL::text END)
    ->  Materialize
          ->  Seq Scan on text_tbl t0
-(9 rows)
+(10 rows)
 
 select t0.*
 from
@@ -6099,7 +6163,8 @@ where q2 = 456;
    ->  Index Only Scan using tenk1_unique2 on public.tenk1 t
          Output: t.unique2
          Index Cond: (t.unique2 = ((i4.f1 + 1)))
-(13 rows)
+         Index Bound Cond: (t.unique2 = ((i4.f1 + 1)))
+(14 rows)
 
 select i8.*, ss.v, t.unique2
   from int8_tbl i8
@@ -6228,7 +6293,8 @@ explain (costs off)
    ->  Seq Scan on int4_tbl b
    ->  Index Scan using tenk1_unique1 on tenk1 a
          Index Cond: (unique1 = b.f1)
-(4 rows)
+         Index Bound Cond: (unique1 = b.f1)
+(5 rows)
 
 select unique2, x.*
 from int4_tbl x, lateral (select unique2 from tenk1 where f1 = unique1) ss;
@@ -6246,7 +6312,8 @@ explain (costs off)
    ->  Seq Scan on int4_tbl x
    ->  Index Scan using tenk1_unique1 on tenk1
          Index Cond: (unique1 = x.f1)
-(4 rows)
+         Index Bound Cond: (unique1 = x.f1)
+(5 rows)
 
 explain (costs off)
   select unique2, x.*
@@ -6257,7 +6324,8 @@ explain (costs off)
    ->  Seq Scan on int4_tbl x
    ->  Index Scan using tenk1_unique1 on tenk1
          Index Cond: (unique1 = x.f1)
-(4 rows)
+         Index Bound Cond: (unique1 = x.f1)
+(5 rows)
 
 select unique2, x.*
 from int4_tbl x left join lateral (select unique1, unique2 from tenk1 where f1 = unique1) ss on true;
@@ -6279,7 +6347,8 @@ explain (costs off)
    ->  Seq Scan on int4_tbl x
    ->  Index Scan using tenk1_unique1 on tenk1
          Index Cond: (unique1 = x.f1)
-(4 rows)
+         Index Bound Cond: (unique1 = x.f1)
+(5 rows)
 
 -- check scoping of lateral versus parent references
 -- the first of these should return int8_tbl.q2, the second int8_tbl.q1
@@ -6400,8 +6469,8 @@ select count(*) from tenk1 a,
 explain (costs off)
   select count(*) from tenk1 a,
     tenk1 b join lateral (values(a.unique1),(-1)) ss(x) on b.unique2 = ss.x;
-                            QUERY PLAN                            
-------------------------------------------------------------------
+                              QUERY PLAN                              
+----------------------------------------------------------------------
  Aggregate
    ->  Nested Loop
          ->  Nested Loop
@@ -6412,7 +6481,8 @@ explain (costs off)
                Cache Mode: logical
                ->  Index Only Scan using tenk1_unique2 on tenk1 b
                      Index Cond: (unique2 = "*VALUES*".column1)
-(10 rows)
+                     Index Bound Cond: (unique2 = "*VALUES*".column1)
+(11 rows)
 
 select count(*) from tenk1 a,
   tenk1 b join lateral (values(a.unique1),(-1)) ss(x) on b.unique2 = ss.x;
@@ -7191,8 +7261,8 @@ select * from
   lateral (select f1 from int4_tbl
            where f1 = any (select unique1 from tenk1
                            where unique2 = v.x offset 0)) ss;
-                              QUERY PLAN                              
-----------------------------------------------------------------------
+                                 QUERY PLAN                                 
+----------------------------------------------------------------------------
  Nested Loop
    Output: "*VALUES*".column1, "*VALUES*".column2, int4_tbl.f1
    ->  Values Scan on "*VALUES*"
@@ -7207,7 +7277,8 @@ select * from
                ->  Index Scan using tenk1_unique2 on public.tenk1
                      Output: tenk1.unique1
                      Index Cond: (tenk1.unique2 = "*VALUES*".column2)
-(14 rows)
+                     Index Bound Cond: (tenk1.unique2 = "*VALUES*".column2)
+(15 rows)
 
 select * from
   (values (0,9998), (1,1000)) v(id,x),
@@ -7439,7 +7510,8 @@ select * from fkest f1
                      Filter: (x100 = 2)
    ->  Index Scan using fkest_x_x10_x100_idx on fkest f3
          Index Cond: (x = f1.x)
-(10 rows)
+         Index Bound Cond: (x = f1.x)
+(11 rows)
 
 alter table fkest add constraint fk
   foreign key (x, x10b, x100) references fkest (x, x10, x100);
@@ -7490,13 +7562,17 @@ where f.c = 1;
          ->  Nested Loop Left Join
                ->  Index Scan using fkest_c_key on fkest f
                      Index Cond: (c = 1)
+                     Index Bound Cond: (c = 1)
                ->  Index Only Scan using fkest1_pkey on fkest1 f1
                      Index Cond: ((a = f.a) AND (b = f.b))
+                     Index Bound Cond: ((a = f.a) AND (b = f.b))
          ->  Index Only Scan using fkest1_pkey on fkest1 f2
                Index Cond: ((a = f.a) AND (b = f.b))
+               Index Bound Cond: ((a = f.a) AND (b = f.b))
    ->  Index Only Scan using fkest1_pkey on fkest1 f3
          Index Cond: ((a = f.a) AND (b = f.b))
-(11 rows)
+         Index Bound Cond: ((a = f.a) AND (b = f.b))
+(15 rows)
 
 rollback;
 --
@@ -7819,15 +7895,16 @@ where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1;
 explain (costs off) select * from j1
 inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2
 where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1 and j2.id1 = any (array[1]);
-                     QUERY PLAN                     
-----------------------------------------------------
+                        QUERY PLAN                        
+----------------------------------------------------------
  Merge Join
    Merge Cond: (j1.id1 = j2.id1)
    Join Filter: (j2.id2 = j1.id2)
    ->  Index Scan using j1_id1_idx on j1
    ->  Index Scan using j2_id1_idx on j2
          Index Cond: (id1 = ANY ('{1}'::integer[]))
-(6 rows)
+         Index Bound Cond: (id1 = ANY ('{1}'::integer[]))
+(7 rows)
 
 select * from j1
 inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2
@@ -7842,15 +7919,16 @@ where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1 and j2.id1 = any (array[1]);
 explain (costs off) select * from j1
 inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2
 where j1.id1 % 1000 = 1 and j2.id1 % 1000 = 1 and j2.id1 >= any (array[1,5]);
-                      QUERY PLAN                       
--------------------------------------------------------
+                         QUERY PLAN                          
+-------------------------------------------------------------
  Merge Join
    Merge Cond: (j1.id1 = j2.id1)
    Join Filter: (j2.id2 = j1.id2)
    ->  Index Scan using j1_id1_idx on j1
    ->  Index Scan using j2_id1_idx on j2
          Index Cond: (id1 >= ANY ('{1,5}'::integer[]))
-(6 rows)
+         Index Bound Cond: (id1 >= ANY ('{1,5}'::integer[]))
+(7 rows)
 
 select * from j1
 inner join j2 on j1.id1 = j2.id1 and j1.id2 = j2.id2
@@ -7891,10 +7969,12 @@ where exists (select 1 from tenk1 t3
                ->  Index Only Scan using onek_unique1 on public.onek t1
                      Output: t1.unique1
                      Index Cond: (t1.unique1 < 1)
+                     Index Bound Cond: (t1.unique1 < 1)
    ->  Index Only Scan using tenk1_hundred on public.tenk1 t2
          Output: t2.hundred
          Index Cond: (t2.hundred = t3.tenthous)
-(18 rows)
+         Index Bound Cond: (t2.hundred = t3.tenthous)
+(20 rows)
 
 -- ... unless it actually is unique
 create table j3 as select unique1, tenthous from onek;
@@ -7915,13 +7995,16 @@ where exists (select 1 from j3
          ->  Index Only Scan using onek_unique1 on public.onek t1
                Output: t1.unique1
                Index Cond: (t1.unique1 < 1)
+               Index Bound Cond: (t1.unique1 < 1)
          ->  Index Only Scan using j3_unique1_tenthous_idx on public.j3
                Output: j3.unique1, j3.tenthous
                Index Cond: (j3.unique1 = t1.unique1)
+               Index Bound Cond: (j3.unique1 = t1.unique1)
    ->  Index Only Scan using tenk1_hundred on public.tenk1 t2
          Output: t2.hundred
          Index Cond: (t2.hundred = j3.tenthous)
-(13 rows)
+         Index Bound Cond: (t2.hundred = j3.tenthous)
+(16 rows)
 
 drop table j3;
 -- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
@@ -7951,7 +8034,8 @@ SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS
                Recheck Cond: (a = 1)
                ->  Bitmap Index Scan on skip_fetch_a_idx
                      Index Cond: (a = 1)
-(7 rows)
+                     Index Bound Cond: (a = 1)
+(8 rows)
 
 SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
  a 
diff --git a/src/test/regress/expected/memoize.out b/src/test/regress/expected/memoize.out
index 0fd103c06b..400433e933 100644
--- a/src/test/regress/expected/memoize.out
+++ b/src/test/regress/expected/memoize.out
@@ -48,8 +48,9 @@ WHERE t2.unique1 < 1000;', false);
                Hits: 980  Misses: 20  Evictions: Zero  Overflows: 0  Memory Usage: NkB
                ->  Index Only Scan using tenk1_unique1 on tenk1 t1 (actual rows=1 loops=N)
                      Index Cond: (unique1 = t2.twenty)
+                     Index Bound Cond: (unique1 = t2.twenty)
                      Heap Fetches: N
-(12 rows)
+(13 rows)
 
 -- And check we get the expected results.
 SELECT COUNT(*),AVG(t1.unique1) FROM tenk1 t1
@@ -79,8 +80,9 @@ WHERE t1.unique1 < 1000;', false);
                Hits: 980  Misses: 20  Evictions: Zero  Overflows: 0  Memory Usage: NkB
                ->  Index Only Scan using tenk1_unique1 on tenk1 t2 (actual rows=1 loops=N)
                      Index Cond: (unique1 = t1.twenty)
+                     Index Bound Cond: (unique1 = t1.twenty)
                      Heap Fetches: N
-(12 rows)
+(13 rows)
 
 -- And check we get the expected results.
 SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1,
@@ -106,6 +108,7 @@ WHERE t1.unique1 < 10;', false);
    ->  Nested Loop Left Join (actual rows=20 loops=N)
          ->  Index Scan using tenk1_unique1 on tenk1 t1 (actual rows=10 loops=N)
                Index Cond: (unique1 < 10)
+               Index Bound Cond: (unique1 < 10)
          ->  Memoize (actual rows=2 loops=N)
                Cache Key: t1.two
                Cache Mode: binary
@@ -115,7 +118,8 @@ WHERE t1.unique1 < 10;', false);
                      Rows Removed by Filter: 2
                      ->  Index Scan using tenk1_unique1 on tenk1 t2_1 (actual rows=4 loops=N)
                            Index Cond: (unique1 < 4)
-(13 rows)
+                           Index Bound Cond: (unique1 < 4)
+(15 rows)
 
 -- And check we get the expected results.
 SELECT COUNT(*),AVG(t2.t1two) FROM tenk1 t1 LEFT JOIN
@@ -154,9 +158,10 @@ ON t1.x = t2.t::numeric AND t1.t::numeric = t2.x;', false);
          Hits: 20  Misses: 20  Evictions: Zero  Overflows: 0  Memory Usage: NkB
          ->  Index Only Scan using expr_key_idx_x_t on expr_key t2 (actual rows=2 loops=N)
                Index Cond: (x = (t1.t)::numeric)
+               Index Bound Cond: (x = (t1.t)::numeric)
                Filter: (t1.x = (t)::numeric)
                Heap Fetches: N
-(10 rows)
+(11 rows)
 
 DROP TABLE expr_key;
 -- Reduce work_mem and hash_mem_multiplier so that we see some cache evictions
@@ -182,8 +187,9 @@ WHERE t2.unique1 < 1200;', true);
                Hits: N  Misses: N  Evictions: N  Overflows: 0  Memory Usage: NkB
                ->  Index Only Scan using tenk1_unique1 on tenk1 t1 (actual rows=1 loops=N)
                      Index Cond: (unique1 = t2.thousand)
+                     Index Bound Cond: (unique1 = t2.thousand)
                      Heap Fetches: N
-(12 rows)
+(13 rows)
 
 CREATE TABLE flt (f float);
 CREATE INDEX flt_f_idx ON flt (f);
@@ -204,8 +210,9 @@ SELECT * FROM flt f1 INNER JOIN flt f2 ON f1.f = f2.f;', false);
          Hits: 1  Misses: 1  Evictions: Zero  Overflows: 0  Memory Usage: NkB
          ->  Index Only Scan using flt_f_idx on flt f2 (actual rows=2 loops=N)
                Index Cond: (f = f1.f)
+               Index Bound Cond: (f = f1.f)
                Heap Fetches: N
-(10 rows)
+(11 rows)
 
 -- Ensure memoize operates in binary mode
 SELECT explain_memoize('
@@ -221,8 +228,9 @@ SELECT * FROM flt f1 INNER JOIN flt f2 ON f1.f >= f2.f;', false);
          Hits: 0  Misses: 2  Evictions: Zero  Overflows: 0  Memory Usage: NkB
          ->  Index Only Scan using flt_f_idx on flt f2 (actual rows=2 loops=N)
                Index Cond: (f <= f1.f)
+               Index Bound Cond: (f <= f1.f)
                Heap Fetches: N
-(10 rows)
+(11 rows)
 
 DROP TABLE flt;
 -- Exercise Memoize in binary mode with a large fixed width type and a
@@ -247,7 +255,8 @@ SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.n >= s2.n;', false);
          Hits: 3  Misses: 3  Evictions: Zero  Overflows: 0  Memory Usage: NkB
          ->  Index Scan using strtest_n_idx on strtest s2 (actual rows=4 loops=N)
                Index Cond: (n <= s1.n)
-(8 rows)
+               Index Bound Cond: (n <= s1.n)
+(9 rows)
 
 -- Ensure we get 3 hits and 3 misses
 SELECT explain_memoize('
@@ -262,7 +271,8 @@ SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.t >= s2.t;', false);
          Hits: 3  Misses: 3  Evictions: Zero  Overflows: 0  Memory Usage: NkB
          ->  Index Scan using strtest_t_idx on strtest s2 (actual rows=4 loops=N)
                Index Cond: (t <= s1.t)
-(8 rows)
+               Index Bound Cond: (t <= s1.t)
+(9 rows)
 
 DROP TABLE strtest;
 -- Ensure memoize works with partitionwise join
@@ -289,6 +299,7 @@ SELECT * FROM prt t1 INNER JOIN prt t2 ON t1.a = t2.a;', false);
                Hits: 3  Misses: 1  Evictions: Zero  Overflows: 0  Memory Usage: NkB
                ->  Index Only Scan using iprt_p1_a on prt_p1 t2_1 (actual rows=4 loops=N)
                      Index Cond: (a = t1_1.a)
+                     Index Bound Cond: (a = t1_1.a)
                      Heap Fetches: N
    ->  Nested Loop (actual rows=16 loops=N)
          ->  Index Only Scan using iprt_p2_a on prt_p2 t1_2 (actual rows=4 loops=N)
@@ -299,8 +310,9 @@ SELECT * FROM prt t1 INNER JOIN prt t2 ON t1.a = t2.a;', false);
                Hits: 3  Misses: 1  Evictions: Zero  Overflows: 0  Memory Usage: NkB
                ->  Index Only Scan using iprt_p2_a on prt_p2 t2_2 (actual rows=4 loops=N)
                      Index Cond: (a = t1_2.a)
+                     Index Bound Cond: (a = t1_2.a)
                      Heap Fetches: N
-(21 rows)
+(23 rows)
 
 -- Ensure memoize works with parameterized union-all Append path
 SET enable_partitionwise_join TO off;
@@ -320,11 +332,13 @@ ON t1.a = t2.a;', false);
          ->  Append (actual rows=4 loops=N)
                ->  Index Only Scan using iprt_p1_a on prt_p1 (actual rows=4 loops=N)
                      Index Cond: (a = t1.a)
+                     Index Bound Cond: (a = t1.a)
                      Heap Fetches: N
                ->  Index Only Scan using iprt_p2_a on prt_p2 (actual rows=0 loops=N)
                      Index Cond: (a = t1.a)
+                     Index Bound Cond: (a = t1.a)
                      Heap Fetches: N
-(14 rows)
+(16 rows)
 
 DROP TABLE prt;
 RESET enable_partitionwise_join;
@@ -342,6 +356,7 @@ WHERE unique1 < 3
 ----------------------------------------------------------------
  Index Scan using tenk1_unique1 on tenk1 t0
    Index Cond: (unique1 < 3)
+   Index Bound Cond: (unique1 < 3)
    Filter: EXISTS(SubPlan 1)
    SubPlan 1
      ->  Nested Loop
@@ -352,8 +367,9 @@ WHERE unique1 < 3
                  Cache Mode: logical
                  ->  Index Scan using tenk1_unique1 on tenk1 t1
                        Index Cond: (unique1 = t2.hundred)
+                       Index Bound Cond: (unique1 = t2.hundred)
                        Filter: (t0.ten = twenty)
-(13 rows)
+(15 rows)
 
 -- Ensure the above query returns the correct result
 SELECT unique1 FROM tenk1 t0
@@ -394,12 +410,14 @@ WHERE t1.unique1 < 1000;
                            Recheck Cond: (unique1 < 1000)
                            ->  Bitmap Index Scan on tenk1_unique1
                                  Index Cond: (unique1 < 1000)
+                                 Index Bound Cond: (unique1 < 1000)
                      ->  Memoize
                            Cache Key: t1.twenty
                            Cache Mode: logical
                            ->  Index Only Scan using tenk1_unique1 on tenk1 t2
                                  Index Cond: (unique1 = t1.twenty)
-(14 rows)
+                                 Index Bound Cond: (unique1 = t1.twenty)
+(16 rows)
 
 -- And ensure the parallel plan gives us the correct results.
 SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1,
diff --git a/src/test/regress/expected/misc_functions.out b/src/test/regress/expected/misc_functions.out
index d94056862a..8186f5667e 100644
--- a/src/test/regress/expected/misc_functions.out
+++ b/src/test/regress/expected/misc_functions.out
@@ -566,7 +566,8 @@ WHERE my_int_eq(a.unique2, 42);
          Filter: my_int_eq(unique2, 42)
    ->  Index Scan using tenk1_unique1 on tenk1 b
          Index Cond: (unique1 = a.unique1)
-(5 rows)
+         Index Bound Cond: (unique1 = a.unique1)
+(6 rows)
 
 -- Also test non-default rowcount estimate
 CREATE FUNCTION my_gen_series(int, int) RETURNS SETOF integer
@@ -592,7 +593,8 @@ SELECT * FROM tenk1 a JOIN my_gen_series(1,10) g ON a.unique1 = g;
    ->  Function Scan on my_gen_series g
    ->  Index Scan using tenk1_unique1 on tenk1 a
          Index Cond: (unique1 = g.g)
-(4 rows)
+         Index Bound Cond: (unique1 = g.g)
+(5 rows)
 
 -- Test functions for control data
 SELECT count(*) > 0 AS ok FROM pg_control_checkpoint();
diff --git a/src/test/regress/expected/partition_join.out b/src/test/regress/expected/partition_join.out
index 6d07f86b9b..6f8218fbec 100644
--- a/src/test/regress/expected/partition_join.out
+++ b/src/test/regress/expected/partition_join.out
@@ -173,7 +173,8 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHE
                      Filter: (a = 0)
                ->  Index Scan using iprt1_p3_a on prt1_p3 t1_3
                      Index Cond: (a = t2_3.b)
-(20 rows)
+                     Index Bound Cond: (a = t2_3.b)
+(21 rows)
 
 SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHT JOIN prt2 t2 ON t1.a = t2.b WHERE t2.a = 0 ORDER BY t1.a, t2.b;
   a  |  c   |  b  |  c   
@@ -413,25 +414,31 @@ SELECT * FROM prt1 t1 LEFT JOIN LATERAL
                ->  Nested Loop
                      ->  Index Only Scan using iprt1_p1_a on prt1_p1 t2_1
                            Index Cond: (a = t1_1.a)
+                           Index Bound Cond: (a = t1_1.a)
                      ->  Index Scan using iprt2_p1_b on prt2_p1 t3_1
                            Index Cond: (b = t2_1.a)
+                           Index Bound Cond: (b = t2_1.a)
          ->  Nested Loop Left Join
                ->  Seq Scan on prt1_p2 t1_2
                      Filter: (b = 0)
                ->  Nested Loop
                      ->  Index Only Scan using iprt1_p2_a on prt1_p2 t2_2
                            Index Cond: (a = t1_2.a)
+                           Index Bound Cond: (a = t1_2.a)
                      ->  Index Scan using iprt2_p2_b on prt2_p2 t3_2
                            Index Cond: (b = t2_2.a)
+                           Index Bound Cond: (b = t2_2.a)
          ->  Nested Loop Left Join
                ->  Seq Scan on prt1_p3 t1_3
                      Filter: (b = 0)
                ->  Nested Loop
                      ->  Index Only Scan using iprt1_p3_a on prt1_p3 t2_3
                            Index Cond: (a = t1_3.a)
+                           Index Bound Cond: (a = t1_3.a)
                      ->  Index Scan using iprt2_p3_b on prt2_p3 t3_3
                            Index Cond: (b = t2_3.a)
-(27 rows)
+                           Index Bound Cond: (b = t2_3.a)
+(33 rows)
 
 SELECT * FROM prt1 t1 LEFT JOIN LATERAL
 			  (SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.b) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss
@@ -543,18 +550,21 @@ SELECT count(*) FROM prt1 t1 LEFT JOIN LATERAL
                ->  Seq Scan on prt1_p1 t1_1
                ->  Index Scan using iprt2_p1_b on prt2_p1 t2_1
                      Index Cond: (b = t1_1.a)
+                     Index Bound Cond: (b = t1_1.a)
                      Filter: (t1_1.b = a)
          ->  Nested Loop
                ->  Seq Scan on prt1_p2 t1_2
                ->  Index Scan using iprt2_p2_b on prt2_p2 t2_2
                      Index Cond: (b = t1_2.a)
+                     Index Bound Cond: (b = t1_2.a)
                      Filter: (t1_2.b = a)
          ->  Nested Loop
                ->  Seq Scan on prt1_p3 t1_3
                ->  Index Scan using iprt2_p3_b on prt2_p3 t2_3
                      Index Cond: (b = t1_3.a)
+                     Index Bound Cond: (b = t1_3.a)
                      Filter: (t1_3.b = a)
-(17 rows)
+(20 rows)
 
 SELECT count(*) FROM prt1 t1 LEFT JOIN LATERAL
 			  (SELECT t1.b AS t1b, t2.* FROM prt2 t2) s
@@ -576,18 +586,21 @@ SELECT count(*) FROM prt1 t1 LEFT JOIN LATERAL
                ->  Seq Scan on prt1_p1 t1_1
                ->  Index Only Scan using iprt2_p1_b on prt2_p1 t2_1
                      Index Cond: (b = t1_1.a)
+                     Index Bound Cond: (b = t1_1.a)
                      Filter: (b = t1_1.b)
          ->  Nested Loop
                ->  Seq Scan on prt1_p2 t1_2
                ->  Index Only Scan using iprt2_p2_b on prt2_p2 t2_2
                      Index Cond: (b = t1_2.a)
+                     Index Bound Cond: (b = t1_2.a)
                      Filter: (b = t1_2.b)
          ->  Nested Loop
                ->  Seq Scan on prt1_p3 t1_3
                ->  Index Only Scan using iprt2_p3_b on prt2_p3 t2_3
                      Index Cond: (b = t1_3.a)
+                     Index Bound Cond: (b = t1_3.a)
                      Filter: (b = t1_3.b)
-(17 rows)
+(20 rows)
 
 SELECT count(*) FROM prt1 t1 LEFT JOIN LATERAL
 			  (SELECT t1.b AS t1b, t2.* FROM prt2 t2) s
@@ -748,6 +761,7 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t
                                  Filter: (b = 0)
                ->  Index Scan using iprt1_e_p1_ab2 on prt1_e_p1 t3_1
                      Index Cond: (((a + b) / 2) = t2_1.b)
+                     Index Bound Cond: (((a + b) / 2) = t2_1.b)
          ->  Nested Loop
                Join Filter: (t1_2.a = ((t3_2.a + t3_2.b) / 2))
                ->  Hash Join
@@ -758,6 +772,7 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t
                                  Filter: (b = 0)
                ->  Index Scan using iprt1_e_p2_ab2 on prt1_e_p2 t3_2
                      Index Cond: (((a + b) / 2) = t2_2.b)
+                     Index Bound Cond: (((a + b) / 2) = t2_2.b)
          ->  Nested Loop
                Join Filter: (t1_3.a = ((t3_3.a + t3_3.b) / 2))
                ->  Hash Join
@@ -768,7 +783,8 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t
                                  Filter: (b = 0)
                ->  Index Scan using iprt1_e_p3_ab2 on prt1_e_p3 t3_3
                      Index Cond: (((a + b) / 2) = t2_3.b)
-(33 rows)
+                     Index Bound Cond: (((a + b) / 2) = t2_3.b)
+(36 rows)
 
 SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2 AND t1.b = 0 ORDER BY t1.a, t2.b;
   a  |  c   |  b  |  c   | ?column? | c 
@@ -851,6 +867,7 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2
                                  Filter: (c = 0)
                ->  Index Scan using iprt2_p1_b on prt2_p1 t2_1
                      Index Cond: (b = t1_1.a)
+                     Index Bound Cond: (b = t1_1.a)
          ->  Nested Loop Left Join
                ->  Hash Right Join
                      Hash Cond: (t1_2.a = ((t3_2.a + t3_2.b) / 2))
@@ -860,6 +877,7 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2
                                  Filter: (c = 0)
                ->  Index Scan using iprt2_p2_b on prt2_p2 t2_2
                      Index Cond: (b = t1_2.a)
+                     Index Bound Cond: (b = t1_2.a)
          ->  Nested Loop Left Join
                ->  Hash Right Join
                      Hash Cond: (t1_3.a = ((t3_3.a + t3_3.b) / 2))
@@ -869,7 +887,8 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2
                                  Filter: (c = 0)
                ->  Index Scan using iprt2_p3_b on prt2_p3 t2_3
                      Index Cond: (b = t1_3.a)
-(30 rows)
+                     Index Bound Cond: (b = t1_3.a)
+(33 rows)
 
 SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.c = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
   a  |  c   |  b  |  c   | ?column? | c 
@@ -1075,6 +1094,7 @@ SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHER
                                        Filter: (a = 0)
                ->  Index Scan using iprt1_p1_a on prt1_p1 t1_2
                      Index Cond: (a = ((t2_1.a + t2_1.b) / 2))
+                     Index Bound Cond: (a = ((t2_1.a + t2_1.b) / 2))
                      Filter: (b = 0)
          ->  Nested Loop
                Join Filter: (t1_3.a = t1_6.b)
@@ -1088,6 +1108,7 @@ SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHER
                                        Filter: (a = 0)
                ->  Index Scan using iprt1_p2_a on prt1_p2 t1_3
                      Index Cond: (a = ((t2_2.a + t2_2.b) / 2))
+                     Index Bound Cond: (a = ((t2_2.a + t2_2.b) / 2))
                      Filter: (b = 0)
          ->  Nested Loop
                Join Filter: (t1_4.a = t1_7.b)
@@ -1098,10 +1119,12 @@ SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHER
                                  Filter: (a = 0)
                            ->  Index Scan using iprt1_e_p3_ab2 on prt1_e_p3 t2_3
                                  Index Cond: (((a + b) / 2) = t1_7.b)
+                                 Index Bound Cond: (((a + b) / 2) = t1_7.b)
                ->  Index Scan using iprt1_p3_a on prt1_p3 t1_4
                      Index Cond: (a = ((t2_3.a + t2_3.b) / 2))
+                     Index Bound Cond: (a = ((t2_3.a + t2_3.b) / 2))
                      Filter: (b = 0)
-(41 rows)
+(45 rows)
 
 SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.a = 0 AND t1.b = (t2.a + t2.b)/2) AND t1.b = 0 ORDER BY t1.a;
   a  | b |  c   
@@ -1130,6 +1153,7 @@ SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (
                                        Filter: (c = 0)
                ->  Index Scan using iprt1_p1_a on prt1_p1 t1_3
                      Index Cond: (a = t1_6.b)
+                     Index Bound Cond: (a = t1_6.b)
                      Filter: (b = 0)
          ->  Nested Loop
                ->  HashAggregate
@@ -1142,6 +1166,7 @@ SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (
                                        Filter: (c = 0)
                ->  Index Scan using iprt1_p2_a on prt1_p2 t1_4
                      Index Cond: (a = t1_7.b)
+                     Index Bound Cond: (a = t1_7.b)
                      Filter: (b = 0)
          ->  Nested Loop
                ->  HashAggregate
@@ -1154,8 +1179,9 @@ SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (
                                        Filter: (c = 0)
                ->  Index Scan using iprt1_p3_a on prt1_p3 t1_5
                      Index Cond: (a = t1_8.b)
+                     Index Bound Cond: (a = t1_8.b)
                      Filter: (b = 0)
-(39 rows)
+(42 rows)
 
 SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2 FROM prt1_e t1 WHERE t1.c = 0)) AND t1.b = 0 ORDER BY t1.a;
   a  | b |  c   
@@ -2249,11 +2275,14 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON (t1.a < t2.b);
    ->  Append
          ->  Index Scan using iprt2_p1_b on prt2_p1 t2_1
                Index Cond: (b > t1.a)
+               Index Bound Cond: (b > t1.a)
          ->  Index Scan using iprt2_p2_b on prt2_p2 t2_2
                Index Cond: (b > t1.a)
+               Index Bound Cond: (b > t1.a)
          ->  Index Scan using iprt2_p3_b on prt2_p3 t2_3
                Index Cond: (b > t1.a)
-(12 rows)
+               Index Bound Cond: (b > t1.a)
+(15 rows)
 
 -- equi-join with join condition on partial keys does not qualify for
 -- partitionwise join
@@ -2409,8 +2438,10 @@ where not exists (select 1 from prtx2
                ->  BitmapAnd
                      ->  Bitmap Index Scan on prtx2_1_b_idx
                            Index Cond: (b = prtx1_1.b)
+                           Index Bound Cond: (b = prtx1_1.b)
                      ->  Bitmap Index Scan on prtx2_1_c_idx
                            Index Cond: (c = 123)
+                           Index Bound Cond: (c = 123)
    ->  Nested Loop Anti Join
          ->  Seq Scan on prtx1_2
                Filter: ((a < 20) AND (c = 120))
@@ -2420,9 +2451,11 @@ where not exists (select 1 from prtx2
                ->  BitmapAnd
                      ->  Bitmap Index Scan on prtx2_2_b_idx
                            Index Cond: (b = prtx1_2.b)
+                           Index Bound Cond: (b = prtx1_2.b)
                      ->  Bitmap Index Scan on prtx2_2_c_idx
                            Index Cond: (c = 123)
-(23 rows)
+                           Index Bound Cond: (c = 123)
+(27 rows)
 
 select * from prtx1
 where not exists (select 1 from prtx2
@@ -2438,8 +2471,8 @@ select * from prtx1
 where not exists (select 1 from prtx2
                   where prtx2.a=prtx1.a and (prtx2.b=prtx1.b+1 or prtx2.c=99))
   and a<20 and c=91;
-                           QUERY PLAN                            
------------------------------------------------------------------
+                            QUERY PLAN                             
+-------------------------------------------------------------------
  Append
    ->  Nested Loop Anti Join
          ->  Seq Scan on prtx1_1
@@ -2450,8 +2483,10 @@ where not exists (select 1 from prtx2
                ->  BitmapOr
                      ->  Bitmap Index Scan on prtx2_1_b_idx
                            Index Cond: (b = (prtx1_1.b + 1))
+                           Index Bound Cond: (b = (prtx1_1.b + 1))
                      ->  Bitmap Index Scan on prtx2_1_c_idx
                            Index Cond: (c = 99)
+                           Index Bound Cond: (c = 99)
    ->  Nested Loop Anti Join
          ->  Seq Scan on prtx1_2
                Filter: ((a < 20) AND (c = 91))
@@ -2461,9 +2496,11 @@ where not exists (select 1 from prtx2
                ->  BitmapOr
                      ->  Bitmap Index Scan on prtx2_2_b_idx
                            Index Cond: (b = (prtx1_2.b + 1))
+                           Index Bound Cond: (b = (prtx1_2.b + 1))
                      ->  Bitmap Index Scan on prtx2_2_c_idx
                            Index Cond: (c = 99)
-(23 rows)
+                           Index Bound Cond: (c = 99)
+(27 rows)
 
 select * from prtx1
 where not exists (select 1 from prtx2
@@ -2963,8 +3000,10 @@ SELECT t1.b, t1.c, t2.a, t2.c, t3.a, t3.c FROM prt2_adv t1 LEFT JOIN prt1_adv t2
                            Filter: (a = 0)
                      ->  Index Scan using prt1_adv_p1_a_idx on prt1_adv_p1 t3_1
                            Index Cond: (a = t1_1.b)
+                           Index Bound Cond: (a = t1_1.b)
                ->  Index Scan using prt1_adv_p1_a_idx on prt1_adv_p1 t2_1
                      Index Cond: (a = t1_1.b)
+                     Index Bound Cond: (a = t1_1.b)
          ->  Hash Right Join
                Hash Cond: (t2_2.a = t1_2.b)
                ->  Seq Scan on prt1_adv_p2 t2_2
@@ -2985,7 +3024,7 @@ SELECT t1.b, t1.c, t2.a, t2.c, t3.a, t3.c FROM prt2_adv t1 LEFT JOIN prt1_adv t2
                            ->  Hash
                                  ->  Seq Scan on prt2_adv_p3 t1_3
                                        Filter: (a = 0)
-(31 rows)
+(33 rows)
 
 SELECT t1.b, t1.c, t2.a, t2.c, t3.a, t3.c FROM prt2_adv t1 LEFT JOIN prt1_adv t2 ON (t1.b = t2.a) INNER JOIN prt1_adv t3 ON (t1.b = t3.a) WHERE t1.a = 0 ORDER BY t1.b, t2.a, t3.a;
   b  |  c   |  a  |  c   |  a  |  c   
@@ -5123,11 +5162,13 @@ SELECT x.id, y.id FROM fract_t x LEFT JOIN fract_t y USING (id) ORDER BY x.id DE
                ->  Index Only Scan Backward using fract_t0_pkey on fract_t0 x_1
                ->  Index Only Scan using fract_t0_pkey on fract_t0 y_1
                      Index Cond: (id = x_1.id)
+                     Index Bound Cond: (id = x_1.id)
          ->  Nested Loop Left Join
                ->  Index Only Scan Backward using fract_t1_pkey on fract_t1 x_2
                ->  Index Only Scan using fract_t1_pkey on fract_t1 y_2
                      Index Cond: (id = x_2.id)
-(11 rows)
+                     Index Bound Cond: (id = x_2.id)
+(13 rows)
 
 -- cleanup
 DROP TABLE fract_t;
diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out
index 7ca98397ae..ddb139fe3f 100644
--- a/src/test/regress/expected/partition_prune.out
+++ b/src/test/regress/expected/partition_prune.out
@@ -2463,23 +2463,32 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on
                      ->  Append (actual rows=N loops=N)
                            ->  Index Scan using ab_a1_b1_a_idx on ab_a1_b1 ab_1 (actual rows=N loops=N)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a1_b2_a_idx on ab_a1_b2 ab_2 (actual rows=N loops=N)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a1_b3_a_idx on ab_a1_b3 ab_3 (actual rows=N loops=N)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a2_b1_a_idx on ab_a2_b1 ab_4 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a2_b2_a_idx on ab_a2_b2 ab_5 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a2_b3_a_idx on ab_a2_b3 ab_6 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a3_b1_a_idx on ab_a3_b1 ab_7 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a3_b2_a_idx on ab_a3_b2 ab_8 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a3_b3_a_idx on ab_a3_b3 ab_9 (never executed)
                                  Index Cond: (a = a.a)
-(27 rows)
+                                 Index Bound Cond: (a = a.a)
+(36 rows)
 
 -- Ensure the same partitions are pruned when we make the nested loop
 -- parameter an Expr rather than a plain Param.
@@ -2497,23 +2506,32 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on
                      ->  Append (actual rows=N loops=N)
                            ->  Index Scan using ab_a1_b1_a_idx on ab_a1_b1 ab_1 (actual rows=N loops=N)
                                  Index Cond: (a = (a.a + 0))
+                                 Index Bound Cond: (a = (a.a + 0))
                            ->  Index Scan using ab_a1_b2_a_idx on ab_a1_b2 ab_2 (actual rows=N loops=N)
                                  Index Cond: (a = (a.a + 0))
+                                 Index Bound Cond: (a = (a.a + 0))
                            ->  Index Scan using ab_a1_b3_a_idx on ab_a1_b3 ab_3 (actual rows=N loops=N)
                                  Index Cond: (a = (a.a + 0))
+                                 Index Bound Cond: (a = (a.a + 0))
                            ->  Index Scan using ab_a2_b1_a_idx on ab_a2_b1 ab_4 (never executed)
                                  Index Cond: (a = (a.a + 0))
+                                 Index Bound Cond: (a = (a.a + 0))
                            ->  Index Scan using ab_a2_b2_a_idx on ab_a2_b2 ab_5 (never executed)
                                  Index Cond: (a = (a.a + 0))
+                                 Index Bound Cond: (a = (a.a + 0))
                            ->  Index Scan using ab_a2_b3_a_idx on ab_a2_b3 ab_6 (never executed)
                                  Index Cond: (a = (a.a + 0))
+                                 Index Bound Cond: (a = (a.a + 0))
                            ->  Index Scan using ab_a3_b1_a_idx on ab_a3_b1 ab_7 (never executed)
                                  Index Cond: (a = (a.a + 0))
+                                 Index Bound Cond: (a = (a.a + 0))
                            ->  Index Scan using ab_a3_b2_a_idx on ab_a3_b2 ab_8 (never executed)
                                  Index Cond: (a = (a.a + 0))
+                                 Index Bound Cond: (a = (a.a + 0))
                            ->  Index Scan using ab_a3_b3_a_idx on ab_a3_b3 ab_9 (never executed)
                                  Index Cond: (a = (a.a + 0))
-(27 rows)
+                                 Index Bound Cond: (a = (a.a + 0))
+(36 rows)
 
 insert into lprt_a values(3),(3);
 select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a where a.a in(1, 0, 3)');
@@ -2530,23 +2548,32 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on
                      ->  Append (actual rows=N loops=N)
                            ->  Index Scan using ab_a1_b1_a_idx on ab_a1_b1 ab_1 (actual rows=N loops=N)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a1_b2_a_idx on ab_a1_b2 ab_2 (actual rows=N loops=N)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a1_b3_a_idx on ab_a1_b3 ab_3 (actual rows=N loops=N)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a2_b1_a_idx on ab_a2_b1 ab_4 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a2_b2_a_idx on ab_a2_b2 ab_5 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a2_b3_a_idx on ab_a2_b3 ab_6 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a3_b1_a_idx on ab_a3_b1 ab_7 (actual rows=N loops=N)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a3_b2_a_idx on ab_a3_b2 ab_8 (actual rows=N loops=N)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a3_b3_a_idx on ab_a3_b3 ab_9 (actual rows=N loops=N)
                                  Index Cond: (a = a.a)
-(27 rows)
+                                 Index Bound Cond: (a = a.a)
+(36 rows)
 
 select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a where a.a in(1, 0, 0)');
                                         explain_parallel_append                                         
@@ -2563,23 +2590,32 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on
                      ->  Append (actual rows=N loops=N)
                            ->  Index Scan using ab_a1_b1_a_idx on ab_a1_b1 ab_1 (actual rows=N loops=N)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a1_b2_a_idx on ab_a1_b2 ab_2 (actual rows=N loops=N)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a1_b3_a_idx on ab_a1_b3 ab_3 (actual rows=N loops=N)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a2_b1_a_idx on ab_a2_b1 ab_4 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a2_b2_a_idx on ab_a2_b2 ab_5 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a2_b3_a_idx on ab_a2_b3 ab_6 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a3_b1_a_idx on ab_a3_b1 ab_7 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a3_b2_a_idx on ab_a3_b2 ab_8 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a3_b3_a_idx on ab_a3_b3 ab_9 (never executed)
                                  Index Cond: (a = a.a)
-(28 rows)
+                                 Index Bound Cond: (a = a.a)
+(37 rows)
 
 delete from lprt_a where a = 1;
 select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a where a.a in(1, 0, 0)');
@@ -2597,23 +2633,32 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on
                      ->  Append (actual rows=N loops=N)
                            ->  Index Scan using ab_a1_b1_a_idx on ab_a1_b1 ab_1 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a1_b2_a_idx on ab_a1_b2 ab_2 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a1_b3_a_idx on ab_a1_b3 ab_3 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a2_b1_a_idx on ab_a2_b1 ab_4 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a2_b2_a_idx on ab_a2_b2 ab_5 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a2_b3_a_idx on ab_a2_b3 ab_6 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a3_b1_a_idx on ab_a3_b1 ab_7 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a3_b2_a_idx on ab_a3_b2 ab_8 (never executed)
                                  Index Cond: (a = a.a)
+                                 Index Bound Cond: (a = a.a)
                            ->  Index Scan using ab_a3_b3_a_idx on ab_a3_b3 ab_9 (never executed)
                                  Index Cond: (a = a.a)
-(28 rows)
+                                 Index Bound Cond: (a = a.a)
+(37 rows)
 
 reset enable_hashjoin;
 reset enable_mergejoin;
@@ -2639,47 +2684,56 @@ select * from ab where a = (select max(a) from lprt_a) and b = (select max(a)-1
          Filter: (b = (InitPlan 2).col1)
          ->  Bitmap Index Scan on ab_a1_b1_a_idx (never executed)
                Index Cond: (a = (InitPlan 1).col1)
+               Index Bound Cond: (a = (InitPlan 1).col1)
    ->  Bitmap Heap Scan on ab_a1_b2 ab_2 (never executed)
          Recheck Cond: (a = (InitPlan 1).col1)
          Filter: (b = (InitPlan 2).col1)
          ->  Bitmap Index Scan on ab_a1_b2_a_idx (never executed)
                Index Cond: (a = (InitPlan 1).col1)
+               Index Bound Cond: (a = (InitPlan 1).col1)
    ->  Bitmap Heap Scan on ab_a1_b3 ab_3 (never executed)
          Recheck Cond: (a = (InitPlan 1).col1)
          Filter: (b = (InitPlan 2).col1)
          ->  Bitmap Index Scan on ab_a1_b3_a_idx (never executed)
                Index Cond: (a = (InitPlan 1).col1)
+               Index Bound Cond: (a = (InitPlan 1).col1)
    ->  Bitmap Heap Scan on ab_a2_b1 ab_4 (never executed)
          Recheck Cond: (a = (InitPlan 1).col1)
          Filter: (b = (InitPlan 2).col1)
          ->  Bitmap Index Scan on ab_a2_b1_a_idx (never executed)
                Index Cond: (a = (InitPlan 1).col1)
+               Index Bound Cond: (a = (InitPlan 1).col1)
    ->  Bitmap Heap Scan on ab_a2_b2 ab_5 (never executed)
          Recheck Cond: (a = (InitPlan 1).col1)
          Filter: (b = (InitPlan 2).col1)
          ->  Bitmap Index Scan on ab_a2_b2_a_idx (never executed)
                Index Cond: (a = (InitPlan 1).col1)
+               Index Bound Cond: (a = (InitPlan 1).col1)
    ->  Bitmap Heap Scan on ab_a2_b3 ab_6 (never executed)
          Recheck Cond: (a = (InitPlan 1).col1)
          Filter: (b = (InitPlan 2).col1)
          ->  Bitmap Index Scan on ab_a2_b3_a_idx (never executed)
                Index Cond: (a = (InitPlan 1).col1)
+               Index Bound Cond: (a = (InitPlan 1).col1)
    ->  Bitmap Heap Scan on ab_a3_b1 ab_7 (never executed)
          Recheck Cond: (a = (InitPlan 1).col1)
          Filter: (b = (InitPlan 2).col1)
          ->  Bitmap Index Scan on ab_a3_b1_a_idx (never executed)
                Index Cond: (a = (InitPlan 1).col1)
+               Index Bound Cond: (a = (InitPlan 1).col1)
    ->  Bitmap Heap Scan on ab_a3_b2 ab_8 (actual rows=0 loops=1)
          Recheck Cond: (a = (InitPlan 1).col1)
          Filter: (b = (InitPlan 2).col1)
          ->  Bitmap Index Scan on ab_a3_b2_a_idx (actual rows=0 loops=1)
                Index Cond: (a = (InitPlan 1).col1)
+               Index Bound Cond: (a = (InitPlan 1).col1)
    ->  Bitmap Heap Scan on ab_a3_b3 ab_9 (never executed)
          Recheck Cond: (a = (InitPlan 1).col1)
          Filter: (b = (InitPlan 2).col1)
          ->  Bitmap Index Scan on ab_a3_b3_a_idx (never executed)
                Index Cond: (a = (InitPlan 1).col1)
-(52 rows)
+               Index Bound Cond: (a = (InitPlan 1).col1)
+(61 rows)
 
 -- Test run-time partition pruning with UNION ALL parents
 explain (analyze, costs off, summary off, timing off)
@@ -2695,16 +2749,19 @@ select * from (select * from ab where a = 1 union all select * from ab) ab where
                Filter: (b = (InitPlan 1).col1)
                ->  Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1)
                      Index Cond: (a = 1)
+                     Index Bound Cond: (a = 1)
          ->  Bitmap Heap Scan on ab_a1_b2 ab_12 (never executed)
                Recheck Cond: (a = 1)
                Filter: (b = (InitPlan 1).col1)
                ->  Bitmap Index Scan on ab_a1_b2_a_idx (never executed)
                      Index Cond: (a = 1)
+                     Index Bound Cond: (a = 1)
          ->  Bitmap Heap Scan on ab_a1_b3 ab_13 (never executed)
                Recheck Cond: (a = 1)
                Filter: (b = (InitPlan 1).col1)
                ->  Bitmap Index Scan on ab_a1_b3_a_idx (never executed)
                      Index Cond: (a = 1)
+                     Index Bound Cond: (a = 1)
    ->  Seq Scan on ab_a1_b1 ab_1 (actual rows=0 loops=1)
          Filter: (b = (InitPlan 1).col1)
    ->  Seq Scan on ab_a1_b2 ab_2 (never executed)
@@ -2723,7 +2780,7 @@ select * from (select * from ab where a = 1 union all select * from ab) ab where
          Filter: (b = (InitPlan 1).col1)
    ->  Seq Scan on ab_a3_b3 ab_9 (never executed)
          Filter: (b = (InitPlan 1).col1)
-(37 rows)
+(40 rows)
 
 -- A case containing a UNION ALL with a non-partitioned child.
 explain (analyze, costs off, summary off, timing off)
@@ -2739,16 +2796,19 @@ select * from (select * from ab where a = 1 union all (values(10,5)) union all s
                Filter: (b = (InitPlan 1).col1)
                ->  Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1)
                      Index Cond: (a = 1)
+                     Index Bound Cond: (a = 1)
          ->  Bitmap Heap Scan on ab_a1_b2 ab_12 (never executed)
                Recheck Cond: (a = 1)
                Filter: (b = (InitPlan 1).col1)
                ->  Bitmap Index Scan on ab_a1_b2_a_idx (never executed)
                      Index Cond: (a = 1)
+                     Index Bound Cond: (a = 1)
          ->  Bitmap Heap Scan on ab_a1_b3 ab_13 (never executed)
                Recheck Cond: (a = 1)
                Filter: (b = (InitPlan 1).col1)
                ->  Bitmap Index Scan on ab_a1_b3_a_idx (never executed)
                      Index Cond: (a = 1)
+                     Index Bound Cond: (a = 1)
    ->  Result (actual rows=0 loops=1)
          One-Time Filter: (5 = (InitPlan 1).col1)
    ->  Seq Scan on ab_a1_b1 ab_1 (actual rows=0 loops=1)
@@ -2769,7 +2829,7 @@ select * from (select * from ab where a = 1 union all (values(10,5)) union all s
          Filter: (b = (InitPlan 1).col1)
    ->  Seq Scan on ab_a3_b3 ab_9 (never executed)
          Filter: (b = (InitPlan 1).col1)
-(39 rows)
+(42 rows)
 
 -- Another UNION ALL test, but containing a mix of exec init and exec run-time pruning.
 create table xy_1 (x int, y int);
@@ -2840,33 +2900,39 @@ update ab_a1 set b = 3 from ab where ab.a = 1 and ab.a = ab_a1.a;
                      Recheck Cond: (a = 1)
                      ->  Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1)
                            Index Cond: (a = 1)
+                           Index Bound Cond: (a = 1)
                ->  Bitmap Heap Scan on ab_a1_b2 ab_a1_2 (actual rows=1 loops=1)
                      Recheck Cond: (a = 1)
                      Heap Blocks: exact=1
                      ->  Bitmap Index Scan on ab_a1_b2_a_idx (actual rows=1 loops=1)
                            Index Cond: (a = 1)
+                           Index Bound Cond: (a = 1)
                ->  Bitmap Heap Scan on ab_a1_b3 ab_a1_3 (actual rows=0 loops=1)
                      Recheck Cond: (a = 1)
                      Heap Blocks: exact=1
                      ->  Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1)
                            Index Cond: (a = 1)
+                           Index Bound Cond: (a = 1)
          ->  Materialize (actual rows=1 loops=1)
                ->  Append (actual rows=1 loops=1)
                      ->  Bitmap Heap Scan on ab_a1_b1 ab_1 (actual rows=0 loops=1)
                            Recheck Cond: (a = 1)
                            ->  Bitmap Index Scan on ab_a1_b1_a_idx (actual rows=0 loops=1)
                                  Index Cond: (a = 1)
+                                 Index Bound Cond: (a = 1)
                      ->  Bitmap Heap Scan on ab_a1_b2 ab_2 (actual rows=1 loops=1)
                            Recheck Cond: (a = 1)
                            Heap Blocks: exact=1
                            ->  Bitmap Index Scan on ab_a1_b2_a_idx (actual rows=1 loops=1)
                                  Index Cond: (a = 1)
+                                 Index Bound Cond: (a = 1)
                      ->  Bitmap Heap Scan on ab_a1_b3 ab_3 (actual rows=0 loops=1)
                            Recheck Cond: (a = 1)
                            Heap Blocks: exact=1
                            ->  Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1)
                                  Index Cond: (a = 1)
-(36 rows)
+                                 Index Bound Cond: (a = 1)
+(42 rows)
 
 table ab;
  a | b 
@@ -2941,17 +3007,23 @@ select * from tbl1 join tprt on tbl1.col1 > tprt.col1;
    ->  Append (actual rows=3 loops=2)
          ->  Index Scan using tprt1_idx on tprt_1 (actual rows=2 loops=2)
                Index Cond: (col1 < tbl1.col1)
+               Index Bound Cond: (col1 < tbl1.col1)
          ->  Index Scan using tprt2_idx on tprt_2 (actual rows=2 loops=1)
                Index Cond: (col1 < tbl1.col1)
+               Index Bound Cond: (col1 < tbl1.col1)
          ->  Index Scan using tprt3_idx on tprt_3 (never executed)
                Index Cond: (col1 < tbl1.col1)
+               Index Bound Cond: (col1 < tbl1.col1)
          ->  Index Scan using tprt4_idx on tprt_4 (never executed)
                Index Cond: (col1 < tbl1.col1)
+               Index Bound Cond: (col1 < tbl1.col1)
          ->  Index Scan using tprt5_idx on tprt_5 (never executed)
                Index Cond: (col1 < tbl1.col1)
+               Index Bound Cond: (col1 < tbl1.col1)
          ->  Index Scan using tprt6_idx on tprt_6 (never executed)
                Index Cond: (col1 < tbl1.col1)
-(15 rows)
+               Index Bound Cond: (col1 < tbl1.col1)
+(21 rows)
 
 explain (analyze, costs off, summary off, timing off)
 select * from tbl1 join tprt on tbl1.col1 = tprt.col1;
@@ -2962,17 +3034,23 @@ select * from tbl1 join tprt on tbl1.col1 = tprt.col1;
    ->  Append (actual rows=1 loops=2)
          ->  Index Scan using tprt1_idx on tprt_1 (never executed)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt2_idx on tprt_2 (actual rows=1 loops=2)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt3_idx on tprt_3 (never executed)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt4_idx on tprt_4 (never executed)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt5_idx on tprt_5 (never executed)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt6_idx on tprt_6 (never executed)
                Index Cond: (col1 = tbl1.col1)
-(15 rows)
+               Index Bound Cond: (col1 = tbl1.col1)
+(21 rows)
 
 select tbl1.col1, tprt.col1 from tbl1
 inner join tprt on tbl1.col1 > tprt.col1
@@ -3007,17 +3085,23 @@ select * from tbl1 inner join tprt on tbl1.col1 > tprt.col1;
    ->  Append (actual rows=5 loops=5)
          ->  Index Scan using tprt1_idx on tprt_1 (actual rows=2 loops=5)
                Index Cond: (col1 < tbl1.col1)
+               Index Bound Cond: (col1 < tbl1.col1)
          ->  Index Scan using tprt2_idx on tprt_2 (actual rows=3 loops=4)
                Index Cond: (col1 < tbl1.col1)
+               Index Bound Cond: (col1 < tbl1.col1)
          ->  Index Scan using tprt3_idx on tprt_3 (actual rows=1 loops=2)
                Index Cond: (col1 < tbl1.col1)
+               Index Bound Cond: (col1 < tbl1.col1)
          ->  Index Scan using tprt4_idx on tprt_4 (never executed)
                Index Cond: (col1 < tbl1.col1)
+               Index Bound Cond: (col1 < tbl1.col1)
          ->  Index Scan using tprt5_idx on tprt_5 (never executed)
                Index Cond: (col1 < tbl1.col1)
+               Index Bound Cond: (col1 < tbl1.col1)
          ->  Index Scan using tprt6_idx on tprt_6 (never executed)
                Index Cond: (col1 < tbl1.col1)
-(15 rows)
+               Index Bound Cond: (col1 < tbl1.col1)
+(21 rows)
 
 explain (analyze, costs off, summary off, timing off)
 select * from tbl1 inner join tprt on tbl1.col1 = tprt.col1;
@@ -3028,17 +3112,23 @@ select * from tbl1 inner join tprt on tbl1.col1 = tprt.col1;
    ->  Append (actual rows=1 loops=5)
          ->  Index Scan using tprt1_idx on tprt_1 (never executed)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt2_idx on tprt_2 (actual rows=1 loops=2)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt3_idx on tprt_3 (actual rows=0 loops=3)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt4_idx on tprt_4 (never executed)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt5_idx on tprt_5 (never executed)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt6_idx on tprt_6 (never executed)
                Index Cond: (col1 = tbl1.col1)
-(15 rows)
+               Index Bound Cond: (col1 = tbl1.col1)
+(21 rows)
 
 select tbl1.col1, tprt.col1 from tbl1
 inner join tprt on tbl1.col1 > tprt.col1
@@ -3092,17 +3182,23 @@ select * from tbl1 join tprt on tbl1.col1 < tprt.col1;
    ->  Append (actual rows=1 loops=1)
          ->  Index Scan using tprt1_idx on tprt_1 (never executed)
                Index Cond: (col1 > tbl1.col1)
+               Index Bound Cond: (col1 > tbl1.col1)
          ->  Index Scan using tprt2_idx on tprt_2 (never executed)
                Index Cond: (col1 > tbl1.col1)
+               Index Bound Cond: (col1 > tbl1.col1)
          ->  Index Scan using tprt3_idx on tprt_3 (never executed)
                Index Cond: (col1 > tbl1.col1)
+               Index Bound Cond: (col1 > tbl1.col1)
          ->  Index Scan using tprt4_idx on tprt_4 (never executed)
                Index Cond: (col1 > tbl1.col1)
+               Index Bound Cond: (col1 > tbl1.col1)
          ->  Index Scan using tprt5_idx on tprt_5 (never executed)
                Index Cond: (col1 > tbl1.col1)
+               Index Bound Cond: (col1 > tbl1.col1)
          ->  Index Scan using tprt6_idx on tprt_6 (actual rows=1 loops=1)
                Index Cond: (col1 > tbl1.col1)
-(15 rows)
+               Index Bound Cond: (col1 > tbl1.col1)
+(21 rows)
 
 select tbl1.col1, tprt.col1 from tbl1
 inner join tprt on tbl1.col1 < tprt.col1
@@ -3124,17 +3220,23 @@ select * from tbl1 join tprt on tbl1.col1 = tprt.col1;
    ->  Append (actual rows=0 loops=1)
          ->  Index Scan using tprt1_idx on tprt_1 (never executed)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt2_idx on tprt_2 (never executed)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt3_idx on tprt_3 (never executed)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt4_idx on tprt_4 (never executed)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt5_idx on tprt_5 (never executed)
                Index Cond: (col1 = tbl1.col1)
+               Index Bound Cond: (col1 = tbl1.col1)
          ->  Index Scan using tprt6_idx on tprt_6 (never executed)
                Index Cond: (col1 = tbl1.col1)
-(15 rows)
+               Index Bound Cond: (col1 = tbl1.col1)
+(21 rows)
 
 select tbl1.col1, tprt.col1 from tbl1
 inner join tprt on tbl1.col1 = tprt.col1
@@ -3533,13 +3635,14 @@ explain (analyze, costs off, summary off, timing off) select * from ma_test wher
              ->  Limit (actual rows=1 loops=1)
                    ->  Index Scan using ma_test_p2_b_idx on ma_test_p2 (actual rows=1 loops=1)
                          Index Cond: (b IS NOT NULL)
+                         Index Bound Cond: (b IS NOT NULL)
    ->  Index Scan using ma_test_p1_b_idx on ma_test_p1 ma_test_1 (never executed)
          Filter: (a >= (InitPlan 2).col1)
    ->  Index Scan using ma_test_p2_b_idx on ma_test_p2 ma_test_2 (actual rows=10 loops=1)
          Filter: (a >= (InitPlan 2).col1)
    ->  Index Scan using ma_test_p3_b_idx on ma_test_p3 ma_test_3 (actual rows=10 loops=1)
          Filter: (a >= (InitPlan 2).col1)
-(14 rows)
+(15 rows)
 
 reset enable_seqscan;
 reset enable_sort;
diff --git a/src/test/regress/expected/plancache.out b/src/test/regress/expected/plancache.out
index 4e59188196..c77ec2ab8b 100644
--- a/src/test/regress/expected/plancache.out
+++ b/src/test/regress/expected/plancache.out
@@ -299,7 +299,8 @@ explain (costs off) execute test_mode_pp(2);
  Aggregate
    ->  Index Only Scan using test_mode_a_idx on test_mode
          Index Cond: (a = 2)
-(3 rows)
+         Index Bound Cond: (a = 2)
+(4 rows)
 
 select name, generic_plans, custom_plans from pg_prepared_statements
   where  name = 'test_mode_pp';
@@ -388,7 +389,8 @@ explain (costs off) execute test_mode_pp(2);
  Aggregate
    ->  Index Only Scan using test_mode_a_idx on test_mode
          Index Cond: (a = 2)
-(3 rows)
+         Index Bound Cond: (a = 2)
+(4 rows)
 
 select name, generic_plans, custom_plans from pg_prepared_statements
   where  name = 'test_mode_pp';
diff --git a/src/test/regress/expected/portals.out b/src/test/regress/expected/portals.out
index 06726ed4ab..39c9d703f5 100644
--- a/src/test/regress/expected/portals.out
+++ b/src/test/regress/expected/portals.out
@@ -1340,11 +1340,12 @@ ROLLBACK;
 BEGIN;
 EXPLAIN (costs off)
 DECLARE c1 CURSOR FOR SELECT stringu1 FROM onek WHERE stringu1 = 'DZAAAA';
-                 QUERY PLAN                  
----------------------------------------------
+                   QUERY PLAN                    
+-------------------------------------------------
  Index Only Scan using onek_stringu1 on onek
    Index Cond: (stringu1 = 'DZAAAA'::name)
-(2 rows)
+   Index Bound Cond: (stringu1 = 'DZAAAA'::name)
+(3 rows)
 
 DECLARE c1 CURSOR FOR SELECT stringu1 FROM onek WHERE stringu1 = 'DZAAAA';
 FETCH FROM c1;
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index eb4b762ea1..bf5039361a 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -391,8 +391,9 @@ EXPLAIN (COSTS OFF) SELECT * FROM atest12v x, atest12v y WHERE x.a = y.b;
          Filter: (b <<< 5)
    ->  Index Scan using atest12_a_idx on atest12
          Index Cond: (a = atest12_1.b)
+         Index Bound Cond: (a = atest12_1.b)
          Filter: (b <<< 5)
-(6 rows)
+(7 rows)
 
 -- And this one.
 EXPLAIN (COSTS OFF) SELECT * FROM atest12 x, atest12 y
@@ -404,7 +405,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM atest12 x, atest12 y
          Filter: (abs(a) <<< 5)
    ->  Index Scan using atest12_a_idx on atest12 x
          Index Cond: (a = y.b)
-(5 rows)
+         Index Bound Cond: (a = y.b)
+(6 rows)
 
 -- This should also be a nestloop, but the security barrier forces the inner
 -- scan to be materialized
@@ -440,8 +442,9 @@ EXPLAIN (COSTS OFF) SELECT * FROM atest12v x, atest12v y WHERE x.a = y.b;
          Filter: (b <<< 5)
    ->  Index Scan using atest12_a_idx on atest12
          Index Cond: (a = atest12_1.b)
+         Index Bound Cond: (a = atest12_1.b)
          Filter: (b <<< 5)
-(6 rows)
+(7 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM atest12sbv x, atest12sbv y WHERE x.a = y.b;
                 QUERY PLAN                 
@@ -465,8 +468,9 @@ EXPLAIN (COSTS OFF) SELECT * FROM atest12v x, atest12v y
          Filter: ((b <<< 5) AND (abs(a) <<< 5))
    ->  Index Scan using atest12_a_idx on atest12
          Index Cond: (a = atest12_1.b)
+         Index Bound Cond: (a = atest12_1.b)
          Filter: (b <<< 5)
-(6 rows)
+(7 rows)
 
 -- But a security barrier view isolates the leaky operator.
 EXPLAIN (COSTS OFF) SELECT * FROM atest12sbv x, atest12sbv y
@@ -496,8 +500,9 @@ EXPLAIN (COSTS OFF) SELECT * FROM atest12v x, atest12v y WHERE x.a = y.b;
          Filter: (b <<< 5)
    ->  Index Scan using atest12_a_idx on atest12
          Index Cond: (a = atest12_1.b)
+         Index Bound Cond: (a = atest12_1.b)
          Filter: (b <<< 5)
-(6 rows)
+(7 rows)
 
 -- But not for this, due to lack of table-wide permissions needed
 -- to make use of the expression index's statistics.
diff --git a/src/test/regress/expected/regex.out b/src/test/regress/expected/regex.out
index ae0de7307d..e663323b7c 100644
--- a/src/test/regress/expected/regex.out
+++ b/src/test/regress/expected/regex.out
@@ -296,52 +296,58 @@ explain (costs off) select * from pg_proc where proname ~ 'abc';
 (2 rows)
 
 explain (costs off) select * from pg_proc where proname ~ '^abc';
-                              QUERY PLAN                              
-----------------------------------------------------------------------
+                                 QUERY PLAN                                 
+----------------------------------------------------------------------------
  Index Scan using pg_proc_proname_args_nsp_index on pg_proc
    Index Cond: ((proname >= 'abc'::text) AND (proname < 'abd'::text))
+   Index Bound Cond: ((proname >= 'abc'::text) AND (proname < 'abd'::text))
    Filter: (proname ~ '^abc'::text)
-(3 rows)
+(4 rows)
 
 explain (costs off) select * from pg_proc where proname ~ '^abc$';
                          QUERY PLAN                         
 ------------------------------------------------------------
  Index Scan using pg_proc_proname_args_nsp_index on pg_proc
    Index Cond: (proname = 'abc'::text)
+   Index Bound Cond: (proname = 'abc'::text)
    Filter: (proname ~ '^abc$'::text)
-(3 rows)
+(4 rows)
 
 explain (costs off) select * from pg_proc where proname ~ '^abcd*e';
-                              QUERY PLAN                              
-----------------------------------------------------------------------
+                                 QUERY PLAN                                 
+----------------------------------------------------------------------------
  Index Scan using pg_proc_proname_args_nsp_index on pg_proc
    Index Cond: ((proname >= 'abc'::text) AND (proname < 'abd'::text))
+   Index Bound Cond: ((proname >= 'abc'::text) AND (proname < 'abd'::text))
    Filter: (proname ~ '^abcd*e'::text)
-(3 rows)
+(4 rows)
 
 explain (costs off) select * from pg_proc where proname ~ '^abc+d';
-                              QUERY PLAN                              
-----------------------------------------------------------------------
+                                 QUERY PLAN                                 
+----------------------------------------------------------------------------
  Index Scan using pg_proc_proname_args_nsp_index on pg_proc
    Index Cond: ((proname >= 'abc'::text) AND (proname < 'abd'::text))
+   Index Bound Cond: ((proname >= 'abc'::text) AND (proname < 'abd'::text))
    Filter: (proname ~ '^abc+d'::text)
-(3 rows)
+(4 rows)
 
 explain (costs off) select * from pg_proc where proname ~ '^(abc)(def)';
-                                 QUERY PLAN                                 
-----------------------------------------------------------------------------
+                                    QUERY PLAN                                    
+----------------------------------------------------------------------------------
  Index Scan using pg_proc_proname_args_nsp_index on pg_proc
    Index Cond: ((proname >= 'abcdef'::text) AND (proname < 'abcdeg'::text))
+   Index Bound Cond: ((proname >= 'abcdef'::text) AND (proname < 'abcdeg'::text))
    Filter: (proname ~ '^(abc)(def)'::text)
-(3 rows)
+(4 rows)
 
 explain (costs off) select * from pg_proc where proname ~ '^(abc)$';
                          QUERY PLAN                         
 ------------------------------------------------------------
  Index Scan using pg_proc_proname_args_nsp_index on pg_proc
    Index Cond: (proname = 'abc'::text)
+   Index Bound Cond: (proname = 'abc'::text)
    Filter: (proname ~ '^(abc)$'::text)
-(3 rows)
+(4 rows)
 
 explain (costs off) select * from pg_proc where proname ~ '^(abc)?d';
                QUERY PLAN               
@@ -351,12 +357,13 @@ explain (costs off) select * from pg_proc where proname ~ '^(abc)?d';
 (2 rows)
 
 explain (costs off) select * from pg_proc where proname ~ '^abcd(x|(?=\w\w)q)';
-                               QUERY PLAN                               
-------------------------------------------------------------------------
+                                  QUERY PLAN                                  
+------------------------------------------------------------------------------
  Index Scan using pg_proc_proname_args_nsp_index on pg_proc
    Index Cond: ((proname >= 'abcd'::text) AND (proname < 'abce'::text))
+   Index Bound Cond: ((proname >= 'abcd'::text) AND (proname < 'abce'::text))
    Filter: (proname ~ '^abcd(x|(?=\w\w)q)'::text)
-(3 rows)
+(4 rows)
 
 -- Test for infinite loop in pullback() (CVE-2007-4772)
 select 'a' ~ '($|^)*';
diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out
index 319190855b..737f37f415 100644
--- a/src/test/regress/expected/rowsecurity.out
+++ b/src/test/regress/expected/rowsecurity.out
@@ -272,7 +272,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle);
    InitPlan 1
      ->  Index Scan using uaccount_pkey on uaccount
            Index Cond: (pguser = CURRENT_USER)
-(5 rows)
+           Index Bound Cond: (pguser = CURRENT_USER)
+(6 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle);
                                 QUERY PLAN                                
@@ -282,11 +283,12 @@ EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dt
    InitPlan 1
      ->  Index Scan using uaccount_pkey on uaccount
            Index Cond: (pguser = CURRENT_USER)
+           Index Bound Cond: (pguser = CURRENT_USER)
    ->  Seq Scan on category
    ->  Hash
          ->  Seq Scan on document
                Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
-(9 rows)
+(10 rows)
 
 -- viewpoint from regress_rls_dave
 SET SESSION AUTHORIZATION regress_rls_dave;
@@ -336,7 +338,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM document WHERE f_leak(dtitle);
    InitPlan 1
      ->  Index Scan using uaccount_pkey on uaccount
            Index Cond: (pguser = CURRENT_USER)
-(5 rows)
+           Index Bound Cond: (pguser = CURRENT_USER)
+(6 rows)
 
 EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dtitle);
                                                        QUERY PLAN                                                        
@@ -346,11 +349,12 @@ EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dt
    InitPlan 1
      ->  Index Scan using uaccount_pkey on uaccount
            Index Cond: (pguser = CURRENT_USER)
+           Index Bound Cond: (pguser = CURRENT_USER)
    ->  Seq Scan on category
    ->  Hash
          ->  Seq Scan on document
                Filter: ((cid <> 44) AND (cid <> 44) AND (cid < 50) AND (dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
-(9 rows)
+(10 rows)
 
 -- 44 would technically fail for both p2r and p1r, but we should get an error
 -- back from p1r for this because it sorts first
@@ -437,7 +441,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM document NATURAL JOIN category WHERE f_leak(dt
          Filter: ((dauthor = CURRENT_USER) AND f_leak(dtitle))
    ->  Index Scan using category_pkey on category
          Index Cond: (cid = document.cid)
-(5 rows)
+         Index Bound Cond: (cid = document.cid)
+(6 rows)
 
 -- interaction of FK/PK constraints
 SET SESSION AUTHORIZATION regress_rls_alice;
@@ -991,13 +996,14 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
    InitPlan 1
      ->  Index Scan using uaccount_pkey on uaccount
            Index Cond: (pguser = CURRENT_USER)
+           Index Bound Cond: (pguser = CURRENT_USER)
    ->  Seq Scan on part_document_fiction part_document_1
          Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
    ->  Seq Scan on part_document_satire part_document_2
          Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
    ->  Seq Scan on part_document_nonfiction part_document_3
          Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
-(10 rows)
+(11 rows)
 
 -- viewpoint from regress_rls_carol
 SET SESSION AUTHORIZATION regress_rls_carol;
@@ -1033,13 +1039,14 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
    InitPlan 1
      ->  Index Scan using uaccount_pkey on uaccount
            Index Cond: (pguser = CURRENT_USER)
+           Index Bound Cond: (pguser = CURRENT_USER)
    ->  Seq Scan on part_document_fiction part_document_1
          Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
    ->  Seq Scan on part_document_satire part_document_2
          Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
    ->  Seq Scan on part_document_nonfiction part_document_3
          Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
-(10 rows)
+(11 rows)
 
 -- viewpoint from regress_rls_dave
 SET SESSION AUTHORIZATION regress_rls_dave;
@@ -1064,7 +1071,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
    InitPlan 1
      ->  Index Scan using uaccount_pkey on uaccount
            Index Cond: (pguser = CURRENT_USER)
-(5 rows)
+           Index Bound Cond: (pguser = CURRENT_USER)
+(6 rows)
 
 -- pp1 ERROR
 INSERT INTO part_document VALUES (100, 11, 5, 'regress_rls_dave', 'testing pp1'); -- fail
@@ -1142,7 +1150,8 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
    InitPlan 1
      ->  Index Scan using uaccount_pkey on uaccount
            Index Cond: (pguser = CURRENT_USER)
-(5 rows)
+           Index Bound Cond: (pguser = CURRENT_USER)
+(6 rows)
 
 -- viewpoint from regress_rls_carol
 SET SESSION AUTHORIZATION regress_rls_carol;
@@ -1180,13 +1189,14 @@ EXPLAIN (COSTS OFF) SELECT * FROM part_document WHERE f_leak(dtitle);
    InitPlan 1
      ->  Index Scan using uaccount_pkey on uaccount
            Index Cond: (pguser = CURRENT_USER)
+           Index Bound Cond: (pguser = CURRENT_USER)
    ->  Seq Scan on part_document_fiction part_document_1
          Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
    ->  Seq Scan on part_document_satire part_document_2
          Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
    ->  Seq Scan on part_document_nonfiction part_document_3
          Filter: ((dlevel <= (InitPlan 1).col1) AND f_leak(dtitle))
-(10 rows)
+(11 rows)
 
 -- only owner can change policies
 ALTER POLICY pp1 ON part_document USING (true);    --fail
diff --git a/src/test/regress/expected/rowtypes.out b/src/test/regress/expected/rowtypes.out
index b400b58f76..744a4e0f5c 100644
--- a/src/test/regress/expected/rowtypes.out
+++ b/src/test/regress/expected/rowtypes.out
@@ -302,11 +302,12 @@ explain (costs off)
 select thousand, tenthous from tenk1
 where (thousand, tenthous) >= (997, 5000)
 order by thousand, tenthous;
-                        QUERY PLAN                         
------------------------------------------------------------
+                           QUERY PLAN                            
+-----------------------------------------------------------------
  Index Only Scan using tenk1_thous_tenthous on tenk1
    Index Cond: (ROW(thousand, tenthous) >= ROW(997, 5000))
-(2 rows)
+   Index Bound Cond: (ROW(thousand, tenthous) >= ROW(997, 5000))
+(3 rows)
 
 select thousand, tenthous from tenk1
 where (thousand, tenthous) >= (997, 5000)
@@ -344,15 +345,16 @@ explain (costs off)
 select thousand, tenthous, four from tenk1
 where (thousand, tenthous, four) > (998, 5000, 3)
 order by thousand, tenthous;
-                              QUERY PLAN                               
------------------------------------------------------------------------
+                                 QUERY PLAN                                  
+-----------------------------------------------------------------------------
  Sort
    Sort Key: thousand, tenthous
    ->  Bitmap Heap Scan on tenk1
          Filter: (ROW(thousand, tenthous, four) > ROW(998, 5000, 3))
          ->  Bitmap Index Scan on tenk1_thous_tenthous
                Index Cond: (ROW(thousand, tenthous) >= ROW(998, 5000))
-(6 rows)
+               Index Bound Cond: (ROW(thousand, tenthous) >= ROW(998, 5000))
+(7 rows)
 
 select thousand, tenthous, four from tenk1
 where (thousand, tenthous, four) > (998, 5000, 3)
@@ -380,11 +382,12 @@ explain (costs off)
 select thousand, tenthous from tenk1
 where (998, 5000) < (thousand, tenthous)
 order by thousand, tenthous;
-                        QUERY PLAN                        
-----------------------------------------------------------
+                           QUERY PLAN                           
+----------------------------------------------------------------
  Index Only Scan using tenk1_thous_tenthous on tenk1
    Index Cond: (ROW(thousand, tenthous) > ROW(998, 5000))
-(2 rows)
+   Index Bound Cond: (ROW(thousand, tenthous) > ROW(998, 5000))
+(3 rows)
 
 select thousand, tenthous from tenk1
 where (998, 5000) < (thousand, tenthous)
@@ -420,7 +423,8 @@ order by thousand, hundred;
          Filter: (ROW(998, 5000) < ROW(thousand, hundred))
          ->  Bitmap Index Scan on tenk1_thous_tenthous
                Index Cond: (thousand >= 998)
-(6 rows)
+               Index Bound Cond: (thousand >= 998)
+(7 rows)
 
 select thousand, hundred from tenk1
 where (998, 5000) < (thousand, hundred)
@@ -448,11 +452,12 @@ create index on test_table (a,b);
 set enable_sort = off;
 explain (costs off)
 select a,b from test_table where (a,b) > ('a','a') order by a,b;
-                       QUERY PLAN                       
---------------------------------------------------------
+                         QUERY PLAN                          
+-------------------------------------------------------------
  Index Only Scan using test_table_a_b_idx on test_table
    Index Cond: (ROW(a, b) > ROW('a'::text, 'a'::text))
-(2 rows)
+   Index Bound Cond: (ROW(a, b) > ROW('a'::text, 'a'::text))
+(3 rows)
 
 select a,b from test_table where (a,b) > ('a','a') order by a,b;
  a | b 
@@ -1132,12 +1137,13 @@ explain (costs off)
 select row_to_json(q) from
   (select thousand, tenthous from tenk1
    where thousand = 42 and tenthous < 2000 offset 0) q;
-                         QUERY PLAN                          
--------------------------------------------------------------
+                            QUERY PLAN                             
+-------------------------------------------------------------------
  Subquery Scan on q
    ->  Index Only Scan using tenk1_thous_tenthous on tenk1
          Index Cond: ((thousand = 42) AND (tenthous < 2000))
-(3 rows)
+         Index Bound Cond: ((thousand = 42) AND (tenthous < 2000))
+(4 rows)
 
 select row_to_json(q) from
   (select thousand, tenthous from tenk1
diff --git a/src/test/regress/expected/select.out b/src/test/regress/expected/select.out
index 33a6dceb0e..6a5e462c96 100644
--- a/src/test/regress/expected/select.out
+++ b/src/test/regress/expected/select.out
@@ -747,8 +747,9 @@ select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA';
 -----------------------------------------
  Index Scan using onek2_u2_prtl on onek2
    Index Cond: (unique2 = 11)
+   Index Bound Cond: (unique2 = 11)
    Filter: (stringu1 = 'ATAAAA'::name)
-(3 rows)
+(4 rows)
 
 select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA';
  unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 
@@ -763,8 +764,9 @@ select * from onek2 where unique2 = 11 and stringu1 = 'ATAAAA';
 -----------------------------------------------------------------
  Index Scan using onek2_u2_prtl on onek2 (actual rows=1 loops=1)
    Index Cond: (unique2 = 11)
+   Index Bound Cond: (unique2 = 11)
    Filter: (stringu1 = 'ATAAAA'::name)
-(3 rows)
+(4 rows)
 
 explain (costs off)
 select unique2 from onek2 where unique2 = 11 and stringu1 = 'ATAAAA';
@@ -772,8 +774,9 @@ select unique2 from onek2 where unique2 = 11 and stringu1 = 'ATAAAA';
 -----------------------------------------
  Index Scan using onek2_u2_prtl on onek2
    Index Cond: (unique2 = 11)
+   Index Bound Cond: (unique2 = 11)
    Filter: (stringu1 = 'ATAAAA'::name)
-(3 rows)
+(4 rows)
 
 select unique2 from onek2 where unique2 = 11 and stringu1 = 'ATAAAA';
  unique2 
@@ -788,7 +791,8 @@ select * from onek2 where unique2 = 11 and stringu1 < 'B';
 -----------------------------------------
  Index Scan using onek2_u2_prtl on onek2
    Index Cond: (unique2 = 11)
-(2 rows)
+   Index Bound Cond: (unique2 = 11)
+(3 rows)
 
 select * from onek2 where unique2 = 11 and stringu1 < 'B';
  unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 
@@ -802,7 +806,8 @@ select unique2 from onek2 where unique2 = 11 and stringu1 < 'B';
 ----------------------------------------------
  Index Only Scan using onek2_u2_prtl on onek2
    Index Cond: (unique2 = 11)
-(2 rows)
+   Index Bound Cond: (unique2 = 11)
+(3 rows)
 
 select unique2 from onek2 where unique2 = 11 and stringu1 < 'B';
  unique2 
@@ -818,8 +823,9 @@ select unique2 from onek2 where unique2 = 11 and stringu1 < 'B' for update;
  LockRows
    ->  Index Scan using onek2_u2_prtl on onek2
          Index Cond: (unique2 = 11)
+         Index Bound Cond: (unique2 = 11)
          Filter: (stringu1 < 'B'::name)
-(4 rows)
+(5 rows)
 
 select unique2 from onek2 where unique2 = 11 and stringu1 < 'B' for update;
  unique2 
@@ -852,7 +858,8 @@ select unique2 from onek2 where unique2 = 11 and stringu1 < 'B';
    Recheck Cond: ((unique2 = 11) AND (stringu1 < 'B'::name))
    ->  Bitmap Index Scan on onek2_u2_prtl
          Index Cond: (unique2 = 11)
-(4 rows)
+         Index Bound Cond: (unique2 = 11)
+(5 rows)
 
 select unique2 from onek2 where unique2 = 11 and stringu1 < 'B';
  unique2 
@@ -873,9 +880,11 @@ select unique1, unique2 from onek2
    ->  BitmapOr
          ->  Bitmap Index Scan on onek2_u2_prtl
                Index Cond: (unique2 = 11)
+               Index Bound Cond: (unique2 = 11)
          ->  Bitmap Index Scan on onek2_u1_prtl
                Index Cond: (unique1 = 0)
-(8 rows)
+               Index Bound Cond: (unique1 = 0)
+(10 rows)
 
 select unique1, unique2 from onek2
   where (unique2 = 11 or unique1 = 0) and stringu1 < 'B';
@@ -895,9 +904,11 @@ select unique1, unique2 from onek2
    ->  BitmapOr
          ->  Bitmap Index Scan on onek2_u2_prtl
                Index Cond: (unique2 = 11)
+               Index Bound Cond: (unique2 = 11)
          ->  Bitmap Index Scan on onek2_u1_prtl
                Index Cond: (unique1 = 0)
-(7 rows)
+               Index Bound Cond: (unique1 = 0)
+(9 rows)
 
 select unique1, unique2 from onek2
   where (unique2 = 11 and stringu1 < 'B') or unique1 = 0;
diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out
index 87273fa635..16f0866af8 100644
--- a/src/test/regress/expected/select_parallel.out
+++ b/src/test/regress/expected/select_parallel.out
@@ -372,7 +372,8 @@ explain (costs off)
          ->  Partial Aggregate
                ->  Parallel Index Scan using tenk1_hundred on tenk1
                      Index Cond: (hundred > 1)
-(6 rows)
+                     Index Bound Cond: (hundred > 1)
+(7 rows)
 
 select  count((unique1)) from tenk1 where hundred > 1;
  count 
@@ -384,8 +385,8 @@ select  count((unique1)) from tenk1 where hundred > 1;
 explain (costs off)
   select count((unique1)) from tenk1
   where hundred = any ((select array_agg(i) from generate_series(1, 100, 15) i)::int[]);
-                             QUERY PLAN                              
----------------------------------------------------------------------
+                                QUERY PLAN                                 
+---------------------------------------------------------------------------
  Finalize Aggregate
    InitPlan 1
      ->  Aggregate
@@ -395,7 +396,8 @@ explain (costs off)
          ->  Partial Aggregate
                ->  Parallel Index Scan using tenk1_hundred on tenk1
                      Index Cond: (hundred = ANY ((InitPlan 1).col1))
-(9 rows)
+                     Index Bound Cond: (hundred = ANY ((InitPlan 1).col1))
+(10 rows)
 
 select count((unique1)) from tenk1
 where hundred = any ((select array_agg(i) from generate_series(1, 100, 15) i)::int[]);
@@ -415,7 +417,8 @@ explain (costs off)
          ->  Partial Aggregate
                ->  Parallel Index Only Scan using tenk1_thous_tenthous on tenk1
                      Index Cond: (thousand > 95)
-(6 rows)
+                     Index Bound Cond: (thousand > 95)
+(7 rows)
 
 select  count(*) from tenk1 where thousand > 95;
  count 
@@ -439,7 +442,8 @@ select * from
                ->  Partial Aggregate
                      ->  Parallel Index Scan using tenk1_hundred on tenk1
                            Index Cond: (hundred > 10)
-(8 rows)
+                           Index Bound Cond: (hundred > 10)
+(9 rows)
 
 select * from
   (select count(unique1) from tenk1 where hundred > 10) ss
@@ -465,7 +469,8 @@ select * from
                ->  Partial Aggregate
                      ->  Parallel Index Only Scan using tenk1_thous_tenthous on tenk1
                            Index Cond: (thousand > 99)
-(8 rows)
+                           Index Bound Cond: (thousand > 99)
+(9 rows)
 
 select * from
   (select count(*) from tenk1 where thousand > 99) ss
@@ -546,7 +551,8 @@ explain (costs off)
                      Recheck Cond: (hundred > 1)
                      ->  Bitmap Index Scan on tenk1_hundred
                            Index Cond: (hundred > 1)
-(10 rows)
+                           Index Bound Cond: (hundred > 1)
+(11 rows)
 
 select count(*) from tenk1, tenk2 where tenk1.hundred > 1 and tenk2.thousand=0;
  count 
@@ -1025,7 +1031,8 @@ explain (costs off)
    Single Copy: true
    ->  Index Scan using tenk1_unique1 on tenk1
          Index Cond: (unique1 = 1)
-(5 rows)
+         Index Bound Cond: (unique1 = 1)
+(6 rows)
 
 ROLLBACK TO SAVEPOINT settings;
 -- exercise record typmod remapping between backends
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 6e08898b18..1f60eba633 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -618,7 +618,8 @@ EXPLAIN (COSTS off) SELECT count(*) FROM test_last_scan WHERE idx_col = 1;
  Aggregate
    ->  Index Scan using test_last_scan_pkey on test_last_scan
          Index Cond: (idx_col = 1)
-(3 rows)
+         Index Bound Cond: (idx_col = 1)
+(4 rows)
 
 SELECT count(*) FROM test_last_scan WHERE idx_col = 1;
  count 
@@ -696,7 +697,8 @@ EXPLAIN (COSTS off) SELECT count(*) FROM test_last_scan WHERE idx_col = 1;
  Aggregate
    ->  Index Scan using test_last_scan_pkey on test_last_scan
          Index Cond: (idx_col = 1)
-(3 rows)
+         Index Bound Cond: (idx_col = 1)
+(4 rows)
 
 SELECT count(*) FROM test_last_scan WHERE idx_col = 1;
  count 
@@ -741,7 +743,8 @@ EXPLAIN (COSTS off) SELECT count(*) FROM test_last_scan WHERE idx_col = 1;
          Recheck Cond: (idx_col = 1)
          ->  Bitmap Index Scan on test_last_scan_pkey
                Index Cond: (idx_col = 1)
-(5 rows)
+               Index Bound Cond: (idx_col = 1)
+(6 rows)
 
 SELECT count(*) FROM test_last_scan WHERE idx_col = 1;
  count 
diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out
index 9eecdc1e92..8d536b8396 100644
--- a/src/test/regress/expected/subselect.out
+++ b/src/test/regress/expected/subselect.out
@@ -1051,10 +1051,12 @@ where (exists(select 1 from tenk1 k where k.unique1 = t.unique2) or ten < 0)
          Filter: (EXISTS(SubPlan 1) OR (ten < 0))
          ->  Bitmap Index Scan on tenk1_thous_tenthous
                Index Cond: (thousand = 1)
+               Index Bound Cond: (thousand = 1)
          SubPlan 1
            ->  Index Only Scan using tenk1_unique1 on tenk1 k
                  Index Cond: (unique1 = t.unique2)
-(9 rows)
+                 Index Bound Cond: (unique1 = t.unique2)
+(11 rows)
 
 select count(*) from tenk1 t
 where (exists(select 1 from tenk1 k where k.unique1 = t.unique2) or ten < 0)
@@ -1203,11 +1205,12 @@ where o.ten = 0;
          ->  Index Scan using onek_unique1 on public.onek i
                Output: (ANY (i.ten = (hashed SubPlan 1).col1)), random()
                Index Cond: (i.unique1 = o.unique1)
+               Index Bound Cond: (i.unique1 = o.unique1)
                SubPlan 1
                  ->  Seq Scan on public.int4_tbl
                        Output: int4_tbl.f1
                        Filter: (int4_tbl.f1 <= o.hundred)
-(14 rows)
+(15 rows)
 
 select sum(ss.tst::int) from
   onek o cross join lateral (
@@ -1231,8 +1234,8 @@ select count(*) from
     select * from onek i2 where i2.unique1 = o.unique2
   ) ss
 where o.ten = 1;
-                                  QUERY PLAN                                  
-------------------------------------------------------------------------------
+                                  QUERY PLAN                                   
+-------------------------------------------------------------------------------
  Aggregate
    ->  Nested Loop
          ->  Seq Scan on onek o
@@ -1243,10 +1246,12 @@ where o.ten = 1;
                            ->  Subquery Scan on "*SELECT* 1"
                                  ->  Index Scan using onek_unique1 on onek i1
                                        Index Cond: (unique1 = o.unique1)
+                                       Index Bound Cond: (unique1 = o.unique1)
                            ->  Subquery Scan on "*SELECT* 2"
                                  ->  Index Scan using onek_unique1 on onek i2
                                        Index Cond: (unique1 = o.unique2)
-(13 rows)
+                                       Index Bound Cond: (unique1 = o.unique2)
+(15 rows)
 
 select count(*) from
   onek o cross join lateral (
@@ -2102,6 +2107,7 @@ ON B.hundred in (SELECT min(c.hundred) FROM tenk2 C WHERE c.odd = b.odd);
                                    ->  Limit
                                          ->  Index Scan using tenk2_hundred on tenk2 c
                                                Index Cond: (hundred IS NOT NULL)
+                                               Index Bound Cond: (hundred IS NOT NULL)
                                                Filter: (odd = b.odd)
-(16 rows)
+(17 rows)
 
diff --git a/src/test/regress/expected/union.out b/src/test/regress/expected/union.out
index 0fd0e1c38b..8735f02adf 100644
--- a/src/test/regress/expected/union.out
+++ b/src/test/regress/expected/union.out
@@ -1105,14 +1105,16 @@ explain (costs off)
   UNION ALL
   SELECT * FROM t2) t
  WHERE ab = 'ab';
-                 QUERY PLAN                  
----------------------------------------------
+                    QUERY PLAN                     
+---------------------------------------------------
  Append
    ->  Index Scan using t1_ab_idx on t1
          Index Cond: ((a || b) = 'ab'::text)
+         Index Bound Cond: ((a || b) = 'ab'::text)
    ->  Index Only Scan using t2_pkey on t2
          Index Cond: (ab = 'ab'::text)
-(5 rows)
+         Index Bound Cond: (ab = 'ab'::text)
+(7 rows)
 
 explain (costs off)
  SELECT * FROM
@@ -1120,16 +1122,18 @@ explain (costs off)
   UNION
   SELECT * FROM t2) t
  WHERE ab = 'ab';
-                    QUERY PLAN                     
----------------------------------------------------
+                       QUERY PLAN                        
+---------------------------------------------------------
  HashAggregate
    Group Key: ((t1.a || t1.b))
    ->  Append
          ->  Index Scan using t1_ab_idx on t1
                Index Cond: ((a || b) = 'ab'::text)
+               Index Bound Cond: ((a || b) = 'ab'::text)
          ->  Index Only Scan using t2_pkey on t2
                Index Cond: (ab = 'ab'::text)
-(7 rows)
+               Index Bound Cond: (ab = 'ab'::text)
+(9 rows)
 
 --
 -- Test that ORDER BY for UNION ALL can be pushed down to inheritance
@@ -1399,16 +1403,18 @@ explain (costs off)
 select * from
   (select * from t3 a union all select * from t3 b) ss
   join int4_tbl on f1 = expensivefunc(x);
-                         QUERY PLAN                         
-------------------------------------------------------------
+                            QUERY PLAN                            
+------------------------------------------------------------------
  Nested Loop
    ->  Seq Scan on int4_tbl
    ->  Append
          ->  Index Scan using t3i on t3 a
                Index Cond: (expensivefunc(x) = int4_tbl.f1)
+               Index Bound Cond: (expensivefunc(x) = int4_tbl.f1)
          ->  Index Scan using t3i on t3 b
                Index Cond: (expensivefunc(x) = int4_tbl.f1)
-(7 rows)
+               Index Bound Cond: (expensivefunc(x) = int4_tbl.f1)
+(9 rows)
 
 select * from
   (select * from t3 a union all select * from t3 b) ss
diff --git a/src/test/regress/expected/updatable_views.out b/src/test/regress/expected/updatable_views.out
index 1d1f568bc4..a2e76f57af 100644
--- a/src/test/regress/expected/updatable_views.out
+++ b/src/test/regress/expected/updatable_views.out
@@ -531,7 +531,8 @@ EXPLAIN (costs off) UPDATE rw_view1 SET a=6 WHERE a=5;
  Update on base_tbl
    ->  Index Scan using base_tbl_pkey on base_tbl
          Index Cond: ((a > 0) AND (a = 5))
-(3 rows)
+         Index Bound Cond: ((a > 0) AND (a = 5))
+(4 rows)
 
 EXPLAIN (costs off) DELETE FROM rw_view1 WHERE a=5;
                     QUERY PLAN                    
@@ -539,7 +540,8 @@ EXPLAIN (costs off) DELETE FROM rw_view1 WHERE a=5;
  Delete on base_tbl
    ->  Index Scan using base_tbl_pkey on base_tbl
          Index Cond: ((a > 0) AND (a = 5))
-(3 rows)
+         Index Bound Cond: ((a > 0) AND (a = 5))
+(4 rows)
 
 EXPLAIN (costs off)
 MERGE INTO rw_view1 t USING (VALUES (5, 'X')) AS v(a,b) ON t.a = v.a
@@ -549,7 +551,8 @@ MERGE INTO rw_view1 t USING (VALUES (5, 'X')) AS v(a,b) ON t.a = v.a
  Merge on base_tbl
    ->  Index Scan using base_tbl_pkey on base_tbl
          Index Cond: ((a > 0) AND (a = 5))
-(3 rows)
+         Index Bound Cond: ((a > 0) AND (a = 5))
+(4 rows)
 
 EXPLAIN (costs off)
 MERGE INTO rw_view1 t
@@ -564,9 +567,10 @@ MERGE INTO rw_view1 t
                Recheck Cond: (a > 0)
                ->  Bitmap Index Scan on base_tbl_pkey
                      Index Cond: (a > 0)
+                     Index Bound Cond: (a > 0)
          ->  Hash
                ->  Function Scan on generate_series
-(9 rows)
+(10 rows)
 
 EXPLAIN (costs off)
 MERGE INTO rw_view1 t
@@ -581,9 +585,10 @@ MERGE INTO rw_view1 t
                Recheck Cond: (a > 0)
                ->  Bitmap Index Scan on base_tbl_pkey
                      Index Cond: (a > 0)
+                     Index Bound Cond: (a > 0)
          ->  Hash
                ->  Function Scan on generate_series
-(9 rows)
+(10 rows)
 
 EXPLAIN (costs off)
 MERGE INTO rw_view1 t
@@ -598,9 +603,10 @@ MERGE INTO rw_view1 t
                Recheck Cond: (a > 0)
                ->  Bitmap Index Scan on base_tbl_pkey
                      Index Cond: (a > 0)
+                     Index Bound Cond: (a > 0)
          ->  Hash
                ->  Function Scan on generate_series
-(9 rows)
+(10 rows)
 
 -- it's still updatable if we add a DO ALSO rule
 CREATE TABLE base_tbl_hist(ts timestamptz default now(), a int, b text);
@@ -723,20 +729,22 @@ SELECT * FROM rw_view2 ORDER BY aaa;
 (3 rows)
 
 EXPLAIN (costs off) UPDATE rw_view2 SET aaa=5 WHERE aaa=4;
-                       QUERY PLAN                       
---------------------------------------------------------
+                          QUERY PLAN                          
+--------------------------------------------------------------
  Update on base_tbl
    ->  Index Scan using base_tbl_pkey on base_tbl
          Index Cond: ((a < 10) AND (a > 0) AND (a = 4))
-(3 rows)
+         Index Bound Cond: ((a < 10) AND (a > 0) AND (a = 4))
+(4 rows)
 
 EXPLAIN (costs off) DELETE FROM rw_view2 WHERE aaa=4;
-                       QUERY PLAN                       
---------------------------------------------------------
+                          QUERY PLAN                          
+--------------------------------------------------------------
  Delete on base_tbl
    ->  Index Scan using base_tbl_pkey on base_tbl
          Index Cond: ((a < 10) AND (a > 0) AND (a = 4))
-(3 rows)
+         Index Bound Cond: ((a < 10) AND (a > 0) AND (a = 4))
+(4 rows)
 
 DROP TABLE base_tbl CASCADE;
 NOTICE:  drop cascades to 2 other objects
@@ -925,13 +933,15 @@ EXPLAIN (costs off) UPDATE rw_view2 SET a=3 WHERE a=2;
    ->  Nested Loop
          ->  Index Scan using base_tbl_pkey on base_tbl
                Index Cond: (a = 2)
+               Index Bound Cond: (a = 2)
          ->  Subquery Scan on rw_view1
                Filter: ((rw_view1.a < 10) AND (rw_view1.a = 2))
                ->  Bitmap Heap Scan on base_tbl base_tbl_1
                      Recheck Cond: (a > 0)
                      ->  Bitmap Index Scan on base_tbl_pkey
                            Index Cond: (a > 0)
-(10 rows)
+                           Index Bound Cond: (a > 0)
+(12 rows)
 
 EXPLAIN (costs off) DELETE FROM rw_view2 WHERE a=2;
                            QUERY PLAN                           
@@ -940,13 +950,15 @@ EXPLAIN (costs off) DELETE FROM rw_view2 WHERE a=2;
    ->  Nested Loop
          ->  Index Scan using base_tbl_pkey on base_tbl
                Index Cond: (a = 2)
+               Index Bound Cond: (a = 2)
          ->  Subquery Scan on rw_view1
                Filter: ((rw_view1.a < 10) AND (rw_view1.a = 2))
                ->  Bitmap Heap Scan on base_tbl base_tbl_1
                      Recheck Cond: (a > 0)
                      ->  Bitmap Index Scan on base_tbl_pkey
                            Index Cond: (a > 0)
-(10 rows)
+                           Index Bound Cond: (a > 0)
+(12 rows)
 
 DROP TABLE base_tbl CASCADE;
 NOTICE:  drop cascades to 2 other objects
@@ -1206,7 +1218,8 @@ EXPLAIN (costs off) UPDATE rw_view2 SET a=3 WHERE a=2;
                Recheck Cond: (a > 0)
                ->  Bitmap Index Scan on base_tbl_pkey
                      Index Cond: (a > 0)
-(7 rows)
+                     Index Bound Cond: (a > 0)
+(8 rows)
 
 EXPLAIN (costs off) DELETE FROM rw_view2 WHERE a=2;
                         QUERY PLAN                        
@@ -1218,7 +1231,8 @@ EXPLAIN (costs off) DELETE FROM rw_view2 WHERE a=2;
                Recheck Cond: (a > 0)
                ->  Bitmap Index Scan on base_tbl_pkey
                      Index Cond: (a > 0)
-(7 rows)
+                     Index Bound Cond: (a > 0)
+(8 rows)
 
 EXPLAIN (costs off)
 MERGE INTO rw_view2 t
@@ -1237,9 +1251,10 @@ MERGE INTO rw_view2 t
                      Recheck Cond: (a > 0)
                      ->  Bitmap Index Scan on base_tbl_pkey
                            Index Cond: (a > 0)
+                           Index Bound Cond: (a > 0)
          ->  Hash
                ->  Function Scan on generate_series x
-(11 rows)
+(12 rows)
 
 -- MERGE with incomplete set of INSTEAD OF triggers
 DROP TRIGGER rw_view1_del_trig ON rw_view1;
@@ -1326,7 +1341,8 @@ UPDATE rw_view1 v SET bb='Updated row 2' WHERE rw_view1_aa(v)=2
  Update on base_tbl
    ->  Index Scan using base_tbl_pkey on base_tbl
          Index Cond: (a = 2)
-(3 rows)
+         Index Bound Cond: (a = 2)
+(4 rows)
 
 DROP TABLE base_tbl CASCADE;
 NOTICE:  drop cascades to 2 other objects
@@ -2711,7 +2727,8 @@ EXPLAIN (costs off) INSERT INTO rw_view1 VALUES (5);
    SubPlan 1
      ->  Index Only Scan using ref_tbl_pkey on ref_tbl r
            Index Cond: (a = b.a)
-(5 rows)
+           Index Bound Cond: (a = b.a)
+(6 rows)
 
 EXPLAIN (costs off) UPDATE rw_view1 SET a = a + 5;
                         QUERY PLAN                         
@@ -2725,7 +2742,8 @@ EXPLAIN (costs off) UPDATE rw_view1 SET a = a + 5;
    SubPlan 1
      ->  Index Only Scan using ref_tbl_pkey on ref_tbl r_1
            Index Cond: (a = b.a)
-(9 rows)
+           Index Bound Cond: (a = b.a)
+(10 rows)
 
 DROP TABLE base_tbl, ref_tbl CASCADE;
 NOTICE:  drop cascades to view rw_view1
@@ -3117,10 +3135,12 @@ EXPLAIN (costs off) DELETE FROM rw_view1 WHERE id = 1 AND snoop(data);
    ->  Nested Loop
          ->  Index Scan using base_tbl_pkey on base_tbl base_tbl_1
                Index Cond: (id = 1)
+               Index Bound Cond: (id = 1)
          ->  Index Scan using base_tbl_pkey on base_tbl
                Index Cond: (id = 1)
+               Index Bound Cond: (id = 1)
                Filter: ((NOT deleted) AND snoop(data))
-(7 rows)
+(9 rows)
 
 DELETE FROM rw_view1 WHERE id = 1 AND snoop(data);
 NOTICE:  snooped value: Row 1
@@ -3131,6 +3151,7 @@ EXPLAIN (costs off) INSERT INTO rw_view1 VALUES (2, 'New row 2');
    InitPlan 1
      ->  Index Only Scan using base_tbl_pkey on base_tbl t
            Index Cond: (id = 2)
+           Index Bound Cond: (id = 2)
    ->  Result
          One-Time Filter: ((InitPlan 1).col1 IS NOT TRUE)
  
@@ -3138,11 +3159,13 @@ EXPLAIN (costs off) INSERT INTO rw_view1 VALUES (2, 'New row 2');
    InitPlan 1
      ->  Index Only Scan using base_tbl_pkey on base_tbl t
            Index Cond: (id = 2)
+           Index Bound Cond: (id = 2)
    ->  Result
          One-Time Filter: (InitPlan 1).col1
          ->  Index Scan using base_tbl_pkey on base_tbl
                Index Cond: (id = 2)
-(15 rows)
+               Index Bound Cond: (id = 2)
+(18 rows)
 
 INSERT INTO rw_view1 VALUES (2, 'New row 2');
 SELECT * FROM base_tbl;
@@ -3211,6 +3234,7 @@ UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6;
                ->  Index Scan using t1_a_idx on public.t1 t1_1
                      Output: t1_1.tableoid, t1_1.ctid
                      Index Cond: ((t1_1.a > 5) AND (t1_1.a < 7))
+                     Index Bound Cond: ((t1_1.a > 5) AND (t1_1.a < 7))
                      Filter: ((t1_1.a <> 6) AND EXISTS(SubPlan 1) AND snoop(t1_1.a) AND leakproof(t1_1.a))
                      SubPlan 1
                        ->  Append
@@ -3221,16 +3245,19 @@ UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6;
                ->  Index Scan using t11_a_idx on public.t11 t1_2
                      Output: t1_2.tableoid, t1_2.ctid
                      Index Cond: ((t1_2.a > 5) AND (t1_2.a < 7))
+                     Index Bound Cond: ((t1_2.a > 5) AND (t1_2.a < 7))
                      Filter: ((t1_2.a <> 6) AND EXISTS(SubPlan 1) AND snoop(t1_2.a) AND leakproof(t1_2.a))
                ->  Index Scan using t12_a_idx on public.t12 t1_3
                      Output: t1_3.tableoid, t1_3.ctid
                      Index Cond: ((t1_3.a > 5) AND (t1_3.a < 7))
+                     Index Bound Cond: ((t1_3.a > 5) AND (t1_3.a < 7))
                      Filter: ((t1_3.a <> 6) AND EXISTS(SubPlan 1) AND snoop(t1_3.a) AND leakproof(t1_3.a))
                ->  Index Scan using t111_a_idx on public.t111 t1_4
                      Output: t1_4.tableoid, t1_4.ctid
                      Index Cond: ((t1_4.a > 5) AND (t1_4.a < 7))
+                     Index Bound Cond: ((t1_4.a > 5) AND (t1_4.a < 7))
                      Filter: ((t1_4.a <> 6) AND EXISTS(SubPlan 1) AND snoop(t1_4.a) AND leakproof(t1_4.a))
-(30 rows)
+(34 rows)
 
 UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6;
 SELECT * FROM v1 WHERE a=100; -- Nothing should have been changed to 100
@@ -3258,6 +3285,7 @@ UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8;
                ->  Index Scan using t1_a_idx on public.t1 t1_1
                      Output: t1_1.a, t1_1.tableoid, t1_1.ctid
                      Index Cond: ((t1_1.a > 5) AND (t1_1.a = 8))
+                     Index Bound Cond: ((t1_1.a > 5) AND (t1_1.a = 8))
                      Filter: (EXISTS(SubPlan 1) AND snoop(t1_1.a) AND leakproof(t1_1.a))
                      SubPlan 1
                        ->  Append
@@ -3268,16 +3296,19 @@ UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8;
                ->  Index Scan using t11_a_idx on public.t11 t1_2
                      Output: t1_2.a, t1_2.tableoid, t1_2.ctid
                      Index Cond: ((t1_2.a > 5) AND (t1_2.a = 8))
+                     Index Bound Cond: ((t1_2.a > 5) AND (t1_2.a = 8))
                      Filter: (EXISTS(SubPlan 1) AND snoop(t1_2.a) AND leakproof(t1_2.a))
                ->  Index Scan using t12_a_idx on public.t12 t1_3
                      Output: t1_3.a, t1_3.tableoid, t1_3.ctid
                      Index Cond: ((t1_3.a > 5) AND (t1_3.a = 8))
+                     Index Bound Cond: ((t1_3.a > 5) AND (t1_3.a = 8))
                      Filter: (EXISTS(SubPlan 1) AND snoop(t1_3.a) AND leakproof(t1_3.a))
                ->  Index Scan using t111_a_idx on public.t111 t1_4
                      Output: t1_4.a, t1_4.tableoid, t1_4.ctid
                      Index Cond: ((t1_4.a > 5) AND (t1_4.a = 8))
+                     Index Bound Cond: ((t1_4.a > 5) AND (t1_4.a = 8))
                      Filter: (EXISTS(SubPlan 1) AND snoop(t1_4.a) AND leakproof(t1_4.a))
-(30 rows)
+(34 rows)
 
 UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8;
 NOTICE:  snooped value: 8
diff --git a/src/test/regress/expected/with.out b/src/test/regress/expected/with.out
index b4f3121751..5c7c257d78 100644
--- a/src/test/regress/expected/with.out
+++ b/src/test/regress/expected/with.out
@@ -670,7 +670,8 @@ select count(*) from tenk1 a
                ->  CTE Scan on x
          ->  Index Only Scan using tenk1_unique1 on tenk1 a
                Index Cond: (unique1 = x.unique1)
-(10 rows)
+               Index Bound Cond: (unique1 = x.unique1)
+(11 rows)
 
 -- test that pathkeys from a materialized CTE are propagated up to the
 -- outer query
-- 
2.34.1

