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	30 Jan 2009 19:42:38 -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/bin/pg_dump/pg_dump.c
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/bin/pg_dump/pg_dump.c,v
retrieving revision 1.517
diff -c -p -r1.517 pg_dump.c
*** src/bin/pg_dump/pg_dump.c	27 Jan 2009 12:40:15 -0000	1.517
--- src/bin/pg_dump/pg_dump.c	30 Jan 2009 19:31:36 -0000
***************
*** 3100,3105 ****
--- 3100,3106 ----
  	int			i_owning_col;
  	int			i_reltablespace;
  	int			i_reloptions;
+ 	int			i_toastreloptions;
  
  	/* Make sure we are in proper schema */
  	selectSourceSchema("pg_catalog");
***************
*** 3131,3152 ****
  		 * owning column, if any (note this dependency is AUTO as of 8.2)
  		 */
  		appendPQExpBuffer(query,
! 						  "SELECT c.tableoid, c.oid, relname, "
! 						  "relacl, relkind, relnamespace, "
! 						  "(%s relowner) as rolname, "
! 						  "relchecks, relhastriggers, "
! 						  "relhasindex, relhasrules, relhasoids, "
  						  "d.refobjid as owning_tab, "
  						  "d.refobjsubid as owning_col, "
  						  "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
! 						  "array_to_string(c.reloptions, ', ') as reloptions "
  						  "from pg_class c "
  						  "left join pg_depend d on "
  						  "(c.relkind = '%c' and "
  						  "d.classid = c.tableoid and d.objid = c.oid and "
  						  "d.objsubid = 0 and "
  						  "d.refclassid = c.tableoid and d.deptype = 'a') "
! 						  "where relkind in ('%c', '%c', '%c', '%c') "
  						  "order by c.oid",
  						  username_subquery,
  						  RELKIND_SEQUENCE,
--- 3132,3155 ----
  		 * owning column, if any (note this dependency is AUTO as of 8.2)
  		 */
  		appendPQExpBuffer(query,
! 						  "SELECT c.tableoid, c.oid, c.relname, "
! 						  "c.relacl, c.relkind, c.relnamespace, "
! 						  "(%s c.relowner) as rolname, "
! 						  "c.relchecks, c.relhastriggers, "
! 						  "c.relhasindex, c.relhasrules, c.relhasoids, "
  						  "d.refobjid as owning_tab, "
  						  "d.refobjsubid as owning_col, "
  						  "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
! 						  "array_to_string(c.reloptions, ', ') as reloptions, "
! 						  "array_to_string(array(select 'toast.' || x from unnest(tc.reloptions) x), ', ') as toast_reloptions "
  						  "from pg_class c "
  						  "left join pg_depend d on "
  						  "(c.relkind = '%c' and "
  						  "d.classid = c.tableoid and d.objid = c.oid and "
  						  "d.objsubid = 0 and "
  						  "d.refclassid = c.tableoid and d.deptype = 'a') "
! 						  "left join pg_class tc on (c.reltoastrelid = tc.oid) "
! 						  "where c.relkind in ('%c', '%c', '%c', '%c') "
  						  "order by c.oid",
  						  username_subquery,
  						  RELKIND_SEQUENCE,
***************
*** 3197,3203 ****
  						  "d.refobjid as owning_tab, "
  						  "d.refobjsubid as owning_col, "
  						  "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
! 						  "NULL as reloptions "
  						  "from pg_class c "
  						  "left join pg_depend d on "
  						  "(c.relkind = '%c' and "
--- 3200,3207 ----
  						  "d.refobjid as owning_tab, "
  						  "d.refobjsubid as owning_col, "
  						  "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
! 						  "NULL as reloptions, "
! 						  "NULL as toast_reloptions "
  						  "from pg_class c "
  						  "left join pg_depend d on "
  						  "(c.relkind = '%c' and "
***************
*** 3226,3232 ****
  						  "d.refobjid as owning_tab, "
  						  "d.refobjsubid as owning_col, "
  						  "NULL as reltablespace, "
! 						  "NULL as reloptions "
  						  "from pg_class c "
  						  "left join pg_depend d on "
  						  "(c.relkind = '%c' and "
--- 3230,3237 ----
  						  "d.refobjid as owning_tab, "
  						  "d.refobjsubid as owning_col, "
  						  "NULL as reltablespace, "
! 						  "NULL as reloptions, "
! 						  "NULL as toast_reloptions "
  						  "from pg_class c "
  						  "left join pg_depend d on "
  						  "(c.relkind = '%c' and "
***************
*** 3251,3257 ****
  						  "NULL::oid as owning_tab, "
  						  "NULL::int4 as owning_col, "
  						  "NULL as reltablespace, "
! 						  "NULL as reloptions "
  						  "from pg_class "
  						  "where relkind in ('%c', '%c', '%c') "
  						  "order by oid",
--- 3256,3263 ----
  						  "NULL::oid as owning_tab, "
  						  "NULL::int4 as owning_col, "
  						  "NULL as reltablespace, "
! 						  "NULL as reloptions, "
! 						  "NULL as toast_reloptions "
  						  "from pg_class "
  						  "where relkind in ('%c', '%c', '%c') "
  						  "order by oid",
***************
*** 3271,3277 ****
  						  "NULL::oid as owning_tab, "
  						  "NULL::int4 as owning_col, "
  						  "NULL as reltablespace, "
! 						  "NULL as reloptions "
  						  "from pg_class "
  						  "where relkind in ('%c', '%c', '%c') "
  						  "order by oid",
--- 3277,3284 ----
  						  "NULL::oid as owning_tab, "
  						  "NULL::int4 as owning_col, "
  						  "NULL as reltablespace, "
! 						  "NULL as reloptions, "
! 						  "NULL as toast_reloptions "
  						  "from pg_class "
  						  "where relkind in ('%c', '%c', '%c') "
  						  "order by oid",
***************
*** 3301,3307 ****
  						  "NULL::oid as owning_tab, "
  						  "NULL::int4 as owning_col, "
  						  "NULL as reltablespace, "
! 						  "NULL as reloptions "
  						  "from pg_class c "
  						  "where relkind in ('%c', '%c') "
  						  "order by oid",
--- 3308,3315 ----
  						  "NULL::oid as owning_tab, "
  						  "NULL::int4 as owning_col, "
  						  "NULL as reltablespace, "
! 						  "NULL as reloptions, "
! 						  "NULL as toast_reloptions "
  						  "from pg_class c "
  						  "where relkind in ('%c', '%c') "
  						  "order by oid",
***************
*** 3344,3349 ****
--- 3352,3358 ----
  	i_owning_col = PQfnumber(res, "owning_col");
  	i_reltablespace = PQfnumber(res, "reltablespace");
  	i_reloptions = PQfnumber(res, "reloptions");
+ 	i_toastreloptions = PQfnumber(res, "toast_reloptions");
  
  	if (lockWaitTimeout && g_fout->remoteVersion >= 70300)
  	{
***************
*** 3389,3394 ****
--- 3398,3404 ----
  		}
  		tblinfo[i].reltablespace = strdup(PQgetvalue(res, i, i_reltablespace));
  		tblinfo[i].reloptions = strdup(PQgetvalue(res, i, i_reloptions));
+ 		tblinfo[i].toast_reloptions = strdup(PQgetvalue(res, i, i_toastreloptions));
  
  		/* other fields were zeroed above */
  
***************
*** 9700,9707 ****
  			appendPQExpBuffer(q, ")");
  		}
  
! 		if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0)
! 			appendPQExpBuffer(q, "\nWITH (%s)", tbinfo->reloptions);
  
  		appendPQExpBuffer(q, ";\n");
  
--- 9710,9733 ----
  			appendPQExpBuffer(q, ")");
  		}
  
! 		if ((tbinfo->reloptions && strlen(tbinfo->reloptions) > 0) ||
! 			(tbinfo->toast_reloptions && strlen(tbinfo->toast_reloptions) > 0))
! 		{
! 			bool	addcomma = false;
! 
! 			appendPQExpBuffer(q, "\nWITH (");
! 			if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0)
! 			{
! 				addcomma = true;
! 				appendPQExpBuffer(q, "%s", tbinfo->reloptions);
! 			}
! 			if (tbinfo->toast_reloptions && strlen(tbinfo->toast_reloptions) > 0)
! 			{
! 				appendPQExpBuffer(q, "%s%s", addcomma ? ", " : "",
! 								  tbinfo->toast_reloptions);
! 			}
! 			appendPQExpBuffer(q, ")");
! 		}
  
  		appendPQExpBuffer(q, ";\n");
  
Index: src/bin/pg_dump/pg_dump.h
===================================================================
RCS file: /home/alvherre/cvs/pgsql/src/bin/pg_dump/pg_dump.h,v
retrieving revision 1.149
diff -c -p -r1.149 pg_dump.h
*** src/bin/pg_dump/pg_dump.h	27 Jan 2009 12:40:15 -0000	1.149
--- src/bin/pg_dump/pg_dump.h	30 Jan 2009 19:28:37 -0000
***************
*** 221,226 ****
--- 221,227 ----
  	char		relkind;
  	char	   *reltablespace;	/* relation tablespace */
  	char	   *reloptions;		/* options specified by WITH (...) */
+ 	char	   *toast_reloptions; /* ditto, for the TOAST table */
  	bool		hasindex;		/* does it have any indexes? */
  	bool		hasrules;		/* does it have any rules? */
  	bool		hastriggers;	/* does it have any triggers? */
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
