agora inbox for [email protected]help / color / mirror / Atom feed
[PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 48+ messages / 2 participants [nested] [flat]
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v37 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index b399592ff8..754f6d64f6 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1009,6 +1009,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1065,6 +1066,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index f9d0d67aa7..bdd4876a84 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 3dd16b9ad5..925f2eac3f 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -708,6 +708,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --snesplnlompos6d4 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v37-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v35 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) --- src/backend/optimizer/plan/initsplan.c | 10 ++++++++++ src/backend/optimizer/util/plancat.c | 10 ++++++++++ src/include/nodes/pathnodes.h | 2 ++ 3 files changed, 22 insertions(+) diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --tbesu4k6dthoevcy Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v8-0002-Introuduce-RelOptInfo.uniquekeys-attribute.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 6da0dcd61c..484dab0a1a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -1005,6 +1005,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1061,6 +1062,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e978b491f6..95b1b14cd3 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -830,6 +830,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, false, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 25545029d7..0b2f9d398a 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -463,6 +464,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 485d1b06c9..9e3ebd488a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -709,6 +709,8 @@ typedef struct RelOptInfo PlannerInfo *subroot; /* if subquery */ List *subplan_params; /* if subquery */ int rel_parallel_workers; /* wanted number of parallel workers */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.21.0 --op7mf2i72xk5yu7c Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v36-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH 01/10] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.30.2 --------------F495F6B18672582269F00FF9 Content-Type: text/x-patch; charset=UTF-8; name="0002-review-20210317.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="0002-review-20210317.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.26.2 --yh7cw345mbttadjz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v38-0002-Introduce-UniqueKey-attributes-on-RelOptInfo-str.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH 01/10] Introduce RelOptInfo->notnullattrs attribute @ 2020-05-03 14:37 一挃 <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: 一挃 @ 2020-05-03 14:37 UTC (permalink / raw) The notnullattrs is calculated from catalog and run-time query. That infomation is translated to child relation as well for partitioned table. --- src/backend/optimizer/path/allpaths.c | 31 ++++++++++++++++++++++++++ src/backend/optimizer/plan/initsplan.c | 10 +++++++++ src/backend/optimizer/util/plancat.c | 10 +++++++++ src/include/nodes/pathnodes.h | 2 ++ 4 files changed, 53 insertions(+) diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index d73ac562eb..37b4223adb 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -998,6 +998,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *childrel; ListCell *parentvars; ListCell *childvars; + int i = -1; /* append_rel_list contains all append rels; ignore others */ if (appinfo->parent_relid != parentRTindex) @@ -1054,6 +1055,36 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, (Node *) rel->reltarget->exprs, 1, &appinfo); + /* Copy notnullattrs. */ + while ((i = bms_next_member(rel->notnullattrs, i)) > 0) + { + AttrNumber attno = i + FirstLowInvalidHeapAttributeNumber; + AttrNumber child_attno; + if (attno == 0) + { + /* Whole row is not null, so must be same for child */ + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + attno - FirstLowInvalidHeapAttributeNumber); + break; + } + if (attno < 0 ) + /* no need to translate system column */ + child_attno = attno; + else + { + Node * node = list_nth(appinfo->translated_vars, attno - 1); + if (!IsA(node, Var)) + /* This may happens at UNION case, like (SELECT a FROM t1 UNION SELECT a + 3 + * FROM t2) t and we know t.a is not null + */ + continue; + child_attno = castNode(Var, node)->varattno; + } + + childrel->notnullattrs = bms_add_member(childrel->notnullattrs, + child_attno - FirstLowInvalidHeapAttributeNumber); + } + /* * We have to make child entries in the EquivalenceClass data * structures as well. This is needed either if the parent diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 02f813cebd..d27167dc76 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -829,6 +829,16 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join, { Node *qual = (Node *) lfirst(l); + /* Set the not null info now */ + ListCell *lc; + List *non_nullable_vars = find_nonnullable_vars(qual); + foreach(lc, non_nullable_vars) + { + Var *var = lfirst_node(Var, lc); + RelOptInfo *rel = root->simple_rel_array[var->varno]; + rel->notnullattrs = bms_add_member(rel->notnullattrs, + var->varattno - FirstLowInvalidHeapAttributeNumber); + } distribute_qual_to_rels(root, qual, below_outer_join, JOIN_INNER, root->qual_security_level, diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index c5947fa418..eebabcfccf 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -117,6 +117,7 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, Relation relation; bool hasindex; List *indexinfos = NIL; + int i; /* * We need not lock the relation since it was already locked, either by @@ -480,6 +481,15 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, if (inhparent && relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) set_relation_partition_info(root, rel, relation); + Assert(rel->notnullattrs == NULL); + for(i = 0; i < relation->rd_att->natts; i++) + { + FormData_pg_attribute attr = relation->rd_att->attrs[i]; + if (attr.attnotnull) + rel->notnullattrs = bms_add_member(rel->notnullattrs, + attr.attnum - FirstLowInvalidHeapAttributeNumber); + } + table_close(relation, NoLock); /* diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 86405a274e..0d61f04d27 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -718,6 +718,8 @@ typedef struct RelOptInfo int rel_parallel_workers; /* wanted number of parallel workers */ uint32 amflags; /* Bitmask of optional features supported by * the table AM */ + /* Not null attrs, start from -FirstLowInvalidHeapAttributeNumber */ + Bitmapset *notnullattrs; /* Information about foreign tables and foreign joins */ Oid serverid; /* identifies server for the table or join */ -- 2.30.2 --------------F495F6B18672582269F00FF9 Content-Type: text/x-patch; charset=UTF-8; name="0002-review-20210317.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="0002-review-20210317.patch" ^ permalink raw reply [nested|flat] 48+ messages in thread
* [PATCH v2 2/2] Disallow [LW]LockAcquire when holding a spin lock-file-mode @ 2024-01-04 14:19 yizhi.fzh <[email protected]> 0 siblings, 0 replies; 48+ messages in thread From: yizhi.fzh @ 2024-01-04 14:19 UTC (permalink / raw) Spinlocks are intended for *very* short-term locks, but sometimes it is misused, this commit guards no [LW]LockAcquire should be called when holding a spin lock. --- src/backend/storage/buffer/bufmgr.c | 1 + src/backend/storage/lmgr/lock.c | 2 ++ src/backend/storage/lmgr/lwlock.c | 2 ++ src/backend/utils/init/globals.c | 1 + src/include/storage/buf_internals.h | 1 + src/include/storage/spin.h | 24 ++++++++++++++++++++++-- 6 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 9f9d3f24ac..d2534ee9aa 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -5419,6 +5419,7 @@ LockBufHdr(BufferDesc *desc) perform_spin_delay(&delayStatus); } finish_spin_delay(&delayStatus); + START_SPIN_LOCK(); return old_buf_state | BM_LOCKED; } diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index b8c57b3e16..0710adbef8 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -776,6 +776,8 @@ LockAcquireExtended(const LOCKTAG *locktag, bool found_conflict; bool log_lock = false; + Assert(SpinLockCount == 0); + if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods)) elog(ERROR, "unrecognized lock method: %d", lockmethodid); lockMethodTable = LockMethods[lockmethodid]; diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 315a78cda9..5709cadcd5 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -1205,6 +1205,8 @@ LWLockAcquire(LWLock *lock, LWLockMode mode) Assert(mode == LW_SHARED || mode == LW_EXCLUSIVE); + Assert(SpinLockCount == 0); + PRINT_LWDEBUG("LWLockAcquire", lock, mode); #ifdef LWLOCK_STATS diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 60bc1217fb..125dc53375 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -40,6 +40,7 @@ volatile sig_atomic_t IdleStatsUpdateTimeoutPending = false; volatile uint32 InterruptHoldoffCount = 0; volatile uint32 QueryCancelHoldoffCount = 0; volatile uint32 CritSectionCount = 0; +volatile uint32 SpinLockCount = 0; int MyProcPid; pg_time_t MyStartTime; diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h index 2c4fd92e39..be2d090308 100644 --- a/src/include/storage/buf_internals.h +++ b/src/include/storage/buf_internals.h @@ -363,6 +363,7 @@ UnlockBufHdr(BufferDesc *desc, uint32 buf_state) { pg_write_barrier(); pg_atomic_write_u32(&desc->state, buf_state & (~BM_LOCKED)); + END_SPIN_LOCK(); } /* in bufmgr.c */ diff --git a/src/include/storage/spin.h b/src/include/storage/spin.h index 5d809cc980..c1b96a047f 100644 --- a/src/include/storage/spin.h +++ b/src/include/storage/spin.h @@ -56,12 +56,32 @@ #include "storage/pg_sema.h" #endif +extern PGDLLIMPORT volatile uint32 SpinLockCount; + +#define START_SPIN_LOCK() (SpinLockCount++) +#define END_SPIN_LOCK() \ +do { \ + Assert(SpinLockCount > 0); \ + SpinLockCount--; \ +} while(0) #define SpinLockInit(lock) S_INIT_LOCK(lock) -#define SpinLockAcquire(lock) S_LOCK(lock) +#define SpinLockAcquire(lock) \ + do \ + { \ + S_LOCK(lock); \ + START_SPIN_LOCK(); \ + } while (false); + + +#define SpinLockRelease(lock) \ + do \ + { \ + S_UNLOCK(lock); \ + END_SPIN_LOCK(); \ + } while (false); -#define SpinLockRelease(lock) S_UNLOCK(lock) #define SpinLockFree(lock) S_LOCK_FREE(lock) -- 2.34.1 --=-=-=-- ^ permalink raw reply [nested|flat] 48+ messages in thread
end of thread, other threads:[~2024-01-04 14:19 UTC | newest] Thread overview: 48+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2020-05-03 14:37 [PATCH 01/10] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v37 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH 01/10] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v35 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v36 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2020-05-03 14:37 [PATCH v38 1/6] Introduce RelOptInfo->notnullattrs attribute 一挃 <[email protected]> 2024-01-04 14:19 [PATCH v2 2/2] Disallow [LW]LockAcquire when holding a spin lock-file-mode yizhi.fzh <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox