Hi! 

There was an interesting idea. Now it is possible to add in runtime options 
for relation, when you are creating a new extension with new access method.

But if you add a custom operator class, you have no tool to tune it's 
behavior. But in some cases it would be nice to have such tool. For example in 
intarray extension for gist__intbig_ops there is an option SIGLENINT that 
defines the length of the signature that will be used while creating index. Now 
it is #defined in the code, but theoretically one can tune index 
size/performance by manually setting SIGLENINT value that is more suitable for 
his data.

Moreover the authors of bloom extension have to create workaround for 
customizing each column behavior: they sets number of bits per column by 
setting reloptions col1 — col16. This is not handy. I would seven say a little 
bit ugly.

So adding options for opclass seems to be really good idea.

As far as in postgres index is a relation, index column is an attribute in 
this relation and each column might have only one opclass, this brings us to 
conclusion that when we as speaking about options of an opclass in the index 
column, then we can actually speak about an options of an attribute.

If we look into pg_attribute table, we will see, that there is already 
attoptions attribute there. So we can use it. Just add a way to add them in 
runtime and teach opclass to use it.

The general idea is the following:

Each access method should have amattoptions function, that works similar to  
amoptions function (parses and validate text[] of attoptions into internal 
data structure) but it takes an additional argument -- the number of an 
attribute we are processing.

amattoptions do this job by calling a specific support function of an opclass, 
that knows how to parse it (and do it in a similar way as amoptions function 
of an access method)

the result of amattoptions should be cached as attoptions are cached now or 
similar way. (In current version of prototype I do it wrong, but should change 
it later)

All the support functions of the access method should accept parsed attoptions 
in their argument lists, and use it if necessary. In the prototype I've 
implemented if for gist opclass, and added attoptions as a last argument of 
all support functions. So it is even backward compatible as all funtions I 
have not touched just ignores this last argument.

The implementation of an access method should get attoptions from cache, if 
they are there, or from am->amattoptions if not (in the prototype it is done 
using get_index_attribute_options function) and pass it to the support 
functions.

In the prototype I've added a member to GISTSTATE structure for 
storing parsed attoptions, and fill in initGISTstate and used it all over the 
code. In other implementations solutions might be different.

So... The prototype I wrote is in attachment. It is really dirty. Some things 
are not done yet. Some things should be changed. But never the less work, and 
it shows what I am going to do better than all explanations.

To see how it works you should do the following:

# create extension intarray ;
# create table test (i int[]);
# create table test2 (i int[]);
# create index ON test USING GIST (i USING gist__intbig_ops WITH OPTIONS 
(sig_len_int=22) ); 
# create index ON test2 USING GIST (i USING gist__intbig_ops WITH OPTIONS 
(sig_len_int=120) ); 

# select attoptions from pg_attribute where attrelid = 'test_i_idx'::regclass 
OR attrelid = 'test2_i_idx'::regclass;

    attoptions     
-------------------
 {sig_len_int=120}
 {sig_len_int=22}
(2 rows)

and if you uncomment development warning output from the code you will see 
that these values are really used through the code.

Speaking of the syntax, I've added WITH OPTIONS keywords for specifying 
attoptions, not just WITH, that most of us would expect.  I did it because 
index_elem, the node that is used for definition of an index column is used not 
only in CREATE INDEX expression, but also in CREATE TABLE CONSTRAINT EXCLUDE. 
Because CREATE TABLE CONSTRAINT EXCLUDE actually creates an index, and one can 
specify there full specification of index element there. But right after this 
you should write "WITH operator" clause. 

So if I will try to use WITH keyword for attoptions, a syntax parser will be 
confused, as it cat not distinguish one WITH keyword from another. So decided 
to use WITH OTPTIONS keywords for attoptions. 

There might be some tricks that will allow to use WITH in both places but I 
think "WITH OPTIONS" might make SQL code more readable, because an expression 
with two "WITH" in a row will be hard to read for human too ;-)

So we come to the last part of this message, that is most important for me for 
the moment:

One of the issues that I've solved while writing this patch, was the 
following: attoptions and reloptions are should use almost the same code for 
options parsing. For reloptions this code is written, it is good, but you 
can't reuse it for attoptions as it is binded to relopt_kind and quite 
centralized.

So first step to implement attoptions for indexes, will be rewriting reoptions 
code to get rid of relopt_kind, make all access methods has its own option 
descriptor catalogs and use reference to this catalog instead of relopt_kind.

This should be a separate patch and I think I will start another thread for 
it. I will write another letter for relopt_kind remove issue...

-- 
Nikolay Shaplov
Postgres Professional: http://www.postgrespro.com
Russian Postgres Company
diff --git a/contrib/bloom/blutils.c b/contrib/bloom/blutils.c
index 05dbe87..f439403 100644
--- a/contrib/bloom/blutils.c
+++ b/contrib/bloom/blutils.c
@@ -36,8 +36,8 @@
 
 PG_FUNCTION_INFO_V1(blhandler);
 
-/* Kind of relation optioms for bloom index */
-static relopt_kind bl_relopt_kind;
+/* Catalog of relation options for bloom index */
+static options_catalog bl_relopt_catalog;
 
 static int32 myRand(void);
 static void mySrand(uint32 seed);
@@ -51,15 +51,18 @@ _PG_init(void)
 	int			i;
 	char		buf[16];
 
-	bl_relopt_kind = add_reloption_kind();
+	bl_relopt_catalog.definitions = NULL;
+	bl_relopt_catalog.num = 0;
+	bl_relopt_catalog.max = 0;
+	bl_relopt_catalog.need_initialization = 1;
 
-	add_int_reloption(bl_relopt_kind, "length",
+	add_int_reloption(0, &bl_relopt_catalog, "length",
 					  "Length of signature in uint16 type", 5, 1, 256);
 
 	for (i = 0; i < INDEX_MAX_KEYS; i++)
 	{
 		snprintf(buf, 16, "col%d", i + 1);
-		add_int_reloption(bl_relopt_kind, buf,
+		add_int_reloption(0, &bl_relopt_catalog, buf,
 					  "Number of bits for corresponding column", 2, 1, 2048);
 	}
 }
@@ -104,6 +107,7 @@ blhandler(PG_FUNCTION_ARGS)
 	amroutine->amcostestimate = blcostestimate;
 	amroutine->amoptions = bloptions;
 	amroutine->amvalidate = blvalidate;
+	amroutine->amattoptions = NULL;
 
 	PG_RETURN_POINTER(amroutine);
 }
@@ -457,7 +461,7 @@ bloptions(Datum reloptions, bool validate)
 		tab[i + 1].offset = offsetof(BloomOptions, bitSize[i]);
 	}
 
-	options = parseRelOptions(reloptions, validate, bl_relopt_kind, &numoptions);
+	options = parseRelOptions(reloptions, validate, &bl_relopt_catalog, 0, &numoptions);
 	rdopts = allocateReloptStruct(sizeof(BloomOptions), options, numoptions);
 	fillRelOptions((void *) rdopts, sizeof(BloomOptions), options, numoptions,
 				   validate, tab, INDEX_MAX_KEYS + 1);
diff --git a/contrib/intarray/_int.h b/contrib/intarray/_int.h
index d524f0f..a05350f 100644
--- a/contrib/intarray/_int.h
+++ b/contrib/intarray/_int.h
@@ -47,15 +47,24 @@
 
 
 /* bigint defines */
-#define SIGLENINT  63			/* >122 => key will toast, so very slow!!! */
-#define SIGLEN	( sizeof(int)*SIGLENINT )
-#define SIGLENBIT (SIGLEN*BITS_PER_BYTE)
+//#define SIGLENINT  63			/* >122 => key will toast, so very slow!!! */
+//#define SIGLEN	( sizeof(int)*SIGLENINT )
+//#define SIGLENBIT (SIGLEN*BITS_PER_BYTE)
 
-typedef char BITVEC[SIGLEN];
+
+#define SIGLEN_BYTES(i) (sizeof(int)*i)	   /* array signature length in bytes */
+#define SIGLEN_BITS(i) \
+			(SIGLEN_BYTES(i)*BITS_PER_BYTE) /* array signature length in bits */
+
+
+//typedef char BITVEC[SIGLEN];
 typedef char *BITVECP;
 
-#define LOOPBYTE \
-			for(i=0;i<SIGLEN;i++)
+//#define LOOPBYTE \
+//			for(i=0;i<SIGLEN;i++)
+
+#define LOOPBYTE_NEW(siglenint) \
+			for(i=0;i<SIGLEN_BYTES(siglenint);i++)
 
 /* beware of multiple evaluation of arguments to these macros! */
 #define GETBYTE(x,i) ( *( (BITVECP)(x) + (int)( (i) / BITS_PER_BYTE ) ) )
@@ -63,8 +72,12 @@ typedef char *BITVECP;
 #define CLRBIT(x,i)   GETBYTE(x,i) &= ~( 0x01 << ( (i) % BITS_PER_BYTE ) )
 #define SETBIT(x,i)   GETBYTE(x,i) |=  ( 0x01 << ( (i) % BITS_PER_BYTE ) )
 #define GETBIT(x,i) ( (GETBYTE(x,i) >> ( (i) % BITS_PER_BYTE )) & 0x01 )
-#define HASHVAL(val) (((unsigned int)(val)) % SIGLENBIT)
-#define HASH(sign, val) SETBIT((sign), HASHVAL(val))
+
+//#define HASHVAL(val) (((unsigned int)(val)) % SIGLENBIT)
+#define HASHVAL_NEW(val, siglenint) (((unsigned int)(val)) % (unsigned int)(SIGLEN_BITS(siglenint)))
+
+//#define HASH(sign, val) SETBIT((sign), HASHVAL(val))
+#define HASH_NEW(sign, val, siglenint) SETBIT((sign), HASHVAL_NEW(val, siglenint))
 
 /*
  * type of index key
@@ -76,12 +89,23 @@ typedef struct
 	char		data[FLEXIBLE_ARRAY_MEMBER];
 } GISTTYPE;
 
+/* intarray opclass options */
+typedef struct IntArrayOpclassOptions
+{
+	int32		vl_len_;		/* varlena header (do not touch directly!) */
+	int			sig_len_int;	/* FIXME comment */
+}	IntArrayOpclassOptions;
+
+
 #define ALLISTRUE		0x04
 
 #define ISALLTRUE(x)	( ((GISTTYPE*)x)->flag & ALLISTRUE )
 
 #define GTHDRSIZE		(VARHDRSZ + sizeof(int32))
-#define CALCGTSIZE(flag) ( GTHDRSIZE+(((flag) & ALLISTRUE) ? 0 : SIGLEN) )
+
+#define GT_EMPTY_SIZE	GTHDRSIZE
+
+#define GT_SIZE(siglenint) (GTHDRSIZE + SIGLEN_BYTES(siglenint))
 
 #define GETSIGN(x)		( (BITVECP)( (char*)x+GTHDRSIZE ) )
 
@@ -94,6 +118,7 @@ typedef void (*formfloat) (ArrayType *, float *);
 /*
  * useful functions
  */
+extern void _PG_init(void);
 bool		isort(int32 *a, int len);
 ArrayType  *new_intArrayType(int num);
 ArrayType  *copy_intArrayType(ArrayType *a);
@@ -109,7 +134,7 @@ bool		inner_int_contains(ArrayType *a, ArrayType *b);
 ArrayType  *inner_int_union(ArrayType *a, ArrayType *b);
 ArrayType  *inner_int_inter(ArrayType *a, ArrayType *b);
 void		rt__int_size(ArrayType *a, float *size);
-void		gensign(BITVEC sign, int *a, int len);
+//void		gensign(BITVECP sign, int *a, int len, void *options);
 
 
 /*****************************************************************************
@@ -155,7 +180,7 @@ typedef struct QUERYTYPE
 #define PG_GETARG_QUERYTYPE_P(n)	  DatumGetQueryTypeP(PG_GETARG_DATUM(n))
 #define PG_GETARG_QUERYTYPE_P_COPY(n) DatumGetQueryTypePCopy(PG_GETARG_DATUM(n))
 
-bool		signconsistent(QUERYTYPE *query, BITVEC sign, bool calcnot);
+bool		signconsistent(QUERYTYPE *query, BITVECP sign, bool calcnot, void *options);
 bool		execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot);
 
 bool		gin_bool_consistent(QUERYTYPE *query, bool *check);
diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c
index 5d9e676..02d09f6 100644
--- a/contrib/intarray/_int_bool.c
+++ b/contrib/intarray/_int_bool.c
@@ -233,7 +233,7 @@ typedef struct
  * is there value 'val' in (sorted) array or not ?
  */
 static bool
-checkcondition_arr(void *checkval, ITEM *item)
+checkcondition_arr(void *checkval, ITEM *item, void *options)
 {
 	int32	   *StopLow = ((CHKVAL *) checkval)->arrb;
 	int32	   *StopHigh = ((CHKVAL *) checkval)->arre;
@@ -254,43 +254,48 @@ checkcondition_arr(void *checkval, ITEM *item)
 	return false;
 }
 
+
 static bool
-checkcondition_bit(void *checkval, ITEM *item)
+checkcondition_bit(void *checkval, ITEM *item, void *options)
 {
-	return GETBIT(checkval, HASHVAL(item->val));
+	  IntArrayOpclassOptions* attoptions;
+
+	attoptions = (IntArrayOpclassOptions*) options;
+	return GETBIT(checkval, HASHVAL_NEW(item->val, attoptions->sig_len_int));
 }
 
+
 /*
  * evaluate boolean expression, using chkcond() to test the primitive cases
  */
 static bool
-execute(ITEM *curitem, void *checkval, bool calcnot,
-		bool (*chkcond) (void *checkval, ITEM *item))
+execute(ITEM *curitem, void *checkval, bool calcnot, void *options,
+		bool (*chkcond) (void *checkval, ITEM *item, void *options))
 {
 	/* since this function recurses, it could be driven to stack overflow */
 	check_stack_depth();
 
 	if (curitem->type == VAL)
-		return (*chkcond) (checkval, curitem);
+		return (*chkcond) (checkval, curitem, options);
 	else if (curitem->val == (int32) '!')
 	{
 		return (calcnot) ?
-			((execute(curitem - 1, checkval, calcnot, chkcond)) ? false : true)
+			((execute(curitem - 1, checkval, calcnot, options, chkcond)) ? false : true)
 			: true;
 	}
 	else if (curitem->val == (int32) '&')
 	{
-		if (execute(curitem + curitem->left, checkval, calcnot, chkcond))
-			return execute(curitem - 1, checkval, calcnot, chkcond);
+		if (execute(curitem + curitem->left, checkval, calcnot, options, chkcond))
+			return execute(curitem - 1, checkval, calcnot, options, chkcond);
 		else
 			return false;
 	}
 	else
 	{							/* |-operator */
-		if (execute(curitem + curitem->left, checkval, calcnot, chkcond))
+		if (execute(curitem + curitem->left, checkval, calcnot, options, chkcond))
 			return true;
 		else
-			return execute(curitem - 1, checkval, calcnot, chkcond);
+			return execute(curitem - 1, checkval, calcnot, options, chkcond);
 	}
 }
 
@@ -298,10 +303,10 @@ execute(ITEM *curitem, void *checkval, bool calcnot,
  * signconsistent & execconsistent called by *_consistent
  */
 bool
-signconsistent(QUERYTYPE *query, BITVEC sign, bool calcnot)
+signconsistent(QUERYTYPE *query, BITVECP sign, bool calcnot, void *options)
 {
 	return execute(GETQUERY(query) + query->size - 1,
-				   (void *) sign, calcnot,
+				   (void *) sign, calcnot, options,
 				   checkcondition_bit);
 }
 
@@ -315,7 +320,7 @@ execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot)
 	chkval.arrb = ARRPTR(array);
 	chkval.arre = chkval.arrb + ARRNELEMS(array);
 	return execute(GETQUERY(query) + query->size - 1,
-				   (void *) &chkval, calcnot,
+				   (void *) &chkval, calcnot, NULL,
 				   checkcondition_arr);
 }
 
@@ -326,7 +331,7 @@ typedef struct
 } GinChkVal;
 
 static bool
-checkcondition_gin(void *checkval, ITEM *item)
+checkcondition_gin(void *checkval, ITEM *item, void *options)
 {
 	GinChkVal  *gcv = (GinChkVal *) checkval;
 
@@ -357,7 +362,7 @@ gin_bool_consistent(QUERYTYPE *query, bool *check)
 	}
 
 	return execute(GETQUERY(query) + query->size - 1,
-				   (void *) &gcv, true,
+				   (void *) &gcv, true, NULL,
 				   checkcondition_gin);
 }
 
@@ -430,7 +435,7 @@ boolop(PG_FUNCTION_ARGS)
 	chkval.arre = chkval.arrb + ARRNELEMS(val);
 	result = execute(GETQUERY(query) + query->size - 1,
 					 &chkval, true,
-					 checkcondition_arr);
+					 NULL, checkcondition_arr);
 	pfree(val);
 
 	PG_FREE_IF_COPY(query, 1);
diff --git a/contrib/intarray/_int_tool.c b/contrib/intarray/_int_tool.c
index 3c52912..52085e4 100644
--- a/contrib/intarray/_int_tool.c
+++ b/contrib/intarray/_int_tool.c
@@ -312,8 +312,9 @@ _int_unique(ArrayType *r)
 	return resize_intArrayType(r, dr + 1 - ARRPTR(r));
 }
 
+#if 0
 void
-gensign(BITVEC sign, int *a, int len)
+gensign(BITVEC sign, int *a, int len, int siglenint)
 {
 	int			i;
 
@@ -324,6 +325,7 @@ gensign(BITVEC sign, int *a, int len)
 		a++;
 	}
 }
+#endif
 
 int32
 intarray_match_first(ArrayType *a, int32 elem)
diff --git a/contrib/intarray/_intbig_gist.c b/contrib/intarray/_intbig_gist.c
index 6dae7c91..af4c16b 100644
--- a/contrib/intarray/_intbig_gist.c
+++ b/contrib/intarray/_intbig_gist.c
@@ -5,6 +5,7 @@
 
 #include "access/gist.h"
 #include "access/stratnum.h"
+#include "access/reloptions.h"
 
 #include "_int.h"
 
@@ -19,6 +20,7 @@ PG_FUNCTION_INFO_V1(g_intbig_penalty);
 PG_FUNCTION_INFO_V1(g_intbig_picksplit);
 PG_FUNCTION_INFO_V1(g_intbig_union);
 PG_FUNCTION_INFO_V1(g_intbig_same);
+PG_FUNCTION_INFO_V1(g_intbig_attoptions);
 
 /* Number of one-bits in an unsigned byte */
 static const uint8 number_of_ones[256] = {
@@ -43,6 +45,30 @@ static const uint8 number_of_ones[256] = {
 PG_FUNCTION_INFO_V1(_intbig_in);
 PG_FUNCTION_INFO_V1(_intbig_out);
 
+/* Catalog of relation options for bloom index */
+static options_catalog intbig_gist_attopt_catalog;
+
+
+void
+_PG_init(void)
+{
+	intbig_gist_attopt_catalog.definitions = NULL;
+	intbig_gist_attopt_catalog.num = 0;
+	intbig_gist_attopt_catalog.max = 0;
+	intbig_gist_attopt_catalog.need_initialization = 1;
+
+	add_int_reloption(0, &intbig_gist_attopt_catalog, "sig_len_int",
+					  "FIXME description", /*63*/ 120, 10, 122);  //FIXME limits
+
+//  elog(WARNING, "_intbig_gist.c _PG_init");
+}
+
+BITVECP
+new_bitvec(int siglenint)
+{
+  return (BITVECP) palloc0(SIGLEN_BYTES(siglenint));
+}
+
 Datum
 _intbig_in(PG_FUNCTION_ARGS)
 {
@@ -66,7 +92,7 @@ _intbig_out(PG_FUNCTION_ARGS)
 ** intbig functions
 *********************************************************************/
 static bool
-_intbig_overlap(GISTTYPE *a, ArrayType *b)
+_intbig_overlap(GISTTYPE *a, ArrayType *b, int siglenint)
 {
 	int			num = ARRNELEMS(b);
 	int32	   *ptr = ARRPTR(b);
@@ -75,7 +101,8 @@ _intbig_overlap(GISTTYPE *a, ArrayType *b)
 
 	while (num--)
 	{
-		if (GETBIT(GETSIGN(a), HASHVAL(*ptr)))
+		if (GETBIT(GETSIGN(a), HASHVAL_NEW(*ptr,siglenint)))
+		
 			return true;
 		ptr++;
 	}
@@ -84,7 +111,7 @@ _intbig_overlap(GISTTYPE *a, ArrayType *b)
 }
 
 static bool
-_intbig_contains(GISTTYPE *a, ArrayType *b)
+_intbig_contains(GISTTYPE *a, ArrayType *b, int siglenint)
 {
 	int			num = ARRNELEMS(b);
 	int32	   *ptr = ARRPTR(b);
@@ -93,7 +120,9 @@ _intbig_contains(GISTTYPE *a, ArrayType *b)
 
 	while (num--)
 	{
-		if (!GETBIT(GETSIGN(a), HASHVAL(*ptr)))
+		if (!GETBIT(GETSIGN(a), HASHVAL_NEW(*ptr, siglenint)))
+
+		
 			return false;
 		ptr++;
 	}
@@ -107,6 +136,10 @@ g_intbig_same(PG_FUNCTION_ARGS)
 	GISTTYPE   *a = (GISTTYPE *) PG_GETARG_POINTER(0);
 	GISTTYPE   *b = (GISTTYPE *) PG_GETARG_POINTER(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
+	IntArrayOpclassOptions *attoptions =
+								(IntArrayOpclassOptions *) PG_GETARG_POINTER(3);
+
+//elog(WARNING, "g_intbig_same!!; sig_len_int=%i", attoptions->sig_len_int);
 
 	if (ISALLTRUE(a) && ISALLTRUE(b))
 		*result = true;
@@ -121,7 +154,8 @@ g_intbig_same(PG_FUNCTION_ARGS)
 					sb = GETSIGN(b);
 
 		*result = true;
-		LOOPBYTE
+//		for(i=0;i<SIGLEN;i++)
+		LOOPBYTE_NEW(attoptions->sig_len_int)
 		{
 			if (sa[i] != sb[i])
 			{
@@ -137,6 +171,10 @@ Datum
 g_intbig_compress(PG_FUNCTION_ARGS)
 {
 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	IntArrayOpclassOptions *attoptions =
+								(IntArrayOpclassOptions *) PG_GETARG_POINTER(1);
+
+//elog(WARNING, "g_intbig_compress!!; sig_len_int=%i", attoptions->sig_len_int);
 
 	if (entry->leafkey)
 	{
@@ -144,8 +182,7 @@ g_intbig_compress(PG_FUNCTION_ARGS)
 		ArrayType  *in = DatumGetArrayTypeP(entry->key);
 		int32	   *ptr;
 		int			num;
-		GISTTYPE   *res = (GISTTYPE *) palloc0(CALCGTSIZE(0));
-
+		GISTTYPE  *res = (GISTTYPE *) palloc0(GT_SIZE(attoptions->sig_len_int));
 		CHECKARRVALID(in);
 		if (ARRISEMPTY(in))
 		{
@@ -157,11 +194,11 @@ g_intbig_compress(PG_FUNCTION_ARGS)
 			ptr = ARRPTR(in);
 			num = ARRNELEMS(in);
 		}
-		SET_VARSIZE(res, CALCGTSIZE(0));
+		SET_VARSIZE(res, GT_SIZE(attoptions->sig_len_int));
 
 		while (num--)
 		{
-			HASH(GETSIGN(res), *ptr);
+			HASH_NEW(GETSIGN(res), *ptr, attoptions->sig_len_int);
 			ptr++;
 		}
 
@@ -182,14 +219,14 @@ g_intbig_compress(PG_FUNCTION_ARGS)
 		BITVECP		sign = GETSIGN(DatumGetPointer(entry->key));
 		GISTTYPE   *res;
 
-		LOOPBYTE
+		LOOPBYTE_NEW(attoptions->sig_len_int)
 		{
 			if ((sign[i] & 0xff) != 0xff)
 				PG_RETURN_POINTER(entry);
 		}
 
-		res = (GISTTYPE *) palloc(CALCGTSIZE(ALLISTRUE));
-		SET_VARSIZE(res, CALCGTSIZE(ALLISTRUE));
+		res = (GISTTYPE *) palloc(GT_EMPTY_SIZE);
+		SET_VARSIZE(res, GT_EMPTY_SIZE);
 		res->flag = ALLISTRUE;
 
 		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
@@ -205,24 +242,22 @@ g_intbig_compress(PG_FUNCTION_ARGS)
 
 
 static int32
-sizebitvec(BITVECP sign)
+sizebitvec(BITVECP sign, IntArrayOpclassOptions *attoptions)
 {
 	int32		size = 0,
 				i;
-
-	LOOPBYTE
+	LOOPBYTE_NEW(attoptions->sig_len_int)
 		size += number_of_ones[(unsigned char) sign[i]];
 	return size;
 }
 
 static int
-hemdistsign(BITVECP a, BITVECP b)
+hemdistsign(BITVECP a, BITVECP b, IntArrayOpclassOptions *attoptions)
 {
 	int			i,
 				diff,
 				dist = 0;
-
-	LOOPBYTE
+	LOOPBYTE_NEW(attoptions->sig_len_int)
 	{
 		diff = (unsigned char) (a[i] ^ b[i]);
 		dist += number_of_ones[diff];
@@ -231,19 +266,20 @@ hemdistsign(BITVECP a, BITVECP b)
 }
 
 static int
-hemdist(GISTTYPE *a, GISTTYPE *b)
+hemdist(GISTTYPE *a, GISTTYPE *b, IntArrayOpclassOptions *attoptions)
 {
+	int siglen_bits = SIGLEN_BITS(attoptions->sig_len_int);
 	if (ISALLTRUE(a))
 	{
 		if (ISALLTRUE(b))
 			return 0;
 		else
-			return SIGLENBIT - sizebitvec(GETSIGN(b));
+			return siglen_bits - sizebitvec(GETSIGN(b), attoptions);
 	}
 	else if (ISALLTRUE(b))
-		return SIGLENBIT - sizebitvec(GETSIGN(a));
+		return siglen_bits - sizebitvec(GETSIGN(a), attoptions);
 
-	return hemdistsign(GETSIGN(a), GETSIGN(b));
+	return hemdistsign(GETSIGN(a), GETSIGN(b), attoptions);
 }
 
 Datum
@@ -253,14 +289,14 @@ g_intbig_decompress(PG_FUNCTION_ARGS)
 }
 
 static int32
-unionkey(BITVECP sbase, GISTTYPE *add)
+unionkey(BITVECP sbase, GISTTYPE *add, IntArrayOpclassOptions *attoptions)
 {
 	int32		i;
 	BITVECP		sadd = GETSIGN(add);
 
 	if (ISALLTRUE(add))
 		return 1;
-	LOOPBYTE
+	LOOPBYTE_NEW(attoptions->sig_len_int)
 		sbase[i] |= sadd[i];
 	return 0;
 }
@@ -270,28 +306,40 @@ g_intbig_union(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
 	int		   *size = (int *) PG_GETARG_POINTER(1);
-	BITVEC		base;
+	IntArrayOpclassOptions *attoptions =
+								(IntArrayOpclassOptions *) PG_GETARG_POINTER(2);
+	BITVECP		base;
 	int32		i,
 				len;
 	int32		flag = 0;
 	GISTTYPE   *result;
+/*
+if (attoptions->sig_len_int == 63)
+{
+elog(WARNING, "g_intbig_compress!!; Right! sig_len_int=%i", attoptions->sig_len_int);
+} else
+{
+elog(WARNING, "g_intbig_compress!!; Wrong!!!!! sig_len_int=%i", attoptions->sig_len_int);
 
-	MemSet((void *) base, 0, sizeof(BITVEC));
+}*/
+//	MemSet((void *) base, 0, SIGLEN_BYTES(attoptions->sig_len_int)); // may be here will be better GT_SIZE(attoptions->sig_len_int)-GT_EMPTY_SIZE the same value but may be more clear
+	base = new_bitvec(attoptions->sig_len_int);
 	for (i = 0; i < entryvec->n; i++)
 	{
-		if (unionkey(base, GETENTRY(entryvec, i)))
+		if (unionkey(base, GETENTRY(entryvec, i), attoptions))
 		{
 			flag = ALLISTRUE;
 			break;
 		}
 	}
 
-	len = CALCGTSIZE(flag);
+	len = ((flag) & ALLISTRUE) ? GT_EMPTY_SIZE : GT_SIZE(attoptions->sig_len_int);
+	
 	result = (GISTTYPE *) palloc(len);
 	SET_VARSIZE(result, len);
 	result->flag = flag;
 	if (!ISALLTRUE(result))
-		memcpy((void *) GETSIGN(result), (void *) base, sizeof(BITVEC));
+		memcpy((void *) GETSIGN(result), (void *) base, SIGLEN_BYTES(attoptions->sig_len_int));
 	*size = len;
 
 	PG_RETURN_POINTER(result);
@@ -303,10 +351,14 @@ g_intbig_penalty(PG_FUNCTION_ARGS)
 	GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); /* always ISSIGNKEY */
 	GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
 	float	   *penalty = (float *) PG_GETARG_POINTER(2);
+	IntArrayOpclassOptions *attoptions =
+								(IntArrayOpclassOptions *) PG_GETARG_POINTER(3);
 	GISTTYPE   *origval = (GISTTYPE *) DatumGetPointer(origentry->key);
 	GISTTYPE   *newval = (GISTTYPE *) DatumGetPointer(newentry->key);
 
-	*penalty = hemdist(origval, newval);
+//elog(WARNING, "g_intbig_penalty!!; sig_len_int=%i", attoptions->sig_len_int);
+
+	*penalty = hemdist(origval, newval, attoptions);
 	PG_RETURN_POINTER(penalty);
 }
 
@@ -329,6 +381,9 @@ g_intbig_picksplit(PG_FUNCTION_ARGS)
 {
 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
 	GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
+	IntArrayOpclassOptions *attoptions =
+								(IntArrayOpclassOptions *) PG_GETARG_POINTER(2);
+
 	OffsetNumber k,
 				j;
 	GISTTYPE   *datum_l,
@@ -350,6 +405,10 @@ g_intbig_picksplit(PG_FUNCTION_ARGS)
 	SPLITCOST  *costvector;
 	GISTTYPE   *_k,
 			   *_j;
+	int			siglen;
+
+//elog(WARNING, "g_intbig_picksplit!!");
+//elog(WARNING, "sig_len_int=%i", attoptions->sig_len_int);
 
 	maxoff = entryvec->n - 2;
 	nbytes = (maxoff + 2) * sizeof(OffsetNumber);
@@ -361,7 +420,7 @@ g_intbig_picksplit(PG_FUNCTION_ARGS)
 		_k = GETENTRY(entryvec, k);
 		for (j = OffsetNumberNext(k); j <= maxoff; j = OffsetNumberNext(j))
 		{
-			size_waste = hemdist(_k, GETENTRY(entryvec, j));
+			size_waste = hemdist(_k, GETENTRY(entryvec, j),attoptions);
 			if (size_waste > waste)
 			{
 				waste = size_waste;
@@ -381,7 +440,7 @@ g_intbig_picksplit(PG_FUNCTION_ARGS)
 		seed_1 = 1;
 		seed_2 = 2;
 	}
-
+	siglen = SIGLEN_BYTES(attoptions->sig_len_int);
 	/* form initial .. */
 	if (ISALLTRUE(GETENTRY(entryvec, seed_1)))
 	{
@@ -391,10 +450,10 @@ g_intbig_picksplit(PG_FUNCTION_ARGS)
 	}
 	else
 	{
-		datum_l = (GISTTYPE *) palloc(GTHDRSIZE + SIGLEN);
-		SET_VARSIZE(datum_l, GTHDRSIZE + SIGLEN);
+		datum_l = (GISTTYPE *) palloc(GTHDRSIZE + siglen);
+		SET_VARSIZE(datum_l, GTHDRSIZE + siglen);
 		datum_l->flag = 0;
-		memcpy((void *) GETSIGN(datum_l), (void *) GETSIGN(GETENTRY(entryvec, seed_1)), sizeof(BITVEC));
+		memcpy((void *) GETSIGN(datum_l), (void *) GETSIGN(GETENTRY(entryvec, seed_1)), SIGLEN_BYTES(attoptions->sig_len_int));
 	}
 	if (ISALLTRUE(GETENTRY(entryvec, seed_2)))
 	{
@@ -404,10 +463,10 @@ g_intbig_picksplit(PG_FUNCTION_ARGS)
 	}
 	else
 	{
-		datum_r = (GISTTYPE *) palloc(GTHDRSIZE + SIGLEN);
-		SET_VARSIZE(datum_r, GTHDRSIZE + SIGLEN);
+		datum_r = (GISTTYPE *) palloc(GTHDRSIZE + siglen);
+		SET_VARSIZE(datum_r, GTHDRSIZE + siglen);
 		datum_r->flag = 0;
-		memcpy((void *) GETSIGN(datum_r), (void *) GETSIGN(GETENTRY(entryvec, seed_2)), sizeof(BITVEC));
+		memcpy((void *) GETSIGN(datum_r), (void *) GETSIGN(GETENTRY(entryvec, seed_2)), SIGLEN_BYTES(attoptions->sig_len_int));
 	}
 
 	maxoff = OffsetNumberNext(maxoff);
@@ -417,8 +476,8 @@ g_intbig_picksplit(PG_FUNCTION_ARGS)
 	{
 		costvector[j - 1].pos = j;
 		_j = GETENTRY(entryvec, j);
-		size_alpha = hemdist(datum_l, _j);
-		size_beta = hemdist(datum_r, _j);
+		size_alpha = hemdist(datum_l, _j, attoptions);
+		size_beta = hemdist(datum_r, _j, attoptions);
 		costvector[j - 1].cost = Abs(size_alpha - size_beta);
 	}
 	qsort((void *) costvector, maxoff, sizeof(SPLITCOST), comparecost);
@@ -442,20 +501,20 @@ g_intbig_picksplit(PG_FUNCTION_ARGS)
 			continue;
 		}
 		_j = GETENTRY(entryvec, j);
-		size_alpha = hemdist(datum_l, _j);
-		size_beta = hemdist(datum_r, _j);
+		size_alpha = hemdist(datum_l, _j, attoptions);
+		size_beta = hemdist(datum_r, _j, attoptions);
 
 		if (size_alpha < size_beta + WISH_F(v->spl_nleft, v->spl_nright, 0.00001))
 		{
 			if (ISALLTRUE(datum_l) || ISALLTRUE(_j))
 			{
 				if (!ISALLTRUE(datum_l))
-					MemSet((void *) union_l, 0xff, sizeof(BITVEC));
+					MemSet((void *) union_l, 0xff, SIGLEN_BYTES(attoptions->sig_len_int));
 			}
 			else
 			{
 				ptr = GETSIGN(_j);
-				LOOPBYTE
+				LOOPBYTE_NEW(attoptions->sig_len_int)
 					union_l[i] |= ptr[i];
 			}
 			*left++ = j;
@@ -466,12 +525,12 @@ g_intbig_picksplit(PG_FUNCTION_ARGS)
 			if (ISALLTRUE(datum_r) || ISALLTRUE(_j))
 			{
 				if (!ISALLTRUE(datum_r))
-					MemSet((void *) union_r, 0xff, sizeof(BITVEC));
+					MemSet((void *) union_r, 0xff, SIGLEN_BYTES(attoptions->sig_len_int));
 			}
 			else
 			{
 				ptr = GETSIGN(_j);
-				LOOPBYTE
+				LOOPBYTE_NEW(attoptions->sig_len_int)
 					union_r[i] |= ptr[i];
 			}
 			*right++ = j;
@@ -497,8 +556,13 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
 
 	/* Oid		subtype = PG_GETARG_OID(3); */
 	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
+	IntArrayOpclassOptions *attoptions =
+								(IntArrayOpclassOptions *) PG_GETARG_POINTER(5);
+
 	bool		retval;
 
+//elog(WARNING, "g_intbig_consistent!!; sig_len_int=%i", attoptions->sig_len_int);
+
 	/* All cases served by this function are inexact */
 	*recheck = true;
 
@@ -509,7 +573,7 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
 	{
 		retval = signconsistent((QUERYTYPE *) query,
 								GETSIGN(DatumGetPointer(entry->key)),
-								false);
+								false, (void*)attoptions);
 		PG_FREE_IF_COPY(query, 1);
 		PG_RETURN_BOOL(retval);
 	}
@@ -519,7 +583,7 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
 	switch (strategy)
 	{
 		case RTOverlapStrategyNumber:
-			retval = _intbig_overlap((GISTTYPE *) DatumGetPointer(entry->key), query);
+			retval = _intbig_overlap((GISTTYPE *) DatumGetPointer(entry->key), query, attoptions->sig_len_int);
 			break;
 		case RTSameStrategyNumber:
 			if (GIST_LEAF(entry))
@@ -527,22 +591,22 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
 				int			i,
 							num = ARRNELEMS(query);
 				int32	   *ptr = ARRPTR(query);
-				BITVEC		qp;
+				BITVECP		qp;
 				BITVECP		dq,
 							de;
 
-				memset(qp, 0, sizeof(BITVEC));
-
+//				memset(qp, 0, SIGLEN_BYTES(attoptions->sig_len_int));
+				qp = new_bitvec(attoptions->sig_len_int);
 				while (num--)
 				{
-					HASH(qp, *ptr);
+					HASH_NEW(qp, *ptr, attoptions->sig_len_int);
 					ptr++;
 				}
 
 				de = GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
 				dq = qp;
 				retval = true;
-				LOOPBYTE
+				LOOPBYTE_NEW(attoptions->sig_len_int)
 				{
 					if (de[i] != dq[i])
 					{
@@ -553,11 +617,11 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
 
 			}
 			else
-				retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key), query);
+				retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key), query, attoptions->sig_len_int);
 			break;
 		case RTContainsStrategyNumber:
 		case RTOldContainsStrategyNumber:
-			retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key), query);
+			retval = _intbig_contains((GISTTYPE *) DatumGetPointer(entry->key), query, attoptions->sig_len_int);
 			break;
 		case RTContainedByStrategyNumber:
 		case RTOldContainedByStrategyNumber:
@@ -566,22 +630,22 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
 				int			i,
 							num = ARRNELEMS(query);
 				int32	   *ptr = ARRPTR(query);
-				BITVEC		qp;
+				BITVECP		qp;
 				BITVECP		dq,
 							de;
 
-				memset(qp, 0, sizeof(BITVEC));
-
+//				memset(qp, 0, SIGLEN_BYTES(attoptions->sig_len_int));
+				qp = new_bitvec(attoptions->sig_len_int);
 				while (num--)
 				{
-					HASH(qp, *ptr);
+					HASH_NEW(qp, *ptr, attoptions->sig_len_int);
 					ptr++;
 				}
 
 				de = GETSIGN((GISTTYPE *) DatumGetPointer(entry->key));
 				dq = qp;
 				retval = true;
-				LOOPBYTE
+				LOOPBYTE_NEW(attoptions->sig_len_int)
 				{
 					if (de[i] & ~dq[i])
 					{
@@ -591,7 +655,7 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
 				}
 			}
 			else
-				retval = _intbig_overlap((GISTTYPE *) DatumGetPointer(entry->key), query);
+				retval = _intbig_overlap((GISTTYPE *) DatumGetPointer(entry->key), query, attoptions->sig_len_int);
 			break;
 		default:
 			retval = FALSE;
@@ -599,3 +663,46 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
 	PG_FREE_IF_COPY(query, 1);
 	PG_RETURN_BOOL(retval);
 }
+
+Datum
+g_intbig_attoptions(PG_FUNCTION_ARGS)
+{
+	relopt_value *options;
+	int			numoptions;
+	IntArrayOpclassOptions *attopts;
+	MemoryContext oldcxt;
+	Datum raw_options = PG_GETARG_DATUM(0);
+	bool validate = PG_GETARG_BOOL(1);
+	relopt_parse_elt tab[] =
+		{{"sig_len_int", RELOPT_TYPE_INT, offsetof(IntArrayOpclassOptions, sig_len_int)}};
+
+
+	options = parseRelOptions(raw_options, validate, &intbig_gist_attopt_catalog, 0, &numoptions);
+	attopts = allocateReloptStruct(sizeof(IntArrayOpclassOptions), options, numoptions);
+
+	fillRelOptions((void *) attopts, sizeof(IntArrayOpclassOptions), options, numoptions,
+				   validate, tab, 1);
+				   
+//	elog(WARNING, "************* %i", attopts->sig_len_int);
+
+//	oldcxt = MemoryContextSwitchTo(TopMemoryContext);
+//	attopts = palloc0(sizeof(IntArrayOpclassOptions));  //FIXME do something else with this palloc
+//	MemoryContextSwitchTo(oldcxt);
+
+//	attopts->sig_len_int = 10;
+
+//	attopts->sig_len_int = 63;
+//	attopts->sig_len_int = 77;
+//	attopts->sig_len_int = 120;
+
+
+	
+	
+//	char s[] = "Awe postgres!";
+//	char * copy;
+//	elog(WARNING, "g_int_getattopdesc!!");
+//	copy = palloc(sizeof(s));
+//	memcpy(copy,s,sizeof(s));
+	PG_RETURN_POINTER(attopts);
+}
+
diff --git a/contrib/intarray/intarray--1.1.sql b/contrib/intarray/intarray--1.1.sql
index 6ee0d5a..23be554 100644
--- a/contrib/intarray/intarray--1.1.sql
+++ b/contrib/intarray/intarray--1.1.sql
@@ -394,6 +394,7 @@ AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
 
+
 -- Create the operator class for indexing
 
 CREATE OPERATOR CLASS gist__int_ops
@@ -413,7 +414,6 @@ DEFAULT FOR TYPE _int4 USING gist AS
 	FUNCTION	6	g_int_picksplit (internal, internal),
 	FUNCTION	7	g_int_same (_int4, _int4, internal);
 
-
 ---------------------------------------------
 -- intbig
 ---------------------------------------------
@@ -435,12 +435,12 @@ CREATE TYPE intbig_gkey (
         OUTPUT = _intbig_out
 );
 
-CREATE FUNCTION g_intbig_consistent(internal,_int4,smallint,oid,internal)
+CREATE FUNCTION g_intbig_consistent(internal,_int4,smallint,oid,internal,internal)
 RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
-CREATE FUNCTION g_intbig_compress(internal)
+CREATE FUNCTION g_intbig_compress(internal, internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
@@ -450,26 +450,31 @@ RETURNS internal
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
-CREATE FUNCTION g_intbig_penalty(internal,internal,internal)
+CREATE FUNCTION g_intbig_penalty(internal, internal, internal, internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
-CREATE FUNCTION g_intbig_picksplit(internal, internal)
+CREATE FUNCTION g_intbig_picksplit(internal, internal, internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
-CREATE FUNCTION g_intbig_union(internal, internal)
+CREATE FUNCTION g_intbig_union(internal, internal, internal)
 RETURNS intbig_gkey
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
-CREATE FUNCTION g_intbig_same(intbig_gkey, intbig_gkey, internal)
+CREATE FUNCTION g_intbig_same(intbig_gkey, intbig_gkey, internal, internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+CREATE FUNCTION g_intbig_attoptions(internal, boolean)
+RETURNS internal
+AS 'MODULE_PATHNAME', 'g_intbig_attoptions'
+LANGUAGE C IMMUTABLE STRICT;
+
 -- register the opclass for indexing (not as default)
 
 CREATE OPERATOR CLASS gist__intbig_ops
@@ -482,13 +487,15 @@ AS
 	OPERATOR	13	@,
 	OPERATOR	14	~,
 	OPERATOR	20	@@ (_int4, query_int),
-	FUNCTION	1	g_intbig_consistent (internal, _int4, smallint, oid, internal),
-	FUNCTION	2	g_intbig_union (internal, internal),
-	FUNCTION	3	g_intbig_compress (internal),
+	FUNCTION	1	g_intbig_consistent (internal, _int4, smallint, oid, internal, internal),
+	FUNCTION	2	g_intbig_union (internal, internal, internal),
+	FUNCTION	3	g_intbig_compress (internal, internal),
 	FUNCTION	4	g_intbig_decompress (internal),
-	FUNCTION	5	g_intbig_penalty (internal, internal, internal),
-	FUNCTION	6	g_intbig_picksplit (internal, internal),
-	FUNCTION	7	g_intbig_same (intbig_gkey, intbig_gkey, internal),
+	FUNCTION	5	g_intbig_penalty (internal, internal, internal, internal),
+	FUNCTION	6	g_intbig_picksplit (internal, internal, internal),
+	FUNCTION	7	g_intbig_same (intbig_gkey, intbig_gkey, internal, internal),
+	FUNCTION	10	g_intbig_attoptions(internal, boolean),
+
 	STORAGE		intbig_gkey;
 
 --GIN
@@ -503,6 +510,8 @@ RETURNS bool
 AS 'MODULE_PATHNAME'
 LANGUAGE C IMMUTABLE STRICT;
 
+
+
 CREATE OPERATOR CLASS gin__int_ops
 FOR TYPE _int4 USING gin
 AS
diff --git a/src/backend/access/brin/brin.c b/src/backend/access/brin/brin.c
index 89bad05..797f367 100644
--- a/src/backend/access/brin/brin.c
+++ b/src/backend/access/brin/brin.c
@@ -110,6 +110,7 @@ brinhandler(PG_FUNCTION_ARGS)
 	amroutine->amendscan = brinendscan;
 	amroutine->ammarkpos = NULL;
 	amroutine->amrestrpos = NULL;
+	amroutine->amattoptions = NULL;
 
 	PG_RETURN_POINTER(amroutine);
 }
@@ -761,7 +762,7 @@ brinoptions(Datum reloptions, bool validate)
 		{"pages_per_range", RELOPT_TYPE_INT, offsetof(BrinOptions, pagesPerRange)}
 	};
 
-	options = parseRelOptions(reloptions, validate, RELOPT_KIND_BRIN,
+	options = parseRelOptions(reloptions, validate, NULL, RELOPT_KIND_BRIN,
 							  &numoptions);
 
 	/* if none set, we're done */
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 7448c7f..a665130 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -378,6 +378,7 @@ static bits32 last_assigned_kind = RELOPT_KIND_LAST_DEFAULT;
 static int	num_custom_options = 0;
 static relopt_gen **custom_options = NULL;
 static bool need_initialization = true;
+static int	max_custom_options = 0;
 
 static void initialize_reloptions(void);
 static void parse_one_reloption(relopt_value *option, char *text_str,
@@ -496,32 +497,31 @@ add_reloption_kind(void)
  *		main parser table.
  */
 static void
-add_reloption(relopt_gen *newoption)
+add_reloption(relopt_gen *newoption, options_catalog * catalog)
 {
-	static int	max_custom_options = 0;
-
-	if (num_custom_options >= max_custom_options)
+	if (catalog->num + 1 >= catalog->max)
 	{
 		MemoryContext oldcxt;
 
 		oldcxt = MemoryContextSwitchTo(TopMemoryContext);
 
-		if (max_custom_options == 0)
+		if (catalog->max == 0)
 		{
-			max_custom_options = 8;
-			custom_options = palloc(max_custom_options * sizeof(relopt_gen *));
+			catalog->max = 8;
+			catalog->definitions = palloc(catalog->max * sizeof(relopt_gen *));
 		}
 		else
 		{
-			max_custom_options *= 2;
-			custom_options = repalloc(custom_options,
-								  max_custom_options * sizeof(relopt_gen *));
+			catalog->max *= 2;
+			catalog->definitions = repalloc(catalog->definitions,
+								  catalog->max * sizeof(relopt_gen *));
 		}
 		MemoryContextSwitchTo(oldcxt);
 	}
-	custom_options[num_custom_options++] = newoption;
-
-	need_initialization = true;
+	catalog->definitions[catalog->num] = newoption;
+	catalog->definitions[catalog->num + 1] = NULL;
+	catalog->num++;
+	catalog->need_initialization = true;
 }
 
 /*
@@ -578,15 +578,33 @@ allocate_reloption(bits32 kinds, int type, char *name, char *desc)
  *		Add a new boolean reloption
  */
 void
-add_bool_reloption(bits32 kinds, char *name, char *desc, bool default_val)
+add_bool_reloption(bits32 kinds, options_catalog * catalog,
+									char *name, char *desc, bool default_val)
 {
 	relopt_bool *newoption;
 
 	newoption = (relopt_bool *) allocate_reloption(kinds, RELOPT_TYPE_BOOL,
 												   name, desc);
 	newoption->default_val = default_val;
-
-	add_reloption((relopt_gen *) newoption);
+	
+	if (catalog)
+	{
+		add_reloption((relopt_gen *) newoption, catalog);
+	} else
+	{
+		options_catalog  static_catalog;
+		static_catalog.num = num_custom_options;
+		static_catalog.max = max_custom_options;
+		static_catalog.need_initialization = need_initialization;
+		static_catalog.definitions = custom_options;
+
+		add_reloption((relopt_gen *) newoption, &static_catalog);
+
+		num_custom_options = static_catalog.num;
+		max_custom_options = static_catalog.max;
+		need_initialization = static_catalog.need_initialization;
+		custom_options = static_catalog.definitions;
+	}
 }
 
 /*
@@ -594,8 +612,8 @@ add_bool_reloption(bits32 kinds, char *name, char *desc, bool default_val)
  *		Add a new integer reloption
  */
 void
-add_int_reloption(bits32 kinds, char *name, char *desc, int default_val,
-				  int min_val, int max_val)
+add_int_reloption(bits32 kinds, options_catalog * catalog,
+			char *name, char *desc, int default_val, int min_val, int max_val)
 {
 	relopt_int *newoption;
 
@@ -605,7 +623,24 @@ add_int_reloption(bits32 kinds, char *name, char *desc, int default_val,
 	newoption->min = min_val;
 	newoption->max = max_val;
 
-	add_reloption((relopt_gen *) newoption);
+	if (catalog)
+	{
+		add_reloption((relopt_gen *) newoption, catalog);
+	} else
+	{
+		options_catalog  static_catalog;
+		static_catalog.num = num_custom_options;
+		static_catalog.max = max_custom_options;
+		static_catalog.need_initialization = need_initialization;
+		static_catalog.definitions = custom_options;
+
+		add_reloption((relopt_gen *) newoption, &static_catalog);
+
+		num_custom_options = static_catalog.num;
+		max_custom_options = static_catalog.max;
+		need_initialization = static_catalog.need_initialization;
+		custom_options = static_catalog.definitions;
+	}
 }
 
 /*
@@ -613,8 +648,9 @@ add_int_reloption(bits32 kinds, char *name, char *desc, int default_val,
  *		Add a new float reloption
  */
 void
-add_real_reloption(bits32 kinds, char *name, char *desc, double default_val,
-				   double min_val, double max_val)
+add_real_reloption(bits32 kinds, options_catalog * catalog,
+							char *name, char *desc, double default_val,
+										double min_val, double max_val)
 {
 	relopt_real *newoption;
 
@@ -624,7 +660,24 @@ add_real_reloption(bits32 kinds, char *name, char *desc, double default_val,
 	newoption->min = min_val;
 	newoption->max = max_val;
 
-	add_reloption((relopt_gen *) newoption);
+	if (catalog)
+	{
+		add_reloption((relopt_gen *) newoption, catalog);
+	} else
+	{
+		options_catalog  static_catalog;
+		static_catalog.num = num_custom_options;
+		static_catalog.max = max_custom_options;
+		static_catalog.need_initialization = need_initialization;
+		static_catalog.definitions = custom_options;
+
+		add_reloption((relopt_gen *) newoption, &static_catalog);
+
+		num_custom_options = static_catalog.num;
+		max_custom_options = static_catalog.max;
+		need_initialization = static_catalog.need_initialization;
+		custom_options = static_catalog.definitions;
+	}
 }
 
 /*
@@ -637,8 +690,8 @@ add_real_reloption(bits32 kinds, char *name, char *desc, double default_val,
  * the validation.
  */
 void
-add_string_reloption(bits32 kinds, char *name, char *desc, char *default_val,
-					 validate_string_relopt validator)
+add_string_reloption(bits32 kinds, options_catalog * catalog, char *name,
+			char *desc, char *default_val, validate_string_relopt validator)
 {
 	relopt_string *newoption;
 
@@ -663,7 +716,24 @@ add_string_reloption(bits32 kinds, char *name, char *desc, char *default_val,
 		newoption->default_isnull = true;
 	}
 
-	add_reloption((relopt_gen *) newoption);
+	if (catalog)
+	{
+		add_reloption((relopt_gen *) newoption, catalog);
+	} else
+	{
+		options_catalog  static_catalog;
+		static_catalog.num = num_custom_options;
+		static_catalog.max = max_custom_options;
+		static_catalog.need_initialization = need_initialization;
+		static_catalog.definitions = custom_options;
+
+		add_reloption((relopt_gen *) newoption, &static_catalog);
+
+		num_custom_options = static_catalog.num;
+		max_custom_options = static_catalog.max;
+		need_initialization = static_catalog.need_initialization;
+		custom_options = static_catalog.definitions;
+	}
 }
 
 /*
@@ -714,13 +784,13 @@ transformRelOptions(Datum oldOptions, List *defList, char *namspace,
 
 		deconstruct_array(array, TEXTOID, -1, false, 'i',
 						  &oldoptions, NULL, &noldoptions);
-
 		for (i = 0; i < noldoptions; i++)
 		{
 			text	   *oldoption = DatumGetTextP(oldoptions[i]);
 			char	   *text_str = VARDATA(oldoption);
 			int			text_len = VARSIZE(oldoption) - VARHDRSZ;
 
+//elog(WARNING, "parsing option %s",text_str);
 			/* Search for a match in defList */
 			foreach(cell, defList)
 			{
@@ -832,6 +902,8 @@ transformRelOptions(Datum oldOptions, List *defList, char *namspace,
 			t = (text *) palloc(len + 1);
 			SET_VARSIZE(t, len);
 			sprintf(VARDATA(t), "%s=%s", def->defname, value);
+			
+//elog(WARNING, "parsing option %s=%s", def->defname, value);
 
 			astate = accumArrayResult(astate, PointerGetDatum(t),
 									  false, TEXTOID,
@@ -964,21 +1036,31 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
  * be freed by the caller.
  */
 relopt_value *
-parseRelOptions(Datum options, bool validate, relopt_kind kind,
-				int *numrelopts)
+parseRelOptions(Datum options, bool validate, options_catalog * catalog,
+				relopt_kind kind, int *numrelopts)
 {
 	relopt_value *reloptions;
 	int			numoptions = 0;
 	int			i;
 	int			j;
+	options_catalog static_catalog;
 
 	if (need_initialization)
 		initialize_reloptions();
 
+	if (! catalog)
+	{
+		static_catalog.definitions = relOpts;
+		catalog = &static_catalog;
+	} else
+	{
+		Assert(kind == 0);
+	}
+
 	/* Build a list of expected options, based on kind */
 
-	for (i = 0; relOpts[i]; i++)
-		if (relOpts[i]->kinds & kind)
+	for (i = 0; catalog->definitions[i]; i++)
+		if (! kind || (catalog->definitions[i]->kinds & kind))
 			numoptions++;
 
 	if (numoptions == 0)
@@ -989,11 +1071,11 @@ parseRelOptions(Datum options, bool validate, relopt_kind kind,
 
 	reloptions = palloc(numoptions * sizeof(relopt_value));
 
-	for (i = 0, j = 0; relOpts[i]; i++)
+	for (i = 0, j = 0; catalog->definitions[i]; i++)
 	{
-		if (relOpts[i]->kinds & kind)
+		if (! kind || (catalog->definitions[i]->kinds & kind))
 		{
-			reloptions[j].gen = relOpts[i];
+			reloptions[j].gen = catalog->definitions[i];
 			reloptions[j].isset = false;
 			j++;
 		}
@@ -1305,7 +1387,7 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
 		offsetof(StdRdOptions, parallel_degree)}
 	};
 
-	options = parseRelOptions(reloptions, validate, kind, &numoptions);
+	options = parseRelOptions(reloptions, validate, NULL, kind, &numoptions);
 
 	/* if none set, we're done */
 	if (numoptions == 0)
@@ -1337,7 +1419,7 @@ view_reloptions(Datum reloptions, bool validate)
 		offsetof(ViewOptions, check_option_offset)}
 	};
 
-	options = parseRelOptions(reloptions, validate, RELOPT_KIND_VIEW, &numoptions);
+	options = parseRelOptions(reloptions, validate, NULL, RELOPT_KIND_VIEW, &numoptions);
 
 	/* if none set, we're done */
 	if (numoptions == 0)
@@ -1417,7 +1499,7 @@ attribute_reloptions(Datum reloptions, bool validate)
 		{"n_distinct_inherited", RELOPT_TYPE_REAL, offsetof(AttributeOpts, n_distinct_inherited)}
 	};
 
-	options = parseRelOptions(reloptions, validate, RELOPT_KIND_ATTRIBUTE,
+	options = parseRelOptions(reloptions, validate, NULL, RELOPT_KIND_ATTRIBUTE,
 							  &numoptions);
 
 	/* if none set, we're done */
@@ -1449,7 +1531,7 @@ tablespace_reloptions(Datum reloptions, bool validate)
 		{"effective_io_concurrency", RELOPT_TYPE_INT, offsetof(TableSpaceOpts, effective_io_concurrency)}
 	};
 
-	options = parseRelOptions(reloptions, validate, RELOPT_KIND_TABLESPACE,
+	options = parseRelOptions(reloptions, validate, NULL, RELOPT_KIND_TABLESPACE,
 							  &numoptions);
 
 	/* if none set, we're done */
diff --git a/src/backend/access/gin/ginutil.c b/src/backend/access/gin/ginutil.c
index a2450f4..051c90e 100644
--- a/src/backend/access/gin/ginutil.c
+++ b/src/backend/access/gin/ginutil.c
@@ -65,6 +65,7 @@ ginhandler(PG_FUNCTION_ARGS)
 	amroutine->amendscan = ginendscan;
 	amroutine->ammarkpos = NULL;
 	amroutine->amrestrpos = NULL;
+	amroutine->amattoptions = NULL;
 
 	PG_RETURN_POINTER(amroutine);
 }
@@ -573,7 +574,7 @@ ginoptions(Datum reloptions, bool validate)
 													 pendingListCleanupSize)}
 	};
 
-	options = parseRelOptions(reloptions, validate, RELOPT_KIND_GIN,
+	options = parseRelOptions(reloptions, validate, NULL, RELOPT_KIND_GIN,
 							  &numoptions);
 
 	/* if none set, we're done */
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index a290887..4a76e2d 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -87,6 +87,7 @@ gisthandler(PG_FUNCTION_ARGS)
 	amroutine->amendscan = gistendscan;
 	amroutine->ammarkpos = NULL;
 	amroutine->amrestrpos = NULL;
+	amroutine->amattoptions = gistattoptions;
 
 	PG_RETURN_POINTER(amroutine);
 }
@@ -1421,6 +1422,7 @@ initGISTstate(Relation index)
 	giststate->scanCxt = scanCxt;
 	giststate->tempCxt = scanCxt;		/* caller must change this if needed */
 	giststate->tupdesc = index->rd_att;
+	giststate->attoptions = get_index_attribute_options(index);
 
 	for (i = 0; i < index->rd_att->natts; i++)
 	{
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index affd635..f73bbac 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -193,11 +193,13 @@ gistindex_keytest(IndexScanDesc scan,
 			Datum		test;
 			bool		recheck;
 			GISTENTRY	de;
+			bytea*		attoptions;
 
 			gistdentryinit(giststate, key->sk_attno - 1, &de,
 						   datum, r, page, offset,
 						   FALSE, isNull);
 
+			attoptions = giststate->attoptions[key->sk_attno - 1];
 			/*
 			 * Call the Consistent function to evaluate the test.  The
 			 * arguments are the index datum (as a GISTENTRY*), the comparison
@@ -213,13 +215,14 @@ gistindex_keytest(IndexScanDesc scan,
 			 */
 			recheck = true;
 
-			test = FunctionCall5Coll(&key->sk_func,
+			test = FunctionCall6Coll(&key->sk_func,
 									 key->sk_collation,
 									 PointerGetDatum(&de),
 									 key->sk_argument,
 									 Int16GetDatum(key->sk_strategy),
 									 ObjectIdGetDatum(key->sk_subtype),
-									 PointerGetDatum(&recheck));
+									 PointerGetDatum(&recheck),
+									 PointerGetDatum(attoptions));
 
 			if (!DatumGetBool(test))
 				return false;
diff --git a/src/backend/access/gist/gistsplit.c b/src/backend/access/gist/gistsplit.c
index d394969..93bd937 100644
--- a/src/backend/access/gist/gistsplit.c
+++ b/src/backend/access/gist/gistsplit.c
@@ -378,18 +378,20 @@ genericPickSplit(GISTSTATE *giststate, GistEntryVector *entryvec, GIST_SPLITVEC
 	evec->n = v->spl_nleft;
 	memcpy(evec->vector, entryvec->vector + FirstOffsetNumber,
 		   sizeof(GISTENTRY) * evec->n);
-	v->spl_ldatum = FunctionCall2Coll(&giststate->unionFn[attno],
+	v->spl_ldatum = FunctionCall3Coll(&giststate->unionFn[attno],
 									  giststate->supportCollation[attno],
 									  PointerGetDatum(evec),
-									  PointerGetDatum(&nbytes));
+									  PointerGetDatum(&nbytes),
+								PointerGetDatum(giststate->attoptions[attno]));
 
 	evec->n = v->spl_nright;
 	memcpy(evec->vector, entryvec->vector + FirstOffsetNumber + v->spl_nleft,
 		   sizeof(GISTENTRY) * evec->n);
-	v->spl_rdatum = FunctionCall2Coll(&giststate->unionFn[attno],
+	v->spl_rdatum = FunctionCall3Coll(&giststate->unionFn[attno],
 									  giststate->supportCollation[attno],
 									  PointerGetDatum(evec),
-									  PointerGetDatum(&nbytes));
+									  PointerGetDatum(&nbytes),
+								PointerGetDatum(giststate->attoptions[attno]));
 }
 
 /*
@@ -425,15 +427,16 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GistSplitVec
 	sv->spl_rdatum_exists = (v->spl_risnull[attno]) ? false : true;
 	sv->spl_ldatum = v->spl_lattr[attno];
 	sv->spl_rdatum = v->spl_rattr[attno];
-
+	
 	/*
 	 * Let the opclass-specific PickSplit method do its thing.  Note that at
 	 * this point we know there are no null keys in the entryvec.
 	 */
-	FunctionCall2Coll(&giststate->picksplitFn[attno],
+	FunctionCall3Coll(&giststate->picksplitFn[attno],
 					  giststate->supportCollation[attno],
 					  PointerGetDatum(entryvec),
-					  PointerGetDatum(sv));
+					  PointerGetDatum(sv),
+					  PointerGetDatum(giststate->attoptions[attno]));
 
 	if (sv->spl_nleft == 0 || sv->spl_nright == 0)
 	{
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index fac166d..60fe6de 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -21,6 +21,13 @@
 #include "storage/lmgr.h"
 #include "utils/builtins.h"
 
+#include "access/htup_details.h"
+#include "utils/syscache.h"
+#include "utils/catcache.h"
+
+#include "catalog/pg_opclass.h"
+#include "catalog/pg_opfamily.h"
+#include "catalog/pg_amproc.h"
 
 /*
  * Write itup vector to page, has no control of free space.
@@ -195,10 +202,11 @@ gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len,
 			}
 
 			/* Make union and store in attr array */
-			attr[i] = FunctionCall2Coll(&giststate->unionFn[i],
+			attr[i] = FunctionCall3Coll(&giststate->unionFn[i],
 										giststate->supportCollation[i],
 										PointerGetDatum(evec),
-										PointerGetDatum(&attrsize));
+										PointerGetDatum(&attrsize),
+								PointerGetDatum(giststate->attoptions[i]));
 
 			isnull[i] = FALSE;
 		}
@@ -264,10 +272,11 @@ gistMakeUnionKey(GISTSTATE *giststate, int attno,
 		}
 
 		*dstisnull = FALSE;
-		*dst = FunctionCall2Coll(&giststate->unionFn[attno],
+		*dst = FunctionCall3Coll(&giststate->unionFn[attno],
 								 giststate->supportCollation[attno],
 								 PointerGetDatum(evec),
-								 PointerGetDatum(&dstsize));
+								 PointerGetDatum(&dstsize),
+								 PointerGetDatum(giststate->attoptions[attno]));
 	}
 }
 
@@ -276,10 +285,11 @@ gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b)
 {
 	bool		result;
 
-	FunctionCall3Coll(&giststate->equalFn[attno],
+	FunctionCall4Coll(&giststate->equalFn[attno],
 					  giststate->supportCollation[attno],
 					  a, b,
-					  PointerGetDatum(&result));
+					  PointerGetDatum(&result),
+					  PointerGetDatum(giststate->attoptions[attno]));
 	return result;
 }
 
@@ -582,9 +592,10 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
 			gistentryinit(centry, attdata[i], r, NULL, (OffsetNumber) 0,
 						  isleaf);
 			cep = (GISTENTRY *)
-				DatumGetPointer(FunctionCall1Coll(&giststate->compressFn[i],
+				DatumGetPointer(FunctionCall2Coll(&giststate->compressFn[i],
 											  giststate->supportCollation[i],
-												  PointerGetDatum(&centry)));
+												  PointerGetDatum(&centry),
+									PointerGetDatum(giststate->attoptions[i])));
 			compatt[i] = cep->key;
 		}
 	}
@@ -670,11 +681,12 @@ gistpenalty(GISTSTATE *giststate, int attno,
 	if (giststate->penaltyFn[attno].fn_strict == FALSE ||
 		(isNullOrig == FALSE && isNullAdd == FALSE))
 	{
-		FunctionCall3Coll(&giststate->penaltyFn[attno],
+		FunctionCall4Coll(&giststate->penaltyFn[attno],
 						  giststate->supportCollation[attno],
 						  PointerGetDatum(orig),
 						  PointerGetDatum(add),
-						  PointerGetDatum(&penalty));
+						  PointerGetDatum(&penalty),
+						  PointerGetDatum(giststate->attoptions[attno]));
 		/* disallow negative or NaN penalty */
 		if (isnan(penalty) || penalty < 0.0)
 			penalty = 0.0;
@@ -819,7 +831,7 @@ gistoptions(Datum reloptions, bool validate)
 		{"buffering", RELOPT_TYPE_STRING, offsetof(GiSTOptions, bufferingModeOffset)}
 	};
 
-	options = parseRelOptions(reloptions, validate, RELOPT_KIND_GIST,
+	options = parseRelOptions(reloptions, validate, NULL, RELOPT_KIND_GIST,
 							  &numoptions);
 
 	/* if none set, we're done */
@@ -864,3 +876,78 @@ gistGetFakeLSN(Relation rel)
 		return GetFakeLSNForUnloggedRel();
 	}
 }
+
+bytea *
+gistattoptions(Oid opfamilyoid, Oid opcintype, Datum reloptions, bool validate)
+{
+	bool		result = true;
+	HeapTuple	familytup;
+	Form_pg_opfamily familyform;
+	char	   *opfamilyname;
+	CatCList   *proclist,
+			   *oprlist;
+	bytea	   *res = NULL;
+
+    bool		ok = false;
+
+	int i;
+
+	/* Fetch opfamily information */
+	familytup = SearchSysCache1(OPFAMILYOID, ObjectIdGetDatum(opfamilyoid));
+	if (!HeapTupleIsValid(familytup))
+		elog(ERROR, "cache lookup failed for operator family %u", opfamilyoid);
+	familyform = (Form_pg_opfamily) GETSTRUCT(familytup);
+
+	opfamilyname = NameStr(familyform->opfname);
+
+	/* Fetch all operators and support functions of the opfamily */
+	oprlist = SearchSysCacheList1(AMOPSTRATEGY, ObjectIdGetDatum(opfamilyoid));
+	proclist = SearchSysCacheList1(AMPROCNUM, ObjectIdGetDatum(opfamilyoid));
+
+	for (i = 0; i < proclist->n_members; i++)
+	{
+		HeapTuple	proctup = &proclist->members[i]->tuple;
+		Form_pg_amproc procform = (Form_pg_amproc) GETSTRUCT(proctup);
+		
+		Oid tmp_oid = procform->amproc; // FIXME rename var;
+		/*
+		 * All GiST support functions should be registered with matching
+		 * left/right types
+		 */
+		if (procform->amproclefttype != procform->amprocrighttype)
+		{
+			ereport(INFO,
+					(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+					 errmsg("gist opfamily %s contains support procedure %s with cross-type registration",
+							opfamilyname,
+							format_procedure(procform->amproc))));
+			result = false;
+		}
+
+		/*
+		 * We can't check signatures except within the specific opclass, since
+		 * we need to know the associated opckeytype in many cases.
+		 */
+		if (procform->amproclefttype != opcintype)
+			continue;
+
+		switch (procform->amprocnum)
+		{
+			case GIST_GET_ATTOPT_DEST_PROC:
+//				elog(WARNING, "2Proper function attopdesc for opclass found %i",(unsigned int) tmp_oid);
+				
+				res = DatumGetPointer(OidFunctionCall2(tmp_oid, reloptions, validate));
+				
+//				elog(WARNING, "Got result:'%i'",*((int *)res +1));
+
+				ok = true;
+				break;
+		}
+	}
+//	if (! ok) elog(WARNING, "2Proper function attopdesc for opclass NOT FOUND");
+
+	ReleaseCatCacheList(proclist);
+	ReleaseCatCacheList(oprlist);
+	ReleaseSysCache(familytup);
+	return res;
+}
\ No newline at end of file
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 49a6c81..42a9460 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -82,6 +82,7 @@ hashhandler(PG_FUNCTION_ARGS)
 	amroutine->amendscan = hashendscan;
 	amroutine->ammarkpos = NULL;
 	amroutine->amrestrpos = NULL;
+	amroutine->amattoptions = NULL;
 
 	PG_RETURN_POINTER(amroutine);
 }
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 013394c..2255a79 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -115,6 +115,7 @@ bthandler(PG_FUNCTION_ARGS)
 	amroutine->amendscan = btendscan;
 	amroutine->ammarkpos = btmarkpos;
 	amroutine->amrestrpos = btrestrpos;
+	amroutine->amattoptions = NULL;
 
 	PG_RETURN_POINTER(amroutine);
 }
diff --git a/src/backend/access/spgist/spgutils.c b/src/backend/access/spgist/spgutils.c
index bc679bf..d5d4132 100644
--- a/src/backend/access/spgist/spgutils.c
+++ b/src/backend/access/spgist/spgutils.c
@@ -66,6 +66,7 @@ spghandler(PG_FUNCTION_ARGS)
 	amroutine->amendscan = spgendscan;
 	amroutine->ammarkpos = NULL;
 	amroutine->amrestrpos = NULL;
+	amroutine->amattoptions = NULL;
 
 	PG_RETURN_POINTER(amroutine);
 }
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index e997b57..e95d0ef 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -600,7 +600,8 @@ CheckAttributeType(const char *attname,
 void
 InsertPgAttributeTuple(Relation pg_attribute_rel,
 					   Form_pg_attribute new_attribute,
-					   CatalogIndexState indstate)
+					   CatalogIndexState indstate,
+					   Datum attoptions)
 {
 	Datum		values[Natts_pg_attribute];
 	bool		nulls[Natts_pg_attribute];
@@ -628,10 +629,14 @@ InsertPgAttributeTuple(Relation pg_attribute_rel,
 	values[Anum_pg_attribute_attislocal - 1] = BoolGetDatum(new_attribute->attislocal);
 	values[Anum_pg_attribute_attinhcount - 1] = Int32GetDatum(new_attribute->attinhcount);
 	values[Anum_pg_attribute_attcollation - 1] = ObjectIdGetDatum(new_attribute->attcollation);
+	if (attoptions != (Datum) 0)
+		values[Anum_pg_attribute_attoptions - 1] = attoptions;
+	else
+		nulls[Anum_pg_attribute_attoptions - 1] = true;
 
 	/* start out with empty permissions and empty options */
 	nulls[Anum_pg_attribute_attacl - 1] = true;
-	nulls[Anum_pg_attribute_attoptions - 1] = true;
+//	nulls[Anum_pg_attribute_attoptions - 1] = true;
 	nulls[Anum_pg_attribute_attfdwoptions - 1] = true;
 
 	tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls);
@@ -689,7 +694,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
 		attr->attstattarget = -1;
 		attr->attcacheoff = -1;
 
-		InsertPgAttributeTuple(rel, attr, indstate);
+		InsertPgAttributeTuple(rel, attr, indstate, (Datum) 0);
 
 		/* Add dependency info */
 		myself.classId = RelationRelationId;
@@ -739,7 +744,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
 				attStruct.attinhcount = oidinhcount;
 			}
 
-			InsertPgAttributeTuple(rel, &attStruct, indstate);
+			InsertPgAttributeTuple(rel, &attStruct, indstate, (Datum) 0);
 		}
 	}
 
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 31a1438..93680aa 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -96,7 +96,8 @@ static TupleDesc ConstructTupleDescriptor(Relation heapRelation,
 						 Oid *classObjectId);
 static void InitializeAttributeOids(Relation indexRelation,
 						int numatts, Oid indexoid);
