Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 3a5b773

Browse files
committed
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.
1 parent 80f95a6 commit 3a5b773

27 files changed

+452
-127
lines changed

doc/src/sgml/ref/create_index.sgml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/create_index.sgml,v 1.69 2008/11/14 10:22:46 petere Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/create_index.sgml,v 1.70 2009/02/02 19:31:38 alvherre Exp $
33
PostgreSQL documentation
44
-->
55

@@ -231,7 +231,8 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] <replaceable class="parameter">name</re
231231
<listitem>
232232
<para>
233233
The name of an index-method-specific storage parameter. See
234-
below for details.
234+
<xref linkend="sql-createindex-storage-parameters" endterm="sql-createindex-storage-parameters-title">
235+
for details.
235236
</para>
236237
</listitem>
237238
</varlistentry>
@@ -265,7 +266,8 @@ CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] <replaceable class="parameter">name</re
265266
<para>
266267
The <literal>WITH</> clause can specify <firstterm>storage parameters</>
267268
for indexes. Each index method can have its own set of allowed storage
268-
parameters. The built-in index methods all accept a single parameter:
269+
parameters. The <literal>B-tree</literal>, <literal>hash</literal> and
270+
<literal>GiST</literal> built-in index methods all accept a single parameter:
269271
</para>
270272

271273
<variablelist>

doc/src/sgml/ref/create_table.sgml

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.111 2008/11/14 10:22:46 petere Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.112 2009/02/02 19:31:38 alvherre Exp $
33
PostgreSQL documentation
44
-->
55

@@ -690,8 +690,8 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is:
690690
for tables, and for indexes associated with a <literal>UNIQUE</literal> or
691691
<literal>PRIMARY KEY</literal> constraint. Storage parameters for
692692
indexes are documented in <xref linkend="SQL-CREATEINDEX"
693-
endterm="sql-createindex-title">. The only storage parameter currently
694-
available for tables is:
693+
endterm="sql-createindex-title">. The storage parameters currently
694+
available for tables are:
695695
</para>
696696

697697
<variablelist>
@@ -714,6 +714,16 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is:
714714
</listitem>
715715
</varlistentry>
716716

717+
<varlistentry>
718+
<term><literal>TOAST.FILLFACTOR</literal></term>
719+
<listitem>
720+
<para>
721+
Same as above, for the supplementary storage table, if any; see
722+
<xref linkend="storage-toast">.
723+
</para>
724+
</listitem>
725+
</varlistentry>
726+
717727
</variablelist>
718728

719729
</refsect2>

src/backend/access/common/reloptions.c

Lines changed: 75 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.19 2009/01/26 19:41:06 alvherre Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.20 2009/02/02 19:31:38 alvherre Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -390,8 +390,10 @@ add_string_reloption(int kind, char *name, char *desc, char *default_val,
390390
}
391391

392392
/*
393-
* Transform a relation options list (list of DefElem) into the text array
394-
* format that is kept in pg_class.reloptions.
393+
* Transform a relation options list (list of ReloptElem) into the text array
394+
* format that is kept in pg_class.reloptions, including only those options
395+
* that are in the passed namespace. The output values do not include the
396+
* namespace.
395397
*
396398
* This is used for three cases: CREATE TABLE/INDEX, ALTER TABLE SET, and
397399
* ALTER TABLE RESET. In the ALTER cases, oldOptions is the existing
@@ -402,14 +404,17 @@ add_string_reloption(int kind, char *name, char *desc, char *default_val,
402404
* in the list (it will be or has been handled by interpretOidsOption()).
403405
*
404406
* Note that this is not responsible for determining whether the options
405-
* are valid.
407+
* are valid, but it does check that namespaces for all the options given are
408+
* listed in validnsps. The NULL namespace is always valid and needs not be
409+
* explicitely listed. Passing a NULL pointer means that only the NULL
410+
* namespace is valid.
406411
*
407412
* Both oldOptions and the result are text arrays (or NULL for "default"),
408413
* but we declare them as Datums to avoid including array.h in reloptions.h.
409414
*/
410415
Datum
411-
transformRelOptions(Datum oldOptions, List *defList,
412-
bool ignoreOids, bool isReset)
416+
transformRelOptions(Datum oldOptions, List *defList, char *namspace,
417+
char *validnsps[], bool ignoreOids, bool isReset)
413418
{
414419
Datum result;
415420
ArrayBuildState *astate;
@@ -444,11 +449,23 @@ transformRelOptions(Datum oldOptions, List *defList,
444449
/* Search for a match in defList */
445450
foreach(cell, defList)
446451
{
447-
DefElem *def = lfirst(cell);
448-
int kw_len = strlen(def->defname);
452+
ReloptElem *def = lfirst(cell);
453+
int kw_len;
449454

455+
/* ignore if not in the same namespace */
456+
if (namspace == NULL)
457+
{
458+
if (def->nmspc != NULL)
459+
continue;
460+
}
461+
else if (def->nmspc == NULL)
462+
continue;
463+
else if (pg_strcasecmp(def->nmspc, namspace) != 0)
464+
continue;
465+
466+
kw_len = strlen(def->optname);
450467
if (text_len > kw_len && text_str[kw_len] == '=' &&
451-
pg_strncasecmp(text_str, def->defname, kw_len) == 0)
468+
pg_strncasecmp(text_str, def->optname, kw_len) == 0)
452469
break;
453470
}
454471
if (!cell)
@@ -468,7 +485,8 @@ transformRelOptions(Datum oldOptions, List *defList,
468485
*/
469486
foreach(cell, defList)
470487
{
471-
DefElem *def = lfirst(cell);
488+
ReloptElem *def = lfirst(cell);
489+
472490

473491
if (isReset)
474492
{
@@ -483,22 +501,62 @@ transformRelOptions(Datum oldOptions, List *defList,
483501
const char *value;
484502
Size len;
485503

486-
if (ignoreOids && pg_strcasecmp(def->defname, "oids") == 0)
504+
/*
505+
* Error out if the namespace is not valid. A NULL namespace
506+
* is always valid.
507+
*/
508+
if (def->nmspc != NULL)
509+
{
510+
bool valid = false;
511+
int i;
512+
513+
if (validnsps)
514+
{
515+
for (i = 0; validnsps[i]; i++)
516+
{
517+
if (pg_strcasecmp(def->nmspc, validnsps[i]) == 0)
518+
{
519+
valid = true;
520+
break;
521+
}
522+
}
523+
}
524+
525+
if (!valid)
526+
ereport(ERROR,
527+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
528+
errmsg("unrecognized parameter namespace \"%s\"",
529+
def->nmspc)));
530+
}
531+
532+
if (ignoreOids && pg_strcasecmp(def->optname, "oids") == 0)
533+
continue;
534+
535+
/* ignore if not in the same namespace */
536+
if (namspace == NULL)
537+
{
538+
if (def->nmspc != NULL)
539+
continue;
540+
}
541+
else if (def->nmspc == NULL)
542+
continue;
543+
else if (pg_strcasecmp(def->nmspc, namspace) != 0)
487544
continue;
488545

489546
/*
490-
* Flatten the DefElem into a text string like "name=arg". If we
491-
* have just "name", assume "name=true" is meant.
547+
* Flatten the ReloptElem into a text string like "name=arg". If we
548+
* have just "name", assume "name=true" is meant. Note: the
549+
* namespace is not output.
492550
*/
493551
if (def->arg != NULL)
494-
value = defGetString(def);
552+
value = reloptGetString(def);
495553
else
496554
value = "true";
497-
len = VARHDRSZ + strlen(def->defname) + 1 + strlen(value);
555+
len = VARHDRSZ + strlen(def->optname) + 1 + strlen(value);
498556
/* +1 leaves room for sprintf's trailing null */
499557
t = (text *) palloc(len + 1);
500558
SET_VARSIZE(t, len);
501-
sprintf(VARDATA(t), "%s=%s", def->defname, value);
559+
sprintf(VARDATA(t), "%s=%s", def->optname, value);
502560

503561
astate = accumArrayResult(astate, PointerGetDatum(t),
504562
false, TEXTOID,
@@ -944,7 +1002,7 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
9441002
}
9451003

9461004
/*
947-
* Parse options for heaps (and perhaps someday toast tables).
1005+
* Parse options for heaps and toast tables.
9481006
*/
9491007
bytea *
9501008
heap_reloptions(char relkind, Datum reloptions, bool validate)

src/backend/catalog/toasting.c

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.12 2009/01/01 17:23:37 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.13 2009/02/02 19:31:38 alvherre Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -32,7 +32,8 @@
3232
#include "utils/syscache.h"
3333

3434

35-
static bool create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid);
35+
static bool create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
36+
Datum reloptions);
3637
static bool needs_toast_table(Relation rel);
3738

3839

@@ -46,7 +47,7 @@ static bool needs_toast_table(Relation rel);
4647
* to end with CommandCounterIncrement if it makes any changes.
4748
*/
4849
void
49-
AlterTableCreateToastTable(Oid relOid)
50+
AlterTableCreateToastTable(Oid relOid, Datum reloptions)
5051
{
5152
Relation rel;
5253

@@ -58,7 +59,7 @@ AlterTableCreateToastTable(Oid relOid)
5859
rel = heap_open(relOid, AccessExclusiveLock);
5960

6061
/* create_toast_table does all the work */
61-
(void) create_toast_table(rel, InvalidOid, InvalidOid);
62+
(void) create_toast_table(rel, InvalidOid, InvalidOid, reloptions);
6263

6364
heap_close(rel, NoLock);
6465
}
@@ -84,7 +85,7 @@ BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid)
8485
relName)));
8586

8687
/* create_toast_table does all the work */
87-
if (!create_toast_table(rel, toastOid, toastIndexOid))
88+
if (!create_toast_table(rel, toastOid, toastIndexOid, (Datum) 0))
8889
elog(ERROR, "\"%s\" does not require a toast table",
8990
relName);
9091

@@ -100,7 +101,7 @@ BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid)
100101
* bootstrap they can be nonzero to specify hand-assigned OIDs
101102
*/
102103
static bool
103-
create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid)
104+
create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptions)
104105
{
105106
Oid relOid = RelationGetRelid(rel);
106107
HeapTuple reltup;
@@ -183,10 +184,6 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid)
183184
else
184185
namespaceid = PG_TOAST_NAMESPACE;
185186

186-
/*
187-
* XXX would it make sense to apply the master's reloptions to the toast
188-
* table? Or maybe some toast-specific reloptions?
189-
*/
190187
toast_relid = heap_create_with_catalog(toast_relname,
191188
namespaceid,
192189
rel->rd_rel->reltablespace,
@@ -199,7 +196,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid)
199196
true,
200197
0,
201198
ONCOMMIT_NOOP,
202-
(Datum) 0,
199+
reloptions,
203200
true);
204201

205202
/* make the toast relation visible, else index creation will fail */

src/backend/commands/cluster.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.181 2009/01/16 13:27:23 heikki Exp $
14+
* $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.182 2009/02/02 19:31:38 alvherre Exp $
1515
*
1616
*-------------------------------------------------------------------------
1717
*/
@@ -668,6 +668,7 @@ make_new_heap(Oid OIDOldHeap, const char *NewName, Oid NewTableSpace)
668668
TupleDesc OldHeapDesc,
669669
tupdesc;
670670
Oid OIDNewHeap;
671+
Oid toastid;
671672
Relation OldHeap;
672673
HeapTuple tuple;
673674
Datum reloptions;
@@ -726,7 +727,24 @@ make_new_heap(Oid OIDOldHeap, const char *NewName, Oid NewTableSpace)
726727
* AlterTableCreateToastTable ends with CommandCounterIncrement(), so that
727728
* the TOAST table will be visible for insertion.
728729
*/
729-
AlterTableCreateToastTable(OIDNewHeap);
730+
toastid = OldHeap->rd_rel->reltoastrelid;
731+
reloptions = (Datum) 0;
732+
if (OidIsValid(toastid))
733+
{
734+
tuple = SearchSysCache(RELOID,
735+
ObjectIdGetDatum(toastid),
736+
0, 0, 0);
737+
if (!HeapTupleIsValid(tuple))
738+
elog(ERROR, "cache lookup failed for relation %u", toastid);
739+
reloptions = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_reloptions,
740+
&isNull);
741+
if (isNull)
742+
reloptions = (Datum) 0;
743+
}
744+
AlterTableCreateToastTable(OIDNewHeap, reloptions);
745+
746+
if (OidIsValid(toastid))
747+
ReleaseSysCache(tuple);
730748

731749
heap_close(OldHeap, NoLock);
732750

0 commit comments

Comments
 (0)