Tom Lane wrote:
> This is not only really ugly, but 100% toast-specific. The
> qualified-name approach ("toast.autovacuum_enabled") has at least
> a chance of being good for something else. Or just make it
> toast_autovacuum_enabled and do the translation magic at some low
> level in the statement execution code.
Does this look better?
This is still WIP, as some cases are not handled correctly; but with
this patch it's possible to set a toast table fillfactor (not that
that's useful for anything AFAICS).
--
Alvaro Herrera http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.
Index: src/backend/access/common/reloptions.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/access/common/reloptions.c,v
retrieving revision 1.16
diff -c -p -r1.16 reloptions.c
*** src/backend/access/common/reloptions.c 6 Jan 2009 14:47:37 -0000 1.16
--- src/backend/access/common/reloptions.c 7 Jan 2009 23:07:22 -0000
*************** add_string_reloption(int kind, char *nam
*** 378,385 ****
}
/*
! * 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
--- 378,387 ----
}
/*
! * 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
*************** add_string_reloption(int kind, char *nam
*** 396,402 ****
* 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;
--- 398,404 ----
* but we declare them as Datums to avoid including array.h in reloptions.h.
*/
Datum
! transformRelOptions(Datum oldOptions, List *defList, char *namspace,
bool ignoreOids, bool isReset)
{
Datum result;
*************** transformRelOptions(Datum oldOptions, Li
*** 432,442 ****
/* 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)
--- 434,444 ----
/* Search for a match in defList */
foreach(cell, defList)
{
! ReloptElem *def = lfirst(cell);
! int 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)
*************** transformRelOptions(Datum oldOptions, Li
*** 456,462 ****
*/
foreach(cell, defList)
{
! DefElem *def = lfirst(cell);
if (isReset)
{
--- 458,464 ----
*/
foreach(cell, defList)
{
! ReloptElem *def = lfirst(cell);
if (isReset)
{
*************** transformRelOptions(Datum oldOptions, Li
*** 471,492 ****
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,
--- 473,506 ----
const char *value;
Size len;
! 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,
*************** default_reloptions(Datum reloptions, boo
*** 784,790 ****
}
/*
! * Parse options for heaps (and perhaps someday toast tables).
*/
bytea *
heap_reloptions(char relkind, Datum reloptions, bool validate)
--- 798,804 ----
}
/*
! * 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/Code/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 7 Jan 2009 22:10:48 -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);
*************** static bool needs_toast_table(Relation r
*** 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;
*************** AlterTableCreateToastTable(Oid relOid)
*** 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);
}
*************** BootstrapToastTable(char *relName, Oid t
*** 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);
*************** BootstrapToastTable(char *relName, Oid t
*** 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;
*************** create_toast_table(Relation rel, Oid toa
*** 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 ----
*************** create_toast_table(Relation rel, Oid toa
*** 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/Code/cvs/pgsql/src/backend/commands/cluster.c,v
retrieving revision 1.180
diff -c -p -r1.180 cluster.c
*** src/backend/commands/cluster.c 1 Jan 2009 17:23:37 -0000 1.180
--- src/backend/commands/cluster.c 7 Jan 2009 22:10:48 -0000
*************** make_new_heap(Oid OIDOldHeap, const char
*** 668,673 ****
--- 668,674 ----
TupleDesc OldHeapDesc,
tupdesc;
Oid OIDNewHeap;
+ Oid toastid;
Relation OldHeap;
HeapTuple tuple;
Datum reloptions;
*************** make_new_heap(Oid OIDOldHeap, const char
*** 726,732 ****
* AlterTableCreateToastTable ends with CommandCounterIncrement(), so that
* the TOAST table will be visible for insertion.
*/
! AlterTableCreateToastTable(OIDNewHeap);
heap_close(OldHeap, NoLock);
--- 727,748 ----
* 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);
! ReleaseSysCache(tuple);
heap_close(OldHeap, NoLock);
Index: src/backend/commands/define.c
===================================================================
RCS file: /home/alvherre/Code/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 7 Jan 2009 23:43:05 -0000
*************** defGetTypeLength(DefElem *def)
*** 306,319 ****
}
/*
! * 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;
}
--- 306,407 ----
}
/*
! * Extract a string value (otherwise uninterpreted) from a ReloptElem.
*/
! char *
! reloptGetString(ReloptElem *def)
{
! if (def->arg == NULL)
! ereport(ERROR,
! (errcode(ERRCODE_SYNTAX_ERROR),
! errmsg("%s requires a parameter",
! def->optname)));
! switch (nodeTag(def->arg))
! {
! case T_Integer:
! {
! char *str = palloc(32);
! snprintf(str, 32, "%ld", (long) intVal(def->arg));
! return str;
! }
! case T_Float:
!
! /*
! * 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 boolean value from a ReloptElem.
! */
! bool
! reloptGetBoolean(ReloptElem *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;
! case 1:
! return true;
! default:
! /* otherwise, error out below */
! break;
! }
! break;
! default:
! {
! char *sval = reloptGetString(def);
!
! if (pg_strcasecmp(sval, "true") == 0)
! return true;
! if (pg_strcasecmp(sval, "false") == 0)
! return false;
!
! }
! break;
! }
! ereport(ERROR,
! (errcode(ERRCODE_SYNTAX_ERROR),
! errmsg("%s requires a Boolean value",
! def->optname)));
! return false; /* keep compiler quiet */
! }
!
! /*
! * 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/Code/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 7 Jan 2009 22:17:00 -0000
*************** DefineIndex(RangeVar *heapRelation,
*** 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, false, false);
(void) index_reloptions(amoptions, reloptions, true);
Index: src/backend/commands/sequence.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/commands/sequence.c,v
retrieving revision 1.156
diff -c -p -r1.156 sequence.c
*** src/backend/commands/sequence.c 1 Jan 2009 17:23:39 -0000 1.156
--- src/backend/commands/sequence.c 7 Jan 2009 23:43:29 -0000
*************** DefineSequence(CreateSeqStmt *seq)
*** 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/Code/cvs/pgsql/src/backend/commands/tablecmds.c,v
retrieving revision 1.276
diff -c -p -r1.276 tablecmds.c
*** src/backend/commands/tablecmds.c 1 Jan 2009 17:23:39 -0000 1.276
--- src/backend/commands/tablecmds.c 7 Jan 2009 22:10:48 -0000
*************** DefineRelation(CreateStmt *stmt, char re
*** 417,423 ****
/*
* Parse and validate reloptions, if any.
*/
! reloptions = transformRelOptions((Datum) 0, stmt->options, true, false);
(void) heap_reloptions(relkind, reloptions, true);
--- 417,423 ----
/*
* Parse and validate reloptions, if any.
*/
! reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, true, false);
(void) heap_reloptions(relkind, reloptions, true);
*************** ATRewriteCatalogs(List **wqueue)
*** 2547,2553 ****
(tab->subcmds[AT_PASS_ADD_COL] ||
tab->subcmds[AT_PASS_ALTER_TYPE] ||
tab->subcmds[AT_PASS_COL_ATTRS]))
! AlterTableCreateToastTable(tab->relid);
}
}
--- 2547,2553 ----
(tab->subcmds[AT_PASS_ADD_COL] ||
tab->subcmds[AT_PASS_ALTER_TYPE] ||
tab->subcmds[AT_PASS_COL_ATTRS]))
! AlterTableCreateToastTable(tab->relid, (Datum) 0); /* FIXME must preserve */
}
}
*************** ATExecSetRelOptions(Relation rel, List *
*** 6435,6441 ****
/* Generate new proposed reloptions (text array) */
newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
! defList, false, isReset);
/* Validate */
switch (rel->rd_rel->relkind)
--- 6435,6441 ----
/* Generate new proposed reloptions (text array) */
newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
! defList, NULL, false, isReset);
/* Validate */
switch (rel->rd_rel->relkind)
Index: src/backend/commands/typecmds.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/commands/typecmds.c,v
retrieving revision 1.129
diff -c -p -r1.129 typecmds.c
*** src/backend/commands/typecmds.c 1 Jan 2009 17:23:40 -0000 1.129
--- src/backend/commands/typecmds.c 7 Jan 2009 23:43:37 -0000
*************** DefineCompositeType(const RangeVar *type
*** 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/Code/cvs/pgsql/src/backend/commands/view.c,v
retrieving revision 1.111
diff -c -p -r1.111 view.c
*** src/backend/commands/view.c 1 Jan 2009 17:23:40 -0000 1.111
--- src/backend/commands/view.c 7 Jan 2009 23:43:43 -0000
*************** DefineVirtualRelation(const RangeVar *re
*** 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/Code/cvs/pgsql/src/backend/executor/execMain.c,v
retrieving revision 1.320
diff -c -p -r1.320 execMain.c
*** src/backend/executor/execMain.c 1 Jan 2009 17:23:41 -0000 1.320
--- src/backend/executor/execMain.c 7 Jan 2009 22:10:48 -0000
*************** OpenIntoRel(QueryDesc *queryDesc)
*** 2787,2792 ****
--- 2787,2793 ----
/* Parse and validate any reloptions */
reloptions = transformRelOptions((Datum) 0,
into->options,
+ NULL,
true,
false);
(void) heap_reloptions(RELKIND_RELATION, reloptions, true);
*************** OpenIntoRel(QueryDesc *queryDesc)
*** 2823,2829 ****
* AlterTableCreateToastTable ends with CommandCounterIncrement(), so that
* the TOAST table will be visible for insertion.
*/
! AlterTableCreateToastTable(intoRelationId);
/*
* And open the constructed table for writing.
--- 2824,2838 ----
* AlterTableCreateToastTable ends with CommandCounterIncrement(), so that
* the TOAST table will be visible for insertion.
*/
! reloptions = transformRelOptions((Datum) 0,
! into->options,
! "toast",
! 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/Code/cvs/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.419
diff -c -p -r1.419 copyfuncs.c
*** src/backend/nodes/copyfuncs.c 1 Jan 2009 17:23:43 -0000 1.419
--- src/backend/nodes/copyfuncs.c 7 Jan 2009 22:21:31 -0000
*************** _copyOptionDefElem(OptionDefElem *from)
*** 2123,2128 ****
--- 2123,2140 ----
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)
{
*************** copyObject(void *from)
*** 4066,4071 ****
--- 4078,4086 ----
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/makefuncs.c
===================================================================
RCS file: /home/alvherre/Code/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 7 Jan 2009 22:10:48 -0000
*************** makeOptionDefElem(int op, DefElem *def)
*** 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/parser/gram.y
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.651
diff -c -p -r2.651 gram.y
*** src/backend/parser/gram.y 1 Jan 2009 17:23:45 -0000 2.651
--- src/backend/parser/gram.y 7 Jan 2009 23:43:59 -0000
*************** static TypeName *TableFuncTypeName(List
*** 157,162 ****
--- 157,163 ----
FuncWithArgs *funwithargs;
DefElem *defelt;
OptionDefElem *optdef;
+ ReloptElem *reloptel;
SortBy *sortby;
WindowDef *windef;
JoinExpr *jexpr;
*************** static TypeName *TableFuncTypeName(List
*** 263,268 ****
--- 264,270 ----
%type <list> stmtblock stmtmulti
OptTableElementList TableElementList OptInherit definition
+ 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
*************** static TypeName *TableFuncTypeName(List
*** 276,282 ****
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
--- 278,284 ----
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
*************** static TypeName *TableFuncTypeName(List
*** 333,338 ****
--- 335,341 ----
%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
*************** alter_table_cmd:
*** 1772,1778 ****
$$ = (Node *)n;
}
/* ALTER TABLE <name> SET (...) */
! | SET definition
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_SetRelOptions;
--- 1775,1781 ----
$$ = (Node *)n;
}
/* ALTER TABLE <name> SET (...) */
! | SET reloptions
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_SetRelOptions;
*************** alter_table_cmd:
*** 1780,1786 ****
$$ = (Node *)n;
}
/* ALTER TABLE <name> RESET (...) */
! | RESET definition
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_ResetRelOptions;
--- 1783,1789 ----
$$ = (Node *)n;
}
/* ALTER TABLE <name> RESET (...) */
! | RESET reloptions
{
AlterTableCmd *n = makeNode(AlterTableCmd);
n->subtype = AT_ResetRelOptions;
*************** alter_using:
*** 1805,1811 ****
--- 1808,1840 ----
| /* EMPTY */ { $$ = NULL; }
;
+ reloptions:
+ '(' reloption_list ')' { $$ = $2; }
+ ;
+
+ 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);
+ }
+ ;
/*****************************************************************************
*
*************** OptInherit: INHERITS '(' qualified_name_
*** 2431,2439 ****
/* 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; }
;
--- 2460,2468 ----
/* 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; }
;
Index: src/backend/parser/parse_clause.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/parser/parse_clause.c,v
retrieving revision 1.185
diff -c -p -r1.185 parse_clause.c
*** src/backend/parser/parse_clause.c 1 Jan 2009 17:23:45 -0000 1.185
--- src/backend/parser/parse_clause.c 7 Jan 2009 23:04:33 -0000
*************** interpretInhOption(InhOption inhOpt)
*** 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.
*************** interpretOidsOption(List *defList)
*** 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/Code/cvs/pgsql/src/backend/tcop/utility.c,v
retrieving revision 1.304
diff -c -p -r1.304 utility.c
*** src/backend/tcop/utility.c 1 Jan 2009 17:23:48 -0000 1.304
--- src/backend/tcop/utility.c 7 Jan 2009 22:10:48 -0000
***************
*** 16,21 ****
--- 16,22 ----
*/
#include "postgres.h"
+ #include "access/reloptions.h"
#include "access/twophase.h"
#include "access/xact.h"
#include "catalog/catalog.h"
*************** ProcessUtility(Node *parsetree,
*** 422,427 ****
--- 423,430 ----
if (IsA(stmt, CreateStmt))
{
+ Datum toast_options;
+
/* Create the table itself */
relOid = DefineRelation((CreateStmt *) stmt,
RELKIND_RELATION);
*************** ProcessUtility(Node *parsetree,
*** 431,437 ****
* needs a secondary relation too.
*/
CommandCounterIncrement();
! AlterTableCreateToastTable(relOid);
}
else
{
--- 434,449 ----
* needs a secondary relation too.
*/
CommandCounterIncrement();
!
! /* parse and validate reloptions for the toast table */
! toast_options = transformRelOptions((Datum) 0,
! ((CreateStmt *)stmt)->options,
! "toast",
! 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/Code/cvs/pgsql/src/include/access/reloptions.h,v
retrieving revision 1.8
diff -c -p -r1.8 reloptions.h
*** src/include/access/reloptions.h 6 Jan 2009 14:47:37 -0000 1.8
--- src/include/access/reloptions.h 7 Jan 2009 22:10:48 -0000
*************** extern void add_string_reloption(int kin
*** 201,207 ****
char *default_val);
extern Datum transformRelOptions(Datum oldOptions, List *defList,
! bool ignoreOids, bool isReset);
extern List *untransformRelOptions(Datum options);
extern relopt_value *parseRelOptions(Datum options, bool validate,
relopt_kind kind, int *numrelopts);
--- 201,207 ----
char *default_val);
extern Datum transformRelOptions(Datum oldOptions, List *defList,
! char *namspace, bool ignoreOids, bool isReset);
extern List *untransformRelOptions(Datum options);
extern relopt_value *parseRelOptions(Datum options, bool validate,
relopt_kind kind, int *numrelopts);
Index: src/include/catalog/toasting.h
===================================================================
RCS file: /home/alvherre/Code/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 7 Jan 2009 22:10:48 -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/Code/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 7 Jan 2009 23:43:21 -0000
*************** extern int64 defGetInt64(DefElem *def);
*** 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 *def);
! extern bool reloptGetBoolean(ReloptElem *def);
! extern ReloptElem *reloptWithOids(bool value);
#endif /* DEFREM_H */
Index: src/include/nodes/makefuncs.h
===================================================================
RCS file: /home/alvherre/Code/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 7 Jan 2009 22:10:48 -0000
*************** extern DefElem *makeDefElem(char *name,
*** 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/Code/cvs/pgsql/src/include/nodes/nodes.h,v
retrieving revision 1.218
diff -c -p -r1.218 nodes.h
*** src/include/nodes/nodes.h 1 Jan 2009 17:24:00 -0000 1.218
--- src/include/nodes/nodes.h 7 Jan 2009 22:10:48 -0000
*************** typedef enum NodeTag
*** 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/Code/cvs/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.387
diff -c -p -r1.387 parsenodes.h
*** src/include/nodes/parsenodes.h 1 Jan 2009 17:24:00 -0000 1.387
--- src/include/nodes/parsenodes.h 7 Jan 2009 22:10:48 -0000
*************** typedef struct OptionDefElem
*** 532,537 ****
--- 532,548 ----
} 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
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers