diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index 86b512a..ddae8f7 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -72,7 +72,8 @@ typedef enum RangeDatumContent
 {
 	RANGE_DATUM_FINITE = 0,		/* actual datum stored elsewhere */
 	RANGE_DATUM_NEG_INF,		/* negative infinity */
-	RANGE_DATUM_POS_INF			/* positive infinity */
+	RANGE_DATUM_POS_INF,		/* positive infinity */
+	RANGE_DATUM_DEFAULT			/* Default Datum */
 } RangeDatumContent;
 
 typedef struct PartitionBoundInfoData
@@ -89,10 +90,8 @@ typedef struct PartitionBoundInfoData
 								 * partitioned table) */
 	int			null_index;		/* Index of the null-accepting partition; -1
 								 * if there isn't one */
-	bool		has_default;		/* Is there a default partition? Currently false
-								 * for a range partitioned table */
-	int			default_index;		/* Index of the default list partition. -1 for
-								 * range partitioned tables */
+	bool		has_default;	/* Is there a default partition? */
+	int			default_index;	/* Index of the default list partition. */
 } PartitionBoundInfoData;
 
 #define partition_bound_accepts_nulls(bi) ((bi)->null_index != -1)
@@ -135,7 +134,7 @@ static void get_range_key_properties(PartitionKey key, int keynum,
 						 Const **lower_val, Const **upper_val);
 static List *get_qual_for_list(PartitionKey key, PartitionBoundSpec *spec,
 							   bool is_def, List *boundspecs);
