Re: Configuration parameters for plugin modules - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: Configuration parameters for plugin modules |
Date | |
Msg-id | 200405261510.i4QFAXc04604@candle.pha.pa.us Whole thread Raw |
In response to | Re: Configuration parameters for plugin modules (Thomas Hallgren <thhal@mailblocks.com>) |
List | pgsql-patches |
Patch applied. Thanks. As far as the documentation issues, these are all C interface issues, so we usually just add comments into the C code for plugin developers to use. Feel free to submit those if they are not already there. --------------------------------------------------------------------------- Thomas Hallgren wrote: > Same patch as before but I added a small change to the gram.y enabling > SET command to use qualified names. > > - thomas > Index: doc/src/sgml/runtime.sgml > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v > retrieving revision 1.263 > diff -u -r1.263 runtime.sgml > --- doc/src/sgml/runtime.sgml 29 Apr 2004 04:37:09 -0000 1.263 > +++ doc/src/sgml/runtime.sgml 19 May 2004 21:01:40 -0000 > @@ -2924,6 +2924,60 @@ > </variablelist> > </sect2> > > + <sect2 id="runtime-config-custom"> > + <title>Customized Options</title> > + > + <para> > + The following was designed to allow options not normally known to > + <productname>PostgreSQL</productname> to be declared in the posgresql.conf > + file and/or manipulated using the <command>SET</command> in a controlled > + manner so that add-on modules to the postgres proper (such as lanugage > + mappings for triggers and functions) can be configured in a unified way. > + </para> > + > + <variablelist> > + > + <varlistentry id="guc-custom_variable_classes" xreflabel="custom_variable_classes"> > + <term><varname>custom_variable_classes</varname> (<type>string</type>)</term> > + <indexterm><primary>custom_variable_classes</></> > + <listitem> > + <para> > + This variable specifies one or several classes to be used for custom > + variables. A custom variable is a variable not normally known to > + the <productname>PostgreSQL</productname> proper but used by some add > + on module. > + </para> > + > + <para> > + Aribtrary variables can be defined for each class specified here. Those > + variables will be treated as placeholders and have no meaning until the > + module that defines them is loaded. When a module for a specific class is > + loaded, it will add the proper variable definitions for the class > + associated with it, convert any placeholder values according to those > + definitions, and issue warnings for any placeholders that then remains. > + </para> > + > + <para> > + Here is an example what custom variables might look like: > + > +<programlisting> > +custom_variable_class = 'plr,pljava' > +plr.foo = '/usr/lib/R' > +pljava.baz = 1 > +plruby.var = true <== this one would generate an error > +</programlisting> > + </para> > + > + <para> > + This option can only be set at server start or in the > + <filename>postgresql.conf</filename> configuration file. > + </para> > + > + </listitem> > + </varlistentry> > + </variablelist> > + </sect2> > + > <sect2 id="runtime-config-developer"> > <title>Developer Options</title> > > Index: src/backend/parser/gram.y > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/parser/gram.y,v > retrieving revision 2.454 > diff -u -r2.454 gram.y > --- src/backend/parser/gram.y 10 May 2004 22:44:45 -0000 2.454 > +++ src/backend/parser/gram.y 19 May 2004 21:01:43 -0000 > @@ -309,7 +309,7 @@ > %type <str> Sconst comment_text > %type <str> UserId opt_boolean ColId_or_Sconst > %type <list> var_list var_list_or_default > -%type <str> ColId ColLabel type_name param_name > +%type <str> ColId ColLabel var_name type_name param_name > %type <node> var_value zone_value > > %type <keyword> unreserved_keyword func_name_keyword > @@ -857,14 +857,14 @@ > } > ; > > -set_rest: ColId TO var_list_or_default > +set_rest: var_name TO var_list_or_default > { > VariableSetStmt *n = makeNode(VariableSetStmt); > n->name = $1; > n->args = $3; > $$ = n; > } > - | ColId '=' var_list_or_default > + | var_name '=' var_list_or_default > { > VariableSetStmt *n = makeNode(VariableSetStmt); > n->name = $1; > @@ -914,6 +914,19 @@ > n->name = "session_authorization"; > n->args = NIL; > $$ = n; > + } > + ; > + > +var_name: > + ColId { $$ = $1; } > + | var_name '.' ColId > + { > + int qLen = strlen($1); > + char* qualName = palloc(qLen + strlen($3) + 2); > + strcpy(qualName, $1); > + qualName[qLen] = '.'; > + strcpy(qualName + qLen + 1, $3); > + $$ = qualName; > } > ; > > Index: src/backend/utils/misc/guc-file.l > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/guc-file.l,v > retrieving revision 1.21 > diff -u -r1.21 guc-file.l > --- src/backend/utils/misc/guc-file.l 24 Feb 2004 22:06:32 -0000 1.21 > +++ src/backend/utils/misc/guc-file.l 19 May 2004 21:01:43 -0000 > @@ -34,6 +34,7 @@ > GUC_REAL = 4, > GUC_EQUALS = 5, > GUC_UNQUOTED_STRING = 6, > + GUC_QUALIFIED_ID = 7, > GUC_EOL = 99, > GUC_ERROR = 100 > }; > @@ -65,6 +66,7 @@ > LETTER_OR_DIGIT [A-Za-z_0-9\200-\377] > > ID {LETTER}{LETTER_OR_DIGIT}* > +QUALIFIED_ID {ID}"."{ID} > > UNQUOTED_STRING {LETTER}({LETTER_OR_DIGIT}|[-._:/])* > STRING \'([^'\n]|\\.)*\' > @@ -76,6 +78,7 @@ > #.*$ /* eat comment */ > > {ID} return GUC_ID; > +{QUALIFIED_ID} return GUC_QUALIFIED_ID; > {STRING} return GUC_STRING; > {UNQUOTED_STRING} return GUC_UNQUOTED_STRING; > {INTEGER} return GUC_INTEGER; > @@ -180,7 +183,7 @@ > case 0: /* no previous input */ > if (token == GUC_EOL) /* empty line */ > continue; > - if (token != GUC_ID) > + if (token != GUC_ID && token != GUC_QUALIFIED_ID) > goto parse_error; > opt_name = strdup(yytext); > if (opt_name == NULL) > @@ -216,6 +219,24 @@ > case 2: /* now we'd like an end of line */ > if (token != GUC_EOL) > goto parse_error; > + > + if (strcmp(opt_name, "custom_variable_classes") == 0) > + { > + /* This variable must be added first as it controls the validity > + * of other variables > + */ > + if (!set_config_option(opt_name, opt_value, context, > + PGC_S_FILE, false, true)) > + { > + FreeFile(fp); > + free(filename); > + goto cleanup_exit; > + } > + > + /* Don't include in list */ > + parse_state = 0; > + break; > + } > > /* append to list */ > item = malloc(sizeof *item); > Index: src/backend/utils/misc/guc.c > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v > retrieving revision 1.205 > diff -u -r1.205 guc.c > --- src/backend/utils/misc/guc.c 8 May 2004 02:11:46 -0000 1.205 > +++ src/backend/utils/misc/guc.c 19 May 2004 21:01:44 -0000 > @@ -20,6 +20,7 @@ > #include <float.h> > #include <limits.h> > #include <unistd.h> > +#include <ctype.h> > > #include "utils/guc.h" > #include "utils/guc_tables.h" > @@ -103,6 +104,8 @@ > static const char *assign_log_stmtlvl(int *var, const char *newval, > bool doit, GucSource source); > static bool assign_phony_autocommit(bool newval, bool doit, GucSource source); > +static const char *assign_custom_variable_classes(const char *newval, bool doit, > + GucSource source); > static bool assign_stage_log_stats(bool newval, bool doit, GucSource source); > static bool assign_log_stats(bool newval, bool doit, GucSource source); > > @@ -167,6 +170,7 @@ > static char *session_authorization_string; > static char *timezone_string; > static char *XactIsoLevel_string; > +static char *custom_variable_classes; > static int max_function_args; > static int max_index_keys; > static int max_identifier_length; > @@ -1728,6 +1732,16 @@ > XLOG_sync_method_default, assign_xlog_sync_method, NULL > }, > > + { > + {"custom_variable_classes", PGC_POSTMASTER, RESOURCES_KERNEL, > + gettext_noop("Sets the list of known custom variable classes"), > + NULL, > + GUC_LIST_INPUT | GUC_LIST_QUOTE > + }, > + &custom_variable_classes, > + NULL, assign_custom_variable_classes, NULL > + }, > + > /* End-of-list marker */ > { > {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL > @@ -1753,8 +1767,15 @@ > /* > * Actual lookup of variables is done through this single, sorted array. > */ > -struct config_generic **guc_variables; > -int num_guc_variables; > +static struct config_generic **guc_variables; > + > +/* Current number of variables contained in the vector > + */ > +static int num_guc_variables; > + > +/* Vector capacity > + */ > +static int size_guc_variables; > > static bool guc_dirty; /* TRUE if need to do commit/abort work */ > > @@ -1768,6 +1789,10 @@ > static void ReportGUCOption(struct config_generic * record); > static char *_ShowOption(struct config_generic * record); > > +struct config_generic** get_guc_variables() > +{ > + return guc_variables; > +} > > /* > * Build the sorted array. This is split out so that it could be > @@ -1777,6 +1802,7 @@ > void > build_guc_variables(void) > { > + int size_vars; > int num_vars = 0; > struct config_generic **guc_vars; > int i; > @@ -1814,8 +1840,12 @@ > num_vars++; > } > > + /* Create table with 20% slack > + */ > + size_vars = num_vars + num_vars / 4; > + > guc_vars = (struct config_generic **) > - malloc(num_vars * sizeof(struct config_generic *)); > + malloc(size_vars * sizeof(struct config_generic *)); > if (!guc_vars) > ereport(FATAL, > (errcode(ERRCODE_OUT_OF_MEMORY), > @@ -1835,15 +1865,105 @@ > for (i = 0; ConfigureNamesString[i].gen.name; i++) > guc_vars[num_vars++] = &ConfigureNamesString[i].gen; > > - qsort((void *) guc_vars, num_vars, sizeof(struct config_generic *), > - guc_var_compare); > - > if (guc_variables) > free(guc_variables); > guc_variables = guc_vars; > num_guc_variables = num_vars; > + size_guc_variables = size_vars; > + qsort((void*) guc_variables, num_guc_variables, > + sizeof(struct config_generic*), guc_var_compare); > +} > + > +static bool > +is_custom_class(const char *name, int dotPos) > +{ > + /* The assign_custom_variable_classes has made sure no empty > + * identifiers or whitespace exists in the variable > + */ > + bool result = false; > + const char *ccs = GetConfigOption("custom_variable_classes"); > + if(ccs != NULL) > + { > + const char *start = ccs; > + for(;; ++ccs) > + { > + int c = *ccs; > + if(c == 0 || c == ',') > + { > + if(dotPos == ccs - start && strncmp(start, name, dotPos) == 0) > + { > + result = true; > + break; > + } > + if(c == 0) > + break; > + start = ccs + 1; > + } > + } > + } > + return result; > } > > +/* > + * Add a new GUC variable to the list of known variables. The > + * list is expanded if needed. > + */ > +static void > +add_guc_variable(struct config_generic *var) > +{ > + if(num_guc_variables + 1 >= size_guc_variables) > + { > + /* Increase the vector with 20% > + */ > + int size_vars = size_guc_variables + size_guc_variables / 4; > + if(size_vars == 0) > + size_vars = 100; > + > + struct config_generic** guc_vars = (struct config_generic**) > + malloc(size_vars * sizeof(struct config_generic*)); > + > + if (guc_variables != NULL) > + { > + memcpy(guc_vars, guc_variables, > + num_guc_variables * sizeof(struct config_generic*)); > + free(guc_variables); > + } > + > + guc_variables = guc_vars; > + size_guc_variables = size_vars; > + } > + guc_variables[num_guc_variables++] = var; > + qsort((void*) guc_variables, num_guc_variables, > + sizeof(struct config_generic*), guc_var_compare); > +} > + > +/* > + * Create and add a placeholder variable. Its presumed to belong > + * to a valid custom variable class at this point. > + */ > +static struct config_string* > +add_placeholder_variable(const char *name) > +{ > + size_t sz = sizeof(struct config_string) + sizeof(char*); > + struct config_string* var = (struct config_string*)malloc(sz); > + struct config_generic* gen = &var->gen; > + > + memset(var, 0, sz); > + > + gen->name = strdup(name); > + gen->context = PGC_USERSET; > + gen->group = CUSTOM_OPTIONS; > + gen->short_desc = "GUC placeholder variable"; > + gen->flags = GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE | GUC_CUSTOM_PLACEHOLDER; > + gen->vartype = PGC_STRING; > + > + /* The char* is allocated at the end of the struct since we have > + * no 'static' place to point to. > + */ > + var->variable = (char**)(var + 1); > + add_guc_variable((struct config_generic*)var); > + return var; > +} > > /* > * Look up option NAME. If it exists, return a pointer to its record, > @@ -1852,6 +1972,7 @@ > static struct config_generic * > find_option(const char *name) > { > + const char *dot; > const char **key = &name; > struct config_generic **res; > int i; > @@ -1881,6 +2002,16 @@ > return find_option(map_old_guc_names[i+1]); > } > > + /* Check if the name is qualified, and if so, check if the qualifier > + * maps to a custom variable class. > + */ > + dot = strchr(name, GUC_QUALIFIER_SEPARATOR); > + if(dot != NULL && is_custom_class(name, dot - name)) > + /* > + * Add a placeholder variable for this name > + */ > + return (struct config_generic*)add_placeholder_variable(name); > + > /* Unknown name */ > return NULL; > } > @@ -3459,6 +3590,196 @@ > PG_RETURN_TEXT_P(result_text); > } > > +static void > +define_custom_variable(struct config_generic* variable) > +{ > + const char* name = variable->name; > + const char** nameAddr = &name; > + const char* value; > + struct config_string* pHolder; > + struct config_generic** res = (struct config_generic**)bsearch( > + (void*)&nameAddr, > + (void*)guc_variables, > + num_guc_variables, > + sizeof(struct config_generic*), > + guc_var_compare); > + > + if(res == NULL) > + { > + add_guc_variable(variable); > + return; > + } > + > + /* This better be a placeholder > + */ > + if(((*res)->flags & GUC_CUSTOM_PLACEHOLDER) == 0) > + { > + ereport(ERROR, > + (errcode(ERRCODE_INTERNAL_ERROR), > + errmsg("attempt to redefine parameter \"%s\"", name))); > + } > + pHolder = (struct config_string*)*res; > + > + /* We have the same name, no sorting is necessary. > + */ > + *res = variable; > + > + value = *pHolder->variable; > + > + /* Assign the variable stored in the placeholder to the real > + * variable. > + */ > + set_config_option(name, value, > + pHolder->gen.context, pHolder->gen.source, > + false, true); > + > + /* Free up stuff occupied by the placeholder variable > + */ > + if(value != NULL) > + free((void*)value); > + > + if(pHolder->reset_val != NULL && pHolder->reset_val != value) > + free(pHolder->reset_val); > + > + if(pHolder->session_val != NULL > + && pHolder->session_val != value > + && pHolder->session_val != pHolder->reset_val) > + free(pHolder->session_val); > + > + if(pHolder->tentative_val != NULL > + && pHolder->tentative_val != value > + && pHolder->tentative_val != pHolder->reset_val > + && pHolder->tentative_val != pHolder->session_val) > + free(pHolder->tentative_val); > + > + free(pHolder); > +} > + > +static void init_custom_variable( > + struct config_generic* gen, > + const char* name, > + const char* short_desc, > + const char* long_desc, > + GucContext context, > + enum config_type type) > +{ > + gen->name = strdup(name); > + gen->context = context; > + gen->group = CUSTOM_OPTIONS; > + gen->short_desc = short_desc; > + gen->long_desc = long_desc; > + gen->vartype = type; > +} > + > +void DefineCustomBoolVariable( > + const char* name, > + const char* short_desc, > + const char* long_desc, > + bool* valueAddr, > + GucContext context, > + GucBoolAssignHook assign_hook, > + GucShowHook show_hook) > +{ > + size_t sz = sizeof(struct config_bool); > + struct config_bool* var = (struct config_bool*)malloc(sz); > + > + memset(var, 0, sz); > + init_custom_variable(&var->gen, name, short_desc, long_desc, context, PGC_BOOL); > + > + var->variable = valueAddr; > + var->reset_val = *valueAddr; > + var->assign_hook = assign_hook; > + var->show_hook = show_hook; > + define_custom_variable(&var->gen); > +} > + > +void DefineCustomIntVariable( > + const char* name, > + const char* short_desc, > + const char* long_desc, > + int* valueAddr, > + GucContext context, > + GucIntAssignHook assign_hook, > + GucShowHook show_hook) > +{ > + size_t sz = sizeof(struct config_int); > + struct config_int* var = (struct config_int*)malloc(sz); > + > + memset(var, 0, sz); > + init_custom_variable(&var->gen, name, short_desc, long_desc, context, PGC_INT); > + > + var->variable = valueAddr; > + var->reset_val = *valueAddr; > + var->assign_hook = assign_hook; > + var->show_hook = show_hook; > + define_custom_variable(&var->gen); > +} > + > +void DefineCustomRealVariable( > + const char* name, > + const char* short_desc, > + const char* long_desc, > + double* valueAddr, > + GucContext context, > + GucRealAssignHook assign_hook, > + GucShowHook show_hook) > +{ > + size_t sz = sizeof(struct config_real); > + struct config_real* var = (struct config_real*)malloc(sz); > + > + memset(var, 0, sz); > + init_custom_variable(&var->gen, name, short_desc, long_desc, context, PGC_REAL); > + > + var->variable = valueAddr; > + var->reset_val = *valueAddr; > + var->assign_hook = assign_hook; > + var->show_hook = show_hook; > + define_custom_variable(&var->gen); > +} > + > +void DefineCustomStringVariable( > + const char* name, > + const char* short_desc, > + const char* long_desc, > + char** valueAddr, > + GucContext context, > + GucStringAssignHook assign_hook, > + GucShowHook show_hook) > +{ > + size_t sz = sizeof(struct config_string); > + struct config_string* var = (struct config_string*)malloc(sz); > + > + memset(var, 0, sz); > + init_custom_variable(&var->gen, name, short_desc, long_desc, context, PGC_STRING); > + > + var->variable = valueAddr; > + var->reset_val = *valueAddr; > + var->assign_hook = assign_hook; > + var->show_hook = show_hook; > + define_custom_variable(&var->gen); > +} > + > +extern void EmittWarningsOnPlaceholders(const char* className) > +{ > + struct config_generic** vars = guc_variables; > + struct config_generic** last = vars + num_guc_variables; > + > + int nameLen = strlen(className); > + while(vars < last) > + { > + struct config_generic* var = *vars++; > + if((var->flags & GUC_CUSTOM_PLACEHOLDER) != 0 && > + strncmp(className, var->name, nameLen) == 0 && > + var->name[nameLen] == GUC_QUALIFIER_SEPARATOR) > + { > + ereport(INFO, > + (errcode(ERRCODE_UNDEFINED_OBJECT), > + errmsg("unrecognized configuration parameter \"%s\"", var->name))); > + } > + } > +} > + > + > /* > * SHOW command > */ > @@ -4710,6 +5031,68 @@ > return true; > } > > +static const char * > +assign_custom_variable_classes(const char *newval, bool doit, GucSource source) > +{ > + /* Check syntax. newval must be a comma separated list of identifiers. > + * Whitespace is allowed but skipped. > + */ > + bool hasSpaceAfterToken = false; > + const char *cp = newval; > + int symLen = 0; > + int c; > + StringInfoData buf; > + > + initStringInfo(&buf); > + while((c = *cp++) != 0) > + { > + if(isspace(c)) > + { > + if(symLen > 0) > + hasSpaceAfterToken = true; > + continue; > + } > + > + if(c == ',') > + { > + hasSpaceAfterToken = false; > + if(symLen > 0) > + { > + symLen = 0; > + appendStringInfoChar(&buf, ','); > + } > + continue; > + } > + > + if(hasSpaceAfterToken || !isalnum(c)) > + { > + /* Syntax error due to token following space after > + * token or non alpha numeric character > + */ > + pfree(buf.data); > + ereport(WARNING, > + (errcode(ERRCODE_SYNTAX_ERROR), > + errmsg("illegal syntax for custom_variable_classes \"%s\"", newval))); > + return NULL; > + } > + symLen++; > + appendStringInfoChar(&buf, (char)c); > + } > + > + if(symLen == 0 && buf.len > 0) > + /* > + * Remove stray ',' at end > + */ > + buf.data[--buf.len] = 0; > + > + if(buf.len == 0) > + newval = NULL; > + else if(doit) > + newval = strdup(buf.data); > + > + pfree(buf.data); > + return newval; > +} > > static bool > assign_stage_log_stats(bool newval, bool doit, GucSource source) > Index: src/backend/utils/misc/help_config.c > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/help_config.c,v > retrieving revision 1.9 > diff -u -r1.9 help_config.c > --- src/backend/utils/misc/help_config.c 29 Nov 2003 19:52:04 -0000 1.9 > +++ src/backend/utils/misc/help_config.c 19 May 2004 21:01:44 -0000 > @@ -47,13 +47,15 @@ > GucInfoMain(void) > { > int i; > + struct config_generic **guc_vars = get_guc_variables(); > + int numOpts = GetNumConfigOptions(); > > /* Initialize the guc_variables[] array */ > build_guc_variables(); > > - for (i = 0; i < num_guc_variables; i++) > + for (i = 0; i < numOpts; i++) > { > - mixedStruct *var = (mixedStruct *) guc_variables[i]; > + mixedStruct *var = (mixedStruct *) guc_vars[i]; > > if (displayStruct(var)) > printMixedStruct(var); > Index: src/include/utils/guc.h > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/include/utils/guc.h,v > retrieving revision 1.45 > diff -u -r1.45 guc.h > --- src/include/utils/guc.h 7 Apr 2004 05:05:50 -0000 1.45 > +++ src/include/utils/guc.h 19 May 2004 21:01:45 -0000 > @@ -102,6 +102,15 @@ > PGC_S_SESSION /* SET command */ > } GucSource; > > +typedef const char* (*GucStringAssignHook)(const char *newval, bool doit, GucSource source); > +typedef bool (*GucBoolAssignHook)(bool newval, bool doit, GucSource source); > +typedef bool (*GucIntAssignHook)(int newval, bool doit, GucSource source); > +typedef bool (*GucRealAssignHook)(double newval, bool doit, GucSource source); > + > +typedef const char* (*GucShowHook)(void); > + > +#define GUC_QUALIFIER_SEPARATOR '.' > + > /* GUC vars that are actually declared in guc.c, rather than elsewhere */ > extern bool log_duration; > extern bool Debug_print_plan; > @@ -129,6 +138,45 @@ > > extern void SetConfigOption(const char *name, const char *value, > GucContext context, GucSource source); > + > +extern void DefineCustomBoolVariable( > + const char* name, > + const char* short_desc, > + const char* long_desc, > + bool* valueAddr, > + GucContext context, > + GucBoolAssignHook assign_hook, > + GucShowHook show_hook); > + > +extern void DefineCustomIntVariable( > + const char* name, > + const char* short_desc, > + const char* long_desc, > + int* valueAddr, > + GucContext context, > + GucIntAssignHook assign_hook, > + GucShowHook show_hook); > + > +extern void DefineCustomRealVariable( > + const char* name, > + const char* short_desc, > + const char* long_desc, > + double* valueAddr, > + GucContext context, > + GucRealAssignHook assign_hook, > + GucShowHook show_hook); > + > +extern void DefineCustomStringVariable( > + const char* name, > + const char* short_desc, > + const char* long_desc, > + char** valueAddr, > + GucContext context, > + GucStringAssignHook assign_hook, > + GucShowHook show_hook); > + > +extern void EmittWarningsOnPlaceholders(const char* className); > + > extern const char *GetConfigOption(const char *name); > extern const char *GetConfigOptionResetString(const char *name); > extern void ProcessConfigFile(GucContext context); > Index: src/include/utils/guc_tables.h > =================================================================== > RCS file: /projects/cvsroot/pgsql-server/src/include/utils/guc_tables.h,v > retrieving revision 1.10 > diff -u -r1.10 guc_tables.h > --- src/include/utils/guc_tables.h 5 Apr 2004 03:02:11 -0000 1.10 > +++ src/include/utils/guc_tables.h 19 May 2004 21:01:45 -0000 > @@ -51,7 +51,8 @@ > COMPAT_OPTIONS_PREVIOUS, > COMPAT_OPTIONS_CLIENT, > DEVELOPER_OPTIONS, > - COMPILE_OPTIONS > + COMPILE_OPTIONS, > + CUSTOM_OPTIONS > }; > > /* > @@ -98,6 +99,7 @@ > #define GUC_REPORT 0x0010 /* auto-report changes to client */ > #define GUC_NOT_IN_SAMPLE 0x0020 /* not in postgresql.conf.sample */ > #define GUC_DISALLOW_IN_FILE 0x0040 /* can't set in postgresql.conf */ > +#define GUC_CUSTOM_PLACEHOLDER 0x0080 /* placeholder for a custom variable */ > > /* bit values in status field */ > #define GUC_HAVE_TENTATIVE 0x0001 /* tentative value is defined */ > @@ -113,8 +115,8 @@ > /* (all but reset_val are constants) */ > bool *variable; > bool reset_val; > - bool (*assign_hook) (bool newval, bool doit, GucSource source); > - const char *(*show_hook) (void); > + GucBoolAssignHook assign_hook; > + GucShowHook show_hook; > /* variable fields, initialized at runtime: */ > bool session_val; > bool tentative_val; > @@ -129,8 +131,8 @@ > int reset_val; > int min; > int max; > - bool (*assign_hook) (int newval, bool doit, GucSource source); > - const char *(*show_hook) (void); > + GucIntAssignHook assign_hook; > + GucShowHook show_hook; > /* variable fields, initialized at runtime: */ > int session_val; > int tentative_val; > @@ -145,8 +147,8 @@ > double reset_val; > double min; > double max; > - bool (*assign_hook) (double newval, bool doit, GucSource source); > - const char *(*show_hook) (void); > + GucRealAssignHook assign_hook; > + GucShowHook show_hook; > /* variable fields, initialized at runtime: */ > double session_val; > double tentative_val; > @@ -159,8 +161,8 @@ > /* (all are constants) */ > char **variable; > const char *boot_val; > - const char *(*assign_hook) (const char *newval, bool doit, GucSource source); > - const char *(*show_hook) (void); > + GucStringAssignHook assign_hook; > + GucShowHook show_hook; > /* variable fields, initialized at runtime: */ > char *reset_val; > char *session_val; > @@ -173,9 +175,8 @@ > extern const char *const GucContext_Names[]; > extern const char *const GucSource_Names[]; > > -/* the current set of variables */ > -extern struct config_generic **guc_variables; > -extern int num_guc_variables; > +/* get the current set of variables */ > +extern struct config_generic **get_guc_variables(void); > > extern void build_guc_variables(void); > > > ---------------------------(end of broadcast)--------------------------- > TIP 6: Have you searched our list archives? > > http://archives.postgresql.org -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 359-1001 + If your life is a hard drive, | 13 Roberts Road + Christ can be your backup. | Newtown Square, Pennsylvania 19073
pgsql-patches by date: