diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 71e20f2..4cfd759 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -3874,6 +3874,17 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
        partial index.
       </entry>
      </row>
+
+     <row>
+      <entry><structfield>indoptions</structfield></entry>
+      <entry><type>text[]</type></entry>
+      <entry></entry>
+      <entry>
+       This is an array of <structfield>indnatts</structfield> strings that
+       store per-column opclass options or null.  Each array element is a
+       serialized array of column's opclass options in reloptions format or null.
+      </entry>
+     </row>
     </tbody>
    </tgroup>
   </table>
diff --git a/doc/src/sgml/indices.sgml b/doc/src/sgml/indices.sgml
index 0818196..e6c967b 100644
--- a/doc/src/sgml/indices.sgml
+++ b/doc/src/sgml/indices.sgml
@@ -983,7 +983,7 @@ CREATE UNIQUE INDEX tests_success_constraint ON tests (subject, target)
    An index definition can specify an <firstterm>operator
    class</firstterm> for each column of an index.
 <synopsis>
-CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> (<replaceable>column</replaceable> <replaceable>opclass</replaceable> <optional><replaceable>sort options</replaceable></optional> <optional>, ...</optional>);
+CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> (<replaceable>column</replaceable> <replaceable>opclass</replaceable> [ ( <replaceable>opclass_options</replaceable> ) ] <optional><replaceable>sort options</replaceable></optional> <optional>, ...</optional>);
 </synopsis>
    The operator class identifies the operators to be used by the index
    for that column.  For example, a B-tree index on the type <type>int4</type>
diff --git a/doc/src/sgml/ref/create_index.sgml b/doc/src/sgml/ref/create_index.sgml
index 1fd21e1..907b436 100644
--- a/doc/src/sgml/ref/create_index.sgml
+++ b/doc/src/sgml/ref/create_index.sgml
@@ -22,7 +22,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] <replaceable class="parameter">name</replaceable> ] ON [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ USING <replaceable class="parameter">method</replaceable> ]
-    ( { <replaceable class="parameter">column_name</replaceable> | ( <replaceable class="parameter">expression</replaceable> ) } [ COLLATE <replaceable class="parameter">collation</replaceable> ] [ <replaceable class="parameter">opclass</replaceable> ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )
+    ( { <replaceable class="parameter">column_name</replaceable> | ( <replaceable class="parameter">expression</replaceable> ) } [ COLLATE <replaceable class="parameter">collation</replaceable> ] [ { <replaceable class="parameter">opclass</replaceable> | DEFAULT } [ ( <replaceable class="parameter">opclass_parameter</replaceable> = <replaceable class="parameter">value</replaceable> [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )
     [ WITH ( <replaceable class="parameter">storage_parameter</replaceable> = <replaceable class="parameter">value</replaceable> [, ... ] ) ]
     [ TABLESPACE <replaceable class="parameter">tablespace_name</replaceable> ]
     [ WHERE <replaceable class="parameter">predicate</replaceable> ]
@@ -232,6 +232,15 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] <replaceable class=
      </varlistentry>
 
      <varlistentry>
+      <term><replaceable class="parameter">opclass_parameter</replaceable></term>
+      <listitem>
+       <para>
+        The name of an operator class parameter. See below for details.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
       <term><literal>ASC</literal></term>
       <listitem>
        <para>
@@ -544,8 +553,9 @@ Indexes:
   </para>
 
   <para>
-   An <firstterm>operator class</firstterm> can be specified for each
-   column of an index. The operator class identifies the operators to be
+   An <firstterm>operator class</firstterm> with its optional parameters 
+   can be specified for each column of an index.
+   The operator class identifies the operators to be
    used by the index for that column. For example, a B-tree index on
    four-byte integers would use the <literal>int4_ops</literal> class;
    this operator class includes comparison functions for four-byte
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 46276ce..4c72986 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1007,6 +1007,60 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 	return options;
 }
 
+static void
+parseRelOptionsInternal(Datum options, bool validate,
+				 relopt_value *reloptions, int numoptions)
+{
+	ArrayType  *array = DatumGetArrayTypeP(options);
+	Datum	   *optiondatums;
+	int			noptions;
+	int			i;
+
+	deconstruct_array(array, TEXTOID, -1, false, 'i',
+					  &optiondatums, NULL, &noptions);
+
+	for (i = 0; i < noptions; i++)
+	{
+		char	   *text_str = VARDATA(optiondatums[i]);
+		int			text_len = VARSIZE(optiondatums[i]) - VARHDRSZ;
+		int			j;
+
+		/* Search for a match in reloptions */
+		for (j = 0; j < numoptions; j++)
+		{
+			int			kw_len = reloptions[j].gen->namelen;
+
+			if (text_len > kw_len && text_str[kw_len] == '=' &&
+				strncmp(text_str, reloptions[j].gen->name, kw_len) == 0)
+			{
+				parse_one_reloption(&reloptions[j], text_str, text_len,
+									validate);
+				break;
+			}
+		}
+
+		if (j >= numoptions && validate)
+		{
+			char	   *s;
+			char	   *p;
+
+			s = TextDatumGetCString(optiondatums[i]);
+			p = strchr(s, '=');
+			if (p)
+				*p = '\0';
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("unrecognized parameter \"%s\"", s)));
+		}
+	}
+
+	/* It's worth avoiding memory leaks in this function */
+	pfree(optiondatums);
+
+	if (((void *) array) != DatumGetPointer(options))
+		pfree(array);
+}
+
 /*
  * Interpret reloptions that are given in text-array format.
  *
@@ -1061,57 +1115,61 @@ parseRelOptions(Datum options, bool validate, relopt_kind kind,
 
 	/* Done if no options */
 	if (PointerIsValid(DatumGetPointer(options)))
-	{
-		ArrayType  *array = DatumGetArrayTypeP(options);
-		Datum	   *optiondatums;
-		int			noptions;
+		parseRelOptionsInternal(options, validate, reloptions, numoptions);
 
-		deconstruct_array(array, TEXTOID, -1, false, 'i',
-						  &optiondatums, NULL, &noptions);
+	*numrelopts = numoptions;
+	return reloptions;
+}
 
-		for (i = 0; i < noptions; i++)
-		{
-			char	   *text_str = VARDATA(optiondatums[i]);
-			int			text_len = VARSIZE(optiondatums[i]) - VARHDRSZ;
-			int			j;
+/* Parse local unregistered options. */
+relopt_value *
+parseLocalRelOptions(Datum options, bool validate,
+					 relopt_gen *optgen[], int nopts)
+{
+	relopt_value *values = palloc(sizeof(*values) * nopts);
+	int			i;
 
-			/* Search for a match in reloptions */
-			for (j = 0; j < numoptions; j++)
-			{
-				int			kw_len = reloptions[j].gen->namelen;
+	for (i = 0; i < nopts; i++)
+	{
+		values[i].gen = optgen[i];
+		values[i].isset = false;
+	}
 
-				if (text_len > kw_len && text_str[kw_len] == '=' &&
-					strncmp(text_str, reloptions[j].gen->name, kw_len) == 0)
-				{
-					parse_one_reloption(&reloptions[j], text_str, text_len,
-										validate);
-					break;
-				}
-			}
+	if (options != (Datum) 0)
+		parseRelOptionsInternal(options, validate, values, nopts);
 
-			if (j >= numoptions && validate)
-			{
-				char	   *s;
-				char	   *p;
+	return values;
+}
 
-				s = TextDatumGetCString(optiondatums[i]);
-				p = strchr(s, '=');
-				if (p)
-					*p = '\0';
-				ereport(ERROR,
-						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-						 errmsg("unrecognized parameter \"%s\"", s)));
-			}
-		}
+/*
+ * Parse local options, allocate a bytea struct that's of the specified
+ * 'base_size' plus any extra space that's needed for string variables,
+ * fill its option's fields located at the given offsets and return it.
+ */
+void *
+parseAndFillLocalRelOptions(Datum options, relopt_gen *optgen[], int offsets[],
+							int noptions, size_t base_size, bool validate)
+{
+	relopt_parse_elt *elems = palloc(sizeof(*elems) * noptions);
+	relopt_value *vals;
+	void	   *opts;
+	int			i;
 
-		/* It's worth avoiding memory leaks in this function */
-		pfree(optiondatums);
-		if (((void *) array) != DatumGetPointer(options))
-			pfree(array);
+	for (i = 0; i < noptions; i++)
+	{
+		elems[i].optname = optgen[i]->name;
+		elems[i].opttype = optgen[i]->type;
+		elems[i].offset = offsets[i];
 	}
 
-	*numrelopts = numoptions;
-	return reloptions;
+	vals = parseLocalRelOptions(options, validate, optgen, noptions);
+	opts = allocateReloptStruct(base_size, vals, noptions);
+	fillRelOptions(opts, base_size, vals, noptions, validate, elems, noptions);
+
+	if (elems)
+		pfree(elems);
+
+	return opts;
 }
 
 /*
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 91247f0..9f8aad2 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -75,11 +75,14 @@
 #include "access/xlog.h"
 #include "catalog/catalog.h"
 #include "catalog/index.h"
+#include "commands/defrem.h"
 #include "pgstat.h"
 #include "storage/bufmgr.h"
 #include "storage/lmgr.h"
 #include "storage/predicate.h"
+#include "utils/ruleutils.h"
 #include "utils/snapmgr.h"
+#include "utils/syscache.h"
 #include "utils/tqual.h"
 
 
@@ -898,3 +901,72 @@ index_getprocinfo(Relation irel,
 
 	return locinfo;
 }
+
+/*
+ * Parse opclass-specific options for index column.
+ *
+ *	amoptions	index relation
+ *	attnum		column number
+ *	indoptions	options as text[] datum
+ *	validate	error flag
+ */
+bytea *
+index_opclass_options(Relation relation, AttrNumber attnum, Datum indoptions,
+					  bool validate)
+{
+	amopclassoptions_function amopclassoptions =
+		relation->rd_amroutine->amopclassoptions;
+
+	if (!amopclassoptions)
+	{
+		if (validate && PointerIsValid(DatumGetPointer(indoptions)))
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+					 errmsg("access method \"%s\" does not support opclass options ",
+							 get_am_name(relation->rd_rel->relam))));
+
+		return NULL;
+	}
+
+	return amopclassoptions(relation, attnum, indoptions, validate);
+}
+
+bytea *
+index_opclass_options_generic(Relation indrel, AttrNumber attnum,
+							  uint16 procnum, Datum reloptions, bool validate)
+{
+	Oid			procid = index_getprocid(indrel, attnum, procnum);
+	FmgrInfo   *procinfo;
+
+	if (!OidIsValid(procid))
+	{
+		StringInfoData opclassname;
+		Oid			opclass;
+		Datum		indclassDatum;
+		oidvector  *indclass;
+		bool		isnull;
+
+		if (!DatumGetPointer(reloptions))
+			return NULL;
+
+		indclassDatum = SysCacheGetAttr(INDEXRELID, indrel->rd_indextuple,
+										Anum_pg_index_indclass, &isnull);
+		Assert(!isnull);
+		indclass = (oidvector *) DatumGetPointer(indclassDatum);
+
+		opclass = indclass->values[attnum - 1];
+
+		initStringInfo(&opclassname);
+		get_opclass_name(opclass, InvalidOid, &opclassname);
+
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("operator class%s has no options ", opclassname.data)));
+	}
+
+	procinfo = index_getprocinfo(indrel, attnum, procnum);
+
+	return (bytea *) DatumGetPointer(FunctionCall2(procinfo,
+												   reloptions,
+												   BoolGetDatum(validate)));
+}
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 564f206..f74cac1 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -25,6 +25,7 @@
 
 #include "access/amapi.h"
 #include "access/multixact.h"
+#include "access/reloptions.h"
 #include "access/relscan.h"
 #include "access/sysattr.h"
 #include "access/transam.h"
@@ -586,6 +587,7 @@ UpdateIndexRelation(Oid indexoid,
 	int2vector *indoption;
 	Datum		exprsDatum;
 	Datum		predDatum;
+	Datum		indoptionsDatum;
 	Datum		values[Natts_pg_index];
 	bool		nulls[Natts_pg_index];
 	Relation	pg_index;
@@ -632,6 +634,53 @@ UpdateIndexRelation(Oid indexoid,
 	else
 		predDatum = (Datum) 0;
 
+	if (indexInfo->ii_OpclassOptions != NULL)
+	{
+		Datum	   *vals = palloc(sizeof(Datum) * indexInfo->ii_NumIndexAttrs);
+		bool	   *nulls = palloc(sizeof(bool) * indexInfo->ii_NumIndexAttrs);
+		int			dims[1];
+		int			lbs[1];
+
+		for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
+		{
+			Datum		options = indexInfo->ii_OpclassOptions[i];
+
+			nulls[i] = options == (Datum) 0;
+
+			if (!nulls[i])
+			{
+				FunctionCallInfoData fcinfo;
+				Datum		result;
+				FmgrInfo	flinfo = { 0 };
+
+				InitFunctionCallInfoData(fcinfo, &flinfo, 1, InvalidOid, NULL,
+										 NULL);
+
+				fcinfo.arg[0] = options;
+				fcinfo.argnull[0] = false;
+
+				flinfo.fn_mcxt = CurrentMemoryContext;
+
+				result = array_out(&fcinfo);
+
+				/* Check for null result, since caller is clearly not expecting one */
+				if (fcinfo.isnull)
+					elog(ERROR, "function %p returned NULL", (void *) array_out);
+
+				vals[i] = CStringGetTextDatum(DatumGetCString(result));
+			}
+		}
+
+		dims[0] = indexInfo->ii_NumIndexAttrs;
+		lbs[0] = 1;
+
+		indoptionsDatum = PointerGetDatum(construct_md_array(vals, nulls, 1,
+															 dims, lbs, TEXTOID,
+															 -1, false, 'i'));
+	}
+	else
+		indoptionsDatum = (Datum) 0;
+
 	/*
 	 * open the system catalog index relation
 	 */
@@ -665,6 +714,9 @@ UpdateIndexRelation(Oid indexoid,
 	values[Anum_pg_index_indpred - 1] = predDatum;
 	if (predDatum == (Datum) 0)
 		nulls[Anum_pg_index_indpred - 1] = true;
+	values[Anum_pg_index_indoptions - 1] = indoptionsDatum;
+	if (indoptionsDatum == (Datum) 0)
+		nulls[Anum_pg_index_indoptions - 1] = true;
 
 	tuple = heap_form_tuple(RelationGetDescr(pg_index), values, nulls);
 
@@ -1140,6 +1192,12 @@ index_create(Relation heapRelation,
 	else
 		Assert(indexRelation->rd_indexcxt != NULL);
 
+	/* Validate opclass-specific options */
+	if (indexInfo->ii_OpclassOptions)
+		for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++)
+			(void) index_opclass_options(indexRelation, i + 1,
+										 indexInfo->ii_OpclassOptions[i], true);
+
 	/*
 	 * If this is bootstrap (initdb) time, then we don't actually fill in the
 	 * index yet.  We'll be creating more indexes and classes later, so we
@@ -1777,6 +1835,8 @@ BuildIndexInfo(Relation index)
 		ii->ii_ExclusionStrats = NULL;
 	}
 
+	ii->ii_OpclassOptions = RelationGetRawOpclassOptions(index);
+
 	/* other info */
 	ii->ii_Unique = indexStruct->indisunique;
 	ii->ii_ReadyForInserts = IndexIsReady(indexStruct);
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 8bf2698..099fb7d 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -311,6 +311,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
 	indexInfo->ii_ExclusionOps = NULL;
 	indexInfo->ii_ExclusionProcs = NULL;
 	indexInfo->ii_ExclusionStrats = NULL;
+	indexInfo->ii_OpclassOptions = NULL;
 	indexInfo->ii_Unique = true;
 	indexInfo->ii_ReadyForInserts = true;
 	indexInfo->ii_Concurrent = false;
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 3e48a58..97cf5d9 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -612,6 +612,7 @@ DefineIndex(Oid relationId,
 	indexInfo->ii_ExclusionOps = NULL;
 	indexInfo->ii_ExclusionProcs = NULL;
 	indexInfo->ii_ExclusionStrats = NULL;
+	indexInfo->ii_OpclassOptions = NULL;	/* for now */
 	indexInfo->ii_Unique = stmt->unique;
 	/* In a concurrent build, mark it not-ready-for-inserts */
 	indexInfo->ii_ReadyForInserts = !stmt->concurrent;
@@ -1348,12 +1349,11 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
 	ListCell   *nextExclOp;
 	ListCell   *lc;
 	int			attn;
+	int			ncols = list_length(attList);
 
 	/* Allocate space for exclusion operator info, if needed */
 	if (exclusionOpNames)
 	{
-		int			ncols = list_length(attList);
-
 		Assert(list_length(exclusionOpNames) == ncols);
 		indexInfo->ii_ExclusionOps = (Oid *) palloc(sizeof(Oid) * ncols);
 		indexInfo->ii_ExclusionProcs = (Oid *) palloc(sizeof(Oid) * ncols);
@@ -1594,6 +1594,17 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
 								accessMethodName)));
 		}
 
+		/* Set up the per-column opclass options (indoptions field). */
+		if (attribute->opclassopts)
+		{
+			if (!indexInfo->ii_OpclassOptions)
+				indexInfo->ii_OpclassOptions = palloc0(sizeof(Datum) * ncols);
+
+			indexInfo->ii_OpclassOptions[attn] =
+				transformRelOptions((Datum) 0, attribute->opclassopts,
+									NULL, NULL, false, false);
+		}
+
 		attn++;
 	}
 }
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 266a3ef..e089a6a 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2807,6 +2807,7 @@ _copyIndexElem(const IndexElem *from)
 	COPY_STRING_FIELD(indexcolname);
 	COPY_NODE_FIELD(collation);
 	COPY_NODE_FIELD(opclass);