-static List *get_qual_for_range(PartitionKey key, PartitionBoundSpec *spec);
+static List *get_qual_for_range(PartitionKey key, PartitionBoundSpec *spec, bool is_def);
 static List *generate_partition_qual(Relation rel);
 
 static PartitionRangeBound *make_one_range_bound(PartitionKey key, int index,
@@ -146,6 +145,7 @@ static int32 partition_rbound_cmp(PartitionKey key,
 static int32 partition_rbound_datum_cmp(PartitionKey key,
 						   Datum *rb_datums, RangeDatumContent *rb_content,
 						   Datum *tuple_datums);
+static List *get_qual_for_range_default(Relation parent, Oid *defid);
 
 static int32 partition_bound_cmp(PartitionKey key,
 					PartitionBoundInfo boundinfo,
@@ -176,11 +176,11 @@ RelationBuildPartitionDesc(Relation rel)
 	MemoryContext oldcxt;
 
 	int			ndatums = 0;
+	bool		found_def = false;
+	int			def_index = -1;
 
 	/* List partitioning specific */
 	PartitionListValue **all_values = NULL;
-	bool		found_def = false;
-	int			def_index = -1;
 	int			null_index = -1;
 
 	/* Range partitioning specific */
@@ -345,10 +345,21 @@ RelationBuildPartitionDesc(Relation rel)
 				PartitionBoundSpec *spec = lfirst(cell);
 				PartitionRangeBound *lower,
 						   *upper;
+				ListCell   *lc;
 
 				if (spec->strategy != PARTITION_STRATEGY_RANGE)
 					elog(ERROR, "invalid strategy in partition bound spec");
 
+				foreach(lc, spec->lowerdatums)
+				{
+					if (isDefaultPartitionBound((Node *) lfirst(lc)))
+					{
+						found_def = true;
+						def_index = i;
+						break;
+					}
+				}
+
 				lower = make_one_range_bound(key, i, spec->lowerdatums,
 											 true);
 				upper = make_one_range_bound(key, i, spec->upperdatums,
@@ -559,6 +570,9 @@ RelationBuildPartitionDesc(Relation rel)
 							boundinfo->content[i][j] = rbounds[i]->content[j];
 						}
 
+						if (found_def && mapping[def_index] == -1)
+							mapping[def_index] = next_index++;
+
 						/*
 						 * There is no mapping for invalid indexes.
 						 *
@@ -581,6 +595,11 @@ RelationBuildPartitionDesc(Relation rel)
 							boundinfo->indexes[i] = mapping[orig_index];
 						}
 					}
+
+					if (found_def)
+						boundinfo->default_index = mapping[def_index];
+					else
+						boundinfo->default_index = -1;
 					boundinfo->indexes[i] = -1;
 					break;
 				}
@@ -750,7 +769,6 @@ check_new_partition_bound(char *relname, Relation parent, Node *bound)
 						}
 					}
 				}
-
 				break;
 			}
 
@@ -763,95 +781,113 @@ check_new_partition_bound(char *relname, Relation parent, Node *bound)
 				lower = make_one_range_bound(key, -1, spec->lowerdatums, true);
 				upper = make_one_range_bound(key, -1, spec->upperdatums, false);
 
+
 				/*
-				 * First check if the resulting range would be empty with
-				 * specified lower and upper bounds
+				 * If the new partition is default check if the parent table
+				 * already has a default partition
 				 */
-				if (partition_rbound_cmp(key, lower->datums, lower->content, true,
-										 upper) >= 0)
-					ereport(ERROR,
-							(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
-					errmsg("cannot create range partition with empty range"),
-							 parser_errposition(pstate, spec->location)));
 
-				if (partdesc->nparts > 0)
+				if ((lower->content[0] == RANGE_DATUM_DEFAULT))
+				{
+					if (partdesc->nparts > 0 && partdesc->boundinfo->has_default)
+					{
+						overlap = true;
+						with = partdesc->boundinfo->default_index;
+						break;
+					}
+				}
+				else
 				{
-					PartitionBoundInfo boundinfo = partdesc->boundinfo;
-					int			off1,
-								off2;
-					bool		equal = false;
-
-					Assert(boundinfo && boundinfo->ndatums > 0 &&
-						   boundinfo->strategy == PARTITION_STRATEGY_RANGE);
-
-					/*
-					 * Firstly, find the greatest range bound that is less
-					 * than or equal to the new lower bound.
-					 */
-					off1 = partition_bound_bsearch(key, boundinfo, lower, true,
-												   &equal);
-
 					/*
-					 * off1 == -1 means that all existing bounds are greater
-					 * than the new lower bound.  In that case and the case
-					 * where no partition is defined between the bounds at
-					 * off1 and off1 + 1, we have a "gap" in the range that
-					 * could be occupied by the new partition.  We confirm if
-					 * so by checking whether the new upper bound is confined
-					 * within the gap.
+					 * First check if the resulting range would be empty with
+					 * specified lower and upper bounds
 					 */
-					if (!equal && boundinfo->indexes[off1 + 1] < 0)
+					if (partition_rbound_cmp(key, lower->datums, lower->content, true,
+											 upper) >= 0)
+						ereport(ERROR,
+								(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+								 errmsg("cannot create range partition with empty range"),
+								 parser_errposition(pstate, spec->location)));
+
+					if (partdesc->nparts > 0)
 					{
-						off2 = partition_bound_bsearch(key, boundinfo, upper,
-													   true, &equal);
+						PartitionBoundInfo boundinfo = partdesc->boundinfo;
+						int			off1,
+									off2;
+						bool		equal = false;
+
+						Assert(boundinfo && boundinfo->ndatums > 0 &&
+							boundinfo->strategy == PARTITION_STRATEGY_RANGE);
 
 						/*
-						 * If the new upper bound is returned to be equal to
-						 * the bound at off2, the latter must be the upper
-						 * bound of some partition with which the new
-						 * partition clearly overlaps.
-						 *
-						 * Also, if bound at off2 is not same as the one
-						 * returned for the new lower bound (IOW, off1 !=
-						 * off2), then the new partition overlaps at least one
-						 * partition.
+						 * Firstly, find the greatest range bound that is less
+						 * than or equal to the new lower bound.
 						 */
-						if (equal || off1 != off2)
+						off1 = partition_bound_bsearch(key, boundinfo, lower, true,
+													   &equal);
+
+						/*
+						 * off1 == -1 means that all existing bounds are
+						 * greater than the new lower bound.  In that case and
+						 * the case where no partition is defined between the
+						 * bounds at off1 and off1 + 1, we have a "gap" in the
+						 * range that could be occupied by the new partition.
+						 * We confirm if so by checking whether the new upper
+						 * bound is confined within the gap.
+						 */
+						if (!equal && boundinfo->indexes[off1 + 1] < 0)
 						{
-							overlap = true;
+							off2 = partition_bound_bsearch(key, boundinfo, upper,
+														   true, &equal);
 
 							/*
-							 * The bound at off2 could be the lower bound of
-							 * the partition with which the new partition
-							 * overlaps.  In that case, use the upper bound
-							 * (that is, the bound at off2 + 1) to get the
-							 * index of that partition.
+							 * If the new upper bound is returned to be equal
+							 * to the bound at off2, the latter must be the
+							 * upper bound of some partition with which the
+							 * new partition clearly overlaps.
+							 *
+							 * Also, if bound at off2 is not same as the one
+							 * returned for the new lower bound (IOW, off1 !=
+							 * off2), then the new partition overlaps at least
+							 * one partition.
 							 */
-							if (boundinfo->indexes[off2] < 0)
-								with = boundinfo->indexes[off2 + 1];
-							else
-								with = boundinfo->indexes[off2];
+							if (equal || off1 != off2)
+							{
+								overlap = true;
+
+								/*
+								 * The bound at off2 could be the lower bound
+								 * of the partition with which the new
+								 * partition overlaps.  In that case, use the
+								 * upper bound (that is, the bound at off2 +
+								 * 1) to get the index of that partition.
+								 */
+								if (boundinfo->indexes[off2] < 0)
+									with = boundinfo->indexes[off2 + 1];
+								else
+									with = boundinfo->indexes[off2];
+							}
+						}
+						else
+						{
+							/*
+							 * Equal has been set to true and there is no
+							 * "gap" between the bound at off1 and that at
+							 * off1 + 1, so the new partition will overlap
+							 * some partition. In the former case, the new
+							 * lower bound is found to be equal to the bound
+							 * at off1, which could only ever be true if the
+							 * latter is the lower bound of some partition.
+							 * It's clear in such a case that the new
+							 * partition overlaps that partition, whose index
+							 * we get using its upper bound (that is, using
+							 * the bound at off1 + 1).
+							 */
+							overlap = true;
+							with = boundinfo->indexes[off1 + 1];
 						}
-					}
-					else
-					{
-						/*
-						 * Equal has been set to true and there is no "gap"
-						 * between the bound at off1 and that at off1 + 1, so
-						 * the new partition will overlap some partition. In
-						 * the former case, the new lower bound is found to be
-						 * equal to the bound at off1, which could only ever
-						 * be true if the latter is the lower bound of some
-						 * partition.  It's clear in such a case that the new
-						 * partition overlaps that partition, whose index we
-						 * get using its upper bound (that is, using the bound
-						 * at off1 + 1).
-						 */
-						overlap = true;
-						with = boundinfo->indexes[off1 + 1];
 					}
 				}
-
 				break;
 			}
 
@@ -871,13 +907,12 @@ check_new_partition_bound(char *relname, Relation parent, Node *bound)
 	}
 
 	/*
-	 * When adding a list partition after default partition, scan the
-	 * default partition for rows satisfying the new partition
-	 * constraint. If found don't allow addition of a new partition.
-	 * Otherwise continue with the creation of new  partition.
+	 * When adding a partition after default partition, scan the default
+	 * partition for rows satisfying the new partition constraint. If found,
+	 * don't allow addition of a new partition. Otherwise continue with the
+	 * creation of new	partition.
 	 */
-	if (spec->strategy == PARTITION_STRATEGY_LIST && partdesc->nparts > 0
-		&& boundinfo->has_default)
+	if (partdesc->nparts > 0 && boundinfo->has_default)
 	{
 		List	       *partConstraint = NIL;
 		ExprContext    *econtext;
@@ -1104,6 +1139,77 @@ get_qual_for_default(Relation parent, Oid *defid)
 	return boundspecs;
 }
 
+
+static List *
+get_qual_for_range_default(Relation parent, Oid *defid)
+{
+	PartitionKey key = RelationGetPartitionKey(parent);
+	List	   *inhoids;
+	ListCell   *cell;
+	List	   *result = NIL;
+
+	inhoids = find_inheritance_children(RelationGetRelid(parent), AccessExclusiveLock);
+
+	foreach(cell, inhoids)
+	{
+		Oid			inhrelid = lfirst_oid(cell);
+		HeapTuple	tuple;
+		Datum		datum;
+		bool		isnull;
+		bool		def_elem = false;
+		PartitionBoundSpec *bspec;
+		ListCell   *cell_u,
+				   *cell_l;
+
+		tuple = SearchSysCache1(RELOID, inhrelid);
+		if (!HeapTupleIsValid(tuple))
+			elog(ERROR, "cache lookup failed for relation %u", inhrelid);
+
+		/*
+		 * It is possible that the pg_class tuple of a partition has not been
+		 * updated yet to set its relpartbound field.  The only case where
+		 * this happens is when we open the parent relation to check using its
+		 * partition descriptor that a new partition's bound does not overlap
+		 * some existing partition.
+		 */
+		if (!((Form_pg_class) GETSTRUCT(tuple))->relispartition)
+		{
+			ReleaseSysCache(tuple);
+			continue;
+		}
+
+		datum = SysCacheGetAttr(RELOID, tuple,
+								Anum_pg_class_relpartbound,
+								&isnull);
+
+		Assert(!isnull);
+		bspec = (PartitionBoundSpec *) stringToNode(TextDatumGetCString(datum));
+
+		forboth(cell_l, bspec->lowerdatums, cell_u, bspec->upperdatums)
+		{
+			Node	   *value = lfirst(cell_l);
+
+			if (isDefaultPartitionBound(value))
+			{
+				def_elem = true;
+				*defid = inhrelid;
+				break;
+			}
+		}
+		if (!def_elem)
+		{
+			List	   *boundspecs = get_qual_for_range(key, bspec, true);
+
+			result = lappend(result,
+							 list_length(boundspecs) > 1
+							 ? makeBoolExpr(OR_EXPR, boundspecs, -1)
+							 : linitial(boundspecs));
+		}
+		ReleaseSysCache(tuple);
+	}
+	return result;
+}
+
 /*
  * Return a list of executable expressions as new partition constraint
  * for default partition while adding a new partition after default
@@ -1119,16 +1225,22 @@ generate_qual_for_defaultpart(Relation parent, Node *bound, Oid * defid)
 	List       *bound_datums;
 
 	spec = (PartitionBoundSpec *) bound;
-	bound_datums = list_copy(spec->listdatums);
+	if (spec->strategy == PARTITION_STRATEGY_LIST)
+	{
+		bound_datums = list_copy(spec->listdatums);
+		boundspecs = get_qual_for_default(parent, defid);
 
-	boundspecs = get_qual_for_default(parent, defid);
+		foreach(cell, bound_datums)
+		{
+			Node	   *value = lfirst(cell);
 
-	foreach(cell, bound_datums)
-	{
-		Node *value = lfirst(cell);
-		boundspecs = lappend(boundspecs, value);
+			boundspecs = lappend(boundspecs, value);
+		}
+		partConstraint = get_qual_for_list(key, spec, true, boundspecs);
 	}
-	partConstraint = get_qual_for_list(key, spec, true, boundspecs);
+	else if (spec->strategy == PARTITION_STRATEGY_RANGE)
+		partConstraint = get_qual_for_range_default(parent, defid);
+
 	return partConstraint;
 }
 
@@ -1166,7 +1278,17 @@ get_qual_from_partbound(Relation rel, Relation parent, Node *bound)
 			break;
 		case PARTITION_STRATEGY_RANGE:
 			Assert(spec->strategy == PARTITION_STRATEGY_RANGE);
-			my_qual = get_qual_for_range(key, spec);
+			foreach(cell, spec->lowerdatums)
+			{
+				Node	   *value = lfirst(cell);
+
+				if (isDefaultPartitionBound(value))
+					is_def = true;
+			}
+			if (is_def)
+				my_qual = get_qual_for_range_default(parent, &defid);
+			else
+				my_qual = get_qual_for_range(key, spec, is_def);
 			break;
 
 		default:
@@ -1542,6 +1664,12 @@ make_partition_op_expr(PartitionKey key, int keynum,
 			}
 
 		case PARTITION_STRATEGY_RANGE:
+			if (is_def && ((operoid = get_negator(operoid)) == InvalidOid))
+				ereport(ERROR, (errcode(ERRCODE_CHECK_VIOLATION),
+								errmsg("DEFAULT partition cannot be used"
+									   " without negator of operator  %s",
+									   get_opname(operoid))));
+
 			result = make_opclause(operoid,
 								   BOOLOID,
 								   false,
@@ -1754,7 +1882,7 @@ get_range_key_properties(PartitionKey key, int keynum,
  * expect a non-empty list.
  */
 static List *
-get_qual_for_range(PartitionKey key, PartitionBoundSpec *spec)
+get_qual_for_range(PartitionKey key, PartitionBoundSpec *spec, bool is_def)
 {
 	List	   *result = NIL;
 	ListCell   *cell1,
@@ -1889,7 +2017,7 @@ get_qual_for_range(PartitionKey key, PartitionBoundSpec *spec)
 		result = lappend(result,
 						 make_partition_op_expr(key, i, BTEqualStrategyNumber,
 												keyCol, (Expr *) lower_val,
-												false));
+												is_def));
 
 		i++;
 	}
@@ -1948,7 +2076,7 @@ get_qual_for_range(PartitionKey key, PartitionBoundSpec *spec)
 																   strategy,
 																   keyCol,
 														(Expr *) lower_val,
-																   false));
+																   is_def));
 			}
 
 			if (need_next_upper_arm && upper_val)
@@ -1971,7 +2099,7 @@ get_qual_for_range(PartitionKey key, PartitionBoundSpec *spec)
 																   strategy,
 																   keyCol,
 														(Expr *) upper_val,
-																   false));
+																   is_def));
 
 			}
 
@@ -2385,10 +2513,12 @@ make_one_range_bound(PartitionKey key, int index, List *datums, bool lower)
 		PartitionRangeDatum *datum = lfirst(cell);
 
 		/* What's contained in this range datum? */
-		bound->content[i] = !datum->infinite
-			? RANGE_DATUM_FINITE
-			: (lower ? RANGE_DATUM_NEG_INF
-			   : RANGE_DATUM_POS_INF);
+		bound->content[i] = (datum->type == T_DefElem)
+			? RANGE_DATUM_DEFAULT
+			: (!datum->infinite
+			   ? RANGE_DATUM_FINITE
+			   : (lower ? RANGE_DATUM_NEG_INF
+				  : RANGE_DATUM_POS_INF));
 
 		if (bound->content[i] == RANGE_DATUM_FINITE)
 		{
@@ -2436,15 +2566,25 @@ partition_rbound_cmp(PartitionKey key,
 	for (i = 0; i < key->partnatts; i++)
 	{
 		/*
-		 * First, handle cases involving infinity, which don't require
-		 * invoking the comparison proc.
+		 * First, handle cases involving infinity and default, which don't
+		 * require invoking the comparison proc.
 		 */
+		if (content1[i] == RANGE_DATUM_DEFAULT ||
+			content2[i] == RANGE_DATUM_DEFAULT)
+		{
+			if (content1[i] == content2[i])
+				return 0;
+			else if (content1[i] == RANGE_DATUM_DEFAULT)
+				return lower1 ? 1 : -1;
+			else
+				return lower1 ? -1 : 1;
+		}
 		if (content1[i] != RANGE_DATUM_FINITE &&
 			content2[i] != RANGE_DATUM_FINITE)
 
 			/*
-			 * Both are infinity, so they are equal unless one is negative
-			 * infinity and other positive (or vice versa)
+			 * Both are infinity, so they are equal unless one is
+			 * negative infinity and other positive (or vice versa)
 			 */
 			return content1[i] == content2[i] ? 0
 				: (content1[i] < content2[i] ? -1 : 1);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 3af286f..7ba6425 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -2682,7 +2682,10 @@ ForValues:
 					PartitionBoundSpec *n = makeNode(PartitionBoundSpec);
 
 					n->strategy = PARTITION_DEFAULT;
+					n->isdefault = true;
 					n->listdatums = $1;
+					n->lowerdatums = $1;
+					n->upperdatums = $1;
 					n->location = @1;
 
 					$$ = (Node *) n;
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 306a5d1..b6495f9 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -3384,15 +3384,29 @@ transformPartitionBound(ParseState *pstate, Relation parent, Node *bound)
 					j;
 		char	   *colname;
 		bool		seen_unbounded;
+		bool		is_def;
 
 		if (spec->strategy != PARTITION_STRATEGY_RANGE)
-			ereport(ERROR,
-					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
-				 errmsg("invalid bound specification for a range partition"),
-					 parser_errposition(pstate, exprLocation(bound))));
-
+		{
+			/*
+			 * If the partition is the default partition switch back to
+			 * PARTITION_STRATEGY_RANGE
+			 */
+			if (spec->strategy == PARTITION_DEFAULT)
+			{
+				is_def = true;
+				result_spec->strategy = PARTITION_STRATEGY_RANGE;
+			}
+			else
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+					errmsg("invalid bound specification for a range partition"),
+						 parser_errposition(pstate, exprLocation(bound))));
+		}
 		Assert(spec->lowerdatums != NIL && spec->upperdatums != NIL);
 
