Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5010bad

Browse files
author
Commitfest Bot
committed
[CF 5685] v5 - Reduce "Var IS [NOT] NULL" quals during constant folding
This branch was automatically generated by a robot using patches from an email thread registered at: https://commitfest.postgresql.org/patch/5685 The branch will be overwritten each time a new patch version is posted to the thread, and also periodically to check for bitrot caused by changes on the master branch. Patch(es): https://www.postgresql.org/message-id/CAMbWs4-7D4L=74y5YmgLp5pm0cL_oH+cOWjT1-ZxP_Cc6t+SJQ@mail.gmail.com Author(s): Richard Guo
2 parents e050af2 + abc0476 commit 5010bad

File tree

19 files changed

+565
-227
lines changed

19 files changed

+565
-227
lines changed

contrib/postgres_fdw/expected/postgres_fdw.out

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -710,12 +710,12 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1; -- Op
710710
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = (- "C 1")))
711711
(3 rows)
712712

713-
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr
714-
QUERY PLAN
715-
--------------------------------------------------------------------------------------------------------------------------------------------
713+
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c3 IS NOT NULL) IS DISTINCT FROM (c3 IS NOT NULL); -- DistinctExpr
714+
QUERY PLAN
715+
--------------------------------------------------------------------------------------------------------------------------------------
716716
Foreign Scan on public.ft1 t1
717717
Output: c1, c2, c3, c4, c5, c6, c7, c8
718-
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((("C 1" IS NOT NULL) IS DISTINCT FROM ("C 1" IS NOT NULL)))
718+
Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (((c3 IS NOT NULL) IS DISTINCT FROM (c3 IS NOT NULL)))
719719
(3 rows)
720720

721721
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = ANY(ARRAY[c2, 1, c1 + 0]); -- ScalarArrayOpExpr

contrib/postgres_fdw/sql/postgres_fdw.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c3 IS NULL; -- Nu
352352
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c3 IS NOT NULL; -- NullTest
353353
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr
354354
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1; -- OpExpr(l)
355-
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr
355+
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c3 IS NOT NULL) IS DISTINCT FROM (c3 IS NOT NULL); -- DistinctExpr
356356
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = ANY(ARRAY[c2, 1, c1 + 0]); -- ScalarArrayOpExpr
357357
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = (ARRAY[c1,c2,3])[1]; -- SubscriptingRef
358358
EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c6 = E'foo''s\\bar'; -- check special chars

src/backend/optimizer/plan/initsplan.c

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3048,36 +3048,16 @@ add_base_clause_to_rel(PlannerInfo *root, Index relid,
30483048
* expr_is_nonnullable
30493049
* Check to see if the Expr cannot be NULL
30503050
*
3051-
* If the Expr is a simple Var that is defined NOT NULL and meanwhile is not
3052-
* nulled by any outer joins, then we can know that it cannot be NULL.
3051+
* Currently we only support simple Vars.
30533052
*/
30543053
static bool
30553054
expr_is_nonnullable(PlannerInfo *root, Expr *expr)
30563055
{
3057-
RelOptInfo *rel;
3058-
Var *var;
3059-
30603056
/* For now only check simple Vars */
30613057
if (!IsA(expr, Var))
30623058
return false;
30633059

3064-
var = (Var *) expr;
3065-
3066-
/* could the Var be nulled by any outer joins? */
3067-
if (!bms_is_empty(var->varnullingrels))
3068-
return false;
3069-
3070-
/* system columns cannot be NULL */
3071-
if (var->varattno < 0)
3072-
return true;
3073-
3074-
/* is the column defined NOT NULL? */
3075-
rel = find_base_rel(root, var->varno);
3076-
if (var->varattno > 0 &&
3077-
bms_is_member(var->varattno, rel->notnullattnums))
3078-
return true;
3079-
3080-
return false;
3060+
return var_is_nonnullable(root, (Var *) expr, true);
30813061
}
30823062

30833063
/*

src/backend/optimizer/plan/planner.c

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions,
342342
glob->transientPlan = false;
343343
glob->dependsOnRole = false;
344344
glob->partition_directory = NULL;
345+
glob->rel_notnullatts_hash = NULL;
345346

346347
/*
347348
* Assess whether it's feasible to use parallel mode for this query. We
@@ -720,6 +721,18 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root,
720721
*/
721722
transform_MERGE_to_join(parse);
722723

724+
/*
725+
* Scan the rangetable for relation RTEs and retrieve the necessary
726+
* catalog information for each relation. Using this information, clear
727+
* the inh flag for any relation that has no children, collect not-null
728+
* attribute numbers for any relation that has column not-null
729+
* constraints, and expand virtual generated columns for any relation that
730+
* contains them. Note that this step does not descend into sublinks and
731+
* subqueries; if we pull up any sublinks or subqueries below, their
732+
* relation RTEs are processed just before pulling them up.
733+
*/
734+
parse = root->parse = preprocess_relation_rtes(root);
735+
723736
/*
724737
* If the FROM clause is empty, replace it with a dummy RTE_RESULT RTE, so
725738
* that we don't need so many special cases to deal with that situation.
@@ -743,14 +756,6 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root,
743756
*/
744757
preprocess_function_rtes(root);
745758

746-
/*
747-
* Scan the rangetable for relations with virtual generated columns, and
748-
* replace all Var nodes in the query that reference these columns with
749-
* the generation expressions. Recursion issues here are handled in the
750-
* same way as for SubLinks.
751-
*/
752-
parse = root->parse = expand_virtual_generated_columns(root);
753-
754759
/*
755760
* Check to see if any subqueries in the jointree can be merged into this
756761
* query.
@@ -787,23 +792,6 @@ subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root,
787792

788793
switch (rte->rtekind)
789794
{
790-
case RTE_RELATION:
791-
if (rte->inh)
792-
{
793-
/*
794-
* Check to see if the relation actually has any children;
795-
* if not, clear the inh flag so we can treat it as a
796-
* plain base relation.
797-
*
798-
* Note: this could give a false-positive result, if the
799-
* rel once had children but no longer does. We used to
800-
* be able to clear rte->inh later on when we discovered
801-
* that, but no more; we have to handle such cases as
802-
* full-fledged inheritance.
803-
*/
804-
rte->inh = has_subclass(rte->relid);
805-
}
806-
break;
807795
case RTE_JOIN:
808796
root->hasJoinRTEs = true;
809797
if (IS_OUTER_JOIN(rte->jointype))

