Re: show() function - updated patch - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: show() function - updated patch |
Date | |
Msg-id | 200207191604.g6JG4SJ14007@candle.pha.pa.us Whole thread Raw |
In response to | Re: show() function - updated patch (Joe Conway <mail@joeconway.com>) |
List | 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: > Joe Conway wrote: > > 2. This patch includes the same Table Function API fixes that I > > submitted on July 9: > > > > http://archives.postgresql.org/pgsql-patches/2002-07/msg00056.php > > > > Please disregard that one *if* this one is applied. If this one is > > rejected please go ahead with the July 9th patch. > > The July 9th Table Function API patch mentioned above is now in CVS, so > here is an updated version of the guc patch which should apply cleanly > against CVS tip. > > If there are no objections, please apply. > > Thanks, > > Joe > Index: src/backend/commands/explain.c > =================================================================== > RCS file: /opt/src/cvs/pgsql/src/backend/commands/explain.c,v > retrieving revision 1.80 > diff -c -r1.80 explain.c > *** src/backend/commands/explain.c 20 Jun 2002 20:29:27 -0000 1.80 > --- src/backend/commands/explain.c 18 Jul 2002 17:54:10 -0000 > *************** > *** 15,20 **** > --- 15,21 ---- > #include "access/heapam.h" > #include "catalog/pg_type.h" > #include "commands/explain.h" > + #include "executor/executor.h" > #include "executor/instrument.h" > #include "lib/stringinfo.h" > #include "nodes/print.h" > *************** > *** 38,52 **** > List *rtable; /* range table */ > } ExplainState; > > - typedef struct TextOutputState > - { > - TupleDesc tupdesc; > - DestReceiver *destfunc; > - } TextOutputState; > - > static StringInfo Explain_PlanToString(Plan *plan, ExplainState *es); > static void ExplainOneQuery(Query *query, ExplainStmt *stmt, > ! TextOutputState *tstate); > static void explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, > int indent, ExplainState *es); > static void show_scan_qual(List *qual, bool is_or_qual, const char *qlabel, > --- 39,47 ---- > List *rtable; /* range table */ > } ExplainState; > > static StringInfo Explain_PlanToString(Plan *plan, ExplainState *es); > static void ExplainOneQuery(Query *query, ExplainStmt *stmt, > ! TupOutputState *tstate); > static void explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, > int indent, ExplainState *es); > static void show_scan_qual(List *qual, bool is_or_qual, const char *qlabel, > *************** > *** 59,69 **** > static void show_sort_keys(List *tlist, int nkeys, const char *qlabel, > StringInfo str, int indent, ExplainState *es); > static Node *make_ors_ands_explicit(List *orclauses); > - static TextOutputState *begin_text_output(CommandDest dest, char *title); > - static void do_text_output(TextOutputState *tstate, char *aline); > - static void do_text_output_multiline(TextOutputState *tstate, char *text); > - static void end_text_output(TextOutputState *tstate); > - > > /* > * ExplainQuery - > --- 54,59 ---- > *************** > *** 73,88 **** > ExplainQuery(ExplainStmt *stmt, CommandDest dest) > { > Query *query = stmt->query; > ! TextOutputState *tstate; > List *rewritten; > List *l; > > ! tstate = begin_text_output(dest, "QUERY PLAN"); > > if (query->commandType == CMD_UTILITY) > { > /* rewriter will not cope with utility statements */ > ! do_text_output(tstate, "Utility statements have no plan structure"); > } > else > { > --- 63,85 ---- > ExplainQuery(ExplainStmt *stmt, CommandDest dest) > { > Query *query = stmt->query; > ! TupOutputState *tstate; > ! TupleDesc tupdesc; > List *rewritten; > List *l; > > ! /* need a tuple descriptor representing a single TEXT column */ > ! tupdesc = CreateTemplateTupleDesc(1); > ! TupleDescInitEntry(tupdesc, (AttrNumber) 1, "QUERY PLAN", > ! TEXTOID, -1, 0, false); > ! > ! /* prepare for projection of tuples */ > ! tstate = begin_tup_output_tupdesc(dest, tupdesc); > > if (query->commandType == CMD_UTILITY) > { > /* rewriter will not cope with utility statements */ > ! PROJECT_LINE_OF_TEXT("Utility statements have no plan structure"); > } > else > { > *************** > *** 92,98 **** > if (rewritten == NIL) > { > /* In the case of an INSTEAD NOTHING, tell at least that */ > ! do_text_output(tstate, "Query rewrites to nothing"); > } > else > { > --- 89,95 ---- > if (rewritten == NIL) > { > /* In the case of an INSTEAD NOTHING, tell at least that */ > ! PROJECT_LINE_OF_TEXT("Query rewrites to nothing"); > } > else > { > *************** > *** 102,113 **** > ExplainOneQuery(lfirst(l), stmt, tstate); > /* put a blank line between plans */ > if (lnext(l) != NIL) > ! do_text_output(tstate, ""); > } > } > } > > ! end_text_output(tstate); > } > > /* > --- 99,110 ---- > ExplainOneQuery(lfirst(l), stmt, tstate); > /* put a blank line between plans */ > if (lnext(l) != NIL) > ! PROJECT_LINE_OF_TEXT(""); > } > } > } > > ! end_tup_output(tstate); > } > > /* > *************** > *** 115,121 **** > * print out the execution plan for one query > */ > static void > ! ExplainOneQuery(Query *query, ExplainStmt *stmt, TextOutputState *tstate) > { > Plan *plan; > ExplainState *es; > --- 112,118 ---- > * print out the execution plan for one query > */ > static void > ! ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate) > { > Plan *plan; > ExplainState *es; > *************** > *** 125,133 **** > if (query->commandType == CMD_UTILITY) > { > if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt)) > ! do_text_output(tstate, "NOTIFY"); > else > ! do_text_output(tstate, "UTILITY"); > return; > } > > --- 122,130 ---- > if (query->commandType == CMD_UTILITY) > { > if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt)) > ! PROJECT_LINE_OF_TEXT("NOTIFY"); > else > ! PROJECT_LINE_OF_TEXT("UTILITY"); > return; > } > > *************** > *** 192,198 **** > do_text_output_multiline(tstate, f); > pfree(f); > if (es->printCost) > ! do_text_output(tstate, ""); /* separator line */ > } > } > > --- 189,195 ---- > do_text_output_multiline(tstate, f); > pfree(f); > if (es->printCost) > ! PROJECT_LINE_OF_TEXT(""); /* separator line */ > } > } > > *************** > *** 836,914 **** > > return (Node *) make_orclause(args); > } > - } > - > - > - /* > - * Functions for sending text to the frontend (or other specified destination) > - * as though it is a SELECT result. > - * > - * We tell the frontend that the table structure is a single TEXT column. > - */ > - > - static TextOutputState * > - begin_text_output(CommandDest dest, char *title) > - { > - TextOutputState *tstate; > - TupleDesc tupdesc; > - > - tstate = (TextOutputState *) palloc(sizeof(TextOutputState)); > - > - /* need a tuple descriptor representing a single TEXT column */ > - tupdesc = CreateTemplateTupleDesc(1); > - TupleDescInitEntry(tupdesc, (AttrNumber) 1, title, > - TEXTOID, -1, 0, false); > - > - tstate->tupdesc = tupdesc; > - tstate->destfunc = DestToFunction(dest); > - > - (*tstate->destfunc->setup) (tstate->destfunc, (int) CMD_SELECT, > - NULL, tupdesc); > - > - return tstate; > - } > - > - /* write a single line of text */ > - static void > - do_text_output(TextOutputState *tstate, char *aline) > - { > - HeapTuple tuple; > - Datum values[1]; > - char nulls[1]; > - > - /* form a tuple and send it to the receiver */ > - values[0] = DirectFunctionCall1(textin, CStringGetDatum(aline)); > - nulls[0] = ' '; > - tuple = heap_formtuple(tstate->tupdesc, values, nulls); > - (*tstate->destfunc->receiveTuple) (tuple, > - tstate->tupdesc, > - tstate->destfunc); > - pfree(DatumGetPointer(values[0])); > - heap_freetuple(tuple); > - } > - > - /* write a chunk of text, breaking at newline characters */ > - /* NB: scribbles on its input! */ > - static void > - do_text_output_multiline(TextOutputState *tstate, char *text) > - { > - while (*text) > - { > - char *eol; > - > - eol = strchr(text, '\n'); > - if (eol) > - *eol++ = '\0'; > - else > - eol = text + strlen(text); > - do_text_output(tstate, text); > - text = eol; > - } > - } > - > - static void > - end_text_output(TextOutputState *tstate) > - { > - (*tstate->destfunc->cleanup) (tstate->destfunc); > - pfree(tstate); > } > --- 833,836 ---- > Index: src/backend/executor/execTuples.c > =================================================================== > RCS file: /opt/src/cvs/pgsql/src/backend/executor/execTuples.c,v > retrieving revision 1.54 > diff -c -r1.54 execTuples.c > *** src/backend/executor/execTuples.c 18 Jul 2002 04:40:30 -0000 1.54 > --- src/backend/executor/execTuples.c 18 Jul 2002 17:54:10 -0000 > *************** > *** 790,792 **** > --- 790,862 ---- > return tuple; > } > > + /* > + * Functions for sending tuples to the frontend (or other specified destination) > + * as though it is a SELECT result. These are used by utility commands that > + * need to project directly to the destination and don't need or want full > + * Table Function capability. Currently used by EXPLAIN and SHOW ALL > + */ > + TupOutputState * > + begin_tup_output_tupdesc(CommandDest dest, TupleDesc tupdesc) > + { > + TupOutputState *tstate; > + > + tstate = (TupOutputState *) palloc(sizeof(TupOutputState)); > + > + tstate->tupdesc = tupdesc; > + tstate->destfunc = DestToFunction(dest); > + > + (*tstate->destfunc->setup) (tstate->destfunc, (int) CMD_SELECT, > + NULL, tupdesc); > + > + return tstate; > + } > + > + /* > + * write a single tuple > + * > + * values is a list of the external C string representations of the values > + * to be projected. > + */ > + void > + do_tup_output(TupOutputState *tstate, char **values) > + { > + /* build a tuple from the input strings using the tupdesc */ > + AttInMetadata *attinmeta = TupleDescGetAttInMetadata(tstate->tupdesc); > + HeapTuple tuple = BuildTupleFromCStrings(attinmeta, values); > + > + /* send the tuple to the receiver */ > + (*tstate->destfunc->receiveTuple) (tuple, > + tstate->tupdesc, > + tstate->destfunc); > + /* clean up */ > + heap_freetuple(tuple); > + } > + > + /* write a chunk of text, breaking at newline characters > + * NB: scribbles on its input! > + * Should only be used for a single TEXT attribute tupdesc. > + */ > + void > + do_text_output_multiline(TupOutputState *tstate, char *text) > + { > + while (*text) > + { > + char *eol; > + > + eol = strchr(text, '\n'); > + if (eol) > + *eol++ = '\0'; > + else > + eol = text + strlen(text); > + do_tup_output(tstate, &text); > + text = eol; > + } > + } > + > + void > + end_tup_output(TupOutputState *tstate) > + { > + (*tstate->destfunc->cleanup) (tstate->destfunc); > + pfree(tstate); > + } > Index: src/backend/utils/misc/guc.c > =================================================================== > RCS file: /opt/src/cvs/pgsql/src/backend/utils/misc/guc.c,v > retrieving revision 1.72 > diff -c -r1.72 guc.c > *** src/backend/utils/misc/guc.c 18 Jul 2002 02:02:30 -0000 1.72 > --- src/backend/utils/misc/guc.c 18 Jul 2002 17:54:10 -0000 > *************** > *** 23,30 **** > --- 23,32 ---- > > #include "access/xlog.h" > #include "catalog/namespace.h" > + #include "catalog/pg_type.h" > #include "commands/async.h" > #include "commands/variable.h" > + #include "executor/executor.h" > #include "fmgr.h" > #include "libpq/auth.h" > #include "libpq/pqcomm.h" > *************** > *** 826,832 **** > > > static int guc_var_compare(const void *a, const void *b); > ! static void _ShowOption(struct config_generic *record); > > > /* > --- 828,834 ---- > > > static int guc_var_compare(const void *a, const void *b); > ! static char *_ShowOption(struct config_generic *record); > > > /* > *************** > *** 2168,2173 **** > --- 2170,2226 ---- > } > > /* > + * SET command wrapped as a SQL callable function. > + */ > + Datum > + set_config_by_name(PG_FUNCTION_ARGS) > + { > + char *name; > + char *value; > + char *new_value; > + bool is_local; > + text *result_text; > + > + if (PG_ARGISNULL(0)) > + elog(ERROR, "SET variable name is required"); > + > + /* Get the GUC variable name */ > + name = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0)))); > + > + /* Get the desired value or set to NULL for a reset request */ > + if (PG_ARGISNULL(1)) > + value = NULL; > + else > + value = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(1)))); > + > + /* > + * Get the desired state of is_local. Default to false > + * if provided value is NULL > + */ > + if (PG_ARGISNULL(2)) > + is_local = false; > + else > + is_local = PG_GETARG_BOOL(2); > + > + /* Note SET DEFAULT (argstring == NULL) is equivalent to RESET */ > + set_config_option(name, > + value, > + (superuser() ? PGC_SUSET : PGC_USERSET), > + PGC_S_SESSION, > + is_local, > + true); > + > + /* get the new current value */ > + new_value = GetConfigOptionByName(name); > + > + /* Convert return string to text */ > + result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(new_value))); > + > + /* return it */ > + PG_RETURN_TEXT_P(result_text); > + } > + > + /* > * SHOW command > */ > void > *************** > *** 2203,2215 **** > void > 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); > } > > /* > --- 2256,2281 ---- > void > ShowGUCConfigOption(const char *name) > { > ! TupOutputState *tstate; > ! TupleDesc tupdesc; > ! CommandDest dest = whereToSendOutput; > ! char *value; > ! > ! /* need a tuple descriptor representing a single TEXT column */ > ! tupdesc = CreateTemplateTupleDesc(1); > ! TupleDescInitEntry(tupdesc, (AttrNumber) 1, (char *) name, > ! TEXTOID, -1, 0, false); > ! > ! /* prepare for projection of tuples */ > ! tstate = begin_tup_output_tupdesc(dest, tupdesc); > > ! /* Get the value */ > ! value = GetConfigOptionByName(name); > > ! /* Send it */ > ! PROJECT_LINE_OF_TEXT(value); > ! > ! end_tup_output(tstate); > } > > /* > *************** > *** 2219,2235 **** > 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]; > --- 2285,2399 ---- > ShowAllGUCConfig(void) > { > int i; > + TupOutputState *tstate; > + TupleDesc tupdesc; > + CommandDest dest = whereToSendOutput; > + char *name; > + char *value; > + char *values[2]; > + > + /* need a tuple descriptor representing two TEXT columns */ > + tupdesc = CreateTemplateTupleDesc(2); > + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name", > + TEXTOID, -1, 0, false); > + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting", > + TEXTOID, -1, 0, false); > + > + /* prepare for projection of tuples */ > + tstate = begin_tup_output_tupdesc(dest, tupdesc); > > for (i = 0; i < num_guc_variables; i++) > { > ! /* Get the next GUC variable name and value */ > ! value = GetConfigOptionByNum(i, &name); > > ! /* assign to the values array */ > ! values[0] = name; > ! values[1] = value; > ! > ! /* send it to dest */ > ! do_tup_output(tstate, values); > ! > ! /* > ! * clean up > ! */ > ! /* we always should have a name */ > ! pfree(name); > ! > ! /* but value can be returned to us as a NULL */ > ! if (value != NULL) > ! pfree(value); > } > + > + end_tup_output(tstate); > } > > ! /* > ! * Return GUC variable value by name > ! */ > ! char * > ! GetConfigOptionByName(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 * > ! GetConfigOptionByNum(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 > ! GetNumConfigOptions(void) > ! { > ! return num_guc_variables; > ! } > ! > ! /* > ! * show_config_by_name - equiv to SHOW X command but implemented as > ! * a function. > ! */ > ! Datum > ! show_config_by_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 = GetConfigOptionByName(varname); > ! > ! /* Convert to text */ > ! result_text = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(varval))); > ! > ! /* return it */ > ! PG_RETURN_TEXT_P(result_text); > ! } > ! > ! static char * > _ShowOption(struct config_generic *record) > { > char buffer[256]; > *************** > *** 2297,2303 **** > break; > } > > ! elog(INFO, "%s is %s", record->name, val); > } > > > --- 2461,2467 ---- > break; > } > > ! return pstrdup(val); > } > > > Index: src/include/catalog/pg_proc.h > =================================================================== > RCS file: /opt/src/cvs/pgsql/src/include/catalog/pg_proc.h,v > retrieving revision 1.243 > diff -c -r1.243 pg_proc.h > *** src/include/catalog/pg_proc.h 20 Jun 2002 20:29:44 -0000 1.243 > --- src/include/catalog/pg_proc.h 18 Jul 2002 17:54:10 -0000 > *************** > *** 2881,2886 **** > --- 2881,2891 ---- > DATA(insert OID = 2074 ( substring PGNSP PGUID 14 f f f t f i 3 25 "25 25 25" 100 0 0 100 "select substring($1,like_escape($2, $3))" - _null_ )); > DESCR("substitutes regular expression with escape argument"); > > + DATA(insert OID = 2090 ( current_setting PGNSP PGUID 12 f f f t f s 1 25 "25" 100 0 0 100 show_config_by_name - _null_)); > + DESCR("SHOW X as a function"); > + DATA(insert OID = 2091 ( set_config PGNSP PGUID 12 f f f f f v 3 25 "25 25 16" 100 0 0 100 set_config_by_name- _null_ )); > + DESCR("SET X as a function"); > + > /* Aggregates (moved here from pg_aggregate for 7.3) */ > > DATA(insert OID = 2100 ( avg PGNSP PGUID 12 t f f f f i 1 1700 "20" 100 0 0 100 aggregate_dummy - _null_)); > Index: src/include/executor/executor.h > =================================================================== > RCS file: /opt/src/cvs/pgsql/src/include/executor/executor.h,v > retrieving revision 1.69 > diff -c -r1.69 executor.h > *** src/include/executor/executor.h 26 Jun 2002 21:58:56 -0000 1.69 > --- src/include/executor/executor.h 18 Jul 2002 17:54:10 -0000 > *************** > *** 121,126 **** > --- 121,145 ---- > extern TupleDesc ExecTypeFromTL(List *targetList); > extern void SetChangedParamList(Plan *node, List *newchg); > > + typedef struct TupOutputState > + { > + TupleDesc tupdesc; > + DestReceiver *destfunc; > + } TupOutputState; > + > + extern TupOutputState *begin_tup_output_tupdesc(CommandDest dest, TupleDesc tupdesc); > + extern void do_tup_output(TupOutputState *tstate, char **values); > + extern void do_text_output_multiline(TupOutputState *tstate, char *text); > + extern void end_tup_output(TupOutputState *tstate); > + > + #define PROJECT_LINE_OF_TEXT(text_to_project) \ > + do { \ > + char *values[1]; \ > + values[0] = text_to_project; \ > + do_tup_output(tstate, values); \ > + } while (0) > + > + > /* > * prototypes from functions in execUtils.c > */ > Index: src/include/utils/builtins.h > =================================================================== > RCS file: /opt/src/cvs/pgsql/src/include/utils/builtins.h,v > retrieving revision 1.186 > diff -c -r1.186 builtins.h > *** src/include/utils/builtins.h 20 Jun 2002 20:29:52 -0000 1.186 > --- src/include/utils/builtins.h 18 Jul 2002 17:54:10 -0000 > *************** > *** 633,636 **** > --- 633,640 ---- > extern Datum quote_ident(PG_FUNCTION_ARGS); > extern Datum quote_literal(PG_FUNCTION_ARGS); > > + /* guc.c */ > + extern Datum show_config_by_name(PG_FUNCTION_ARGS); > + extern Datum set_config_by_name(PG_FUNCTION_ARGS); > + > #endif /* BUILTINS_H */ > 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 18 Jul 2002 17:54:10 -0000 > *************** > *** 86,91 **** > --- 86,94 ---- > bool isLocal, bool DoIt); > extern void ShowGUCConfigOption(const char *name); > extern void ShowAllGUCConfig(void); > + extern char *GetConfigOptionByName(const char *name); > + extern char *GetConfigOptionByNum(int varnum, char **varname); > + extern int GetNumConfigOptions(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@candle.pha.pa.us | (610) 853-3000 + If your life is a hard drive, | 830 Blythe Avenue + Christ can be your backup. | Drexel Hill, Pennsylvania 19026
pgsql-patches by date: