mirror of
https://github.com/postgres/postgres.git
synced 2025-08-31 17:02:12 +03:00
Allow reloption names to have qualifiers, initially supporting a TOAST
qualifier, and add support for this in pg_dump. This allows TOAST tables to have user-defined fillfactor, and will also enable us to move the autovacuum parameters to reloptions without taking away the possibility of setting values for TOAST tables.
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.181 2009/01/16 13:27:23 heikki Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.182 2009/02/02 19:31:38 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -668,6 +668,7 @@ make_new_heap(Oid OIDOldHeap, const char *NewName, Oid NewTableSpace)
|
||||
TupleDesc OldHeapDesc,
|
||||
tupdesc;
|
||||
Oid OIDNewHeap;
|
||||
Oid toastid;
|
||||
Relation OldHeap;
|
||||
HeapTuple tuple;
|
||||
Datum reloptions;
|
||||
@@ -726,7 +727,24 @@ make_new_heap(Oid OIDOldHeap, const char *NewName, Oid NewTableSpace)
|
||||
* AlterTableCreateToastTable ends with CommandCounterIncrement(), so that
|
||||
* the TOAST table will be visible for insertion.
|
||||
*/
|
||||
AlterTableCreateToastTable(OIDNewHeap);
|
||||
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);
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/define.c,v 1.102 2009/01/01 17:23:37 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/define.c,v 1.103 2009/02/02 19:31:38 alvherre Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@@ -55,24 +55,20 @@ case_translate_language_name(const char *input)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Extract a string value (otherwise uninterpreted) from a DefElem.
|
||||
*/
|
||||
char *
|
||||
defGetString(DefElem *def)
|
||||
static char *
|
||||
nodeGetString(Node *value, char *name)
|
||||
{
|
||||
if (def->arg == NULL)
|
||||
if (value == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("%s requires a parameter",
|
||||
def->defname)));
|
||||
switch (nodeTag(def->arg))
|
||||
errmsg("%s requires a parameter", name)));
|
||||
switch (nodeTag(value))
|
||||
{
|
||||
case T_Integer:
|
||||
{
|
||||
char *str = palloc(32);
|
||||
|
||||
snprintf(str, 32, "%ld", (long) intVal(def->arg));
|
||||
snprintf(str, 32, "%ld", (long) intVal(value));
|
||||
return str;
|
||||
}
|
||||
case T_Float:
|
||||
@@ -81,19 +77,28 @@ defGetString(DefElem *def)
|
||||
* T_Float values are kept in string form, so this type cheat
|
||||
* works (and doesn't risk losing precision)
|
||||
*/
|
||||
return strVal(def->arg);
|
||||
return strVal(value);
|
||||
case T_String:
|
||||
return strVal(def->arg);
|
||||
return strVal(value);
|
||||
case T_TypeName:
|
||||
return TypeNameToString((TypeName *) def->arg);
|
||||
return TypeNameToString((TypeName *) value);
|
||||
case T_List:
|
||||
return NameListToString((List *) def->arg);
|
||||
return NameListToString((List *) value);
|
||||
default:
|
||||
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(def->arg));
|
||||
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.
|
||||
*/
|
||||
@@ -120,25 +125,22 @@ defGetNumeric(DefElem *def)
|
||||
return 0; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract a boolean value from a DefElem.
|
||||
*/
|
||||
bool
|
||||
defGetBoolean(DefElem *def)
|
||||
static bool
|
||||
nodeGetBoolean(Node *value, char *name)
|
||||
{
|
||||
/*
|
||||
* If no parameter given, assume "true" is meant.
|
||||
*/
|
||||
if (def->arg == NULL)
|
||||
if (value == NULL)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* Allow 0, 1, "true", "false"
|
||||
*/
|
||||
switch (nodeTag(def->arg))
|
||||
switch (nodeTag(value))
|
||||
{
|
||||
case T_Integer:
|
||||
switch (intVal(def->arg))
|
||||
switch (intVal(value))
|
||||
{
|
||||
case 0:
|
||||
return false;
|
||||
@@ -151,7 +153,7 @@ defGetBoolean(DefElem *def)
|
||||
break;
|
||||
default:
|
||||
{
|
||||
char *sval = defGetString(def);
|
||||
char *sval = nodeGetString(value, name);
|
||||
|
||||
if (pg_strcasecmp(sval, "true") == 0)
|
||||
return true;
|
||||
@@ -163,11 +165,19 @@ defGetBoolean(DefElem *def)
|
||||
}
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("%s requires a Boolean value",
|
||||
def->defname)));
|
||||
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.
|
||||
*/
|
||||
@@ -305,15 +315,35 @@ defGetTypeLength(DefElem *def)
|
||||
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";
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.181 2009/01/01 17:23:38 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.182 2009/02/02 19:31:38 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -398,7 +398,7 @@ DefineIndex(RangeVar *heapRelation,
|
||||
/*
|
||||
* Parse AM-specific options, convert to text array form, validate.
|
||||
*/
|
||||
reloptions = transformRelOptions((Datum) 0, options, false, false);
|
||||
reloptions = transformRelOptions((Datum) 0, options, NULL, NULL, false, false);
|
||||
|
||||
(void) index_reloptions(amoptions, reloptions, true);
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.157 2009/01/20 18:59:37 heikki Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.158 2009/02/02 19:31:38 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -198,7 +198,7 @@ DefineSequence(CreateSeqStmt *seq)
|
||||
stmt->relation = seq->sequence;
|
||||
stmt->inhRelations = NIL;
|
||||
stmt->constraints = NIL;
|
||||
stmt->options = list_make1(defWithOids(false));
|
||||
stmt->options = list_make1(reloptWithOids(false));
|
||||
stmt->oncommit = ONCOMMIT_NOOP;
|
||||
stmt->tablespacename = NULL;
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.278 2009/01/22 20:16:02 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.279 2009/02/02 19:31:38 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -351,6 +351,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
Datum reloptions;
|
||||
ListCell *listptr;
|
||||
AttrNumber attnum;
|
||||
static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
|
||||
|
||||
/*
|
||||
* Truncate relname to appropriate length (probably a waste of time, as
|
||||
@@ -418,7 +419,8 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
/*
|
||||
* Parse and validate reloptions, if any.
|
||||
*/
|
||||
reloptions = transformRelOptions((Datum) 0, stmt->options, true, false);
|
||||
reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
|
||||
true, false);
|
||||
|
||||
(void) heap_reloptions(relkind, reloptions, true);
|
||||
|
||||
@@ -2572,7 +2574,7 @@ ATRewriteCatalogs(List **wqueue)
|
||||
(tab->subcmds[AT_PASS_ADD_COL] ||
|
||||
tab->subcmds[AT_PASS_ALTER_TYPE] ||
|
||||
tab->subcmds[AT_PASS_COL_ATTRS]))
|
||||
AlterTableCreateToastTable(tab->relid);
|
||||
AlterTableCreateToastTable(tab->relid, (Datum) 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6457,6 +6459,7 @@ ATExecSetRelOptions(Relation rel, List *defList, bool isReset)
|
||||
Datum repl_val[Natts_pg_class];
|
||||
bool repl_null[Natts_pg_class];
|
||||
bool repl_repl[Natts_pg_class];
|
||||
static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
|
||||
|
||||
if (defList == NIL)
|
||||
return; /* nothing to do */
|
||||
@@ -6475,7 +6478,7 @@ ATExecSetRelOptions(Relation rel, List *defList, bool isReset)
|
||||
|
||||
/* Generate new proposed reloptions (text array) */
|
||||
newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
|
||||
defList, false, isReset);
|
||||
defList, NULL, validnsps, false, isReset);
|
||||
|
||||
/* Validate */
|
||||
switch (rel->rd_rel->relkind)
|
||||
@@ -6521,6 +6524,53 @@ ATExecSetRelOptions(Relation rel, List *defList, bool isReset)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.130 2009/01/09 15:46:10 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.131 2009/02/02 19:31:39 alvherre Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@@ -1491,7 +1491,7 @@ DefineCompositeType(const RangeVar *typevar, List *coldeflist)
|
||||
createStmt->tableElts = coldeflist;
|
||||
createStmt->inhRelations = NIL;
|
||||
createStmt->constraints = NIL;
|
||||
createStmt->options = list_make1(defWithOids(false));
|
||||
createStmt->options = list_make1(reloptWithOids(false));
|
||||
createStmt->oncommit = ONCOMMIT_NOOP;
|
||||
createStmt->tablespacename = NULL;
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.113 2009/01/27 12:40:15 petere Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.114 2009/02/02 19:31:39 alvherre Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -229,7 +229,7 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace)
|
||||
createStmt->tableElts = attrList;
|
||||
createStmt->inhRelations = NIL;
|
||||
createStmt->constraints = NIL;
|
||||
createStmt->options = list_make1(defWithOids(false));
|
||||
createStmt->options = list_make1(reloptWithOids(false));
|
||||
createStmt->oncommit = ONCOMMIT_NOOP;
|
||||
createStmt->tablespacename = NULL;
|
||||
|
||||
|
Reference in New Issue
Block a user