aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util/plancat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/util/plancat.c')
-rw-r--r--src/backend/optimizer/util/plancat.c42
1 files changed, 37 insertions, 5 deletions
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index d29f9ff0929..5f927095edc 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.139 2008/01/01 19:45:50 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.140 2008/01/12 00:11:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -47,7 +47,8 @@ get_relation_info_hook_type get_relation_info_hook = NULL;
static void estimate_rel_size(Relation rel, int32 *attr_widths,
BlockNumber *pages, double *tuples);
-static List *get_relation_constraints(Oid relationObjectId, RelOptInfo *rel);
+static List *get_relation_constraints(Oid relationObjectId, RelOptInfo *rel,
+ bool include_notnull);
/*
@@ -453,12 +454,16 @@ estimate_rel_size(Relation rel, int32 *attr_widths,
* indicated by rel->relid. This allows the expressions to be easily
* compared to expressions taken from WHERE.
*
+ * If include_notnull is true, "col IS NOT NULL" expressions are generated
+ * and added to the result for each column that's marked attnotnull.
+ *
* Note: at present this is invoked at most once per relation per planner
* run, and in many cases it won't be invoked at all, so there seems no
* point in caching the data in RelOptInfo.
*/
static List *
-get_relation_constraints(Oid relationObjectId, RelOptInfo *rel)
+get_relation_constraints(Oid relationObjectId, RelOptInfo *rel,
+ bool include_notnull)
{
List *result = NIL;
Index varno = rel->relid;
@@ -513,6 +518,30 @@ get_relation_constraints(Oid relationObjectId, RelOptInfo *rel)
result = list_concat(result,
make_ands_implicit((Expr *) cexpr));
}
+
+ /* Add NOT NULL constraints in expression form, if requested */
+ if (include_notnull && constr->has_not_null)
+ {
+ int natts = relation->rd_att->natts;
+
+ for (i = 1; i <= natts; i++)
+ {
+ Form_pg_attribute att = relation->rd_att->attrs[i - 1];
+
+ if (att->attnotnull && !att->attisdropped)
+ {
+ NullTest *ntest = makeNode(NullTest);
+
+ ntest->arg = (Expr *) makeVar(varno,
+ i,
+ att->atttypid,
+ att->atttypmod,
+ 0);
+ ntest->nulltesttype = IS_NOT_NULL;
+ result = lappend(result, ntest);
+ }
+ }
+ }
}
heap_close(relation, NoLock);
@@ -567,8 +596,11 @@ relation_excluded_by_constraints(RelOptInfo *rel, RangeTblEntry *rte)
if (rte->rtekind != RTE_RELATION || rte->inh)
return false;
- /* OK to fetch the constraint expressions */
- constraint_pred = get_relation_constraints(rte->relid, rel);
+ /*
+ * OK to fetch the constraint expressions. Include "col IS NOT NULL"
+ * expressions for attnotnull columns, in case we can refute those.
+ */
+ constraint_pred = get_relation_constraints(rte->relid, rel, true);
/*
* We do not currently enforce that CHECK constraints contain only