+		if(!is_def)
+		{
 		if (list_length(spec->lowerdatums) != partnatts)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
@@ -3401,6 +3415,7 @@ transformPartitionBound(ParseState *pstate, Relation parent, Node *bound)
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
 					 errmsg("TO must specify exactly one value per partitioning column")));
+		}
 
 		/*
 		 * Check that no finite value follows a UNBOUNDED literal in either of
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 5bff62a..038c937 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -8689,6 +8689,17 @@ get_rule_expr(Node *node, deparse_context *context,
 							   list_length(spec->lowerdatums) ==
 							   list_length(spec->upperdatums));
 
+						foreach(cell, spec->lowerdatums)
+						{
+							if (isDefaultPartitionBound((Node *) lfirst(cell)))
+							{
+								appendStringInfoString(buf, "DEFAULT");
+								is_def = true;
+								break;
+							}
+						}
+						if (is_def)
+							break;
 						appendStringInfoString(buf, "FOR VALUES");
 						appendStringInfoString(buf, " FROM");
 						appendStringInfoString(buf, " (");
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index e632a42..8fe1aa5 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -791,6 +791,8 @@ typedef struct PartitionBoundSpec
 
 	char		strategy;
 
+	bool		isdefault;
+
 	/* List partition values */
 	List	   *listdatums;
 
