Alvaro Herrera wrote:
> Euler Taveira de Oliveira wrote:
> > Alvaro Herrera escreveu:
> > > I wasn't sure of the best place to add a check.  I have added it to
> > > transformRelOptions; I am not entirely comfortable with it, because it
> > > works, but it still allows this:
> > > 
> > IMHO it's the appropriate place.
> 
> I think the best place would be parseRelOptions.  The problem is that
> transformRelOptions does not apply any semantics to the values it's
> parsing; it doesn't know about the relopt_kind for example.  That stuff
> is only known by parseRelOptions, but when the options reach that point,
> they have already lost the namespace (due to transformRelOptions).

Okay, so I've changed things so that the transformRelOptions' caller is
now in charge of passing an array of valid option namespaces.  This is
working A-OK.  I'm now going to figure out appropriate pg_dump support
and commit as soon as possible.

-- 
Alvaro Herrera                        http://www.advogato.org/person/alvherre
"No es bueno caminar con un hombre muerto"
Index: src/backend/access/common/reloptions.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/access/common/reloptions.c,v
retrieving revision 1.19
diff -c -p -r1.19 reloptions.c
*** src/backend/access/common/reloptions.c	26 Jan 2009 19:41:06 -0000	1.19
--- src/backend/access/common/reloptions.c	29 Jan 2009 18:01:12 -0000
***************
*** 390,397 ****
  }
  
  /*
!  * Transform a relation options list (list of DefElem) into the text array
!  * format that is kept in pg_class.reloptions.
   *
   * This is used for three cases: CREATE TABLE/INDEX, ALTER TABLE SET, and
   * ALTER TABLE RESET.  In the ALTER cases, oldOptions is the existing
--- 390,399 ----
  }
  
  /*
!  * Transform a relation options list (list of ReloptElem) into the text array
!  * format that is kept in pg_class.reloptions, including only those options
!  * that are in the passed namespace.  The output values do not include the
!  * namespace.
   *
   * This is used for three cases: CREATE TABLE/INDEX, ALTER TABLE SET, and
   * ALTER TABLE RESET.  In the ALTER cases, oldOptions is the existing
***************
*** 402,415 ****
   * in the list (it will be or has been handled by interpretOidsOption()).
   *
   * Note that this is not responsible for determining whether the options
!  * are valid.
   *
   * Both oldOptions and the result are text arrays (or NULL for "default"),
   * but we declare them as Datums to avoid including array.h in reloptions.h.
   */
  Datum
! transformRelOptions(Datum oldOptions, List *defList,
! 					bool ignoreOids, bool isReset)
  {
  	Datum		result;
  	ArrayBuildState *astate;
--- 404,420 ----
   * in the list (it will be or has been handled by interpretOidsOption()).
   *
   * Note that this is not responsible for determining whether the options
!  * are valid, but it does check that namespaces for all the options given are
!  * listed in validnsps.  The NULL namespace is always valid and needs not be
!  * explicitely listed.  Passing a NULL pointer means that only the NULL
!  * namespace is valid.
   *
   * Both oldOptions and the result are text arrays (or NULL for "default"),
   * but we declare them as Datums to avoid including array.h in reloptions.h.
   */
  Datum
! transformRelOptions(Datum oldOptions, List *defList, char *namspace,
! 					char *validnsps[], bool ignoreOids, bool isReset)
  {
  	Datum		result;
  	ArrayBuildState *astate;
***************
*** 444,454 ****
  			/* Search for a match in defList */
  			foreach(cell, defList)
  			{
! 				DefElem    *def = lfirst(cell);
! 				int			kw_len = strlen(def->defname);
  
  				if (text_len > kw_len && text_str[kw_len] == '=' &&
! 					pg_strncasecmp(text_str, def->defname, kw_len) == 0)
  					break;
  			}
  			if (!cell)
--- 449,471 ----
  			/* Search for a match in defList */
  			foreach(cell, defList)
  			{
! 				ReloptElem *def = lfirst(cell);
! 				int			kw_len;
  
+ 				/* ignore if not in the same namespace */
+ 				if (namspace == NULL)
+ 				{
+ 					if (def->nmspc != NULL)
+ 						continue;
+ 				}
+ 				else if (def->nmspc == NULL)
+ 					continue;
+ 				else if (pg_strcasecmp(def->nmspc, namspace) != 0)
+ 					continue;
+ 
+ 				kw_len = strlen(def->optname);
  				if (text_len > kw_len && text_str[kw_len] == '=' &&
! 					pg_strncasecmp(text_str, def->optname, kw_len) == 0)
  					break;
  			}
  			if (!cell)
***************
*** 468,474 ****
  	 */
  	foreach(cell, defList)
  	{
! 		DefElem    *def = lfirst(cell);
  
  		if (isReset)
  		{
--- 485,492 ----
  	 */
  	foreach(cell, defList)
  	{
! 		ReloptElem    *def = lfirst(cell);
! 
  
  		if (isReset)
  		{
***************
*** 483,504 ****
  			const char *value;
  			Size		len;
  
! 			if (ignoreOids && pg_strcasecmp(def->defname, "oids") == 0)
  				continue;
  
  			/*
! 			 * Flatten the DefElem into a text string like "name=arg". If we
! 			 * have just "name", assume "name=true" is meant.
  			 */
  			if (def->arg != NULL)
! 				value = defGetString(def);
  			else
  				value = "true";
! 			len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
  			/* +1 leaves room for sprintf's trailing null */
  			t = (text *) palloc(len + 1);
  			SET_VARSIZE(t, len);
! 			sprintf(VARDATA(t), "%s=%s", def->defname, value);
  
  			astate = accumArrayResult(astate, PointerGetDatum(t),
  									  false, TEXTOID,
--- 501,562 ----
  			const char *value;
  			Size		len;
  
! 			/*
! 			 * Error out if the namespace is not valid.  A NULL namespace
! 			 * is always valid.
! 			 */
! 			if (def->nmspc != NULL)
! 			{
! 				bool	valid = false;
! 				int		i;
! 
! 				if (validnsps)
! 				{
! 					for (i = 0; validnsps[i]; i++)
! 					{
! 						if (pg_strcasecmp(def->nmspc, validnsps[i]) == 0)
! 						{
! 							valid = true;
! 							break;
! 						}
! 					}
! 				}
! 
! 				if (!valid)
! 					ereport(ERROR,
! 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
! 							 errmsg("unrecognized parameter namespace \"%s\"",
! 									def->nmspc)));
! 			}
! 
! 			if (ignoreOids && pg_strcasecmp(def->optname, "oids") == 0)
! 				continue;
! 
! 			/* ignore if not in the same namespace */
! 			if (namspace == NULL)
! 			{
! 				if (def->nmspc != NULL)
! 					continue;
! 			}
! 			else if (def->nmspc == NULL)
! 				continue;
! 			else if (pg_strcasecmp(def->nmspc, namspace) != 0)
  				continue;
  
  			/*
! 			 * Flatten the ReloptElem into a text string like "name=arg". If we
! 			 * have just "name", assume "name=true" is meant.  Note: the
! 			 * namespace is not output.
  			 */
  			if (def->arg != NULL)
! 				value = reloptGetString(def);
  			else
  				value = "true";
! 			len = VARHDRSZ + strlen(def->optname) + 1 + strlen(value);
  			/* +1 leaves room for sprintf's trailing null */
  			t = (text *) palloc(len + 1);
  			SET_VARSIZE(t, len);
! 			sprintf(VARDATA(t), "%s=%s", def->optname, value);
  
  			astate = accumArrayResult(astate, PointerGetDatum(t),
  									  false, TEXTOID,
***************
*** 944,950 ****
  }
  
  /*
!  * Parse options for heaps (and perhaps someday toast tables).
   */
  bytea *
  heap_reloptions(char relkind, Datum reloptions, bool validate)
--- 1002,1008 ----
  }
  
  /*
!  * Parse options for heaps and toast tables.
   */
  bytea *
  heap_reloptions(char relkind, Datum reloptions, bool validate)
Index: src/backend/catalog/toasting.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/toasting.c,v
retrieving revision 1.12
diff -c -p -r1.12 toasting.c
*** src/backend/catalog/toasting.c	1 Jan 2009 17:23:37 -0000	1.12
--- src/backend/catalog/toasting.c	29 Jan 2009 16:46:45 -0000
***************
*** 32,38 ****
  #include "utils/syscache.h"
  
  
! static bool create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid);
  static bool needs_toast_table(Relation rel);
  
  
--- 32,39 ----
  #include "utils/syscache.h"
  
  
! static bool create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
! 				   Datum reloptions);
  static bool needs_toast_table(Relation rel);
  
  
***************
*** 46,52 ****
   * to end with CommandCounterIncrement if it makes any changes.
   */
  void
! AlterTableCreateToastTable(Oid relOid)
  {
  	Relation	rel;
  
--- 47,53 ----
   * to end with CommandCounterIncrement if it makes any changes.
   */
  void
! AlterTableCreateToastTable(Oid relOid, Datum reloptions)
  {
  	Relation	rel;
  
***************
*** 58,64 ****
  	rel = heap_open(relOid, AccessExclusiveLock);
  
  	/* create_toast_table does all the work */
! 	(void) create_toast_table(rel, InvalidOid, InvalidOid);
  
  	heap_close(rel, NoLock);
  }
--- 59,65 ----
  	rel = heap_open(relOid, AccessExclusiveLock);
  
  	/* create_toast_table does all the work */
! 	(void) create_toast_table(rel, InvalidOid, InvalidOid, reloptions);
  
  	heap_close(rel, NoLock);
  }
***************
*** 84,90 ****
  						relName)));
  
  	/* create_toast_table does all the work */
! 	if (!create_toast_table(rel, toastOid, toastIndexOid))
  		elog(ERROR, "\"%s\" does not require a toast table",
  			 relName);
  
--- 85,91 ----
  						relName)));
  
  	/* create_toast_table does all the work */
! 	if (!create_toast_table(rel, toastOid, toastIndexOid, (Datum) 0))
  		elog(ERROR, "\"%s\" does not require a toast table",
  			 relName);
  
***************
*** 100,106 ****
   * bootstrap they can be nonzero to specify hand-assigned OIDs
   */
  static bool
! create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid)
  {
  	Oid			relOid = RelationGetRelid(rel);
  	HeapTuple	reltup;
--- 101,107 ----
   * bootstrap they can be nonzero to specify hand-assigned OIDs
   */
  static bool
! create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptions)
  {
  	Oid			relOid = RelationGetRelid(rel);
  	HeapTuple	reltup;
***************
*** 183,192 ****
  	else
  		namespaceid = PG_TOAST_NAMESPACE;
  
- 	/*
- 	 * XXX would it make sense to apply the master's reloptions to the toast
- 	 * table?  Or maybe some toast-specific reloptions?
- 	 */
  	toast_relid = heap_create_with_catalog(toast_relname,
  										   namespaceid,
  										   rel->rd_rel->reltablespace,
--- 184,189 ----
***************
*** 199,205 ****
  										   true,
  										   0,
  										   ONCOMMIT_NOOP,
! 										   (Datum) 0,
  										   true);
  
  	/* make the toast relation visible, else index creation will fail */
--- 196,202 ----
  										   true,
  										   0,
  										   ONCOMMIT_NOOP,
! 										   reloptions,
  										   true);
  
  	/* make the toast relation visible, else index creation will fail */
Index: src/backend/commands/cluster.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/cluster.c,v
retrieving revision 1.181
diff -c -p -r1.181 cluster.c
*** src/backend/commands/cluster.c	16 Jan 2009 13:27:23 -0000	1.181
--- src/backend/commands/cluster.c	29 Jan 2009 16:46:45 -0000
***************
*** 668,673 ****
--- 668,674 ----
  	TupleDesc	OldHeapDesc,
  				tupdesc;
  	Oid			OIDNewHeap;
+ 	Oid			toastid;
  	Relation	OldHeap;
  	HeapTuple	tuple;
  	Datum		reloptions;
***************
*** 726,732 ****
  	 * AlterTableCreateToastTable ends with CommandCounterIncrement(), so that
  	 * the TOAST table will be visible for insertion.
  	 */
! 	AlterTableCreateToastTable(OIDNewHeap);
  
  	heap_close(OldHeap, NoLock);
  
--- 727,750 ----
  	 * AlterTableCreateToastTable ends with CommandCounterIncrement(), so that
  	 * the TOAST table will be visible for insertion.
  	 */
! 	toastid = OldHeap->rd_rel->reltoastrelid;
! 	reloptions = (Datum) 0;
! 	if (OidIsValid(toastid))
! 	{
! 		tuple = SearchSysCache(RELOID,
! 							   ObjectIdGetDatum(toastid),
! 							   0, 0, 0);
! 		if (!HeapTupleIsValid(tuple))
! 			elog(ERROR, "cache lookup failed for relation %u", toastid);
! 		reloptions = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
! 									 &isNull);
! 		if (isNull)
! 			reloptions = (Datum) 0;
! 	}
! 	AlterTableCreateToastTable(OIDNewHeap, reloptions);
! 
! 	if (OidIsValid(toastid))
! 		ReleaseSysCache(tuple);
  
  	heap_close(OldHeap, NoLock);
  
Index: src/backend/commands/define.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/define.c,v
retrieving revision 1.102
diff -c -p -r1.102 define.c
*** src/backend/commands/define.c	1 Jan 2009 17:23:37 -0000	1.102
--- src/backend/commands/define.c	29 Jan 2009 16:46:45 -0000
***************
*** 55,78 ****
  }
  
  
! /*
!  * Extract a string value (otherwise uninterpreted) from a DefElem.
!  */
! char *
! defGetString(DefElem *def)
  {
! 	if (def->arg == NULL)
  		ereport(ERROR,
  				(errcode(ERRCODE_SYNTAX_ERROR),
! 				 errmsg("%s requires a parameter",
! 						def->defname)));
! 	switch (nodeTag(def->arg))
  	{
  		case T_Integer:
  			{
  				char	   *str = palloc(32);
  
! 				snprintf(str, 32, "%ld", (long) intVal(def->arg));
  				return str;
  			}
  		case T_Float:
--- 55,74 ----
  }
  
  
! static char *
! nodeGetString(Node *value, char *name)
  {
! 	if (value == NULL)
  		ereport(ERROR,
  				(errcode(ERRCODE_SYNTAX_ERROR),
! 				 errmsg("%s requires a parameter", name)));
! 	switch (nodeTag(value))
  	{
  		case T_Integer:
  			{
  				char	   *str = palloc(32);
  
! 				snprintf(str, 32, "%ld", (long) intVal(value));
  				return str;
  			}
  		case T_Float:
***************
*** 81,100 ****
  			 * T_Float values are kept in string form, so this type cheat
  			 * works (and doesn't risk losing precision)
  			 */
! 			return strVal(def->arg);
  		case T_String:
! 			return strVal(def->arg);
  		case T_TypeName:
! 			return TypeNameToString((TypeName *) def->arg);
  		case T_List:
! 			return NameListToString((List *) def->arg);
  		default:
! 			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
  	}
  	return NULL;				/* keep compiler quiet */
  }
  
  /*
   * Extract a numeric value (actually double) from a DefElem.
   */
  double
--- 77,105 ----
  			 * T_Float values are kept in string form, so this type cheat
  			 * works (and doesn't risk losing precision)
  			 */
! 			return strVal(value);
  		case T_String:
! 			return strVal(value);
  		case T_TypeName:
! 			return TypeNameToString((TypeName *) value);
  		case T_List:
! 			return NameListToString((List *) value);
  		default:
! 			elog(ERROR, "unrecognized node type: %d", (int) nodeTag(value));
  	}
  	return NULL;				/* keep compiler quiet */
  }
  
  /*
+  * Extract a string value (otherwise uninterpreted) from a DefElem.
+  */
+ char *
+ defGetString(DefElem *def)
+ {
+ 	return nodeGetString(def->arg, def->defname);
+ }
+ 
+ /*
   * Extract a numeric value (actually double) from a DefElem.
   */
  double
***************
*** 120,144 ****
  	return 0;					/* keep compiler quiet */
  }
  
! /*
!  * Extract a boolean value from a DefElem.
!  */
! bool
! defGetBoolean(DefElem *def)
  {
  	/*
  	 * If no parameter given, assume "true" is meant.
  	 */
! 	if (def->arg == NULL)
  		return true;
  
  	/*
  	 * Allow 0, 1, "true", "false"
  	 */
! 	switch (nodeTag(def->arg))
  	{
  		case T_Integer:
! 			switch (intVal(def->arg))
  			{
  				case 0:
  					return false;
--- 125,146 ----
  	return 0;					/* keep compiler quiet */
  }
  
! static bool
! nodeGetBoolean(Node *value, char *name)
  {
  	/*
  	 * If no parameter given, assume "true" is meant.
  	 */
! 	if (value == NULL)
  		return true;
  
  	/*
  	 * Allow 0, 1, "true", "false"
  	 */
! 	switch (nodeTag(value))
  	{
  		case T_Integer:
! 			switch (intVal(value))
  			{
  				case 0:
  					return false;
***************
*** 151,157 ****
  			break;
  		default:
  			{
! 				char	   *sval = defGetString(def);
  
  				if (pg_strcasecmp(sval, "true") == 0)
  					return true;
--- 153,159 ----
  			break;
  		default:
  			{
! 				char	   *sval = nodeGetString(value, name);
  
  				if (pg_strcasecmp(sval, "true") == 0)
  					return true;
***************
*** 163,174 ****
  	}
  	ereport(ERROR,
  			(errcode(ERRCODE_SYNTAX_ERROR),
! 			 errmsg("%s requires a Boolean value",
! 					def->defname)));
  	return false;				/* keep compiler quiet */
  }
  
  /*
   * Extract an int64 value from a DefElem.
   */
  int64
--- 165,184 ----
  	}
  	ereport(ERROR,
  			(errcode(ERRCODE_SYNTAX_ERROR),
! 			 errmsg("%s requires a Boolean value", name)));
  	return false;				/* keep compiler quiet */
  }
  
  /*
+  * Extract a boolean value from a DefElem.
+  */
+ bool
+ defGetBoolean(DefElem *def)
+ {
+ 	return nodeGetBoolean(def->arg, def->defname);
+ }
+ 
+ /*
   * Extract an int64 value from a DefElem.
   */
  int64
***************
*** 305,319 ****
  	return 0;					/* keep compiler quiet */
  }
  
  /*
!  * Create a DefElem setting "oids" to the specified value.
   */
! DefElem *
! defWithOids(bool value)
  {
! 	DefElem    *f = makeNode(DefElem);
  
! 	f->defname = "oids";
  	f->arg = (Node *) makeInteger(value);
  	return f;
  }
--- 315,349 ----
  	return 0;					/* keep compiler quiet */
  }
  
+ 
+ /*
+  * Extract a string value (otherwise uninterpreted) from a ReloptElem.
+  */
+ char *
+ reloptGetString(ReloptElem *relopt)
+ {
+ 	return nodeGetString(relopt->arg, relopt->optname);
+ }
+ 
+ /*
+  * Extract a boolean value from a ReloptElem.
+  */
+ bool
+ reloptGetBoolean(ReloptElem *relopt)
+ {
+ 	return nodeGetBoolean(relopt->arg, relopt->optname);
+ }
+ 
  /*
!  * Create a ReloptElem setting "oids" to the specified value.
   */
! ReloptElem *
! reloptWithOids(bool value)
  {
! 	ReloptElem    *f = makeNode(ReloptElem);
  
! 	f->optname = "oids";
! 	f->nmspc = NULL;
  	f->arg = (Node *) makeInteger(value);
  	return f;
  }
Index: src/backend/commands/indexcmds.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/indexcmds.c,v
retrieving revision 1.181
diff -c -p -r1.181 indexcmds.c
*** src/backend/commands/indexcmds.c	1 Jan 2009 17:23:38 -0000	1.181
--- src/backend/commands/indexcmds.c	29 Jan 2009 17:38:56 -0000
***************
*** 398,404 ****
  	/*
  	 * Parse AM-specific options, convert to text array form, validate.
  	 */
! 	reloptions = transformRelOptions((Datum) 0, options, false, false);
  
  	(void) index_reloptions(amoptions, reloptions, true);
  
--- 398,404 ----
  	/*
  	 * Parse AM-specific options, convert to text array form, validate.
  	 */
! 	reloptions = transformRelOptions((Datum) 0, options, NULL, NULL, false, false);
  
  	(void) index_reloptions(amoptions, reloptions, true);
  
Index: src/backend/commands/sequence.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/sequence.c,v
retrieving revision 1.157
diff -c -p -r1.157 sequence.c
*** src/backend/commands/sequence.c	20 Jan 2009 18:59:37 -0000	1.157
--- src/backend/commands/sequence.c	29 Jan 2009 16:46:45 -0000
***************
*** 198,204 ****
  	stmt->relation = seq->sequence;
  	stmt->inhRelations = NIL;
  	stmt->constraints = NIL;
! 	stmt->options = list_make1(defWithOids(false));
  	stmt->oncommit = ONCOMMIT_NOOP;
  	stmt->tablespacename = NULL;
  
--- 198,204 ----
  	stmt->relation = seq->sequence;
  	stmt->inhRelations = NIL;
  	stmt->constraints = NIL;
! 	stmt->options = list_make1(reloptWithOids(false));
  	stmt->oncommit = ONCOMMIT_NOOP;
  	stmt->tablespacename = NULL;
  
Index: src/backend/commands/tablecmds.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.278
diff -c -p -r1.278 tablecmds.c
*** src/backend/commands/tablecmds.c	22 Jan 2009 20:16:02 -0000	1.278
--- src/backend/commands/tablecmds.c	29 Jan 2009 17:48:02 -0000
***************
*** 351,356 ****
--- 351,357 ----
  	Datum		reloptions;
  	ListCell   *listptr;
  	AttrNumber	attnum;
+ 	char	   *validnsps[] = { "toast" };
  
  	/*
  	 * Truncate relname to appropriate length (probably a waste of time, as
***************
*** 418,424 ****
  	/*
  	 * Parse and validate reloptions, if any.
  	 */
! 	reloptions = transformRelOptions((Datum) 0, stmt->options, true, false);
  
  	(void) heap_reloptions(relkind, reloptions, true);
  
--- 419,426 ----
  	/*
  	 * Parse and validate reloptions, if any.
  	 */
! 	reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
! 									 true, false);
  
  	(void) heap_reloptions(relkind, reloptions, true);
  
***************
*** 2572,2578 ****
  			(tab->subcmds[AT_PASS_ADD_COL] ||
  			 tab->subcmds[AT_PASS_ALTER_TYPE] ||
  			 tab->subcmds[AT_PASS_COL_ATTRS]))
! 			AlterTableCreateToastTable(tab->relid);
  	}
  }
  
--- 2574,2580 ----
  			(tab->subcmds[AT_PASS_ADD_COL] ||
  			 tab->subcmds[AT_PASS_ALTER_TYPE] ||
  			 tab->subcmds[AT_PASS_COL_ATTRS]))
! 			AlterTableCreateToastTable(tab->relid, (Datum) 0);
  	}
  }
  
***************
*** 6457,6462 ****
--- 6459,6465 ----
  	Datum		repl_val[Natts_pg_class];
  	bool		repl_null[Natts_pg_class];
  	bool		repl_repl[Natts_pg_class];
+ 	char	   *validnsps[] = { "toast" };
  
  	if (defList == NIL)
  		return;					/* nothing to do */
***************
*** 6475,6481 ****
  
  	/* Generate new proposed reloptions (text array) */
  	newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
! 									 defList, false, isReset);
  
  	/* Validate */
  	switch (rel->rd_rel->relkind)
--- 6478,6484 ----
  
  	/* Generate new proposed reloptions (text array) */
  	newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
! 									 defList, NULL, validnsps, false, isReset);
  
  	/* Validate */
  	switch (rel->rd_rel->relkind)
***************
*** 6521,6526 ****
--- 6524,6576 ----
  
  	ReleaseSysCache(tuple);
  
+ 	/* repeat the whole exercise for the toast table, if there's one */
+ 	if (OidIsValid(rel->rd_rel->reltoastrelid))
+ 	{
+ 		Relation	toastrel;
+ 		Oid			toastid = rel->rd_rel->reltoastrelid;
+ 
+ 		toastrel = heap_open(toastid, AccessExclusiveLock);
+ 
+ 		/* Get the old reloptions */
+ 		tuple = SearchSysCache(RELOID,
+ 							   ObjectIdGetDatum(toastid),
+ 							   0, 0, 0);
+ 		if (!HeapTupleIsValid(tuple))
+ 			elog(ERROR, "cache lookup failed for relation %u", toastid);
+ 
+ 		datum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions, &isnull);
+ 
+ 		newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
+ 										 defList, "toast", validnsps, false, isReset);
+ 
+ 		(void) heap_reloptions(RELKIND_TOASTVALUE, newOptions, true);
+ 
+ 		memset(repl_val, 0, sizeof(repl_val));
+ 		memset(repl_null, false, sizeof(repl_null));
+ 		memset(repl_repl, false, sizeof(repl_repl));
+ 
+ 		if (newOptions != (Datum) 0)
+ 			repl_val[Anum_pg_class_reloptions - 1] = newOptions;
+ 		else
+ 			repl_null[Anum_pg_class_reloptions - 1] = true;
+ 
+ 		repl_repl[Anum_pg_class_reloptions - 1] = true;
+ 
+ 		newtuple = heap_modify_tuple(tuple, RelationGetDescr(pgclass),
+ 									 repl_val, repl_null, repl_repl);
+ 
+ 		simple_heap_update(pgclass, &newtuple->t_self, newtuple);
+ 
+ 		CatalogUpdateIndexes(pgclass, newtuple);
+ 
+ 		heap_freetuple(newtuple);
+ 
+ 		ReleaseSysCache(tuple);
+ 
+ 		heap_close(toastrel, NoLock);
+ 	}
+ 
  	heap_close(pgclass, RowExclusiveLock);
  }
  
Index: src/backend/commands/typecmds.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/typecmds.c,v
retrieving revision 1.130
diff -c -p -r1.130 typecmds.c
*** src/backend/commands/typecmds.c	9 Jan 2009 15:46:10 -0000	1.130
--- src/backend/commands/typecmds.c	29 Jan 2009 16:46:45 -0000
***************
*** 1491,1497 ****
  	createStmt->tableElts = coldeflist;
  	createStmt->inhRelations = NIL;
  	createStmt->constraints = NIL;
! 	createStmt->options = list_make1(defWithOids(false));
  	createStmt->oncommit = ONCOMMIT_NOOP;
  	createStmt->tablespacename = NULL;
  
--- 1491,1497 ----
  	createStmt->tableElts = coldeflist;
  	createStmt->inhRelations = NIL;
  	createStmt->constraints = NIL;
! 	createStmt->options = list_make1(reloptWithOids(false));
  	createStmt->oncommit = ONCOMMIT_NOOP;
  	createStmt->tablespacename = NULL;
  
Index: src/backend/commands/view.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/view.c,v
retrieving revision 1.113
diff -c -p -r1.113 view.c
*** src/backend/commands/view.c	27 Jan 2009 12:40:15 -0000	1.113
--- src/backend/commands/view.c	29 Jan 2009 16:46:45 -0000
***************
*** 229,235 ****
  		createStmt->tableElts = attrList;
  		createStmt->inhRelations = NIL;
  		createStmt->constraints = NIL;
! 		createStmt->options = list_make1(defWithOids(false));
  		createStmt->oncommit = ONCOMMIT_NOOP;
  		createStmt->tablespacename = NULL;
  
--- 229,235 ----
  		createStmt->tableElts = attrList;
  		createStmt->inhRelations = NIL;
  		createStmt->constraints = NIL;
! 		createStmt->options = list_make1(reloptWithOids(false));
  		createStmt->oncommit = ONCOMMIT_NOOP;
  		createStmt->tablespacename = NULL;
  
Index: src/backend/executor/execMain.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/executor/execMain.c,v
retrieving revision 1.321
diff -c -p -r1.321 execMain.c
*** src/backend/executor/execMain.c	22 Jan 2009 20:16:03 -0000	1.321
--- src/backend/executor/execMain.c	29 Jan 2009 17:40:15 -0000
***************
*** 2832,2837 ****
--- 2832,2838 ----
  	Oid			intoRelationId;
  	TupleDesc	tupdesc;
  	DR_intorel *myState;
+ 	char	   *validnsps[] = { "toast" };
  
  	Assert(into);
  
***************
*** 2890,2895 ****
--- 2891,2898 ----
  	/* Parse and validate any reloptions */
  	reloptions = transformRelOptions((Datum) 0,
  									 into->options,
+ 									 NULL,
+ 									 validnsps,
  									 true,
  									 false);
  	(void) heap_reloptions(RELKIND_RELATION, reloptions, true);
***************
*** 2926,2932 ****
  	 * AlterTableCreateToastTable ends with CommandCounterIncrement(), so that
  	 * the TOAST table will be visible for insertion.
  	 */
! 	AlterTableCreateToastTable(intoRelationId);
  
  	/*
  	 * And open the constructed table for writing.
--- 2929,2944 ----
  	 * AlterTableCreateToastTable ends with CommandCounterIncrement(), so that
  	 * the TOAST table will be visible for insertion.
  	 */