-static void AppendAttributeTuples(Relation indexRelation, int numatts);
+static void AppendAttributeTuples(Relation indexRelation, int numatts,
+						Datum *attoptions);
 static void UpdateIndexRelation(Oid indexoid, Oid heapoid,
 					IndexInfo *indexInfo,
 					Oid *collationOids,
@@ -486,7 +487,7 @@ InitializeAttributeOids(Relation indexRelation,
  * ----------------------------------------------------------------
  */
 static void
-AppendAttributeTuples(Relation indexRelation, int numatts)
+AppendAttributeTuples(Relation indexRelation, int numatts, Datum *attoptions)
 {
 	Relation	pg_attribute;
 	CatalogIndexState indstate;
@@ -514,7 +515,8 @@ AppendAttributeTuples(Relation indexRelation, int numatts)
 		Assert(indexTupDesc->attrs[i]->attnum == i + 1);
 		Assert(indexTupDesc->attrs[i]->attcacheoff == -1);
 
-		InsertPgAttributeTuple(pg_attribute, indexTupDesc->attrs[i], indstate);
+		InsertPgAttributeTuple(pg_attribute, indexTupDesc->attrs[i], indstate, 
+		attoptions ? attoptions[i]: (Datum) 0);
 	}
 
 	CatalogCloseIndexes(indstate);
@@ -864,6 +866,7 @@ index_create(Relation heapRelation,
 	indexRelation->rd_rel->relowner = heapRelation->rd_rel->relowner;
 	indexRelation->rd_rel->relam = accessMethodObjectId;
 	indexRelation->rd_rel->relhasoids = false;
+	indexRelation->rd_attoptions = NULL;
 
 	/*
 	 * store index's pg_class entry
@@ -887,7 +890,7 @@ index_create(Relation heapRelation,
 	/*
 	 * append ATTRIBUTE tuples for the index
 	 */
-	AppendAttributeTuples(indexRelation, indexInfo->ii_NumIndexAttrs);
+	AppendAttributeTuples(indexRelation, indexInfo->ii_NumIndexAttrs, indexInfo->ii_AttOptions);
 
 	/* ----------------
 	 *	  update pg_index
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 564e10e..8ec4ecc 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -308,6 +308,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
 	indexInfo->ii_ExpressionsState = NIL;
 	indexInfo->ii_Predicate = NIL;
 	indexInfo->ii_PredicateState = NIL;
+	indexInfo->ii_AttOptions = NULL;
 	indexInfo->ii_ExclusionOps = NULL;
 	indexInfo->ii_ExclusionProcs = NULL;
 	indexInfo->ii_ExclusionStrats = NULL;
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index cf8c816..42cddd3 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -525,7 +525,8 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params,
 			 * If the appropriate flavor of the n_distinct option is
 			 * specified, override with the corresponding value.
 			 */
-			aopt = get_attribute_options(onerel->rd_id, stats->attr->attnum);
+			aopt = get_attribute_options(onerel->rd_rel->relkind, onerel->rd_id,
+										 stats->attr->attnum);
 			if (aopt != NULL)
 			{
 				float8		n_distinct;
@@ -811,7 +812,7 @@ compute_index_stats(Relation onerel, double totalrows,
 			{
 				VacAttrStats *stats = thisdata->vacattrstats[i];
 				AttributeOpts *aopt =
-				get_attribute_options(stats->attr->attrelid,
+				get_attribute_options(RELKIND_RELATION, stats->attr->attrelid,
 									  stats->attr->attnum);
 
 				stats->exprvals = exprvals + i;
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index d14d540..b789d7b 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -67,6 +67,7 @@ static void ComputeIndexAttrs(IndexInfo *indexInfo,
 				  List *exclusionOpNames,
 				  Oid relId,
 				  char *accessMethodName, Oid accessMethodId,
+				  IndexAmRoutine *amRoutine,
 				  bool amcanorder,
 				  bool isconstraint);
 static Oid GetIndexOpClass(List *opclass, Oid attrType,
@@ -193,6 +194,7 @@ CheckIndexCompatible(Oid oldId,
 					  coloptions, attributeList,
 					  exclusionOpNames, relationId,
 					  accessMethodName, accessMethodId,
+					  amRoutine,
 					  amcanorder, isconstraint);
 
 
@@ -523,7 +525,6 @@ DefineIndex(Oid relationId,
 	amcanorder = amRoutine->amcanorder;
 	amoptions = amRoutine->amoptions;
 
-	pfree(amRoutine);
 	ReleaseSysCache(tuple);
 
 	/*
@@ -568,7 +569,9 @@ DefineIndex(Oid relationId,
 					  coloptions, stmt->indexParams,
 					  stmt->excludeOpNames, relationId,
 					  accessMethodName, accessMethodId,
+					  amRoutine,
 					  amcanorder, stmt->isconstraint);
+	pfree(amRoutine);
 
 	/*
 	 * Extra checks when creating a PRIMARY KEY index.
@@ -997,6 +1000,7 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
 				  Oid relId,
 				  char *accessMethodName,
 				  Oid accessMethodId,
+				  IndexAmRoutine *amRoutine,
 				  bool amcanorder,
 				  bool isconstraint)
 {
@@ -1017,7 +1021,8 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
 	}
 	else
 		nextExclOp = NULL;
-
+	
+	indexInfo->ii_AttOptions = (Datum*) palloc0(sizeof(Datum) * list_length(attList)); //FIXME list_length(attList) to ncols
 	/*
 	 * process attributeList
 	 */
@@ -1249,6 +1254,46 @@ ComputeIndexAttrs(IndexInfo *indexInfo,
 								accessMethodName)));
 		}
 
+if (amRoutine->amattoptions)
+{
+	HeapTuple	classtup;
+	Form_pg_opclass classform;
+	Oid			opfamilyoid;
+	Oid			opcintype;
+	Datum		attoptions;
+
+	
+	attoptions = transformRelOptions((Datum) 0, attribute->options,
+									 NULL, NULL, false, false);
+
+	classtup = SearchSysCache1(CLAOID, ObjectIdGetDatum(classOidP[attn]));
+	if (!HeapTupleIsValid(classtup))
+		elog(ERROR, "cache lookup failed for operator class %u", classOidP[attn]);
+	classform = (Form_pg_opclass) GETSTRUCT(classtup);
+
+	opfamilyoid = classform->opcfamily;
+	opcintype = classform->opcintype;
+
+	
+		amRoutine->amattoptions(opfamilyoid, opcintype, attoptions, true); /* Do validate */
+		indexInfo->ii_AttOptions[attn] = attoptions;
+		
+		//
+	if(indexInfo->ii_AttOptions[attn])
+	{
+//  elog(WARNING, "Have amattoptions: %i",*((int *)indexInfo->ii_AttOptions[attn] +1));
+  } else
+  {
+//    elog(WARNING, "Have amattoptions, but there is no options here");
+  }
+	ReleaseSysCache(classtup);
+} else
+{
+		indexInfo->ii_AttOptions[attn] = (Datum) 0;
+//  elog(WARNING, "No amattoptions");
+//  FIXME add ERROR if no attoptions is supporsed to be here...
+}
+
 		attn++;
 	}
 }
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 86e9814..2d2456e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -4858,7 +4858,7 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
 
 	ReleaseSysCache(typeTuple);
 
-	InsertPgAttributeTuple(attrdesc, &attribute, NULL);
+	InsertPgAttributeTuple(attrdesc, &attribute, NULL, (Datum)0);
 
 	heap_close(attrdesc, RowExclusiveLock);
 
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 20e38f0..4b2edbe 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2591,6 +2591,7 @@ _copyIndexElem(const IndexElem *from)
 	COPY_NODE_FIELD(opclass);
 	COPY_SCALAR_FIELD(ordering);
 	COPY_SCALAR_FIELD(nulls_ordering);
+	COPY_NODE_FIELD(options);
 
 	return newnode;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 18ec5f0..56b3d86 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -347,7 +347,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <list>	stmtblock stmtmulti
 				OptTableElementList TableElementList OptInherit definition
 				OptTypedTableElementList TypedTableElementList
-				reloptions opt_reloptions
+				reloptions opt_reloptions opt_attoptions
 				OptWith distinct_clause opt_all_clause opt_definition func_args func_args_list
 				func_args_with_defaults func_args_with_defaults_list
 				aggr_args aggr_args_list
@@ -2973,7 +2973,7 @@ columnDef:	ColId Typename create_generic_options ColQualList
 				}
 		;
 
-columnOptions:	ColId WITH OPTIONS ColQualList
+columnOptions:	ColId WITH_LA OPTIONS ColQualList
 				{
 					ColumnDef *n = makeNode(ColumnDef);
 					n->colname = $1;
@@ -6707,7 +6707,8 @@ index_params:	index_elem							{ $$ = list_make1($1); }
  * 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 opt_collate opt_class opt_attoptions opt_asc_desc opt_nulls_order
 				{
 					$$ = makeNode(IndexElem);
 					$$->name = $1;
@@ -6715,10 +6716,11 @@ index_elem:	ColId opt_collate opt_class opt_asc_desc opt_nulls_order
 					$$->indexcolname = NULL;
 					$$->collation = $2;
 					$$->opclass = $3;
-					$$->ordering = $4;
-					$$->nulls_ordering = $5;
+					$$->options = $4;
+					$$->ordering = $5;
+					$$->nulls_ordering = $6;
 				}
-			| func_expr_windowless opt_collate opt_class opt_asc_desc opt_nulls_order
+			| func_expr_windowless opt_collate opt_class opt_attoptions opt_asc_desc opt_nulls_order
 				{
 					$$ = makeNode(IndexElem);
 					$$->name = NULL;
@@ -6726,10 +6728,11 @@ index_elem:	ColId opt_collate opt_class opt_asc_desc opt_nulls_order
 					$$->indexcolname = NULL;
 					$$->collation = $2;
 					$$->opclass = $3;
-					$$->ordering = $4;
-					$$->nulls_ordering = $5;
+					$$->options = $4;
+					$$->ordering = $5;
+					$$->nulls_ordering = $6;
 				}
-			| '(' a_expr ')' opt_collate opt_class opt_asc_desc opt_nulls_order
+			| '(' a_expr ')' opt_collate opt_class opt_attoptions opt_asc_desc opt_nulls_order
 				{
 					$$ = makeNode(IndexElem);
 					$$->name = NULL;
@@ -6737,8 +6740,9 @@ index_elem:	ColId opt_collate opt_class opt_asc_desc opt_nulls_order
 					$$->indexcolname = NULL;
 					$$->collation = $4;
 					$$->opclass = $5;
-					$$->ordering = $6;
-					$$->nulls_ordering = $7;
+					$$->options = $6;
+					$$->ordering = $7;
+					$$->nulls_ordering = $8;
 				}
 		;
 
@@ -6751,6 +6755,10 @@ opt_class:	any_name								{ $$ = $1; }
 			| /*EMPTY*/								{ $$ = NIL; }
 		;
 
+opt_attoptions:	WITH_LA OPTIONS '(' reloption_list ')'		{ $$ = $4; }
+			 |	/* EMPTY */									{ $$ = NIL; }
+		;
+
 opt_asc_desc: ASC							{ $$ = SORTBY_ASC; }
 			| DESC							{ $$ = SORTBY_DESC; }
 			| /*EMPTY*/						{ $$ = SORTBY_DEFAULT; }
diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c
index 61d24e1..7a14e1e 100644
--- a/src/backend/parser/parser.c
+++ b/src/backend/parser/parser.c
@@ -185,6 +185,7 @@ base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
 			{
 				case TIME:
 				case ORDINALITY:
+				case OPTIONS:
 					cur_token = WITH_LA;
 					break;
 			}
diff --git a/src/backend/utils/cache/attoptcache.c b/src/backend/utils/cache/attoptcache.c
index 54eb864..ae97b9d 100644
--- a/src/backend/utils/cache/attoptcache.c
+++ b/src/backend/utils/cache/attoptcache.c
@@ -22,7 +22,8 @@
 #include "utils/hsearch.h"
 #include "utils/inval.h"
 #include "utils/syscache.h"
-
+#include "utils/rel.h"
+#include "utils/memutils.h"
 
 /* Hash table for informations about each attribute's options */
 static HTAB *AttoptCacheHash = NULL;
@@ -101,7 +102,7 @@ InitializeAttoptCache(void)
  *		Fetch attribute options for a specified table OID.
  */
 AttributeOpts *
-get_attribute_options(Oid attrelid, int attnum)
+get_attribute_options(char relkind, Oid attrelid, int attnum)
 {
 	AttoptCacheKey key;
 	AttoptCacheEntry *attopt;
@@ -177,3 +178,87 @@ get_attribute_options(Oid attrelid, int attnum)
 	memcpy(result, attopt->opts, VARSIZE(attopt->opts));
 	return result;
 }
+
+bytea **
+get_index_attribute_options(Relation index)
+{
+	int natts;
+	int i;
+	IndexAmRoutine* amRoutine;
+	MemoryContext oldcxt;
+
+//	elog(WARNING, "get_index_attribute_options");
+
+	if (index->rd_attoptions)
+	{
+//			elog(WARNING, "hot get");
+
+		if (index->rd_attoptions[0])
+		{
+//			elog(WARNING, "%i ",*((int *) index->rd_attoptions[i] + 1) );
+		}
+	}
+
+	if (index->rd_attoptions)
+			return index->rd_attoptions;
+	natts = index->rd_att->natts;
+
+	oldcxt = MemoryContextSwitchTo(TopMemoryContext);
+	index->rd_attoptions = palloc(sizeof (bytea **)*natts); // FIXME palloc is wrong here; FIXME free this memory somewhere
+	MemoryContextSwitchTo(oldcxt);
+
+	amRoutine = GetIndexAmRoutine(index->rd_amhandler);
+
+	for(i=0;i<natts;i++)
+	{
+		if (amRoutine->amattoptions)
+		{
+			HeapTuple	tp;
+			Datum raw_attoptions = (Datum) 0;
+			Datum parsed_attoptions;
+			
+			tp = SearchSysCache2(ATTNUM,
+						 ObjectIdGetDatum(index->rd_id),
+						 Int16GetDatum(i + 1));
+			if (HeapTupleIsValid(tp))
+			{
+				bool		isNull;
+
+				raw_attoptions = SysCacheGetAttr(ATTNUM,
+												tp,
+												Anum_pg_attribute_attoptions,
+												&isNull);
+				if (isNull)
+						raw_attoptions = (Datum) 0;
+//				if (!isNull) elog(WARNING, "Non null attoptions!");
+				ReleaseSysCache(tp);
+			}
+			parsed_attoptions = amRoutine->amattoptions(
+								index->rd_opfamily[i], index->rd_opcintype[i],
+								raw_attoptions, false);
+			
+			if (parsed_attoptions)
+			{
+				Datum result;
+
+				oldcxt = MemoryContextSwitchTo(TopMemoryContext);
+				result = palloc(VARSIZE(parsed_attoptions));
+				MemoryContextSwitchTo(oldcxt);
+
+				memcpy(result, parsed_attoptions, VARSIZE(parsed_attoptions));
+
+				index->rd_attoptions[i] = result;
+			} else
+			{
+				index->rd_attoptions[i] = NULL;
+			}
+			
+//			elog(WARNING, "coldget %i ",*((int *) index->rd_attoptions[i] + 1) );
+			
+		} else
+		{
+			index->rd_attoptions[i] = NULL;
+		}
+	}
+	return index->rd_attoptions;
+}
diff --git a/src/include/access/amapi.h b/src/include/access/amapi.h
index 35f1061..13804fa 100644
--- a/src/include/access/amapi.h
+++ b/src/include/access/amapi.h
@@ -104,6 +104,10 @@ typedef void (*ammarkpos_function) (IndexScanDesc scan);
 /* restore marked scan position */
 typedef void (*amrestrpos_function) (IndexScanDesc scan);
 
+//typedef char *(*amgetattopdesc_function) (Oid opclassoid);
+
+typedef bytea *(*amattoptions_function) (Oid opfamilyoid, Oid opcintype,
+											Datum reloptions, bool validate);
 
 /*
  * API struct for an index AM.  Note this must be stored in a single palloc'd
@@ -162,6 +166,8 @@ typedef struct IndexAmRoutine
 	amendscan_function amendscan;
 	ammarkpos_function ammarkpos;		/* can be NULL */
 	amrestrpos_function amrestrpos;		/* can be NULL */
+//	amgetattopdesc_function amgetattopdesc;	/* can be NULL */
+	amattoptions_function amattoptions;	/* can be NULL */
 } IndexAmRoutine;
 
 
diff --git a/src/include/access/gist.h b/src/include/access/gist.h
index 4343d6f..d8b5ac8 100644
--- a/src/include/access/gist.h
+++ b/src/include/access/gist.h
@@ -34,7 +34,8 @@
 #define GIST_EQUAL_PROC					7
 #define GIST_DISTANCE_PROC				8
 #define GIST_FETCH_PROC					9
-#define GISTNProcs					9
+#define GIST_GET_ATTOPT_DEST_PROC	   10
+#define GISTNProcs					10
 
 /*
  * Page opaque data in a GiST index page.
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index f9732ba..6989afd 100644
--- a/src/include/access/gist_private.h
+++ b/src/include/access/gist_private.h
@@ -95,6 +95,8 @@ typedef struct GISTSTATE
 
 	/* Collations to pass to the support functions */
 	Oid			supportCollation[INDEX_MAX_KEYS];
+	
+	bytea	  **attoptions; /* FIXME add comment */
 } GISTSTATE;
 
 
@@ -440,6 +442,8 @@ extern void gistdoinsert(Relation r,
 			 Size freespace,
 			 GISTSTATE *GISTstate);
 
+
+
 /* A List of these is returned from gistplacetopage() in *splitinfo */
 typedef struct
 {
@@ -540,6 +544,10 @@ extern void gistMakeUnionKey(GISTSTATE *giststate, int attno,
 
 extern XLogRecPtr gistGetFakeLSN(Relation rel);
 
+// extern char *gistgetattopdesc(Oid opclassoid);
+extern bytea *gistattoptions(Oid opfamilyoid, Oid opcintype,
+											Datum reloptions, bool validate);
+
 /* gistvacuum.c */
 extern IndexBulkDeleteResult *gistbulkdelete(IndexVacuumInfo *info,
 			   IndexBulkDeleteResult *stats,
diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h
index 469ac67..216f0c7 100644
--- a/src/include/access/reloptions.h
+++ b/src/include/access/reloptions.h
@@ -126,6 +126,13 @@ typedef struct
 	int			offset;			/* offset of field in result struct */
 } relopt_parse_elt;
 
+typedef struct
+{
+	relopt_gen	  **definitions;
+	int				num;
+	int				max;
+	bool			need_initialization;
+} options_catalog;
 
 /*
  * These macros exist for the convenience of amoptions writers (but consider
@@ -245,14 +252,16 @@ typedef struct
 
 
 extern relopt_kind add_reloption_kind(void);
-extern void add_bool_reloption(bits32 kinds, char *name, char *desc,
-				   bool default_val);
-extern void add_int_reloption(bits32 kinds, char *name, char *desc,
-				  int default_val, int min_val, int max_val);
-extern void add_real_reloption(bits32 kinds, char *name, char *desc,
-				   double default_val, double min_val, double max_val);
-extern void add_string_reloption(bits32 kinds, char *name, char *desc,
-					 char *default_val, validate_string_relopt validator);
+extern void add_bool_reloption(bits32 kinds, options_catalog * catalog,
+				   char *name, char *desc, bool default_val);
+extern void add_int_reloption(bits32 kinds, options_catalog * catalog,
+			char *name, char *desc, int default_val, int min_val, int max_val);
+extern void add_real_reloption(bits32 kinds, options_catalog * catalog,
+							char *name, char *desc, double default_val,
+											double min_val, double max_val);
+extern void add_string_reloption(bits32 kinds, options_catalog * catalog,
+								char *name, char *desc, char *default_val,
+											validate_string_relopt validator);
 
 extern Datum transformRelOptions(Datum oldOptions, List *defList,
 					char *namspace, char *validnsps[],
@@ -261,7 +270,7 @@ extern List *untransformRelOptions(Datum options);
 extern bytea *extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 				  amoptions_function amoptions);
 extern relopt_value *parseRelOptions(Datum options, bool validate,
-				relopt_kind kind, int *numrelopts);
+			options_catalog * catalog, relopt_kind kind, int *numrelopts);
 extern void *allocateReloptStruct(Size base, relopt_value *options,
 					 int numoptions);
 extern void fillRelOptions(void *rdopts, Size basesize,
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index b80d8d8..a3654a2 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.h
@@ -87,7 +87,8 @@ extern List *heap_truncate_find_FKs(List *relationIds);
 
 extern void InsertPgAttributeTuple(Relation pg_attribute_rel,
 					   Form_pg_attribute new_attribute,
-					   CatalogIndexState indstate);
+					   CatalogIndexState indstate,
+					   Datum attoptions);
 
 extern void InsertPgClassTuple(Relation pg_class_desc,
 				   Relation new_rel_desc,
diff --git a/src/include/catalog/pg_index.h b/src/include/catalog/pg_index.h
index ee97c5d..1540748 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 */
+
 #endif
 } FormData_pg_index;
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index ee4e189..6af4b39 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -40,6 +40,7 @@
  *		ExpressionsState	exec state for expressions, or NIL if none
  *		Predicate			partial-index predicate, or NIL if none
  *		PredicateState		exec state for predicate, or NIL if none
+ *		AttOptions			FIXME
  *		ExclusionOps		Per-column exclusion operators, or NULL if none
  *		ExclusionProcs		Underlying function OIDs for ExclusionOps
  *		ExclusionStrats		Opclass strategy numbers for ExclusionOps
@@ -64,6 +65,7 @@ typedef struct IndexInfo
 	List	   *ii_ExpressionsState;	/* list of ExprState */
 	List	   *ii_Predicate;	/* list of Expr */
 	List	   *ii_PredicateState;		/* list of ExprState */
+	Datum	   *ii_AttOptions;			/* array of attrubute options */
 	Oid		   *ii_ExclusionOps;	/* array with one entry per column */
 	Oid		   *ii_ExclusionProcs;		/* array with one entry per column */
 	uint16	   *ii_ExclusionStrats;		/* array with one entry per column */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 714cf15..fe5c68b 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -638,6 +638,7 @@ typedef struct IndexElem
 	List	   *opclass;		/* name of desired opclass; NIL = default */
 	SortByDir	ordering;		/* ASC/DESC/default */
 	SortByNulls nulls_ordering; /* FIRST/LAST/default */
+	List	   *options;		/* WITH OPTIONS clause options: a list of DefElem */
 } IndexElem;
 
 /*
diff --git a/src/include/utils/attoptcache.h b/src/include/utils/attoptcache.h
index cf8ead0..4411238 100644
--- a/src/include/utils/attoptcache.h
+++ b/src/include/utils/attoptcache.h
@@ -23,6 +23,7 @@ typedef struct AttributeOpts
 	float8		n_distinct_inherited;
 } AttributeOpts;
 
-AttributeOpts *get_attribute_options(Oid spcid, int attnum);
+AttributeOpts *get_attribute_options(char relkind, Oid spcid, int attnum);
+bytea **get_index_attribute_options(Relation index);
 
 #endif   /* ATTOPTCACHE_H */
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index a0ba417..314a267 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -146,6 +146,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_attoptions;	/* FIXME */
 
 	/*
 	 * foreign-table support
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to