Re: [Fwd: contrib/showguc (was Re: [HACKERS] revised sample

From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Joe Conway <mail(at)joeconway(dot)com>
Cc: PostgreSQL-patches <pgsql-patches(at)postgresql(dot)org>
Subject: Re: [Fwd: contrib/showguc (was Re: [HACKERS] revised sample
Date: 2002-06-17 21:44:46
Message-ID: 200206172144.g5HLikx15706@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers pgsql-patches


Your patch has been added to the PostgreSQL unapplied patches list at:

http://candle.pha.pa.us/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

---------------------------------------------------------------------------

Joe Conway wrote:
> Tom Lane wrote:
> > Well, we're not doing that; and I see no good reason to make the thing
> > be a builtin function at all. Since it's just an example, it can very
> > well be a contrib item with a creation script. Probably *should* be,
> > in fact, because dynamically created functions are what other people are
> > going to be building; an example of how to do it as a builtin function
> > isn't as helpful.
>
> Here is a patch for contrib/showguc. It can serve as a reference
> implementation for a C function which returns setof composite. It
> required some small changes in guc.c and guc.h so that the number of GUC
> variables, and their values, could be accessed. Example usage as shown
> below:
>
> test=# select * from show_all_vars() where varname = 'wal_sync_method';
> varname | varval
> -----------------+-----------
> wal_sync_method | fdatasync
> (1 row)
>
> test=# select show_var('wal_sync_method');
> show_var
> -----------
> fdatasync
> (1 row)
>
>
> show_var() is neither composite nor set returning, but it seemed like a
> worthwhile addition. Please apply if there are no objections.
>
> Thanks,
>
> Joe
>

> Index: contrib/showguc/Makefile
> ===================================================================
> RCS file: contrib/showguc/Makefile
> diff -N contrib/showguc/Makefile
> *** /dev/null 1 Jan 1970 00:00:00 -0000
> --- contrib/showguc/Makefile 27 May 2002 00:24:44 -0000
> ***************
> *** 0 ****
> --- 1,9 ----
> + subdir = contrib/showguc
> + top_builddir = ../..
> + include $(top_builddir)/src/Makefile.global
> +
> + MODULES = showguc
> + DATA_built = showguc.sql
> + DOCS = README.showguc
> +
> + include $(top_srcdir)/contrib/contrib-global.mk
> Index: contrib/showguc/README.showguc
> ===================================================================
> RCS file: contrib/showguc/README.showguc
> diff -N contrib/showguc/README.showguc
> *** /dev/null 1 Jan 1970 00:00:00 -0000
> --- contrib/showguc/README.showguc 10 Jun 2002 00:16:48 -0000
> ***************
> *** 0 ****
> --- 1,105 ----
> + /*
> + * showguc
> + *
> + * Sample to demonstrate a C function which returns setof composite.
> + * Joe Conway <mail(at)joeconway(dot)com>
> + *
> + * Copyright 2002 by PostgreSQL Global Development Group
> + *
> + * Permission to use, copy, modify, and distribute this software and its
> + * documentation for any purpose, without fee, and without a written agreement
> + * is hereby granted, provided that the above copyright notice and this
> + * paragraph and the following two paragraphs appear in all copies.
> + *
> + * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
> + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
> + * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
> + * DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + *
> + * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
> + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
> + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
> + * ON AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAS NO OBLIGATIONS TO
> + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
> + *
> + */
> + Version 0.1 (9 June, 2002):
> + First release
> +
> + Release Notes:
> +
> + Version 0.1
> + - initial release
> +
> + Installation:
> + Place these files in a directory called 'showguc' under 'contrib' in the PostgreSQL source tree. Then run:
> +
> + make
> + make install
> +
> + You can use showguc.sql to create the functions in your database of choice, e.g.
> +
> + psql -U postgres template1 < showguc.sql
> +
> + installs following functions into database template1:
> +
> + show_all_vars() - returns all GUC variables
> + show_var(text) - returns value of the requested GUC variable
> +
> + Documentation
> + ==================================================================
> + Name
> +
> + show_all_vars() - returns all GUC variables
> +
> + Synopsis
> +
> + show_all_vars()
> +
> + Inputs
> +
> + none
> +
> + Outputs
> +
> + Returns setof __gucvar, where __gucvar is (varname TEXT, varval TEXT). All
> + GUC variables displayed by SHOW ALL are returned as a set.
> +
> + Example usage
> +
> + test=# select * from show_all_vars() where varname = 'wal_sync_method';
> + varname | varval
> + -----------------+-----------
> + wal_sync_method | fdatasync
> + (1 row)
> +
> + ==================================================================
> + Name
> +
> + show_var(text varname) - returns value of GUC variable varname
> +
> + Synopsis
> +
> + show_var(varname)
> +
> + Inputs
> +
> + varname
> + The name of a GUC variable
> +
> + Outputs
> +
> + Returns the current value of varname.
> +
> + Example usage
> +
> + test=# select show_var('wal_sync_method');
> + show_var
> + -----------
> + fdatasync
> + (1 row)
> +
> + ==================================================================
> + -- Joe Conway
> +
> Index: contrib/showguc/showguc.c
> ===================================================================
> RCS file: contrib/showguc/showguc.c
> diff -N contrib/showguc/showguc.c
> *** /dev/null 1 Jan 1970 00:00:00 -0000
> --- contrib/showguc/showguc.c 10 Jun 2002 00:02:14 -0000
> ***************
> *** 0 ****
> --- 1,152 ----
> + /*
> + * showguc
> + *
> + * Sample to demonstrate a C function which returns setof composite.
> + * Joe Conway <mail(at)joeconway(dot)com>
> + *
> + * Copyright 2002 by PostgreSQL Global Development Group
> + *
> + * Permission to use, copy, modify, and distribute this software and its
> + * documentation for any purpose, without fee, and without a written agreement
> + * is hereby granted, provided that the above copyright notice and this
> + * paragraph and the following two paragraphs appear in all copies.
> + *
> + * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
> + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
> + * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
> + * DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + *
> + * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
> + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
> + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
> + * ON AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAS NO OBLIGATIONS TO
> + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
> + *
> + */
> + #include "postgres.h"
> +
> + #include "fmgr.h"
> + #include "funcapi.h"
> + #include "utils/builtins.h"
> + #include "utils/guc.h"
> +
> + #include "showguc.h"
> +
> + /*
> + * showguc_all - equiv to SHOW ALL command but implemented as
> + * an SRF.
> + */
> + PG_FUNCTION_INFO_V1(showguc_all);
> + Datum
> + showguc_all(PG_FUNCTION_ARGS)
> + {
> + FuncCallContext *funcctx;
> + TupleDesc tupdesc;
> + int call_cntr;
> + int max_calls;
> + TupleTableSlot *slot;
> + AttInMetadata *attinmeta;
> +
> + /* stuff done only on the first call of the function */
> + if(SRF_IS_FIRSTPASS())
> + {
> + /* create a function context for cross-call persistence */
> + funcctx = SRF_FIRSTCALL_INIT();
> +
> + /*
> + * Build a tuple description for a pg__guc tuple
> + */
> + tupdesc = RelationNameGetTupleDesc("__gucvar");
> +
> + /* allocate a slot for a tuple with this tupdesc */
> + slot = TupleDescGetSlot(tupdesc);
> +
> + /* assign slot to function context */
> + funcctx->slot = slot;
> +
> + /*
> + * Generate attribute metadata needed later to produce tuples from raw
> + * C strings
> + */
> + attinmeta = TupleDescGetAttInMetadata(tupdesc);
> + funcctx->attinmeta = attinmeta;
> +
> + /* total number of tuples to be returned */
> + funcctx->max_calls = GetNumGUCConfigOptions();
> + }
> +
> + /* stuff done on every call of the function */
> + funcctx = SRF_PERCALL_SETUP(funcctx);
> +
> + call_cntr = funcctx->call_cntr;
> + max_calls = funcctx->max_calls;
> + slot = funcctx->slot;
> + attinmeta = funcctx->attinmeta;
> +
> + if (call_cntr < max_calls) /* do when there is more left to send */
> + {
> + char *varname;
> + char *varval;
> + char **values;
> + HeapTuple tuple;
> + Datum result;
> +
> + /*
> + * Get the next GUC variable name and value
> + */
> + varval = GetGUCConfigOptionNum(call_cntr, &varname);
> +
> + /*
> + * Prepare a values array for storage in our slot.
> + * This should be an array of C strings which will
> + * be processed later by the appropriate "in" functions.
> + */
> + values = (char **) palloc(2 * sizeof(char *));
> + values[0] = varname;
> + values[1] = varval;
> +
> + /* build a tuple */
> + tuple = BuildTupleFromCStrings(attinmeta, values);
> +
> + /* make the tuple into a datum */
> + result = TupleGetDatum(slot, tuple);
> +
> + /* Clean up */
> + pfree(varname);
> + pfree(values);
> +
> + SRF_RETURN_NEXT(funcctx, result);
> + }
> + else /* do when there is no more left */
> + {
> + SRF_RETURN_DONE(funcctx);
> + }
> + }
> +
> +
> + /*
> + * showguc_name - equiv to SHOW X command but implemented as
> + * a function.
> + */
> + PG_FUNCTION_INFO_V1(showguc_name);
> + Datum
> + showguc_name(PG_FUNCTION_ARGS)
> + {
> + char *varname;
> + char *varval;
> + text *result_text;
> +
> + /* Get the GUC variable name */
> + varname = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0))));
> +
> + /* Get the value */
> + varval = GetGUCConfigOptionName(varname);
> +
> + /* Convert to text */
> + result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(varval)));
> +
> + /* return it */
> + PG_RETURN_TEXT_P(result_text);
> + }
> +
> Index: contrib/showguc/showguc.h
> ===================================================================
> RCS file: contrib/showguc/showguc.h
> diff -N contrib/showguc/showguc.h
> *** /dev/null 1 Jan 1970 00:00:00 -0000
> --- contrib/showguc/showguc.h 10 Jun 2002 00:01:02 -0000
> ***************
> *** 0 ****
> --- 1,37 ----
> + /*
> + * showguc
> + *
> + * Sample to demonstrate a C function which returns setof composite.
> + * Joe Conway <mail(at)joeconway(dot)com>
> + *
> + * Copyright 2002 by PostgreSQL Global Development Group
> + *
> + * Permission to use, copy, modify, and distribute this software and its
> + * documentation for any purpose, without fee, and without a written agreement
> + * is hereby granted, provided that the above copyright notice and this
> + * paragraph and the following two paragraphs appear in all copies.
> + *
> + * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
> + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
> + * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
> + * DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + *
> + * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
> + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
> + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
> + * ON AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAS NO OBLIGATIONS TO
> + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
> + *
> + */
> +
> + #ifndef SHOWGUC_H
> + #define SHOWGUC_H
> +
> + /*
> + * External declarations
> + */
> + extern Datum showguc_all(PG_FUNCTION_ARGS);
> + extern Datum showguc_name(PG_FUNCTION_ARGS);
> +
> + #endif /* SHOWGUC_H */
> Index: contrib/showguc/showguc.sql.in
> ===================================================================
> RCS file: contrib/showguc/showguc.sql.in
> diff -N contrib/showguc/showguc.sql.in
> *** /dev/null 1 Jan 1970 00:00:00 -0000
> --- contrib/showguc/showguc.sql.in 10 Jun 2002 00:03:13 -0000
> ***************
> *** 0 ****
> --- 1,10 ----
> + CREATE VIEW __gucvar AS
> + SELECT
> + ''::TEXT AS varname,
> + ''::TEXT AS varval;
> +
> + CREATE OR REPLACE FUNCTION show_all_vars() RETURNS setof __gucvar
> + AS 'MODULE_PATHNAME','showguc_all' LANGUAGE 'c' STABLE STRICT;
> +
> + CREATE OR REPLACE FUNCTION show_var(text) RETURNS text
> + AS 'MODULE_PATHNAME','showguc_name' LANGUAGE 'c' STABLE STRICT;
> Index: src/backend/utils/misc/guc.c
> ===================================================================
> RCS file: /opt/src/cvs/pgsql/src/backend/utils/misc/guc.c,v
> retrieving revision 1.69
> diff -c -r1.69 guc.c
> *** src/backend/utils/misc/guc.c 17 May 2002 20:32:29 -0000 1.69
> --- src/backend/utils/misc/guc.c 9 Jun 2002 22:51:45 -0000
> ***************
> *** 824,830 ****
>
>
> static int guc_var_compare(const void *a, const void *b);
> ! static void _ShowOption(struct config_generic *record);
>
>
> /*
> --- 824,830 ----
>
>
> static int guc_var_compare(const void *a, const void *b);
> ! static char *_ShowOption(struct config_generic *record);
>
>
> /*
> ***************
> *** 2204,2215 ****
> ShowGUCConfigOption(const char *name)
> {
> struct config_generic *record;
>
> record = find_option(name);
> if (record == NULL)
> elog(ERROR, "Option '%s' is not recognized", name);
>
> ! _ShowOption(record);
> }
>
> /*
> --- 2204,2221 ----
> ShowGUCConfigOption(const char *name)
> {
> struct config_generic *record;
> + char *val;
>
> record = find_option(name);
> if (record == NULL)
> elog(ERROR, "Option '%s' is not recognized", name);
>
> ! val = _ShowOption(record);
> ! if(val != NULL)
> ! {
> ! elog(INFO, "%s is %s", record->name, val);
> ! pfree(val);
> ! }
> }
>
> /*
> ***************
> *** 2219,2239 ****
> ShowAllGUCConfig(void)
> {
> int i;
>
> for (i = 0; i < num_guc_variables; i++)
> {
> struct config_generic *conf = guc_variables[i];
>
> if ((conf->flags & GUC_NO_SHOW_ALL) == 0)
> ! _ShowOption(conf);
> }
> }
>
> ! static void
> _ShowOption(struct config_generic *record)
> {
> char buffer[256];
> const char *val;
>
> switch (record->vartype)
> {
> --- 2225,2295 ----
> ShowAllGUCConfig(void)
> {
> int i;
> + char *val;
>
> for (i = 0; i < num_guc_variables; i++)
> {
> struct config_generic *conf = guc_variables[i];
>
> if ((conf->flags & GUC_NO_SHOW_ALL) == 0)
> ! {
> ! val = _ShowOption(conf);
> ! if(val != NULL)
> ! {
> ! elog(INFO, "%s is %s", conf->name, val);
> ! pfree(val);
> ! }
> ! }
> }
> }
>
> ! /*
> ! * Return GUC variable value by name
> ! */
> ! char *
> ! GetGUCConfigOptionName(const char *name)
> ! {
> ! struct config_generic *record;
> !
> ! record = find_option(name);
> ! if (record == NULL)
> ! elog(ERROR, "Option '%s' is not recognized", name);
> !
> ! return _ShowOption(record);
> ! }
> !
> ! /*
> ! * Return GUC variable value and set varname for a specific
> ! * variable by number.
> ! */
> ! char *
> ! GetGUCConfigOptionNum(int varnum, char **varname)
> ! {
> ! struct config_generic *conf = guc_variables[varnum];
> !
> ! *varname = pstrdup(conf->name);
> !
> ! if ((conf->flags & GUC_NO_SHOW_ALL) == 0)
> ! return _ShowOption(conf);
> ! else
> ! return NULL;
> ! }
> !
> ! /*
> ! * Return the total number of GUC variables
> ! */
> ! int
> ! GetNumGUCConfigOptions(void)
> ! {
> ! return num_guc_variables;
> ! }
> !
> ! static char *
> _ShowOption(struct config_generic *record)
> {
> char buffer[256];
> const char *val;
> + char *retval;
>
> switch (record->vartype)
> {
> ***************
> *** 2297,2303 ****
> break;
> }
>
> ! elog(INFO, "%s is %s", record->name, val);
> }
>
>
> --- 2353,2361 ----
> break;
> }
>
> ! retval = pstrdup(val);
> !
> ! return retval;
> }
>
>
> Index: src/include/utils/guc.h
> ===================================================================
> RCS file: /opt/src/cvs/pgsql/src/include/utils/guc.h,v
> retrieving revision 1.17
> diff -c -r1.17 guc.h
> *** src/include/utils/guc.h 17 May 2002 01:19:19 -0000 1.17
> --- src/include/utils/guc.h 9 Jun 2002 22:45:20 -0000
> ***************
> *** 86,91 ****
> --- 86,94 ----
> bool isLocal, bool DoIt);
> extern void ShowGUCConfigOption(const char *name);
> extern void ShowAllGUCConfig(void);
> + extern char *GetGUCConfigOptionName(const char *name);
> + extern char *GetGUCConfigOptionNum(int varnum, char **varname);
> + extern int GetNumGUCConfigOptions(void);
>
> extern void SetPGVariable(const char *name, List *args, bool is_local);
> extern void GetPGVariable(const char *name);
>

>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/users-lounge/docs/faq.html
>

--
Bruce Momjian | http://candle.pha.pa.us
pgman(at)candle(dot)pha(dot)pa(dot)us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Hiroshi Inoue 2002-06-17 23:59:28 Re: SetQuerySnapshot, once again
Previous Message Bruce Momjian 2002-06-17 21:43:37 Re: Default privileges for new databases (was Re: Can't

Browse pgsql-patches by date

  From Date Subject
Next Message Bruce Momjian 2002-06-17 21:55:46 Re: 2nd revision of SSL patches
Previous Message Bruce Momjian 2002-06-17 21:44:31 Re: [Fwd: C&SRF API patch (was Re: [HACKERS] revised sample