diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 7dd43a9..65fb2d8 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -1124,7 +1124,7 @@ postgresAddForeignUpdateTargets(Query *parsetree,
 				  TIDOID,
 				  -1,
 				  InvalidOid,
-				  0);
+				  0, false);
 
 	/* Wrap it in a resjunk TLE with the right name ... */
 	attrname = "ctid";
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 341262b..7003d7a 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -7551,7 +7551,7 @@ ATPrepAlterColumnType(List **wqueue,
 			transform = (Node *) makeVar(1, attnum,
 										 attTup->atttypid, attTup->atttypmod,
 										 attTup->attcollation,
-										 0);
+										 0, false);
 		}
 
 		transform = coerce_to_target_type(pstate,
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 43530aa..1d25590 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -1060,6 +1060,7 @@ _copyVar(const Var *from)
 	COPY_SCALAR_FIELD(varnoold);
 	COPY_SCALAR_FIELD(varoattno);
 	COPY_LOCATION_FIELD(location);
+	COPY_SCALAR_FIELD(knownnotnull);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index da59c58..ed613fb 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -68,7 +68,8 @@ makeVar(Index varno,
 		Oid vartype,
 		int32 vartypmod,
 		Oid varcollid,
-		Index varlevelsup)
+		Index varlevelsup,
+		bool knownnotnull)
 {
 	Var		   *var = makeNode(Var);
 
@@ -78,7 +79,6 @@ makeVar(Index varno,
 	var->vartypmod = vartypmod;
 	var->varcollid = varcollid;
 	var->varlevelsup = varlevelsup;
-
 	/*
 	 * Since few if any routines ever create Var nodes with varnoold/varoattno
 	 * different from varno/varattno, we don't provide separate arguments for
@@ -90,6 +90,7 @@ makeVar(Index varno,
 
 	/* Likewise, we just set location to "unknown" here */
 	var->location = -1;
+	var->knownnotnull = knownnotnull;
 
 	return var;
 }
@@ -108,7 +109,8 @@ makeVarFromTargetEntry(Index varno,
 				   exprType((Node *) tle->expr),
 				   exprTypmod((Node *) tle->expr),
 				   exprCollation((Node *) tle->expr),
-				   0);
+				   0,
+				   false);
 }
 
 /*
@@ -150,7 +152,8 @@ makeWholeRowVar(RangeTblEntry *rte,
 							 toid,
 							 -1,
 							 InvalidOid,
-							 varlevelsup);
+							 varlevelsup,
+							 false);
 			break;
 
 		case RTE_FUNCTION:
@@ -168,7 +171,8 @@ makeWholeRowVar(RangeTblEntry *rte,
 								 RECORDOID,
 								 -1,
 								 InvalidOid,
-								 varlevelsup);
+								 varlevelsup,
+								 false);
 				break;
 			}
 
@@ -182,7 +186,8 @@ makeWholeRowVar(RangeTblEntry *rte,
 								 toid,
 								 -1,
 								 InvalidOid,
-								 varlevelsup);
+								 varlevelsup,
+								 false);
 			}
 			else if (allowScalar)
 			{
@@ -192,7 +197,8 @@ makeWholeRowVar(RangeTblEntry *rte,
 								 toid,
 								 -1,
 								 exprCollation(fexpr),
-								 varlevelsup);
+								 varlevelsup,
+								 false);
 			}
 			else
 			{
@@ -202,7 +208,8 @@ makeWholeRowVar(RangeTblEntry *rte,
 								 RECORDOID,
 								 -1,
 								 InvalidOid,
-								 varlevelsup);
+								 varlevelsup,
+								 false);
 			}
 			break;
 
@@ -219,7 +226,8 @@ makeWholeRowVar(RangeTblEntry *rte,
 							 RECORDOID,
 							 -1,
 							 InvalidOid,
-							 varlevelsup);
+							 varlevelsup,
+							 false);
 			break;
 	}
 
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 4b641a2..572761e 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -2999,7 +2999,7 @@ fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol)
 					result = makeVar(INDEX_VAR, indexcol + 1,
 									 exprType(lfirst(indexpr_item)), -1,
 									 exprCollation(lfirst(indexpr_item)),
-									 0);
+									 0, false);
 					return (Node *) result;
 				}
 				else
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 768c5c7..cb7863b 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -1398,7 +1398,8 @@ set_dummy_tlist_references(Plan *plan, int rtoffset)
 						 exprType((Node *) oldvar),
 						 exprTypmod((Node *) oldvar),
 						 exprCollation((Node *) oldvar),
-						 0);
+						 0,
+						 false);
 		if (IsA(oldvar, Var))
 		{
 			newvar->varnoold = oldvar->varno + rtoffset;
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index 4ab12e5..875b7b4 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -100,7 +100,8 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
 						  TIDOID,
 						  -1,
 						  InvalidOid,
-						  0);
+						  0,
+						  false);
 			snprintf(resname, sizeof(resname), "ctid%u", rc->rowmarkId);
 			tle = makeTargetEntry((Expr *) var,
 								  list_length(tlist) + 1,
@@ -116,7 +117,8 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
 							  OIDOID,
 							  -1,
 							  InvalidOid,
-							  0);
+							  0,
+							  false);
 				snprintf(resname, sizeof(resname), "tableoid%u", rc->rowmarkId);
 				tle = makeTargetEntry((Expr *) var,
 									  list_length(tlist) + 1,
@@ -303,7 +305,8 @@ expand_targetlist(List *tlist, int command_type,
 													atttype,
 													atttypmod,
 													attcollation,
-													0);
+													0,
+													false);
 					}
 					else
 					{
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 0410fdd..3baf8c1 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -948,7 +948,8 @@ generate_setop_tlist(List *colTypes, List *colCollations,
 									exprType((Node *) inputtle->expr),
 									exprTypmod((Node *) inputtle->expr),
 									exprCollation((Node *) inputtle->expr),
-									0);
+									0,
+									false);
 
 		if (exprType(expr) != colType)
 		{
@@ -1106,7 +1107,8 @@ generate_append_tlist(List *colTypes, List *colCollations,
 								colType,
 								colTypmod,
 								colColl,
-								0);
+								0,
+								false);
 		tle = makeTargetEntry((Expr *) expr,
 							  (AttrNumber) resno++,
 							  pstrdup(reftle->resname),
@@ -1123,7 +1125,8 @@ generate_append_tlist(List *colTypes, List *colCollations,
 								INT4OID,
 								-1,
 								InvalidOid,
-								0);
+								0,
+								false);
 		tle = makeTargetEntry((Expr *) expr,
 							  (AttrNumber) resno++,
 							  pstrdup("flag"),
@@ -1469,7 +1472,8 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation,
 										 atttypid,
 										 atttypmod,
 										 attcollation,
-										 0));
+										 0,
+										 false));
 			continue;
 		}
 
@@ -1515,7 +1519,8 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation,
 									 atttypid,
 									 atttypmod,
 									 attcollation,
-									 0));
+									 0,
+									 false));
 	}
 
 	*translated_vars = vars;
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 97dacaa..aafc415 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -3220,7 +3220,8 @@ eval_const_expressions_mutator(Node *node,
 												fselect->resulttype,
 												fselect->resulttypmod,
 												fselect->resultcollid,
-												((Var *) arg)->varlevelsup);
+												((Var *) arg)->varlevelsup,
+												false);
 				}
 				if (arg && IsA(arg, RowExpr))
 				{
@@ -3306,6 +3307,16 @@ eval_const_expressions_mutator(Node *node,
 					/* Else we need an AND node */
 					return (Node *) make_andclause(newargs);
 				}