+	COPY_NODE_FIELD(opclassopts);
 	COPY_SCALAR_FIELD(ordering);
 	COPY_SCALAR_FIELD(nulls_ordering);
 
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index bbffc87..3c484f4 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -2545,6 +2545,7 @@ _equalIndexElem(const IndexElem *a, const IndexElem *b)
 	COMPARE_STRING_FIELD(indexcolname);
 	COMPARE_NODE_FIELD(collation);
 	COMPARE_NODE_FIELD(opclass);
+	COMPARE_NODE_FIELD(opclassopts);
 	COMPARE_SCALAR_FIELD(ordering);
 	COMPARE_SCALAR_FIELD(nulls_ordering);
 
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 011d2a3..c4c2e2e 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -2872,6 +2872,7 @@ _outIndexElem(StringInfo str, const IndexElem *node)
 	WRITE_STRING_FIELD(indexcolname);
 	WRITE_NODE_FIELD(collation);
 	WRITE_NODE_FIELD(opclass);
+	WRITE_NODE_FIELD(opclassopts);
 	WRITE_ENUM_FIELD(ordering, SortByDir);
 	WRITE_ENUM_FIELD(nulls_ordering, SortByNulls);
 }
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 60f2171..5e8f1dd 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -353,6 +353,10 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
 				info->nulls_first = NULL;
 			}
 
+			/* Fetch index opclass options */
+			info->opclassoptions =
+				RelationGetParsedOpclassOptions(indexRelation);
+
 			/*
 			 * Fetch the index expressions and predicate, if any.  We must
 			 * modify the copies we obtain from the relcache to have the
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index d99f2be..eb780ce 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -483,7 +483,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <alias>	alias_clause opt_alias_clause
 %type <list>	func_alias_clause
 %type <sortby>	sortby
-%type <ielem>	index_elem
+%type <ielem>	index_elem index_elem_options
 %type <node>	table_ref
 %type <jexpr>	joined_table
 %type <range>	relation_expr
@@ -7438,43 +7438,65 @@ index_params:	index_elem							{ $$ = list_make1($1); }
 			| index_params ',' index_elem			{ $$ = lappend($1, $3); }
 		;
 
+
+index_elem_options:
+	opt_collate opt_class opt_asc_desc opt_nulls_order
+		{
+			$$ = makeNode(IndexElem);
+			$$->name = NULL;
+			$$->expr = NULL;
+			$$->indexcolname = NULL;
+			$$->collation = $1;
+			$$->opclass = $2;
+			$$->opclassopts = NIL;
+			$$->ordering = $3;
+			$$->nulls_ordering = $4;
+		}
+	| opt_collate any_name reloptions opt_asc_desc opt_nulls_order
+		{
+			$$ = makeNode(IndexElem);
+			$$->name = NULL;
+			$$->expr = NULL;
+			$$->indexcolname = NULL;
+			$$->collation = $1;
+			$$->opclass = $2;
+			$$->opclassopts = $3;
+			$$->ordering = $4;
+			$$->nulls_ordering = $5;
+		}
+	| opt_collate DEFAULT reloptions opt_asc_desc opt_nulls_order
+		{
+			$$ = makeNode(IndexElem);
+			$$->name = NULL;
+			$$->expr = NULL;
+			$$->indexcolname = NULL;
+			$$->collation = $1;
+			$$->opclass = NIL;
+			$$->opclassopts = $3;
+			$$->ordering = $4;
+			$$->nulls_ordering = $5;
+		}
+	;
+
 /*
  * Index attributes can be either simple column references, or arbitrary
  * expressions in parens.  For backwards-compatibility reasons, we allow
  * an expression that's just a function call to be written without parens.
  */
-index_elem:	ColId opt_collate opt_class opt_asc_desc opt_nulls_order
+index_elem: ColId index_elem_options
 				{
-					$$ = makeNode(IndexElem);
+					$$ = $2;
 					$$->name = $1;
-					$$->expr = NULL;
-					$$->indexcolname = NULL;
-					$$->collation = $2;
-					$$->opclass = $3;
-					$$->ordering = $4;
-					$$->nulls_ordering = $5;
 				}
-			| func_expr_windowless opt_collate opt_class opt_asc_desc opt_nulls_order
+			| func_expr_windowless index_elem_options
 				{
-					$$ = makeNode(IndexElem);
-					$$->name = NULL;
+					$$ = $2;
 					$$->expr = $1;
-					$$->indexcolname = NULL;
-					$$->collation = $2;
-					$$->opclass = $3;
-					$$->ordering = $4;
-					$$->nulls_ordering = $5;
 				}
