~ubuntu-branches/ubuntu/hardy/postgresql-8.4/hardy-backports

« back to all changes in this revision

Viewing changes to src/backend/access/common/reloptions.c

  • Committer: Bazaar Package Importer
  • Author(s): Ubuntu Archive Backport
  • Date: 2009-11-09 13:46:16 UTC
  • mfrom: (5.2.2 sid)
  • Revision ID: james.westby@ubuntu.com-20091109134616-ae14l9tr3g7p2t9y
Tags: 8.4.1-1~hardy1
Automated backport upload; no source changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
 *
9
9
 *
10
10
 * IDENTIFICATION
11
 
 *        $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.26 2009/04/04 21:12:30 tgl Exp $
 
11
 *        $PostgreSQL: pgsql/src/backend/access/common/reloptions.c,v 1.28.2.1 2009/08/27 17:19:31 alvherre Exp $
12
12
 *
13
13
 *-------------------------------------------------------------------------
14
14
 */
65
65
                true
66
66
        },
67
67
        /* list terminator */
68
 
        { { NULL } }
 
68
        {{NULL}}
69
69
};
70
70
 
71
71
static relopt_int intRelOpts[] =
108
108
                        "Minimum number of tuple updates or deletes prior to vacuum",
109
109
                        RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
110
110
                },
111
 
                50, 0, INT_MAX
 
111
                -1, 0, INT_MAX
112
112
        },
113
113
        {
114
114
                {
116
116
                        "Minimum number of tuple inserts, updates or deletes prior to analyze",
117
117
                        RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
118
118
                },
119
 
                50, 0, INT_MAX
 
119
                -1, 0, INT_MAX
120
120
        },
121
121
        {
122
122
                {
124
124
                        "Vacuum cost delay in milliseconds, for autovacuum",
125
125
                        RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
126
126
                },
127
 
                20, 0, 100
 
127
                -1, 0, 100
128
128
        },
129
129
        {
130
130
                {
132
132
                        "Vacuum cost amount available before napping, for autovacuum",
133
133
                        RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
134
134
                },
135
 
                200, 1, 10000
 
135
                -1, 1, 10000
136
136
        },
137
137
        {
138
138
                {
140
140
                        "Minimum age at which VACUUM should freeze a table row, for autovacuum",
141
141
                        RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
142
142
                },
143
 
                100000000, 0, 1000000000
 
143
                -1, 0, 1000000000
144
144
        },
145
145
        {
146
146
                {
148
148
                        "Age at which to autovacuum a table to prevent transaction ID wraparound",
149
149
                        RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
150
150
                },
151
 
                200000000, 100000000, 2000000000
 
151
                -1, 100000000, 2000000000
152
152
        },
153
153
        {
154
154
                {
155
155
                        "autovacuum_freeze_table_age",
156
156
                        "Age at which VACUUM should perform a full table sweep to replace old Xid values with FrozenXID",
157
157
                        RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
158
 
                }, 150000000, 0, 2000000000
 
158
                }, -1, 0, 2000000000
159
159
        },
160
160
        /* list terminator */
161
 
        { { NULL } }
 
161
        {{NULL}}
162
162
};
163
163
 
164
164
static relopt_real realRelOpts[] =
169
169
                        "Number of tuple updates or deletes prior to vacuum as a fraction of reltuples",
170
170
                        RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
171
171
                },
172
 
                0.2, 0.0, 100.0
 
172
                -1, 0.0, 100.0
173
173
        },
174
174
        {
175
175
                {
177
177
                        "Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples",
178
178
                        RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
179
179
                },
180
 
                0.1, 0.0, 100.0
 
180
                -1, 0.0, 100.0
181
181
        },
182
182
        /* list terminator */
183
 
        { { NULL } }
 
183
        {{NULL}}
184
184
};
185
185
 
186
186
static relopt_string stringRelOpts[] =
187
187
{
188
188
        /* list terminator */
189
 
        { { NULL } }
 
189
        {{NULL}}
190
190
};
191
191
 
192
192
static relopt_gen **relOpts = NULL;
193
 
static bits32 last_assigned_kind = RELOPT_KIND_LAST_DEFAULT << 1;
 
193
static bits32 last_assigned_kind = RELOPT_KIND_LAST_DEFAULT;
194
194
 
195
 
static int              num_custom_options = 0;
 
195
static int      num_custom_options = 0;
196
196
static relopt_gen **custom_options = NULL;
197
 
static bool             need_initialization = true;
 
197
static bool need_initialization = true;
198
198
 
199
199
static void initialize_reloptions(void);
200
200
static void parse_one_reloption(relopt_value *option, char *text_str,
202
202
 
203
203
/*
204
204
 * initialize_reloptions
205
 
 *              initialization routine, must be called before parsing
 
205
 *              initialization routine, must be called before parsing
206
206
 *
207
207
 * Initialize the relOpts array and fill each variable's type and name length.
208
208
 */
209
209
static void
210
210
initialize_reloptions(void)
211
211
{
212
 
        int             i;
213
 
        int             j = 0;
 
212
        int                     i;
 
213
        int                     j = 0;
214
214
 
215
215
        for (i = 0; boolRelOpts[i].gen.name; i++)
216
216
                j++;
272
272
 
273
273
/*
274
274
 * add_reloption_kind
275
 
 *              Create a new relopt_kind value, to be used in custom reloptions by
276
 
 *              user-defined AMs.
 
275
 *              Create a new relopt_kind value, to be used in custom reloptions by
 
276
 *              user-defined AMs.
277
277
 */
278
278
relopt_kind
279
279
add_reloption_kind(void)
280
280
{
281
 
        relopt_kind             kind;
282
 
 
283
 
        /* don't hand out the last bit so that the wraparound check is portable */
 
281
        /* don't hand out the last bit so that the enum's behavior is portable */
284
282
        if (last_assigned_kind >= RELOPT_KIND_MAX)
285
283
                ereport(ERROR,
286
284
                                (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
287
 
                                 errmsg("user-defined relation parameter types limit exceeded")));
288
 
 
289
 
        kind = (relopt_kind) last_assigned_kind;
 
285
                        errmsg("user-defined relation parameter types limit exceeded")));
290
286
        last_assigned_kind <<= 1;
291
 
        return kind;
 
287
        return (relopt_kind) last_assigned_kind;
292
288
}
293
289
 
294
290
/*
295
291
 * add_reloption
296
 
 *              Add an already-created custom reloption to the list, and recompute the
297
 
 *              main parser table.
 
292
 *              Add an already-created custom reloption to the list, and recompute the
 
293
 *              main parser table.
298
294
 */
299
295
static void
300
296
add_reloption(relopt_gen *newoption)
301
297
{
302
 
        static int              max_custom_options = 0;
 
298
        static int      max_custom_options = 0;
303
299
 
304
300
        if (num_custom_options >= max_custom_options)
305
301
        {
306
 
                MemoryContext   oldcxt;
 
302
                MemoryContext oldcxt;
307
303
 
308
304
                oldcxt = MemoryContextSwitchTo(TopMemoryContext);
309
305
 
316
312
                {
317
313
                        max_custom_options *= 2;
318
314
                        custom_options = repalloc(custom_options,
319
 
                                                                          max_custom_options * sizeof(relopt_gen *));
 
315
                                                                  max_custom_options * sizeof(relopt_gen *));
320
316
                }
321
317
                MemoryContextSwitchTo(oldcxt);
322
318
        }
327
323
 
328
324
/*
329
325
 * allocate_reloption
330
 
 *              Allocate a new reloption and initialize the type-agnostic fields
331
 
 *              (for types other than string)
 
326
 *              Allocate a new reloption and initialize the type-agnostic fields
 
327
 *              (for types other than string)
332
328
 */
333
329
static relopt_gen *
334
330
allocate_reloption(bits32 kinds, int type, char *name, char *desc)
335
331
{
336
 
        MemoryContext   oldcxt;
337
 
        size_t                  size;
338
 
        relopt_gen         *newoption;
 
332
        MemoryContext oldcxt;
 
333
        size_t          size;
 
334
        relopt_gen *newoption;
339
335
 
340
336
        Assert(type != RELOPT_TYPE_STRING);
341
337
 
354
350
                        break;
355
351
                default:
356
352
                        elog(ERROR, "unsupported option type");
357
 
                        return NULL;    /* keep compiler quiet */
 
353
                        return NULL;            /* keep compiler quiet */
358
354
        }