+				if (!ntest->argisrow && arg && IsA(arg, Var))
+				{
+					/*
+					 * If we encounter a var IS NULL on a var that we know
+					 * can never have NULL values then we can prove the condition
+					 * to always be false
+					 */
+					if (((Var *) arg)->knownnotnull && ntest->nulltesttype == IS_NULL)
+						return makeBoolConst(false, false);
+				}
 				if (!ntest->argisrow && arg && IsA(arg, Const))
 				{
 					Const	   *carg = (Const *) arg;
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index b2becfa..5d56fb6 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -717,7 +717,8 @@ get_relation_constraints(PlannerInfo *root,
 												  att->atttypid,
 												  att->atttypmod,
 												  att->attcollation,
-												  0);
+												  0,
+												  false);
 					ntest->nulltesttype = IS_NOT_NULL;
 					ntest->argisrow = type_is_rowtype(att->atttypid);
 					result = lappend(result, ntest);
@@ -881,7 +882,8 @@ build_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
 							  att_tup->atttypid,
 							  att_tup->atttypmod,
 							  att_tup->attcollation,
-							  0);
+							  0,
+							  att_tup->attnotnull);
 
 				tlist = lappend(tlist,
 								makeTargetEntry((Expr *) var,
@@ -992,7 +994,8 @@ build_index_tlist(PlannerInfo *root, IndexOptInfo *index,
 										att_tup->atttypid,
 										att_tup->atttypmod,
 										att_tup->attcollation,
-										0);
+										0,
+										false);
 		}
 		else
 		{
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index fb6c44c..8804061 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -1398,7 +1398,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
 					  colType,
 					  colTypmod,
 					  colCollation,
-					  0);
+					  0,
+					  false);
 		var->location = exprLocation((Node *) lefttle->expr);
 		tle = makeTargetEntry((Expr *) var,
 							  (AttrNumber) pstate->p_next_resno++,
diff --git a/src/backend/parser/parse_node.c b/src/backend/parser/parse_node.c
index 1e3d1f6..c2c3aec 100644
--- a/src/backend/parser/parse_node.c
+++ b/src/backend/parser/parse_node.c
@@ -191,10 +191,12 @@ make_var(ParseState *pstate, RangeTblEntry *rte, int attrno, int location)
 	Oid			vartypeid;
 	int32		type_mod;
 	Oid			varcollid;
+	bool		knownnotnull;
 
 	vnum = RTERangeTablePosn(pstate, rte, &sublevels_up);
-	get_rte_attribute_type(rte, attrno, &vartypeid, &type_mod, &varcollid);
-	result = makeVar(vnum, attrno, vartypeid, type_mod, varcollid, sublevels_up);
+	get_rte_attribute_type(rte, attrno, &vartypeid, &type_mod, &varcollid, &knownnotnull);
+	result = makeVar(vnum, attrno, vartypeid, type_mod, varcollid, sublevels_up,
+					knownnotnull);
 	result->location = location;
 	return result;
 }
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 478584d..2169a72 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -1844,7 +1844,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
 										  exprType((Node *) te->expr),
 										  exprTypmod((Node *) te->expr),
 										  exprCollation((Node *) te->expr),
