diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 2952bfb7c2..40a3c2c9f4 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -30,21 +30,23 @@
 #include "optimizer/pathnode.h"
 #include "optimizer/paths.h"
 #include "optimizer/predtest.h"
 #include "optimizer/prep.h"
 #include "optimizer/restrictinfo.h"
 #include "optimizer/var.h"
 #include "utils/builtins.h"
 #include "utils/bytea.h"
 #include "utils/lsyscache.h"
 #include "utils/pg_locale.h"
+#include "utils/rangetypes.h"
 #include "utils/selfuncs.h"
+#include "utils/typcache.h"
 
 
 #define IsBooleanOpfamily(opfamily) \
 	((opfamily) == BOOL_BTREE_FAM_OID || (opfamily) == BOOL_HASH_FAM_OID)
 
 #define IndexCollMatchesExprColl(idxcollation, exprcollation) \
 	((idxcollation) == InvalidOid || (idxcollation) == (exprcollation))
 
 /* Whether we are looking for plain indexscan, bitmap scan, or either */
 typedef enum
@@ -180,20 +182,21 @@ static Expr *expand_boolean_index_clause(Node *clause, int indexcol,
 							IndexOptInfo *index);
 static List *expand_indexqual_opclause(RestrictInfo *rinfo,
 						  Oid opfamily, Oid idxcollation);
 static RestrictInfo *expand_indexqual_rowcompare(RestrictInfo *rinfo,
 							IndexOptInfo *index,
 							int indexcol);
 static List *prefix_quals(Node *leftop, Oid opfamily, Oid collation,
 			 Const *prefix, Pattern_Prefix_Status pstatus);
 static List *network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily,
 					 Datum rightop);
+static List *range_elem_contained_quals(Node *leftop, Datum rightop);
 static Datum string_to_datum(const char *str, Oid datatype);
 static Const *string_to_const(const char *str, Oid datatype);
 
 
 /*
  * create_index_paths()
  *	  Generate all interesting index paths for the given relation.
  *	  Candidate paths are added to the rel's pathlist (using add_path).
  *
  * To be considered for an index scan, an index must match one or more
@@ -3286,20 +3289,23 @@ match_special_index_operator(Expr *clause, Oid opfamily, Oid idxcollation,
 			/* the right-hand const is type text for all of these */
 			pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC, expr_coll,
 										   &prefix, NULL);
 			isIndexable = (pstatus != Pattern_Prefix_None);
 			break;
 
 		case OID_INET_SUB_OP:
 		case OID_INET_SUBEQ_OP:
 			isIndexable = true;
 			break;
+		case OID_RANGE_ELEM_CONTAINED_OP:
+			isIndexable = true;
+			break;
 	}
 
 	if (prefix)
 	{
 		pfree(DatumGetPointer(prefix->constvalue));
 		pfree(prefix);
 	}
 
 	/* done if the expression doesn't look indexable */
 	if (!isIndexable)
@@ -3614,20 +3620,27 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily, Oid idxcollation)
 			break;
 
 		case OID_INET_SUB_OP:
 		case OID_INET_SUBEQ_OP:
 			if (!op_in_opfamily(expr_op, opfamily))
 			{
 				return network_prefix_quals(leftop, expr_op, opfamily,
 											patt->constvalue);
 			}
 			break;
+		case OID_RANGE_ELEM_CONTAINED_OP:
+			if (!op_in_opfamily(expr_op, opfamily))
+			{
+				return range_elem_contained_quals(leftop,
+											patt->constvalue);
+			}
+			break;
 	}
 
 	/* Default case: just make a list of the unmodified indexqual */
 	return list_make1(rinfo);
 }
 
 /*
  * expand_indexqual_rowcompare --- expand a single indexqual condition
  *		that is a RowCompareExpr
  *
@@ -4096,20 +4109,124 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily, Datum rightop)
 											InvalidOid, /* not collatable */
 											-1, opr2right,
 											false, false),
 						 InvalidOid, InvalidOid);
 	result = lappend(result, make_simple_restrictinfo(expr));
 
 	return result;
 }
 
 /*
+ * Given an element leftop and a range rightop, and an elem contained-by range
+ * operator, generate suitable indexqual condition(s).
+ */
+static List *
+range_elem_contained_quals(Node *leftop, Datum rightop)
+{
+	Oid				datatype;
+	Oid				opfamily;
+	Oid				opr1oid;
+	Oid				opr2oid;
+	List			*result = NIL;
+	Expr			*expr;
+	RangeType		*range;
+	TypeCacheEntry	*rangetypcache;
+	RangeBound		lbound;
+	RangeBound		ubound;
+	bool			empty;
+
+	switch (leftop->type)
+	{
+		case T_Var:
+			datatype = ((Var *)leftop)->vartype;
+			break;
+		default:
+			elog(ERROR, "unexpected NodeTag: %u", leftop->type);
+			return NIL;
+	}
+
+	opfamily = lookup_type_cache(datatype, TYPECACHE_BTREE_OPFAMILY)->btree_opf;
+
+	range = DatumGetRangeType(rightop);
+	rangetypcache = lookup_type_cache(RangeTypeGetOid(range), TYPECACHE_RANGE_INFO);
+	range_deserialize(rangetypcache, range, &lbound, &ubound, &empty);
+
+	if (empty)
+	{
+		return NIL;
+	}
+
+	if (!lbound.infinite)
+	{
+		if (lbound.inclusive)
+		{
+			opr1oid = get_opfamily_member(opfamily, datatype, datatype,
+										  BTGreaterEqualStrategyNumber);
+			if (opr1oid == InvalidOid)
+			{
+				elog(ERROR, "no >= operator for opfamily %u", opfamily);
+				return NIL;
+			}
+		} else {
+			opr1oid = get_opfamily_member(opfamily, datatype, datatype,
+										  BTGreaterStrategyNumber);
+			if (opr1oid == InvalidOid)
+			{
+				elog(ERROR, "no > operator for opfamily %u", opfamily);
+				return NIL;
+			}
+		}
+
+		expr = make_opclause(opr1oid, BOOLOID, false,
+				(Expr *) leftop,
+				(Expr *) makeConst(rangetypcache->rngelemtype->type_id, -1,
+					rangetypcache->rng_collation,
+					rangetypcache->rngelemtype->typlen, lbound.val,
+					false, rangetypcache->rngelemtype->typbyval),
+				InvalidOid, InvalidOid);
+		result = lappend(result, make_simple_restrictinfo(expr));
+	}
+
+	if (!ubound.infinite)
+	{
+		if (ubound.inclusive)
+		{
+			opr2oid = get_opfamily_member(opfamily, datatype, datatype,
+										  BTLessEqualStrategyNumber);
+			if (opr2oid == InvalidOid)
+			{
+				elog(ERROR, "no <= operator for opfamily %u", opfamily);
+				return NIL;
+			}
+		} else {
+			opr2oid = get_opfamily_member(opfamily, datatype, datatype,
+										  BTLessStrategyNumber);
+			if (opr1oid == InvalidOid)
+			{
+				elog(ERROR, "no < operator for opfamily %u", opfamily);
+				return NIL;
+			}
+		}
+
+		expr = make_opclause(opr2oid, BOOLOID, false,
+				(Expr *) leftop,
+				(Expr *) makeConst(rangetypcache->rngelemtype->type_id, -1,
+					rangetypcache->rng_collation,
+					rangetypcache->rngelemtype->typlen, ubound.val,
+					false, rangetypcache->rngelemtype->typbyval),
+				InvalidOid, InvalidOid);
+		result = lappend(result, make_simple_restrictinfo(expr));
+	}
+	return result;
+}
+
+/*
  * Handy subroutines for match_special_index_operator() and friends.
  */
 
 /*
  * Generate a Datum of the appropriate type from a C string.
  * Note that all of the supported types are pass-by-ref, so the
  * returned value should be pfree'd if no longer needed.
  */
 static Datum
 string_to_datum(const char *str, Oid datatype)
