From d1ecd539477fe640455dc890216a7c1561e047b4 Mon Sep 17 00:00:00 2001 From: Robert Haas <rhaas@postgresql.org> Date: Tue, 24 Jan 2017 16:59:18 -0500 Subject: [PATCH] Add a SHOW command to the replication command language. This is useful infrastructure for an upcoming proposed patch to allow the WAL segment size to be changed at initdb time; tools like pg_basebackup need the ability to interrogate the server setting. But it also doesn't seem like a bad thing to have independently of that; it may find other uses in the future. Robert Haas and Beena Emerson. (The original patch here was by Beena, but I rewrote it to such a degree that most of the code being committed here is mine.) Discussion: http://postgr.es/m/CA+TgmobNo4qz06wHEmy9DszAre3dYx-WNhHSCbU9SAwf+9Ft6g@mail.gmail.com --- doc/src/sgml/protocol.sgml | 24 ++++++++ src/backend/access/common/tupdesc.c | 79 ++++++++++++++++++++++++++ src/backend/replication/repl_gram.y | 22 ++++++- src/backend/replication/repl_scanner.l | 1 + src/backend/replication/walsender.c | 12 ++++ src/backend/utils/misc/guc.c | 16 +++--- src/include/access/tupdesc.h | 7 +++ 7 files changed, 151 insertions(+), 10 deletions(-) diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml index 5f89db5857..028ef10d91 100644 --- a/doc/src/sgml/protocol.sgml +++ b/doc/src/sgml/protocol.sgml @@ -1393,6 +1393,30 @@ The commands accepted in walsender mode are: </listitem> </varlistentry> + <varlistentry> + <term><literal>SHOW</literal> <replaceable class="parameter">name</replaceable> + <indexterm><primary>SHOW</primary></indexterm> + </term> + <listitem> + <para> + Requests the server to send the current setting of a run-time parameter. + This is similar to the SQL command <xref linkend="sql-show">. + </para> + + <variablelist> + <varlistentry> + <term><replaceable class="parameter">name</></term> + <listitem> + <para> + The name of a run-time parameter. Available parameters are documented + in <xref linkend="runtime-config">. + </para> + </listitem> + </varlistentry> + </variablelist> + </listitem> + </varlistentry> + <varlistentry> <term><literal>TIMELINE_HISTORY</literal> <replaceable class="parameter">tli</replaceable> <indexterm><primary>TIMELINE_HISTORY</primary></indexterm> diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c index 54a32c0223..083c0303dc 100644 --- a/src/backend/access/common/tupdesc.c +++ b/src/backend/access/common/tupdesc.c @@ -20,6 +20,7 @@ #include "postgres.h" #include "access/htup_details.h" +#include "catalog/pg_collation.h" #include "catalog/pg_type.h" #include "miscadmin.h" #include "parser/parse_type.h" @@ -553,6 +554,84 @@ TupleDescInitEntry(TupleDesc desc, ReleaseSysCache(tuple); } +/* + * TupleDescInitBuiltinEntry + * Initialize a tuple descriptor without catalog access. Only + * a limited range of builtin types are supported. + */ +void +TupleDescInitBuiltinEntry(TupleDesc desc, + AttrNumber attributeNumber, + const char *attributeName, + Oid oidtypeid, + int32 typmod, + int attdim) +{ + Form_pg_attribute att; + + /* sanity checks */ + AssertArg(PointerIsValid(desc)); + AssertArg(attributeNumber >= 1); + AssertArg(attributeNumber <= desc->natts); + + /* initialize the attribute fields */ + att = desc->attrs[attributeNumber - 1]; + att->attrelid = 0; /* dummy value */ + + /* unlike TupleDescInitEntry, we require an attribute name */ + Assert(attributeName != NULL); + namestrcpy(&(att->attname), attributeName); + + att->attstattarget = -1; + att->attcacheoff = -1; + att->atttypmod = typmod; + + att->attnum = attributeNumber; + att->attndims = attdim; + + att->attnotnull = false; + att->atthasdef = false; + att->attisdropped = false; + att->attislocal = true; + att->attinhcount = 0; + /* attacl, attoptions and attfdwoptions are not present in tupledescs */ + + att->atttypid = oidtypeid; + + /* + * Our goal here is to support just enough types to let basic builtin + * commands work without catalog access - e.g. so that we can do certain + * things even in processes that are not connected to a database. + */ + switch (oidtypeid) + { + case TEXTOID: + case TEXTARRAYOID: + att->attlen = -1; + att->attbyval = false; + att->attalign = 'i'; + att->attstorage = 'x'; + att->attcollation = DEFAULT_COLLATION_OID; + break; + + case BOOLOID: + att->attlen = 1; + att->attbyval = true; + att->attalign = 'c'; + att->attstorage = 'p'; + att->attcollation = InvalidOid; + break; + + case INT4OID: + att->attlen = 4; + att->attbyval = true; + att->attalign = 'i'; + att->attstorage = 'p'; + att->attcollation = InvalidOid; + break; + } +} + /* * TupleDescInitEntryCollation * diff --git a/src/backend/replication/repl_gram.y b/src/backend/replication/repl_gram.y index d962c76819..b35d0f0cd1 100644 --- a/src/backend/replication/repl_gram.y +++ b/src/backend/replication/repl_gram.y @@ -61,6 +61,7 @@ Node *replication_parse_result; /* Keyword tokens. */ %token K_BASE_BACKUP %token K_IDENTIFY_SYSTEM +%token K_SHOW %token K_START_REPLICATION %token K_CREATE_REPLICATION_SLOT %token K_DROP_REPLICATION_SLOT @@ -82,14 +83,14 @@ Node *replication_parse_result; %type <node> command %type <node> base_backup start_replication start_logical_replication create_replication_slot drop_replication_slot identify_system - timeline_history + timeline_history show %type <list> base_backup_opt_list %type <defelt> base_backup_opt %type <uintval> opt_timeline %type <list> plugin_options plugin_opt_list %type <defelt> plugin_opt_elem %type <node> plugin_opt_arg -%type <str> opt_slot +%type <str> opt_slot var_name %type <boolval> opt_reserve_wal opt_temporary %% @@ -112,6 +113,7 @@ command: | create_replication_slot | drop_replication_slot | timeline_history + | show ; /* @@ -124,6 +126,22 @@ identify_system: } ; +/* + * SHOW setting + */ +show: + K_SHOW var_name + { + VariableShowStmt *n = makeNode(VariableShowStmt); + n->name = $2; + $$ = (Node *) n; + } + +var_name: IDENT { $$ = $1; } + | var_name '.' IDENT + { $$ = psprintf("%s.%s", $1, $3); } + ; + /* * BASE_BACKUP [LABEL '<label>'] [PROGRESS] [FAST] [WAL] [NOWAIT] * [MAX_RATE %d] [TABLESPACE_MAP] diff --git a/src/backend/replication/repl_scanner.l b/src/backend/replication/repl_scanner.l index a3b5f92663..37f857925e 100644 --- a/src/backend/replication/repl_scanner.l +++ b/src/backend/replication/repl_scanner.l @@ -83,6 +83,7 @@ identifier {ident_start}{ident_cont}* BASE_BACKUP { return K_BASE_BACKUP; } FAST { return K_FAST; } IDENTIFY_SYSTEM { return K_IDENTIFY_SYSTEM; } +SHOW { return K_SHOW; } LABEL { return K_LABEL; } NOWAIT { return K_NOWAIT; } PROGRESS { return K_PROGRESS; } diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c index f3082c379a..5909b7dd8c 100644 --- a/src/backend/replication/walsender.c +++ b/src/backend/replication/walsender.c @@ -43,6 +43,7 @@ #include <signal.h> #include <unistd.h> +#include "access/printtup.h" #include "access/timeline.h" #include "access/transam.h" #include "access/xact.h" @@ -72,11 +73,13 @@ #include "storage/pmsignal.h" #include "storage/proc.h" #include "storage/procarray.h" +#include "tcop/dest.h" #include "tcop/tcopprot.h" #include "utils/builtins.h" #include "utils/guc.h" #include "utils/memutils.h" #include "utils/pg_lsn.h" +#include "utils/portal.h" #include "utils/ps_status.h" #include "utils/resowner.h" #include "utils/timeout.h" @@ -1365,6 +1368,15 @@ exec_replication_command(const char *cmd_string) SendTimeLineHistory((TimeLineHistoryCmd *) cmd_node); break; + case T_VariableShowStmt: + { + DestReceiver *dest = CreateDestReceiver(DestRemoteSimple); + VariableShowStmt *n = (VariableShowStmt *) cmd_node; + + GetPGVariable(n->name, dest); + } + break; + default: elog(ERROR, "unrecognized replication command node tag: %u", cmd_node->type); diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 5f43b1ec92..74ca4e7432 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -7878,8 +7878,8 @@ ShowGUCConfigOption(const char *name, DestReceiver *dest) /* need a tuple descriptor representing a single TEXT column */ tupdesc = CreateTemplateTupleDesc(1, false); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, varname, - TEXTOID, -1, 0); + TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, varname, + TEXTOID, -1, 0); /* prepare for projection of tuples */ tstate = begin_tup_output_tupdesc(dest, tupdesc); @@ -7905,12 +7905,12 @@ ShowAllGUCConfig(DestReceiver *dest) /* need a tuple descriptor representing three TEXT columns */ tupdesc = CreateTemplateTupleDesc(3, false); - TupleDescInitEntry(tupdesc, (AttrNumber) 1, "name", - TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 2, "setting", - TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "description", - TEXTOID, -1, 0); + TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 1, "name", + TEXTOID, -1, 0); + TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 2, "setting", + TEXTOID, -1, 0); + TupleDescInitBuiltinEntry(tupdesc, (AttrNumber) 3, "description", + TEXTOID, -1, 0); /* prepare for projection of tuples */ tstate = begin_tup_output_tupdesc(dest, tupdesc); diff --git a/src/include/access/tupdesc.h b/src/include/access/tupdesc.h index 0012877237..b48f839028 100644 --- a/src/include/access/tupdesc.h +++ b/src/include/access/tupdesc.h @@ -119,6 +119,13 @@ extern void TupleDescInitEntry(TupleDesc desc, int32 typmod, int attdim); +extern void TupleDescInitBuiltinEntry(TupleDesc desc, + AttrNumber attributeNumber, + const char *attributeName, + Oid oidtypeid, + int32 typmod, + int attdim); + extern void TupleDescInitEntryCollation(TupleDesc desc, AttrNumber attributeNumber, Oid collationid); -- 2.40.0