src/backend/optimizer/plan/subselect.c

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,6 +1458,7 @@ convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink,
14581458
int varno;
14591459
Relids clause_varnos;
14601460
Relids upper_varnos;
1461+
PlannerInfo subroot;
14611462

14621463
Assert(sublink->subLinkType == EXISTS_SUBLINK);
14631464

@@ -1487,6 +1488,24 @@ convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink,
14871488
if (!simplify_EXISTS_query(root, subselect))
14881489
return NULL;
14891490

1491+
/*
1492+
* Scan the rangetable for relation RTEs and retrieve the necessary
1493+
* catalog information for each relation. Using this information, clear
1494+
* the inh flag for any relation that has no children, collect not-null
1495+
* attribute numbers for any relation that has column not-null
1496+
* constraints, and expand virtual generated columns for any relation that
1497+
* contains them.
1498+
*
1499+
* Note: we construct up an entirely dummy PlannerInfo for use here. This
1500+
* is fine because only the "glob" and "parse" links will be used in this
1501+
* case.
1502+
*/
1503+
MemSet(&subroot, 0, sizeof(subroot));
1504+
subroot.type = T_PlannerInfo;
1505+
subroot.glob = root->glob;
1506+
subroot.parse = subselect;
1507+
subselect = preprocess_relation_rtes(&subroot);
1508+
14901509
/*
14911510
* Separate out the WHERE clause. (We could theoretically also remove
14921511
* top-level plain JOIN/ON clauses, but it's probably not worth the
@@ -1732,6 +1751,7 @@ convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
17321751
Node **testexpr, List **paramIds)
17331752
{
17341753
Node *whereClause;
1754+
PlannerInfo subroot;
17351755
List *leftargs,
17361756
*rightargs,
17371757
*opids,
@@ -1791,12 +1811,15 @@ convert_EXISTS_to_ANY(PlannerInfo *root, Query *subselect,
17911811
* parent aliases were flattened already, and we're not going to pull any
17921812
* child Vars (of any description) into the parent.
17931813
*
1794-
* Note: passing the parent's root to eval_const_expressions is
1795-
* technically wrong, but we can get away with it since only the
1796-
* boundParams (if any) are used, and those would be the same in a
1797-
* subroot.
1798-
*/
1799-
whereClause = eval_const_expressions(root, whereClause);
1814+
* Note: we construct up an entirely dummy PlannerInfo to pass to
1815+
* eval_const_expressions. This is fine because only the "glob" and
1816+
* "parse" links are used by eval_const_expressions.
1817+
*/
1818+
MemSet(&subroot, 0, sizeof(subroot));
1819+
subroot.type = T_PlannerInfo;
1820+
subroot.glob = root->glob;
1821+
subroot.parse = subselect;
1822+
whereClause = eval_const_expressions(&subroot, whereClause);
18001823
whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);
18011824
whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
18021825

0 commit comments

Comments
 (0)