! 	reloptions = transformRelOptions((Datum) 0,
! 									 into->options,
! 									 "toast",
! 									 validnsps,
! 									 true,
! 									 false);
! 
! 	(void) heap_reloptions(RELKIND_TOASTVALUE, reloptions, true);
! 
! 	AlterTableCreateToastTable(intoRelationId, reloptions);
  
  	/*
  	 * And open the constructed table for writing.
Index: src/backend/nodes/copyfuncs.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.421
diff -c -p -r1.421 copyfuncs.c
*** src/backend/nodes/copyfuncs.c	22 Jan 2009 20:16:03 -0000	1.421
--- src/backend/nodes/copyfuncs.c	29 Jan 2009 16:46:45 -0000
***************
*** 2125,2130 ****
--- 2125,2142 ----
  	return newnode;
  }
  
+ static ReloptElem *
+ _copyReloptElem(ReloptElem *from)
+ {
+ 	ReloptElem	   *newnode = makeNode(ReloptElem);
+ 
+ 	COPY_STRING_FIELD(optname);
+ 	COPY_STRING_FIELD(nmspc);
+ 	COPY_NODE_FIELD(arg);
+ 
+ 	return newnode;
+ }
+ 
  static LockingClause *
  _copyLockingClause(LockingClause *from)
  {
***************
*** 4079,4084 ****
--- 4091,4099 ----
  		case T_OptionDefElem:
  			retval = _copyOptionDefElem(from);
  			break;
+ 		case T_ReloptElem:
+ 			retval = _copyReloptElem(from);
+ 			break;
  		case T_LockingClause:
  			retval = _copyLockingClause(from);
  			break;
Index: src/backend/nodes/equalfuncs.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/nodes/equalfuncs.c,v
retrieving revision 1.346
diff -c -p -r1.346 equalfuncs.c
*** src/backend/nodes/equalfuncs.c	22 Jan 2009 20:16:03 -0000	1.346
--- src/backend/nodes/equalfuncs.c	29 Jan 2009 16:46:45 -0000
***************
*** 2099,2104 ****
--- 2099,2114 ----
  }
  
  static bool
+ _equalReloptElem(ReloptElem *a, ReloptElem *b)
+ {
+ 	COMPARE_STRING_FIELD(nmspc);
+ 	COMPARE_STRING_FIELD(optname);
+ 	COMPARE_NODE_FIELD(arg);
+ 
+ 	return true;
+ }
+ 
+ static bool
  _equalLockingClause(LockingClause *a, LockingClause *b)
  {
  	COMPARE_NODE_FIELD(lockedRels);
***************
*** 2855,2860 ****
--- 2865,2873 ----
  		case T_OptionDefElem:
  			retval = _equalOptionDefElem(a, b);
  			break;
+ 		case T_ReloptElem:
+ 			retval = _equalReloptElem(a, b);
+ 			break;
  		case T_LockingClause:
  			retval = _equalLockingClause(a, b);
  			break;
Index: src/backend/nodes/makefuncs.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/nodes/makefuncs.c,v
retrieving revision 1.62
diff -c -p -r1.62 makefuncs.c
*** src/backend/nodes/makefuncs.c	1 Jan 2009 17:23:43 -0000	1.62
--- src/backend/nodes/makefuncs.c	29 Jan 2009 16:46:45 -0000
***************
*** 374,376 ****
--- 374,387 ----
  	res->def = def;
  	return res;
  }
+ 
+ ReloptElem *
+ makeReloptElem(char *name, char *nmspc, Node *arg)
+ {
+ 	ReloptElem *res = makeNode(ReloptElem);
+ 
+ 	res->optname = name;
+ 	res->nmspc = nmspc;
+ 	res->arg = arg;
+ 	return res;
+ }
Index: src/backend/nodes/outfuncs.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/nodes/outfuncs.c,v
retrieving revision 1.350
diff -c -p -r1.350 outfuncs.c
*** src/backend/nodes/outfuncs.c	22 Jan 2009 20:16:04 -0000	1.350
--- src/backend/nodes/outfuncs.c	29 Jan 2009 16:46:45 -0000
***************
*** 1805,1810 ****
--- 1805,1820 ----
  }
  
  static void
+ _outReloptElem(StringInfo str, ReloptElem *node)
+ {
+ 	WRITE_NODE_TYPE("RELOPTELEM");
+ 
+ 	WRITE_STRING_FIELD(nmspc);
+ 	WRITE_STRING_FIELD(optname);
+ 	WRITE_NODE_FIELD(arg);
+ }
+ 
+ static void
  _outLockingClause(StringInfo str, LockingClause *node)
  {
  	WRITE_NODE_TYPE("LOCKINGCLAUSE");
***************
*** 2770,2775 ****
--- 2780,2788 ----
  			case T_DefElem:
  				_outDefElem(str, obj);
  				break;
+ 			case T_ReloptElem:
+ 				_outReloptElem(str, obj);
+ 				break;
  			case T_LockingClause:
  				_outLockingClause(str, obj);
  				break;
Index: src/backend/parser/gram.y
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.656
diff -c -p -r2.656 gram.y
*** src/backend/parser/gram.y	22 Jan 2009 20:16:05 -0000	2.656
--- src/backend/parser/gram.y	29 Jan 2009 18:44:23 -0000
***************
*** 164,169 ****
--- 164,170 ----
  	FuncWithArgs		*funwithargs;
  	DefElem				*defelt;
  	OptionDefElem		*optdef;
+ 	ReloptElem			*reloptel;
  	SortBy				*sortby;
  	WindowDef			*windef;
  	JoinExpr			*jexpr;
***************
*** 271,276 ****
--- 272,278 ----
  
  %type <list>	stmtblock stmtmulti
  				OptTableElementList TableElementList OptInherit definition
+ 				reloptions opt_reloptions
  				OptWith opt_distinct opt_definition func_args func_args_list
  				func_args_with_defaults func_args_with_defaults_list
  				func_as createfunc_opt_list alterfunc_opt_list
***************
*** 284,290 ****
  				target_list insert_column_list set_target_list
  				set_clause_list set_clause multiple_set_clause
  				ctext_expr_list ctext_row def_list indirection opt_indirection
! 				group_clause TriggerFuncArgs select_limit
  				opt_select_limit opclass_item_list opclass_drop_list
  				opt_opfamily transaction_mode_list_or_empty
  				TableFuncElementList opt_type_modifiers
--- 286,292 ----
  				target_list insert_column_list set_target_list
  				set_clause_list set_clause multiple_set_clause
  				ctext_expr_list ctext_row def_list indirection opt_indirection
! 				reloption_list group_clause TriggerFuncArgs select_limit
  				opt_select_limit opclass_item_list opclass_drop_list
  				opt_opfamily transaction_mode_list_or_empty
  				TableFuncElementList opt_type_modifiers
***************
*** 342,347 ****
--- 344,350 ----
  %type <node>	TableElement ConstraintElem TableFuncElement
  %type <node>	columnDef
  %type <defelt>	def_elem old_aggr_elem
+ %type <reloptel> reloption_elem
  %type <node>	def_arg columnElem where_clause where_or_current_clause
  				a_expr b_expr c_expr func_expr AexprConst indirection_el
  				columnref in_expr having_clause func_table array_expr
***************
*** 1781,1787 ****
  					$$ = (Node *)n;
  				}
  			/* ALTER TABLE <name> SET (...) */