-										  sublevels_up);
+										  sublevels_up, false);
 						varnode->location = location;
 
 						*colvars = lappend(*colvars, varnode);
@@ -1892,7 +1892,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
 							varnode = makeVar(rtindex, atts_done + 1,
 											  funcrettype, -1,
 											  exprCollation(rtfunc->funcexpr),
-											  sublevels_up);
+											  sublevels_up, false);
 							varnode->location = location;
 
 							*colvars = lappend(*colvars, varnode);
@@ -1934,7 +1934,8 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
 												  attrtype,
 												  attrtypmod,
 												  attrcollation,
-												  sublevels_up);
+												  sublevels_up,
+												  false);
 								varnode->location = location;
 								*colvars = lappend(*colvars, varnode);
 							}
@@ -1962,7 +1963,8 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
 													  INT8OID,
 													  -1,
 													  InvalidOid,
-													  sublevels_up);
+													  sublevels_up,
+													  false);
 
 						*colvars = lappend(*colvars, varnode);
 					}
@@ -2002,7 +2004,8 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
 										  exprType(col),
 										  exprTypmod(col),
 										  colcollation,
-										  sublevels_up);
+										  sublevels_up,
+										  false);
 						varnode->location = location;
 						*colvars = lappend(*colvars, varnode);
 					}