-			| '(' a_expr ')' opt_collate opt_class opt_asc_desc opt_nulls_order
+			| '(' a_expr ')' index_elem_options
 				{
-					$$ = makeNode(IndexElem);
-					$$->name = NULL;
+					$$ = $4;
 					$$->expr = $2;
-					$$->indexcolname = NULL;
-					$$->collation = $4;
-					$$->opclass = $5;
-					$$->ordering = $6;
-					$$->nulls_ordering = $7;
 				}
 		;
 
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 3697466..7e8bd56 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -450,8 +450,6 @@ static void get_from_clause_coldeflist(RangeTblFunction *rtfunc,
 						   deparse_context *context);
 static void get_tablesample_def(TableSampleClause *tablesample,
 					deparse_context *context);
-static void get_opclass_name(Oid opclass, Oid actual_datatype,
-				 StringInfo buf);
 static Node *processIndirection(Node *node, deparse_context *context);
 static void printSubscripts(ArrayRef *aref, deparse_context *context);
 static char *get_relation_name(Oid relid);
@@ -465,6 +463,7 @@ static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2);
 static char *generate_qualified_type_name(Oid typid);
 static text *string_to_text(char *str);
 static char *flatten_reloptions(Oid relid);
+static void get_reloptions(StringInfo buf, Datum reloptions);
 
 #define only_marker(rte)  ((rte)->inh ? "" : "ONLY ")
 
@@ -1180,6 +1179,7 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
 	oidvector  *indcollation;
 	oidvector  *indclass;
 	int2vector *indoption;
+	Datum	   *indoptions = NULL;
 	StringInfoData buf;
 	char	   *str;
 	char	   *sep;
@@ -1215,6 +1215,16 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
 	Assert(!isnull);
 	indoption = (int2vector *) DatumGetPointer(indoptionDatum);
 
+	if (!attrsOnly)
+	{
+		Datum indoptionsDatum = SysCacheGetAttr(INDEXRELID, ht_idx,
+												Anum_pg_index_indoptions,
+												&isnull);
+		if (!isnull)
+			indoptions = ExtractRawOpclassOptions(indoptionsDatum,
+												  idxrec->indnatts);
+	}
+
 	/*
 	 * Fetch the pg_class tuple of the index relation
 	 */
@@ -1338,6 +1348,8 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
 		if (!attrsOnly && (!colno || colno == keyno + 1))
 		{
 			Oid			indcoll;
+			bool		has_options =
+				indoptions && indoptions[keyno] != (Datum) 0;
 
 			/* Add collation, if not default for column */
 			indcoll = indcollation->values[keyno];
@@ -1346,7 +1358,15 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
 								 generate_collation_name((indcoll)));
 
 			/* Add the operator class name, if not default */
-			get_opclass_name(indclass->values[keyno], keycoltype, &buf);
+			get_opclass_name(indclass->values[keyno],
+							 has_options ? InvalidOid : keycoltype, &buf);
+
+			if (has_options)
+			{
+				appendStringInfoString(&buf, " (");
+				get_reloptions(&buf, indoptions[keyno]);
+				appendStringInfoChar(&buf, ')');
+			}
 
 			/* Add options if relevant */
 			if (amroutine->amcanorder)
@@ -10297,7 +10317,7 @@ get_tablesample_def(TableSampleClause *tablesample, deparse_context *context)
  * actual_datatype.  (If you don't want this behavior, just pass
  * InvalidOid for actual_datatype.)
  */
-static void
+void
 get_opclass_name(Oid opclass, Oid actual_datatype,
 				 StringInfo buf)
 {
@@ -10934,6 +10954,62 @@ string_to_text(char *str)
 }
 
 /*
+ * Generate a C string representing a relation options from text[] datum.
+ */
+static void
+get_reloptions(StringInfo buf, Datum reloptions)
+{
+	Datum	   *options;
+	int			noptions;
+	int			i;
+
+	deconstruct_array(DatumGetArrayTypeP(reloptions),
+					  TEXTOID, -1, false, 'i',
+					  &options, NULL, &noptions);
+
+	for (i = 0; i < noptions; i++)
+	{
+		char	   *option = TextDatumGetCString(options[i]);
+		char	   *name;
+		char	   *separator;
+		char	   *value;
+
+		/*
+		 * Each array element should have the form name=value.  If the "="
+		 * is missing for some reason, treat it like an empty value.
+		 */
+		name = option;
+		separator = strchr(option, '=');
+		if (separator)
+		{
+			*separator = '\0';
+			value = separator + 1;
+		}
+		else
+			value = "";
+
+		if (i > 0)
+			appendStringInfoString(buf, ", ");
+		appendStringInfo(buf, "%s=", quote_identifier(name));
+
+		/*
+		 * In general we need to quote the value; but to avoid unnecessary
+		 * clutter, do not quote if it is an identifier that would not
+		 * need quoting.  (We could also allow numbers, but that is a bit
+		 * trickier than it looks --- for example, are leading zeroes
+		 * significant?  We don't want to assume very much here about what
+		 * custom reloptions might mean.)
+		 */
+		if (quote_identifier(value) == value)
+			appendStringInfoString(buf, value);
+		else
+			simple_quote_literal(buf, value);
+
+		pfree(option);
+	}
+}
+
+/*
  * Generate a C string representing a relation's reloptions, or NULL if none.
  */
 static char *
@@ -10953,56 +11029,9 @@ flatten_reloptions(Oid relid)
 	if (!isnull)
 	{
 		StringInfoData buf;
-		Datum	   *options;
-		int			noptions;
-		int			i;
 
 		initStringInfo(&buf);
-
-		deconstruct_array(DatumGetArrayTypeP(reloptions),
-						  TEXTOID, -1, false, 'i',
-						  &options, NULL, &noptions);
-
-		for (i = 0; i < noptions; i++)
-		{
-			char	   *option = TextDatumGetCString(options[i]);
-			char	   *name;
-			char	   *separator;
-			char	   *value;
-
-			/*
-			 * Each array element should have the form name=value.  If the "="
-			 * is missing for some reason, treat it like an empty value.
-			 */
-			name = option;
-			separator = strchr(option, '=');
-			if (separator)
-			{
-				*separator = '\0';
-				value = separator + 1;
-			}
-			else
-				value = "";
-
-			if (i > 0)
-				appendStringInfoString(&buf, ", ");
-			appendStringInfo(&buf, "%s=", quote_identifier(name));
-
-			/*
-			 * In general we need to quote the value; but to avoid unnecessary
-			 * clutter, do not quote if it is an identifier that would not
-			 * need quoting.  (We could also allow numbers, but that is a bit
-			 * trickier than it looks --- for example, are leading zeroes
-			 * significant?  We don't want to assume very much here about what
-			 * custom reloptions might mean.)
-			 */
-			if (quote_identifier(value) == value)
-				appendStringInfoString(&buf, value);
-			else
-				simple_quote_literal(&buf, value);
-
-			pfree(option);
-		}
+		get_reloptions(&buf, reloptions);
 
 		result = buf.data;
 	}
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 1ebf9c4..1556927 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -77,6 +77,7 @@
 #include "storage/smgr.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
+#include "utils/datum.h"
 #include "utils/fmgroids.h"
 #include "utils/inval.h"
 #include "utils/lsyscache.h"
@@ -5212,6 +5213,185 @@ GetRelationPublicationActions(Relation relation)
 }
 
 /*
+ * RelationGetOpclassOptions -- get parsed opclass-specific options for an index
+ */
+bytea **
+RelationGetParsedOpclassOptions(Relation relation)
+{
+	MemoryContext oldcxt;
+	bytea	  **opts;
+	Datum		indoptionsDatum;
+	Datum	   *indoptions;
+	bool	   *indoptionsnulls;
+	int			indoptionsnum;
+	int			i;
+	int			ncols = relation->rd_rel->relnatts;
+	bool		isnull;
+
+	if (relation->rd_indoptions)
+	{
+		opts = palloc(sizeof(*opts) * ncols);
+
+		for (i = 0; i < ncols; i++)
+		{
+			bytea	   *opt = relation->rd_indoptions[i];
+
+			opts[i] = !opt ? NULL : (bytea *)
+				DatumGetPointer(datumCopy(PointerGetDatum(opt), false, -1));
+		}
+
+		return opts;
+	}
+
+	opts = palloc0(sizeof(*opts) * ncols);
+
+	if (relation->rd_indextuple == NULL ||
+		heap_attisnull(relation->rd_indextuple, Anum_pg_index_indoptions))
+	{
+		indoptions = NULL;
+		indoptionsnulls = NULL;
+		indoptionsnum = 0;
+	}
+	else
+	{
+		indoptionsDatum = heap_getattr(relation->rd_indextuple,
+									   Anum_pg_index_indoptions,
+									   GetPgIndexDescriptor(),
+									   &isnull);
+		Assert(!isnull);
+
+		deconstruct_array(DatumGetArrayTypeP(indoptionsDatum),
+						  TEXTOID, -1, false, 'i',
+						  &indoptions, &indoptionsnulls, &indoptionsnum);
+
+		Assert(indoptionsnum == ncols);
+	}
+
+	for (i = 0; i < ncols; i++)
+	{
+		Datum		options;
+
+		if (i < indoptionsnum && !indoptionsnulls[i])
+		{
+			FunctionCallInfoData fcinfo;
+			FmgrInfo	flinfo = { 0 };
+			char	   *optionsstr = TextDatumGetCString(indoptions[i]);
+
+			InitFunctionCallInfoData(fcinfo, &flinfo, 3, InvalidOid, NULL, NULL);
+
+			fcinfo.arg[0] = CStringGetDatum(optionsstr);
+			fcinfo.argnull[0] = false;
+			fcinfo.arg[1] = Int32GetDatum(TEXTOID);
+			fcinfo.argnull[1] = false;
+			fcinfo.arg[2] = Int32GetDatum(-1);
+			fcinfo.argnull[2] = false;
+
+			flinfo.fn_mcxt = CurrentMemoryContext;
+
+			options = array_in(&fcinfo);
+
+			if (fcinfo.isnull)
+				elog(ERROR, "function %p returned NULL", (void *) array_in);
+
+			pfree(optionsstr);
+		}
+		else
+		{
+			options = PointerGetDatum(NULL);
+		}
+
+		opts[i] = index_opclass_options(relation, i + 1, options, false);
+
+		if (options != PointerGetDatum(NULL))
+			pfree(DatumGetPointer(options));
+	}
+
+	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
+
+	relation->rd_indoptions = palloc(sizeof(*opts) * ncols);
+
+	for (i = 0; i < ncols; i++)
+		relation->rd_indoptions[i] = !opts[i] ? NULL : (bytea *)
+			DatumGetPointer(datumCopy(PointerGetDatum(opts[i]), false, -1));
+
+	MemoryContextSwitchTo(oldcxt);
+
+	return opts;
+}
+
+Datum *
+ExtractRawOpclassOptions(Datum indoptionsDatum, int ncols)
+{
+	Datum	   *indoptions;
+	bool	   *indoptionsnulls;
+	int			indoptionsnum;
+	int			i;
+
+	deconstruct_array(DatumGetArrayTypeP(indoptionsDatum),
+					  TEXTOID, -1, false, 'i',
+					  &indoptions, &indoptionsnulls, &indoptionsnum);
+
+	Assert(indoptionsnum == ncols);
+
+	for (i = 0; i < indoptionsnum; i++)
+	{
+		if (indoptionsnulls[i])
+			indoptions[i] = PointerGetDatum(NULL);
+		else
+		{
+			FunctionCallInfoData fcinfo;
+			FmgrInfo	flinfo = { 0 };
+			char	   *optionsstr = TextDatumGetCString(indoptions[i]);
+
+			InitFunctionCallInfoData(fcinfo, &flinfo, 3, InvalidOid, NULL,
+									 NULL);
+
+			fcinfo.arg[0] = CStringGetDatum(optionsstr);
+			fcinfo.argnull[0] = false;
+			fcinfo.arg[1] = Int32GetDatum(TEXTOID);
+			fcinfo.argnull[1] = false;
+			fcinfo.arg[2] = Int32GetDatum(-1);
+			fcinfo.argnull[2] = false;
+
+			flinfo.fn_mcxt = CurrentMemoryContext;
+
+			indoptions[i] = array_in(&fcinfo);
+
+			/* Check for null result, since caller is clearly not expecting one */
+			if (fcinfo.isnull)
+				elog(ERROR, "function %p returned NULL", (void *) array_in);
+		}
+	}
+
+	return indoptions;
+}
+
+/*
+ * RelationGetIndexOpclassOptions -- get opclass-specific options for an index
+ */
+Datum *
+RelationGetRawOpclassOptions(Relation relation)
+{
+	Datum		indoptionsDatum;
+	bool		isnull;
+
+	/* Quick exit if there is nothing to do. */
+	if (relation->rd_indextuple == NULL ||
+		heap_attisnull(relation->rd_indextuple, Anum_pg_index_indoptions))
+		return NULL;
+
+	indoptionsDatum = heap_getattr(relation->rd_indextuple,
+								   Anum_pg_index_indoptions,
+								   GetPgIndexDescriptor(),
+								   &isnull);
+	Assert(!isnull);
+
+	return ExtractRawOpclassOptions(indoptionsDatum,
+									relation->rd_rel->relnatts);
+}
+
+
+/*
  * Routines to support ereport() reports of relation-related errors
  *
  * These could have been put into elog.c, but it seems like a module layering
diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h
index 8d7bc24..bde93c3 100644
--- a/src/include/access/amapi.h
+++ b/src/include/access/amapi.h
@@ -102,6 +102,12 @@ typedef void (*amcostestimate_function) (struct PlannerInfo *root,
 typedef bytea *(*amoptions_function) (Datum reloptions,
 									  bool validate);
 
+/* parse column opclass-specific options */
+typedef bytea *(*amopclassoptions_function) (Relation index,
+											 AttrNumber colno,
+											 Datum indoptions,
+											 bool validate);
+
 /* report AM, index, or index column property */
 typedef bool (*amproperty_function) (Oid index_oid, int attno,
 									 IndexAMProperty prop, const char *propname,
@@ -203,6 +209,7 @@ typedef struct IndexAmRoutine
 	amcanreturn_function amcanreturn;	/* can be NULL */
 	amcostestimate_function amcostestimate;
 	amoptions_function amoptions;
+	amopclassoptions_function amopclassoptions;
 	amproperty_function amproperty; /* can be NULL */
 	amvalidate_function amvalidate;
 	ambeginscan_function ambeginscan;
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
index 24c720b..0d490d6 100644
--- a/src/include/access/genam.h
+++ b/src/include/access/genam.h
@@ -174,6 +174,13 @@ extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum,
 				uint16 procnum);
 extern FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
 				  uint16 procnum);
+extern bytea *index_opclass_options(Relation relation, AttrNumber attnum,
+					  Datum indoptions, bool validate);
+extern bytea *index_opclass_options_generic(Relation relation,
+							  AttrNumber attnum, uint16 procnum,
+							  Datum indoptions, bool validate);
+
+
 
 /*
  * index access method support routines (in genam.c)
diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h
index b32c1e9..9bb82d2 100644
--- a/src/include/access/reloptions.h
+++ b/src/include/access/reloptions.h
@@ -263,12 +263,17 @@ extern bytea *extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 				  amoptions_function amoptions);
 extern relopt_value *parseRelOptions(Datum options, bool validate,
 				relopt_kind kind, int *numrelopts);
+extern relopt_value *parseLocalRelOptions(Datum options, bool validate,
+					 relopt_gen **gen, int nelems);
 extern void *allocateReloptStruct(Size base, relopt_value *options,
 					 int numoptions);
 extern void fillRelOptions(void *rdopts, Size basesize,
 			   relopt_value *options, int numoptions,
 			   bool validate,
 			   const relopt_parse_elt *elems, int nelems);
+extern void *parseAndFillLocalRelOptions(Datum options, relopt_gen *optgen[],
+							int offsets[], int noptions, size_t base_size,
+							bool validate);
 
 extern bytea *default_reloptions(Datum reloptions, bool validate,
 				   relopt_kind kind);
diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h
index 057a9f7..c40d009 100644
--- a/src/include/catalog/pg_index.h
+++ b/src/include/catalog/pg_index.h
@@ -56,6 +56,7 @@ CATALOG(pg_index,2610) BKI_WITHOUT_OIDS BKI_SCHEMA_MACRO
 								 * each zero entry in indkey[] */
 	pg_node_tree indpred;		/* expression tree for predicate, if a partial
 								 * index; else NULL */
+	text		indoptions[1];	/* opclass options */
 #endif
 } FormData_pg_index;
 
@@ -70,7 +71,7 @@ typedef FormData_pg_index *Form_pg_index;
  *		compiler constants for pg_index
  * ----------------
  */
-#define Natts_pg_index					19
+#define Natts_pg_index					20
 #define Anum_pg_index_indexrelid		1
 #define Anum_pg_index_indrelid			2
 #define Anum_pg_index_indnatts			3
