diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index f4717942c3..1b9ae2e901 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -37,10 +37,13 @@ typedef struct RangeQueryClause
 	bool		have_hibound;	/* found a high-bound clause yet? */
 	Selectivity lobound;		/* Selectivity of a var > something clause */
 	Selectivity hibound;		/* Selectivity of a var < something clause */
+	bool		lobound_isdefault;	/* lobound is a default selectivity? */
+	bool		hibound_isdefault;	/* hibound is a default selectivity? */
 } RangeQueryClause;
 
 static void addRangeClause(RangeQueryClause **rqlist, Node *clause,
-			   bool varonleft, bool isLTsel, Selectivity s2);
+			   bool varonleft, bool isLTsel, Selectivity s2,
+			   bool isdefault);
 static RelOptInfo *find_single_rel_for_clauses(PlannerInfo *root,
 							List *clauses);
 
@@ -108,6 +111,7 @@ clauselist_selectivity(PlannerInfo *root,
 	RangeQueryClause *rqlist = NULL;
 	ListCell   *l;
 	int			listidx;
+	bool		isdefault;
 
 	/*
 	 * If there's exactly one clause, just go directly to
@@ -115,7 +119,7 @@ clauselist_selectivity(PlannerInfo *root,
 	 */
 	if (list_length(clauses) == 1)
 		return clause_selectivity(root, (Node *) linitial(clauses),
-								  varRelid, jointype, sjinfo);
+								  varRelid, jointype, sjinfo, &isdefault);
 
 	/*
 	 * Determine if these clauses reference a single relation.  If so, and if
@@ -165,7 +169,8 @@ clauselist_selectivity(PlannerInfo *root,
 			continue;
 
 		/* Always compute the selectivity using clause_selectivity */
-		s2 = clause_selectivity(root, clause, varRelid, jointype, sjinfo);
+		s2 = clause_selectivity(root, clause, varRelid, jointype,
+								sjinfo, &isdefault);
 
 		/*
 		 * Check for being passed a RestrictInfo.
@@ -227,12 +232,12 @@ clauselist_selectivity(PlannerInfo *root,
 					case F_SCALARLTSEL:
 					case F_SCALARLESEL:
 						addRangeClause(&rqlist, clause,
-									   varonleft, true, s2);
+									   varonleft, true, s2, isdefault);
 						break;
 					case F_SCALARGTSEL:
 					case F_SCALARGESEL:
 						addRangeClause(&rqlist, clause,
-									   varonleft, false, s2);
+									   varonleft, false, s2, isdefault);
 						break;
 					default:
 						/* Just merge the selectivity in generically */
@@ -260,12 +265,11 @@ clauselist_selectivity(PlannerInfo *root,
 			Selectivity s2;
 
 			/*
-			 * Exact equality to the default value probably means the
-			 * selectivity function punted.  This is not airtight but should
-			 * be good enough.
+			 * If either selectivity is default, we use a default estimate.
+			 * This is not airtight but should be good enough.
 			 */
-			if (rqlist->hibound == DEFAULT_INEQ_SEL ||
-				rqlist->lobound == DEFAULT_INEQ_SEL)
+			if (rqlist->hibound_isdefault ||
+				rqlist->lobound_isdefault)
 			{
 				s2 = DEFAULT_RANGE_INEQ_SEL;
 			}
@@ -332,7 +336,8 @@ clauselist_selectivity(PlannerInfo *root,
  */
 static void
 addRangeClause(RangeQueryClause **rqlist, Node *clause,
-			   bool varonleft, bool isLTsel, Selectivity s2)
+			   bool varonleft, bool isLTsel, Selectivity s2,
+			   bool isdefault)
 {
 	RangeQueryClause *rqelem;
 	Node	   *var;
@@ -377,6 +382,8 @@ addRangeClause(RangeQueryClause **rqlist, Node *clause,
 				if (rqelem->lobound > s2)
 					rqelem->lobound = s2;
 			}
+			if (isdefault)
+				rqelem->lobound_isdefault = true;
 		}
 		else
 		{
@@ -397,6 +404,8 @@ addRangeClause(RangeQueryClause **rqlist, Node *clause,
 				if (rqelem->hibound > s2)
 					rqelem->hibound = s2;
 			}
+			if (isdefault)
+				rqelem->hibound_isdefault = true;
 		}
 		return;
 	}
@@ -404,17 +413,24 @@ addRangeClause(RangeQueryClause **rqlist, Node *clause,
 	/* No matching var found, so make a new clause-pair data structure */
 	rqelem = (RangeQueryClause *) palloc(sizeof(RangeQueryClause));
 	rqelem->var = var;
+	rqelem->lobound_isdefault = false;
+	rqelem->hibound_isdefault = false;
+
 	if (is_lobound)
 	{
 		rqelem->have_lobound = true;
 		rqelem->have_hibound = false;
 		rqelem->lobound = s2;
+		if (isdefault)
+			rqelem->lobound_isdefault = true;
 	}
 	else
 	{
 		rqelem->have_lobound = false;
 		rqelem->have_hibound = true;
 		rqelem->hibound = s2;
+		if (isdefault)
+			rqelem->lobound_isdefault = true;
 	}
 	rqelem->next = *rqlist;
 	*rqlist = rqelem;
@@ -575,7 +591,8 @@ clause_selectivity(PlannerInfo *root,
 				   Node *clause,
 				   int varRelid,
 				   JoinType jointype,
-				   SpecialJoinInfo *sjinfo)
+				   SpecialJoinInfo *sjinfo,
+				   bool *isdefault)
 {
 	Selectivity s1 = 0.5;		/* default for any unhandled clause type */
 	RestrictInfo *rinfo = NULL;
@@ -695,7 +712,7 @@ clause_selectivity(PlannerInfo *root,
 									  (Node *) get_notclausearg((Expr *) clause),
 									  varRelid,
 									  jointype,
-									  sjinfo);
+									  sjinfo, isdefault);
 	}
 	else if (and_clause(clause))
 	{
@@ -723,7 +740,7 @@ clause_selectivity(PlannerInfo *root,
 												(Node *) lfirst(arg),
 												varRelid,
 												jointype,
-												sjinfo);
+												sjinfo, isdefault);
 
 			s1 = s1 + s2 - s1 * s2;
 		}
@@ -748,7 +765,7 @@ clause_selectivity(PlannerInfo *root,
 			s1 = restriction_selectivity(root, opno,
 										 opclause->args,
 										 opclause->inputcollid,
-										 varRelid);
+										 varRelid, isdefault);
 		}
 
 		/*
@@ -816,7 +833,7 @@ clause_selectivity(PlannerInfo *root,
 								(Node *) ((RelabelType *) clause)->arg,
 								varRelid,
 								jointype,
-								sjinfo);
+								sjinfo, isdefault);
 	}
 	else if (IsA(clause, CoerceToDomain))
 	{
@@ -825,7 +842,7 @@ clause_selectivity(PlannerInfo *root,
 								(Node *) ((CoerceToDomain *) clause)->arg,
 								varRelid,
 								jointype,
-								sjinfo);
+								sjinfo, isdefault);
 	}
 	else
 	{
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 480fd250e9..c181ef0ea6 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -4246,6 +4246,7 @@ approx_tuple_count(PlannerInfo *root, JoinPath *path, List *quals)
 	SpecialJoinInfo sjinfo;
 	Selectivity selec = 1.0;
 	ListCell   *l;
+	bool   isdefault;
 
 	/*
 	 * Make up a SpecialJoinInfo for JOIN_INNER semantics.
@@ -4270,7 +4271,7 @@ approx_tuple_count(PlannerInfo *root, JoinPath *path, List *quals)
 		Node	   *qual = (Node *) lfirst(l);
 
 		/* Note that clause_selectivity will be able to cache its result */