! 			| SET definition
  				{
  					AlterTableCmd *n = makeNode(AlterTableCmd);
  					n->subtype = AT_SetRelOptions;
--- 1784,1790 ----
  					$$ = (Node *)n;
  				}
  			/* ALTER TABLE <name> SET (...) */
! 			| SET reloptions
  				{
  					AlterTableCmd *n = makeNode(AlterTableCmd);
  					n->subtype = AT_SetRelOptions;
***************
*** 1789,1795 ****
  					$$ = (Node *)n;
  				}
  			/* ALTER TABLE <name> RESET (...) */
! 			| RESET definition
  				{
  					AlterTableCmd *n = makeNode(AlterTableCmd);
  					n->subtype = AT_ResetRelOptions;
--- 1792,1798 ----
  					$$ = (Node *)n;
  				}
  			/* ALTER TABLE <name> RESET (...) */
! 			| RESET reloptions
  				{
  					AlterTableCmd *n = makeNode(AlterTableCmd);
  					n->subtype = AT_ResetRelOptions;
***************
*** 1814,1819 ****
--- 1817,1853 ----
  			| /* EMPTY */				{ $$ = NULL; }
  		;
  
+ reloptions:
+ 		  	'(' reloption_list ')'					{ $$ = $2; }
+ 		;
+ 
+ opt_reloptions:		WITH reloptions					{ $$ = $2; }
+ 			 |		/* EMPTY */						{ $$ = NIL; }
+ 		;
+ 
+ reloption_list:
+ 			reloption_elem							{ $$ = list_make1($1); }
+ 			| reloption_list ',' reloption_elem		{ $$ = lappend($1, $3); }
+ 		;
+ 
+ reloption_elem:	
+ 			ColLabel '=' def_arg
+ 				{
+ 					$$ = makeReloptElem($1, NULL, (Node *) $3);
+ 				}
+ 			| ColLabel
+ 				{
+ 					$$ = makeReloptElem($1, NULL, NULL);
+ 				}
+ 			| ColLabel '.' ColLabel '=' def_arg
+ 				{
+ 					$$ = makeReloptElem($3, $1, (Node *) $5);
+ 				}
+ 			| ColLabel '.' ColLabel
+ 				{
+ 					$$ = makeReloptElem($3, $1, NULL);
+ 				}
+ 		;
  
  
  /*****************************************************************************
***************
*** 2440,2448 ****
  
  /* WITH (options) is preferred, WITH OIDS and WITHOUT OIDS are legacy forms */
  OptWith:
! 			WITH definition				{ $$ = $2; }
! 			| WITH OIDS					{ $$ = list_make1(defWithOids(true)); }
! 			| WITHOUT OIDS				{ $$ = list_make1(defWithOids(false)); }
  			| /*EMPTY*/					{ $$ = NIL; }
  		;
  
--- 2474,2482 ----
  
  /* WITH (options) is preferred, WITH OIDS and WITHOUT OIDS are legacy forms */
  OptWith:
! 			WITH reloptions				{ $$ = $2; }
! 			| WITH OIDS					{ $$ = list_make1(reloptWithOids(true)); }
! 			| WITHOUT OIDS				{ $$ = list_make1(reloptWithOids(false)); }
  			| /*EMPTY*/					{ $$ = NIL; }
  		;
  
***************
*** 4473,4479 ****
  
  IndexStmt:	CREATE index_opt_unique INDEX index_name
  			ON qualified_name access_method_clause '(' index_params ')'
! 			opt_definition OptTableSpace where_clause
  				{
  					IndexStmt *n = makeNode(IndexStmt);
  					n->unique = $2;
--- 4507,4513 ----
  
  IndexStmt:	CREATE index_opt_unique INDEX index_name
  			ON qualified_name access_method_clause '(' index_params ')'
! 			opt_reloptions OptTableSpace where_clause
  				{
  					IndexStmt *n = makeNode(IndexStmt);
  					n->unique = $2;
***************
*** 4489,4495 ****
  				}
  			| CREATE index_opt_unique INDEX CONCURRENTLY index_name
  			ON qualified_name access_method_clause '(' index_params ')'
! 			opt_definition OptTableSpace where_clause
  				{
  					IndexStmt *n = makeNode(IndexStmt);
  					n->unique = $2;
--- 4523,4529 ----
  				}
  			| CREATE index_opt_unique INDEX CONCURRENTLY index_name
  			ON qualified_name access_method_clause '(' index_params ')'
! 			opt_reloptions OptTableSpace where_clause
  				{
  					IndexStmt *n = makeNode(IndexStmt);
  					n->unique = $2;
Index: src/backend/parser/parse_clause.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/parser/parse_clause.c,v
retrieving revision 1.186
diff -c -p -r1.186 parse_clause.c
*** src/backend/parser/parse_clause.c	22 Jan 2009 20:16:05 -0000	1.186
--- src/backend/parser/parse_clause.c	29 Jan 2009 16:46:45 -0000
***************
*** 233,239 ****
  }
  
  /*
!  * Given a relation-options list (of DefElems), return true iff the specified
   * table/result set should be created with OIDs. This needs to be done after
   * parsing the query string because the return value can depend upon the
   * default_with_oids GUC var.
--- 233,239 ----
  }
  
  /*
!  * Given a relation-options list (of ReloptElems), return true iff the specified
   * table/result set should be created with OIDs. This needs to be done after
   * parsing the query string because the return value can depend upon the
   * default_with_oids GUC var.
***************
*** 246,255 ****
  	/* Scan list to see if OIDS was included */
  	foreach(cell, defList)
  	{
! 		DefElem    *def = (DefElem *) lfirst(cell);
  
! 		if (pg_strcasecmp(def->defname, "oids") == 0)
! 			return defGetBoolean(def);
  	}
  
  	/* OIDS option was not specified, so use default. */
--- 246,255 ----
  	/* Scan list to see if OIDS was included */
  	foreach(cell, defList)
  	{
! 		ReloptElem    *def = (ReloptElem *) lfirst(cell);
  
! 		if (pg_strcasecmp(def->optname, "oids") == 0)
! 			return reloptGetBoolean(def);
  	}
  
  	/* OIDS option was not specified, so use default. */
Index: src/backend/tcop/utility.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/backend/tcop/utility.c,v
retrieving revision 1.305
diff -c -p -r1.305 utility.c
*** src/backend/tcop/utility.c	22 Jan 2009 20:16:06 -0000	1.305
--- src/backend/tcop/utility.c	29 Jan 2009 17:49:52 -0000
***************
*** 16,21 ****
--- 16,22 ----
   */
  #include "postgres.h"
  
+ #include "access/reloptions.h"
  #include "access/twophase.h"
  #include "access/xact.h"
  #include "catalog/catalog.h"
***************
*** 422,427 ****
--- 423,431 ----
  
  					if (IsA(stmt, CreateStmt))
  					{
+ 						Datum	toast_options;
+ 						char   *validnsps[] = { "toast" };
+ 
  						/* Create the table itself */
  						relOid = DefineRelation((CreateStmt *) stmt,
  												RELKIND_RELATION);
***************
*** 431,437 ****
  						 * needs a secondary relation too.
  						 */
  						CommandCounterIncrement();
! 						AlterTableCreateToastTable(relOid);
  					}
  					else
  					{
--- 435,451 ----
  						 * needs a secondary relation too.
  						 */
  						CommandCounterIncrement();
! 
! 						/* parse and validate reloptions for the toast table */
! 						toast_options = transformRelOptions((Datum) 0,
! 															((CreateStmt *)stmt)->options,
! 															"toast",
! 															validnsps,
! 															true, false);
! 						(void) heap_reloptions(RELKIND_TOASTVALUE, toast_options,
! 											   true);
! 
! 						AlterTableCreateToastTable(relOid, toast_options);
  					}
  					else
  					{
Index: src/include/access/reloptions.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/access/reloptions.h,v
retrieving revision 1.11
diff -c -p -r1.11 reloptions.h
*** src/include/access/reloptions.h	26 Jan 2009 19:41:06 -0000	1.11
--- src/include/access/reloptions.h	29 Jan 2009 17:38:30 -0000
***************
*** 240,245 ****
--- 240,246 ----
  					 char *default_val, validate_string_relopt validator);
  
  extern Datum transformRelOptions(Datum oldOptions, List *defList,
+ 					char *namspace, char *validnsps[],
  					bool ignoreOids, bool isReset);
  extern List *untransformRelOptions(Datum options);
  extern bytea *extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
Index: src/include/catalog/toasting.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/catalog/toasting.h,v
retrieving revision 1.5
diff -c -p -r1.5 toasting.h
*** src/include/catalog/toasting.h	1 Jan 2009 17:23:58 -0000	1.5
--- src/include/catalog/toasting.h	29 Jan 2009 16:46:45 -0000
***************
*** 17,23 ****
  /*
   * toasting.c prototypes
   */
! extern void AlterTableCreateToastTable(Oid relOid);
  extern void BootstrapToastTable(char *relName,
  					Oid toastOid, Oid toastIndexOid);
  
--- 17,23 ----
  /*
   * toasting.c prototypes
   */
! extern void AlterTableCreateToastTable(Oid relOid, Datum reloptions);
  extern void BootstrapToastTable(char *relName,
  					Oid toastOid, Oid toastIndexOid);
  
Index: src/include/commands/defrem.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/commands/defrem.h,v
retrieving revision 1.92
diff -c -p -r1.92 defrem.h
*** src/include/commands/defrem.h	1 Jan 2009 17:23:58 -0000	1.92
--- src/include/commands/defrem.h	29 Jan 2009 16:46:45 -0000
***************
*** 145,150 ****
  extern List *defGetQualifiedName(DefElem *def);
  extern TypeName *defGetTypeName(DefElem *def);
  extern int	defGetTypeLength(DefElem *def);
! extern DefElem *defWithOids(bool value);
  
  #endif   /* DEFREM_H */
--- 145,152 ----
  extern List *defGetQualifiedName(DefElem *def);
  extern TypeName *defGetTypeName(DefElem *def);
  extern int	defGetTypeLength(DefElem *def);
! extern char *reloptGetString(ReloptElem *relopt);
! extern bool reloptGetBoolean(ReloptElem *relopt);
! extern ReloptElem *reloptWithOids(bool value);
  
  #endif   /* DEFREM_H */
Index: src/include/nodes/makefuncs.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/nodes/makefuncs.h,v
retrieving revision 1.65
diff -c -p -r1.65 makefuncs.h
*** src/include/nodes/makefuncs.h	1 Jan 2009 17:24:00 -0000	1.65
--- src/include/nodes/makefuncs.h	29 Jan 2009 16:46:45 -0000
***************
*** 69,72 ****
--- 69,74 ----
  
  extern OptionDefElem *makeOptionDefElem(int op, DefElem *def);
  
+ extern ReloptElem *makeReloptElem(char *name, char *namspc, Node *arg);
+ 
  #endif   /* MAKEFUNC_H */
Index: src/include/nodes/nodes.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/nodes/nodes.h,v
retrieving revision 1.219
diff -c -p -r1.219 nodes.h
*** src/include/nodes/nodes.h	22 Jan 2009 20:16:09 -0000	1.219
--- src/include/nodes/nodes.h	29 Jan 2009 16:46:45 -0000
***************
*** 363,368 ****
--- 363,369 ----
  	T_Constraint,
  	T_DefElem,
  	T_OptionDefElem,
+ 	T_ReloptElem,
  	T_RangeTblEntry,
  	T_SortGroupClause,
  	T_WindowClause,
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.389
diff -c -p -r1.389 parsenodes.h
*** src/include/nodes/parsenodes.h	22 Jan 2009 20:16:09 -0000	1.389
--- src/include/nodes/parsenodes.h	29 Jan 2009 16:46:45 -0000
***************
*** 533,538 ****
--- 533,549 ----
  } OptionDefElem;
  
  /*
+  * Reloption definition.  As DefElem, with optional option namespace.
+  */
+ typedef struct ReloptElem
+ {
+ 	NodeTag		type;
+ 	char	   *nmspc;
+ 	char	   *optname;
+ 	Node	   *arg;
+ } ReloptElem;
+ 
+ /*
   * LockingClause - raw representation of FOR UPDATE/SHARE options
   *
   * Note: lockedRels == NIL means "all relations in query".	Otherwise it
Index: src/interfaces/Makefile
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/interfaces/Makefile,v
retrieving revision 1.56
diff -c -p -r1.56 Makefile
-- 
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