@@ -90,6 +91,7 @@ typedef FormData_pg_index *Form_pg_index;
 #define Anum_pg_index_indoption			17
 #define Anum_pg_index_indexprs			18
 #define Anum_pg_index_indpred			19
+#define Anum_pg_index_indoptions		20
 
 /*
  * Index AMs that support ordered scans must support these two indoption
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index a953820..9e65097 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -129,6 +129,7 @@ typedef struct ExprState
  *		UniqueProcs
  *		UniqueStrats
  *		Unique				is it a unique index?
+ *		OpclassOptions		opclass-specific options, or NULL if none
  *		ReadyForInserts		is it valid for inserts?
  *		Concurrent			are we doing a concurrent index build?
  *		BrokenHotChain		did we detect any broken HOT chains?
@@ -155,6 +156,7 @@ typedef struct IndexInfo
 	Oid		   *ii_UniqueOps;	/* array with one entry per column */
 	Oid		   *ii_UniqueProcs; /* array with one entry per column */
 	uint16	   *ii_UniqueStrats;	/* array with one entry per column */
+	Datum	   *ii_OpclassOptions;	/* array with one entry per column */
 	bool		ii_Unique;
 	bool		ii_ReadyForInserts;
 	bool		ii_Concurrent;
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index ac292bc..5a359f4 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -698,6 +698,7 @@ typedef struct IndexElem
 	char	   *indexcolname;	/* name for index column; NULL = default */
 	List	   *collation;		/* name of collation; NIL = default */
 	List	   *opclass;		/* name of desired opclass; NIL = default */
+	List	   *opclassopts;	/* opclass-specific options, or NIL */
 	SortByDir	ordering;		/* ASC/DESC/default */
 	SortByNulls nulls_ordering; /* FIRST/LAST/default */
 } IndexElem;
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index db8de2d..795f7f6 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -740,6 +740,7 @@ typedef struct IndexOptInfo
 	Oid		   *sortopfamily;	/* OIDs of btree opfamilies, if orderable */
 	bool	   *reverse_sort;	/* is sort order descending? */
 	bool	   *nulls_first;	/* do NULLs come first in the sort order? */
+	bytea	 **opclassoptions;	/* opclass-specific options for columns */
 	bool	   *canreturn;		/* which index cols can be returned in an
 								 * index-only scan? */
 	Oid			relam;			/* OID of the access method (in pg_am) */
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index aa8add5..739478f 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -191,6 +191,7 @@ typedef struct RelationData
 	uint16	   *rd_exclstrats;	/* exclusion ops' strategy numbers, if any */
 	void	   *rd_amcache;		/* available for use by index AM */
 	Oid		   *rd_indcollation;	/* OIDs of index collations */
+	bytea	  **rd_indoptions;	/* parsed opclass-specific options */
 
 	/*
 	 * foreign-table support
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index 8a546ab..8ef5795 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -14,6 +14,7 @@
 #ifndef RELCACHE_H
 #define RELCACHE_H
 
+#include "postgres.h"
 #include "access/tupdesc.h"
 #include "nodes/bitmapset.h"
 
@@ -50,6 +51,9 @@ extern Oid	RelationGetPrimaryKeyIndex(Relation relation);
 extern Oid	RelationGetReplicaIndex(Relation relation);
 extern List *RelationGetIndexExpressions(Relation relation);
 extern List *RelationGetIndexPredicate(Relation relation);
+extern bytea **RelationGetParsedOpclassOptions(Relation relation);
+extern Datum *RelationGetRawOpclassOptions(Relation relation);
+extern Datum *ExtractRawOpclassOptions(Datum indoptionsDatum, int ncols);
 
 typedef enum IndexAttrBitmapKind
 {
diff --git a/src/include/utils/ruleutils.h b/src/include/utils/ruleutils.h
index 9f9b029..86e6953 100644
--- a/src/include/utils/ruleutils.h
+++ b/src/include/utils/ruleutils.h
@@ -34,5 +34,7 @@ extern List *select_rtable_names_for_explain(List *rtable,
 								Bitmapset *rels_used);
 extern char *generate_collation_name(Oid collid);
 extern char *get_range_partbound_string(List *bound_datums);
+extern void get_opclass_name(Oid opclass, Oid actual_datatype, StringInfo buf);
+
 
 #endif							/* RULEUTILS_H */
diff --git a/src/test/regress/expected/btree_index.out b/src/test/regress/expected/btree_index.out
index 755cd17..5504dd9 100644
--- a/src/test/regress/expected/btree_index.out
+++ b/src/test/regress/expected/btree_index.out
@@ -150,3 +150,8 @@ vacuum btree_tall_tbl;
 -- need to insert some rows to cause the fast root page to split.
 insert into btree_tall_tbl (id, t)
   select g, repeat('x', 100) from generate_series(1, 500) g;
+-- Test unsupported btree opclass parameters
+create index on btree_tall_tbl (id int4_ops(foo=1));
+ERROR:  access method "btree" does not support opclass options 
+create index on btree_tall_tbl (id default(foo=1));
+ERROR:  access method "btree" does not support opclass options 
diff --git a/src/test/regress/sql/btree_index.sql b/src/test/regress/sql/btree_index.sql
index 65b08c8..b7a4890 100644
--- a/src/test/regress/sql/btree_index.sql
+++ b/src/test/regress/sql/btree_index.sql
@@ -92,3 +92,7 @@ vacuum btree_tall_tbl;
 -- need to insert some rows to cause the fast root page to split.
 insert into btree_tall_tbl (id, t)
   select g, repeat('x', 100) from generate_series(1, 500) g;
+
+-- Test unsupported btree opclass parameters
+create index on btree_tall_tbl (id int4_ops(foo=1));
+create index on btree_tall_tbl (id default(foo=1));