-		selec *= clause_selectivity(root, qual, 0, JOIN_INNER, &sjinfo);
+		selec *= clause_selectivity(root, qual, 0, JOIN_INNER, &sjinfo, &isdefault);
 	}
 
 	/* Apply it to the input relation sizes */
diff --git a/src/backend/optimizer/util/orclauses.c b/src/backend/optimizer/util/orclauses.c
index 1e78028abe..c92eeae824 100644
--- a/src/backend/optimizer/util/orclauses.c
+++ b/src/backend/optimizer/util/orclauses.c
@@ -260,7 +260,7 @@ consider_new_or_clause(PlannerInfo *root, RelOptInfo *rel,
 	RestrictInfo *or_rinfo;
 	Selectivity or_selec,
 				orig_selec;
-
+	bool  isdefault;
 	/*
 	 * Build a RestrictInfo from the new OR clause.  We can assume it's valid
 	 * as a base restriction clause.
@@ -280,7 +280,7 @@ consider_new_or_clause(PlannerInfo *root, RelOptInfo *rel,
 	 * saving work later.)
 	 */
 	or_selec = clause_selectivity(root, (Node *) or_rinfo,
-								  0, JOIN_INNER, NULL);
+								  0, JOIN_INNER, NULL, &isdefault);
 
 	/*
 	 * The clause is only worth adding to the query if it rejects a useful
@@ -344,7 +344,7 @@ consider_new_or_clause(PlannerInfo *root, RelOptInfo *rel,
 
 		/* Compute inner-join size */
 		orig_selec = clause_selectivity(root, (Node *) join_or_rinfo,
-										0, JOIN_INNER, &sjinfo);
+										0, JOIN_INNER, &sjinfo, &isdefault);
 
 		/* And hack cached selectivity so join size remains the same */
 		join_or_rinfo->norm_selec = orig_selec / or_selec;
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index a570ac0aab..cb7595e69b 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -1740,7 +1740,8 @@ restriction_selectivity(PlannerInfo *root,
 						Oid operatorid,
 						List *args,
 						Oid inputcollid,
-						int varRelid)
+						int varRelid,
+						bool *isdefault)
 {
 	RegProcedure oprrest = get_oprrest(operatorid);
 	float8		result;
@@ -1752,12 +1753,13 @@ restriction_selectivity(PlannerInfo *root,
 	if (!oprrest)
 		return (Selectivity) 0.5;
 
-	result = DatumGetFloat8(OidFunctionCall4Coll(oprrest,
+	result = DatumGetFloat8(OidFunctionCall5Coll(oprrest,
 												 inputcollid,
 												 PointerGetDatum(root),
 												 ObjectIdGetDatum(operatorid),
 												 PointerGetDatum(args),
-												 Int32GetDatum(varRelid)));
+												 Int32GetDatum(varRelid),
+												 PointerGetDatum(isdefault)));
 
 	if (result < 0.0 || result > 1.0)
 		elog(ERROR, "invalid restriction selectivity: %f", result);
diff --git a/src/backend/statistics/dependencies.c b/src/backend/statistics/dependencies.c
index 58d0df20f6..1cee5d213a 100644
--- a/src/backend/statistics/dependencies.c
+++ b/src/backend/statistics/dependencies.c
@@ -954,6 +954,7 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
 	MVDependencies *dependencies;
 	AttrNumber *list_attnums;
 	int			listidx;
+	bool  isdefault;
 
 	/* initialize output argument */
 	*estimatedclauses = NULL;
@@ -1068,7 +1069,7 @@ dependencies_clauselist_selectivity(PlannerInfo *root,
 				clause = (Node *) lfirst(l);
 
 				s2 = clause_selectivity(root, clause, varRelid, jointype,
-										sjinfo);
+										sjinfo, &isdefault);
 
 				/* mark this one as done, so we don't touch it again. */
 				*estimatedclauses = bms_add_member(*estimatedclauses, listidx);
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index c3db9ea070..378619b8c2 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -573,7 +573,8 @@ neqsel(PG_FUNCTION_ARGS)
  */
 static double
 scalarineqsel(PlannerInfo *root, Oid operator, bool isgt, bool iseq,
-			  VariableStatData *vardata, Datum constval, Oid consttype)
+			  VariableStatData *vardata, Datum constval, Oid consttype,
+			  bool *isdefault)
 {
 	Form_pg_statistic stats;
 	FmgrInfo	opproc;
@@ -582,8 +583,11 @@ scalarineqsel(PlannerInfo *root, Oid operator, bool isgt, bool iseq,
 				sumcommon;
 	double		selec;
 
+	*isdefault = false;
+
 	if (!HeapTupleIsValid(vardata->statsTuple))
 	{
+		*isdefault = true;
 		/* no stats available, so default result */
 		return DEFAULT_INEQ_SEL;
 	}
@@ -1101,6 +1105,7 @@ scalarineqsel_wrapper(PG_FUNCTION_ARGS, bool isgt, bool iseq)
 	Oid			operator = PG_GETARG_OID(1);
 	List	   *args = (List *) PG_GETARG_POINTER(2);
 	int			varRelid = PG_GETARG_INT32(3);
+	bool       *isdefault = (bool *) PG_GETARG_POINTER(4);
 	VariableStatData vardata;
 	Node	   *other;
 	bool		varonleft;
@@ -1114,13 +1119,17 @@ scalarineqsel_wrapper(PG_FUNCTION_ARGS, bool isgt, bool iseq)
 	 */
 	if (!get_restriction_variable(root, args, varRelid,
 								  &vardata, &other, &varonleft))
+	{
+		*isdefault = true;
 		PG_RETURN_FLOAT8(DEFAULT_INEQ_SEL);
+	}
 
 	/*
 	 * Can't do anything useful if the something is not a constant, either.
 	 */
 	if (!IsA(other, Const))
 	{
+		*isdefault = true;
 		ReleaseVariableStats(vardata);
 		PG_RETURN_FLOAT8(DEFAULT_INEQ_SEL);
 	}
@@ -1145,6 +1154,7 @@ scalarineqsel_wrapper(PG_FUNCTION_ARGS, bool isgt, bool iseq)
 		operator = get_commutator(operator);
 		if (!operator)
 		{
+			*isdefault = true;
 			/* Use default selectivity (should we raise an error instead?) */
 			ReleaseVariableStats(vardata);
 			PG_RETURN_FLOAT8(DEFAULT_INEQ_SEL);
@@ -1154,7 +1164,7 @@ scalarineqsel_wrapper(PG_FUNCTION_ARGS, bool isgt, bool iseq)
 
 	/* The rest of the work is done by scalarineqsel(). */
 	selec = scalarineqsel(root, operator, isgt, iseq,
-						  &vardata, constval, consttype);
+						  &vardata, constval, consttype, isdefault);
 
 	ReleaseVariableStats(vardata);
 
@@ -1607,6 +1617,7 @@ booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg,
 {
 	VariableStatData vardata;
 	double		selec;
+	bool   isdefault;
 
 	examine_variable(root, arg, varRelid, &vardata);
 
@@ -1731,14 +1742,14 @@ booltestsel(PlannerInfo *root, BoolTestType booltesttype, Node *arg,
 			case IS_TRUE:
 			case IS_NOT_FALSE:
 				selec = (double) clause_selectivity(root, arg,
-													varRelid,
-													jointype, sjinfo);
+													varRelid, jointype,
+													sjinfo, &isdefault);
 				break;
 			case IS_FALSE:
 			case IS_NOT_TRUE:
 				selec = 1.0 - (double) clause_selectivity(root, arg,
-														  varRelid,
-														  jointype, sjinfo);
+														  varRelid, jointype,
+														  sjinfo, &isdefault);
 				break;
 			default:
 				elog(ERROR, "unrecognized booltesttype: %d",
@@ -2235,6 +2246,7 @@ rowcomparesel(PlannerInfo *root,
 	Oid			inputcollid = linitial_oid(clause->inputcollids);
 	List	   *opargs;
 	bool		is_join_clause;
+	bool        isdefault;
 
 	/* Build equivalent arg list for single operator */
 	opargs = list_make2(linitial(clause->largs), linitial(clause->rargs));
@@ -2283,7 +2295,7 @@ rowcomparesel(PlannerInfo *root,
 		s1 = restriction_selectivity(root, opno,
 									 opargs,
 									 inputcollid,
-									 varRelid);
+									 varRelid, &isdefault);
 	}
 
 	return s1;
@@ -3039,6 +3051,7 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
 				rightmin,
 				rightmax;
 	double		selec;
+	bool        isdefault;
 
 	/* Set default results if we can't figure anything out. */
 	/* XXX should default "start" fraction be a bit more than 0? */
@@ -3206,13 +3219,13 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
 	 * non-default estimates, else stick with our 1.0.
 	 */
 	selec = scalarineqsel(root, leop, isgt, true, &leftvar,
-						  rightmax, op_righttype);
+						  rightmax, op_righttype, &isdefault);
 	if (selec != DEFAULT_INEQ_SEL)
 		*leftend = selec;
 
 	/* And similarly for the right variable. */
 	selec = scalarineqsel(root, revleop, isgt, true, &rightvar,
-						  leftmax, op_lefttype);
+						  leftmax, op_lefttype, &isdefault);
 	if (selec != DEFAULT_INEQ_SEL)
 		*rightend = selec;
 
@@ -3236,13 +3249,13 @@ mergejoinscansel(PlannerInfo *root, Node *clause,
 	 * our own default.
 	 */
 	selec = scalarineqsel(root, ltop, isgt, false, &leftvar,
-						  rightmin, op_righttype);
+						  rightmin, op_righttype, &isdefault);
 	if (selec != DEFAULT_INEQ_SEL)
 		*leftstart = selec;
 
 	/* And similarly for the right variable. */
 	selec = scalarineqsel(root, revltop, isgt, false, &rightvar,
-						  leftmin, op_lefttype);
+						  leftmin, op_lefttype, &isdefault);
 	if (selec != DEFAULT_INEQ_SEL)
 		*rightstart = selec;
 
diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h
index 77ca7ff837..19382b8a28 100644
--- a/src/include/optimizer/cost.h
+++ b/src/include/optimizer/cost.h
@@ -214,7 +214,8 @@ extern Selectivity clause_selectivity(PlannerInfo *root,
 				   Node *clause,
 				   int varRelid,
 				   JoinType jointype,
-				   SpecialJoinInfo *sjinfo);
+				   SpecialJoinInfo *sjinfo,
+				   bool *isdefault);
 extern void cost_gather_merge(GatherMergePath *path, PlannerInfo *root,
 				  RelOptInfo *rel, ParamPathInfo *param_info,
 				  Cost input_startup_cost, Cost input_total_cost,
diff --git a/src/include/optimizer/plancat.h b/src/include/optimizer/plancat.h
index 7d53cbbb87..2cb077e6ff 100644
--- a/src/include/optimizer/plancat.h
+++ b/src/include/optimizer/plancat.h
@@ -46,7 +46,8 @@ extern Selectivity restriction_selectivity(PlannerInfo *root,
 						Oid operatorid,
 						List *args,
 						Oid inputcollid,
-						int varRelid);
+						int varRelid,
+						bool *isdefault);
 
 extern Selectivity join_selectivity(PlannerInfo *root,
 				 Oid operatorid,