359
355
 
360
356
        newoption = palloc(size);
375
371
 
376
372
/*
377
373
 * add_bool_reloption
378
 
 *              Add a new boolean reloption
 
374
 *              Add a new boolean reloption
379
375
 */
380
376
void
381
377
add_bool_reloption(bits32 kinds, char *name, char *desc, bool default_val)
382
378
{
383
 
        relopt_bool        *newoption;
 
379
        relopt_bool *newoption;
384
380
 
385
381
        newoption = (relopt_bool *) allocate_reloption(kinds, RELOPT_TYPE_BOOL,
386
382
                                                                                                   name, desc);
391
387
 
392
388
/*
393
389
 * add_int_reloption
394
 
 *              Add a new integer reloption
 
390
 *              Add a new integer reloption
395
391
 */
396
392
void
397
393
add_int_reloption(bits32 kinds, char *name, char *desc, int default_val,
398
394
                                  int min_val, int max_val)
399
395
{
400
 
        relopt_int         *newoption;
 
396
        relopt_int *newoption;
401
397
 
402
398
        newoption = (relopt_int *) allocate_reloption(kinds, RELOPT_TYPE_INT,
403
399
                                                                                                  name, desc);
410
406
 
411
407
/*
412
408
 * add_real_reloption
413
 
 *              Add a new float reloption
 
409
 *              Add a new float reloption
414
410
 */
415
411
void
416
412
add_real_reloption(bits32 kinds, char *name, char *desc, double default_val,
417
 
                                  double min_val, double max_val)
 
413
                                   double min_val, double max_val)
418
414
{
419
 
        relopt_real        *newoption;
 
415
        relopt_real *newoption;
420
416
 
421
417
        newoption = (relopt_real *) allocate_reloption(kinds, RELOPT_TYPE_REAL,
422
418
                                                                                                   name, desc);
432
428
 *              Add a new string reloption
433
429
 *
434
430
 * "validator" is an optional function pointer that can be used to test the
435
 
 * validity of the values.  It must elog(ERROR) when the argument string is
 
431
 * validity of the values.      It must elog(ERROR) when the argument string is
436
432
 * not acceptable for the variable.  Note that the default value must pass
437
433
 * the validation.
438
434
 */
440
436
add_string_reloption(bits32 kinds, char *name, char *desc, char *default_val,
441
437
                                         validate_string_relopt validator)
442
438
{
443
 
        MemoryContext   oldcxt;
444
 
        relopt_string  *newoption;
445
 
        int                             default_len = 0;
 
439
        MemoryContext oldcxt;
 
440
        relopt_string *newoption;
 
441
        int                     default_len = 0;
446
442
 
447
443
        oldcxt = MemoryContextSwitchTo(TopMemoryContext);
448
444
 
499
495
 * Note that this is not responsible for determining whether the options
500
496
 * are valid, but it does check that namespaces for all the options given are
501
497
 * listed in validnsps.  The NULL namespace is always valid and needs not be
502
 
 * explicitely listed.  Passing a NULL pointer means that only the NULL
 
498
 * explicitely listed.  Passing a NULL pointer means that only the NULL
503
499
 * namespace is valid.
504
500
 *
505
501
 * Both oldOptions and the result are text arrays (or NULL for "default"),
542
538
                        /* Search for a match in defList */
543
539
                        foreach(cell, defList)
544
540
                        {
545
 
                                DefElem    *def = (DefElem *) lfirst(cell);
 
541
                                DefElem    *def = (DefElem *) lfirst(cell);
546
542
                                int                     kw_len;
547
543
 
548
544
                                /* ignore if not in the same namespace */
578
574
         */
579
575
        foreach(cell, defList)
580
576
        {
581
 
                DefElem    *def = (DefElem *) lfirst(cell);
 
577
                DefElem    *def = (DefElem *) lfirst(cell);
582
578
 
583
579
                if (isReset)
584
580
                {
594
590
                        Size            len;
595
591
 
596
592
                        /*
597
 
                         * Error out if the namespace is not valid.  A NULL namespace
598
 
                         * is always valid.
 
593
                         * Error out if the namespace is not valid.  A NULL namespace is
 
594
                         * always valid.
599
595
                         */
600
596
                        if (def->defnamespace != NULL)
601
597
                        {
602
 
                                bool    valid = false;
603
 
                                int             i;
 
598
                                bool            valid = false;
 
599
                                int                     i;
604
600
 
605
601
                                if (validnsps)
606
602
                                {
723
719
bytea *
724
720
extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, Oid amoptions)
725
721
{
726
 
        bytea  *options;
727
 
        bool    isnull;
728
 
        Datum   datum;
729
 
        Form_pg_class   classForm;
 
722
        bytea      *options;
 
723
        bool            isnull;
 
724
        Datum           datum;
 
725
        Form_pg_class classForm;
730
726
 
731
727
        datum = fastgetattr(tuple,
732
728
                                                Anum_pg_class_reloptions,
772
768
 * is returned.
773
769
 *
774
770
 * Note: values of type int, bool and real are allocated as part of the
775
 
 * returned array.  Values of type string are allocated separately and must
 
771
 * returned array.      Values of type string are allocated separately and must
776
772
 * be freed by the caller.
777
773
 */
778
774
relopt_value *
898
894
                                parsed = parse_bool(value, &option->values.bool_val);
899
895
                                if (validate && !parsed)
900
896
                                        ereport(ERROR,
901
 
                                                        (errmsg("invalid value for boolean option \"%s\": %s",
902
 
                                                                        option->gen->name, value)));
 
897
                                           (errmsg("invalid value for boolean option \"%s\": %s",
 
898
                                                           option->gen->name, value)));
903
899
                        }
904
900
                        break;
905
901
                case RELOPT_TYPE_INT:
906
902
                        {
907
 
                                relopt_int      *optint = (relopt_int *) option->gen;
 
903
                                relopt_int *optint = (relopt_int *) option->gen;
908
904
 
909
905
                                parsed = parse_int(value, &option->values.int_val, 0, NULL);
910
906
                                if (validate && !parsed)
911
907
                                        ereport(ERROR,
912
 
                                                        (errmsg("invalid value for integer option \"%s\": %s",
913
 
                                                                        option->gen->name, value)));
 
908
                                           (errmsg("invalid value for integer option \"%s\": %s",
 
909
                                                           option->gen->name, value)));
914
910
                                if (validate && (option->values.int_val < optint->min ||
915
911
                                                                 option->values.int_val > optint->max))
916
912
                                        ereport(ERROR,
917
 
                                                        (errmsg("value %s out of bounds for option \"%s\"",
918
 
                                                                        value, option->gen->name),
919
 
                                                         errdetail("Valid values are between \"%d\" and \"%d\".",
920
 
                                                                           optint->min, optint->max)));
 
913
                                                  (errmsg("value %s out of bounds for option \"%s\"",
 
914
                                                                  value, option->gen->name),
 
915
                                         errdetail("Valid values are between \"%d\" and \"%d\".",
 
916
                                                           optint->min, optint->max)));
921
917
                        }
922
918
                        break;
923
919
                case RELOPT_TYPE_REAL:
924
920
                        {
925
 
                                relopt_real     *optreal = (relopt_real *) option->gen;
 
921
                                relopt_real *optreal = (relopt_real *) option->gen;
926
922
 
927
923
                                parsed = parse_real(value, &option->values.real_val);
928
924
                                if (validate && !parsed)
932
928
                                if (validate && (option->values.real_val < optreal->min ||
933
929
                                                                 option->values.real_val > optreal->max))
934
930
                                        ereport(ERROR,
935
 
                                                        (errmsg("value %s out of bounds for option \"%s\"",
936
 
                                                                        value, option->gen->name),
937
 
                                                         errdetail("Valid values are between \"%f\" and \"%f\".",
938
 
                                                                           optreal->min, optreal->max)));
 
931
                                                  (errmsg("value %s out of bounds for option \"%s\"",
 
932
                                                                  value, option->gen->name),
 
933
                                         errdetail("Valid values are between \"%f\" and \"%f\".",
 
934
                                                           optreal->min, optreal->max)));
939
935
                        }
940
936
                        break;
941
937
                case RELOPT_TYPE_STRING:
942
938
                        {
943
 
                                relopt_string   *optstring = (relopt_string *) option->gen;
 
939
                                relopt_string *optstring = (relopt_string *) option->gen;
944
940
 
945
941
                                option->values.string_val = value;
946
942
                                nofree = true;
951
947
                        break;
952
948
                default:
953
949
                        elog(ERROR, "unsupported reloption type %d", option->gen->type);
954
 
                        parsed = true; /* quiet compiler */
 
950
                        parsed = true;          /* quiet compiler */
955
951
                        break;
956
952
        }
957
953
 
971
967
void *
972
968
allocateReloptStruct(Size base, relopt_value *options, int numoptions)
973
969
{
974
 
        Size    size = base;
975
 
        int             i;
 
970
        Size            size = base;
 
971
        int                     i;
976
972
 
977
973
        for (i = 0; i < numoptions; i++)
978
974
                if (options[i].gen->type == RELOPT_TYPE_STRING)
998
994
                           bool validate,
999
995
                           const relopt_parse_elt *elems, int numelems)
1000
996
{
1001
 
        int             i;
1002
 
        int             offset = basesize;
 
997
        int                     i;
 
998
        int                     offset = basesize;
1003
999
 
1004
1000
        for (i = 0; i < numoptions; i++)
1005
1001
        {
1006
 
                int             j;
1007
 
                bool    found = false;
 
1002
                int                     j;
 
1003
                bool            found = false;
1008
1004
 
1009
1005
                for (j = 0; j < numelems; j++)
1010
1006
                {
1011
1007
                        if (pg_strcasecmp(options[i].gen->name, elems[j].optname) == 0)
1012
1008
                        {
1013
1009
                                relopt_string *optstring;
1014
 
                                char   *itempos = ((char *) rdopts) + elems[j].offset;
1015
 
                                char   *string_val;
 
1010
                                char       *itempos = ((char *) rdopts) + elems[j].offset;
 
1011
                                char       *string_val;
1016
1012
 
1017
1013
                                switch (options[i].gen->type)
1018
1014
                                {
1073
1069
bytea *
1074
1070
default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
1075
1071
{
1076
 
        relopt_value   *options;
1077
 
        StdRdOptions   *rdopts;
1078
 
        int                             numoptions;
 
1072
        relopt_value *options;
 
1073
        StdRdOptions *rdopts;
 
1074
        int                     numoptions;
1079
1075
        static const relopt_parse_elt tab[] = {
1080
1076
                {"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
1081
1077
                {"autovacuum_enabled", RELOPT_TYPE_BOOL,
1082
 
                        offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)},
 
1078
                offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, enabled)},
1083
1079
                {"autovacuum_vacuum_threshold", RELOPT_TYPE_INT,
1084
 
                        offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_threshold)},
 
1080
                offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, vacuum_threshold)},
1085
1081
                {"autovacuum_analyze_threshold", RELOPT_TYPE_INT,
1086
 
                        offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_threshold)},
 
1082
                offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, analyze_threshold)},
1087
1083
                {"autovacuum_vacuum_cost_delay", RELOPT_TYPE_INT,
1088
 
                        offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_delay)},
 
1084
                offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, vacuum_cost_delay)},
1089
1085
                {"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,
1090
 
                        offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_limit)},
 
1086
                offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, vacuum_cost_limit)},
1091
1087
                {"autovacuum_freeze_min_age", RELOPT_TYPE_INT,
1092
 
                        offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_min_age)},
 
1088
                offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, freeze_min_age)},
1093
1089
                {"autovacuum_freeze_max_age", RELOPT_TYPE_INT,
1094
 
                        offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_max_age)},
 
1090
                offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, freeze_max_age)},
1095
1091
                {"autovacuum_freeze_table_age", RELOPT_TYPE_INT,
1096
 
                        offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_table_age)},
 
1092
                offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, freeze_table_age)},
1097
1093
                {"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL,
1098
 
                        offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_scale_factor)},
 
1094
                offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, vacuum_scale_factor)},
1099
1095
                {"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,
1100
 
                        offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_scale_factor)}
 
1096
                offsetof(StdRdOptions, autovacuum) +offsetof(AutoVacOpts, analyze_scale_factor)}
1101
1097
        };
1102
1098
 
1103
1099
        options = parseRelOptions(reloptions, validate, kind, &numoptions);