@@ -2070,7 +2073,8 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
 										  exprType(avar),
 										  exprTypmod(avar),
 										  exprCollation(avar),
-										  sublevels_up);
+										  sublevels_up,
+										  false);
 						varnode->location = location;
 
 						*colvars = lappend(*colvars, varnode);
@@ -2111,7 +2115,8 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
 
 						varnode = makeVar(rtindex, varattno,
 										  coltype, coltypmod, colcoll,
-										  sublevels_up);
+										  sublevels_up,
+										  false);
 						*colvars = lappend(*colvars, varnode);
 					}
 				}
@@ -2220,7 +2225,7 @@ expandTupleDesc(TupleDesc tupdesc, Alias *eref, int count, int offset,
 			varnode = makeVar(rtindex, varattno + offset + 1,
 							  attr->atttypid, attr->atttypmod,
 							  attr->attcollation,
-							  sublevels_up);
+							  sublevels_up, attr->attnotnull);
 			varnode->location = location;
 
 			*colvars = lappend(*colvars, varnode);
@@ -2330,7 +2335,7 @@ get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum)
  */
 void
 get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
-					   Oid *vartype, int32 *vartypmod, Oid *varcollid)
+					   Oid *vartype, int32 *vartypmod, Oid *varcollid, bool *knownnotnull)
 {
 	switch (rte->rtekind)
 	{
@@ -2361,6 +2366,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
 				*vartype = att_tup->atttypid;
 				*vartypmod = att_tup->atttypmod;
 				*varcollid = att_tup->attcollation;
+				*knownnotnull = att_tup->attnotnull;
 				ReleaseSysCache(tp);
 			}
 			break;
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index e6c5530..75128df 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -830,7 +830,8 @@ rewriteTargetListIU(Query *parsetree, Relation target_relation,
 										att_tup->atttypid,
 										att_tup->atttypmod,
 										att_tup->attcollation,
-										0);
+										0,
+										false);
 
 			new_tle = makeTargetEntry((Expr *) new_expr,
 									  attrno,
@@ -1214,7 +1215,8 @@ rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte,
 					  TIDOID,
 					  -1,
 					  InvalidOid,
-					  0);
+					  0,
+					  false);
 
 		attrname = "ctid";
 	}
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index e108b85..9dac6c6 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -28,7 +28,8 @@ extern Var *makeVar(Index varno,
 		Oid vartype,
 		int32 vartypmod,
 		Oid varcollid,
-		Index varlevelsup);
+		Index varlevelsup,
+		bool knownnotnull);
 
 extern Var *makeVarFromTargetEntry(Index varno,
 					   TargetEntry *tle);
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 4f03ef9..c8f1185 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -157,6 +157,7 @@ typedef struct Var
 	Index		varnoold;		/* original value of varno, for debugging */
 	AttrNumber	varoattno;		/* original value of varattno */
 	int			location;		/* token location, or -1 if unknown */
+	bool		knownnotnull;	/* is the var known to never be NULL */
 } Var;
 
 /*
diff --git a/src/include/parser/parsetree.h b/src/include/parser/parsetree.h
index ef67b41..49343a2 100644
--- a/src/include/parser/parsetree.h
+++ b/src/include/parser/parsetree.h
@@ -52,7 +52,8 @@ extern char *get_rte_attribute_name(RangeTblEntry *rte, AttrNumber attnum);
  * type and typemod info for that attribute of that RTE.
  */
 extern void get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
-					   Oid *vartype, int32 *vartypmod, Oid *varcollid);
+					   Oid *vartype, int32 *vartypmod, Oid *varcollid,
+					   bool *knownnotnull);
 
 /*
  * Check whether an attribute of an RTE has been dropped (note that
