From 78f5cc3649a4253c66a7146b2312f8005f8cee57 Mon Sep 17 00:00:00 2001 From: Masahiro Ikeda 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