From: Tom Lane <tgl@sss.pgh.pa.us>
To: Corey Huinker <corey.huinker@gmail.com>
Cc: Fabien COELHO <coelho@cri.ensmp.fr>
Cc: Greg Stark <stark@mit.edu>
Cc: Erik Rijkers <er@xs4all.nl>
Cc: Robert Haas <robertmhaas@gmail.com>
Cc: Daniel Verite <daniel@manitou-mail.org>
Cc: Jim Nasby <Jim.Nasby@bluetreble.com>
Cc: PostgreSQL <pgsql-hackers@postgresql.org>
Subject: Re: \if, \elseif, \else, \endif (was Re: PSQL commands: \quit_if, \quit_unless)
Date: Mon, 13 Mar 2017 11:18:29 -0400
Message-ID: <10108.1489418309@sss.pgh.pa.us> (raw)
In-Reply-To: <13293.1489279510@sss.pgh.pa.us>
References: <CADkLM=dcMHeSOQZv0Dd8AO4cM+OzADg7u8PcA7d8pNezmLDo=g@mail.gmail.com>
<CADkLM=c_DDcUXadhfPL4Qcb9QxWbwP6OW_pL=TffLGw=PDiWPQ@mail.gmail.com>
<alpine.DEB.2.20.1702240729060.21598@lancre>
<CADkLM=edWn9Kfj10BUAr4VTkLxAmkAc_u0_6AfjHTBC6phmhRQ@mail.gmail.com>
<alpine.DEB.2.20.1702260807540.10344@lancre>
<CADkLM=dwGETiOV=3J=7JGM=acoMRgHz2CnrETek-wdYYE6AuJQ@mail.gmail.com>
<CADkLM=eLwZHnK82E=qtLMxWy_UDJe-XUMUK1xABPgSP386H4Qw@mail.gmail.com>
<alpine.DEB.2.20.1703010851190.762@lancre>
<CADkLM=fCuLWGxEqmWrOk2tZWEi0bAU6xO58+O5-VxLWpnFFhoA@mail.gmail.com>
<alpine.DEB.2.20.1703011742300.762@lancre>
<CADkLM=eeyM_5eFyty6S_VDK-rJXNaKPJmB5mELC04n1xfWZK=Q@mail.gmail.com>
<alpine.DEB.2.20.1703020710260.762@lancre>
<CADkLM=e9BY_-PT96mcs4qqiLtt8t-Fp=e_AdycW-aS0OQvbC9Q@mail.gmail.com>
<alpine.DEB.2.20.1703021042470.21981@lancre>
<CADkLM=e3vpXixqQd9X_wD0LVL1vkrq4oPu33xzsTr3CokSRnWA@mail.gmail.com>
<alpine.DEB.2.20.1703030709210.12372@lancre>
<alpine.DEB.2.20.1703030723050.12372@lancre>
<C! ADkLM=dLtw4GtfbZM=jTgsp3nQ1r6DcSque-DxV7fJ0rYqhyRw@mail.gmail.com>
<13293.1489279510@sss.pgh.pa.us>
List-Unsubscribe: <mailto:majordomo@postgresql.org?body=unsub%20pgsql-hackers>
I wrote:
> IIRC, I objected to putting knowledge of ConditionalStack
> into the shared psqlscan.l lexer, and I still think that would be a bad
> idea; but we need some way to get the lexer to shut that off. Probably
> the best way is to add a passthrough "void *" argument that would let the
> get_variable callback function mechanize the rule about not expanding
> in a false branch.
Here's a proposed patch that adds a passthrough of this sort.
The passthrough argument is passed only to the get_variable callback.
I dithered about whether to also pass it to the write_error callback,
but ultimately decided not to for now. Neither psql nor pgbench wants it,
and in the case of psql we'd have to invent a separate wrapper function
because we would certainly not want to change the signature of
psql_error().
Barring objection I'll push this so that Corey can rebase over it.
regards, tom lane
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackersAttachments:
[text/x-diff] psql-lexer-callback-passthrough.patch (6.5K, ../10108.1489418309@sss.pgh.pa.us/2-psql-lexer-callback-passthrough.patch)
download | inline diff:diff --git a/src/bin/psql/common.c b/src/bin/psql/common.cindex 1aa56ab..e9d4fe6 100644
*** a/src/bin/psql/common.c
--- b/src/bin/psql/common.c
*************** setQFout(const char *fname)
*** 119,127 ****
* If "escape" is true, return the value suitably quoted and escaped,
* as an identifier or string literal depending on "as_ident".
* (Failure in escaping should lead to returning NULL.)
*/
char *
! psql_get_variable(const char *varname, bool escape, bool as_ident)
{
char *result;
const char *value;
--- 119,131 ----
* If "escape" is true, return the value suitably quoted and escaped,
* as an identifier or string literal depending on "as_ident".
* (Failure in escaping should lead to returning NULL.)
+ *+ * "passthrough" is the pointer previously given to psql_scan_set_passthrough.+ * psql currently doesn't use this.
*/
char *
! psql_get_variable(const char *varname, bool escape, bool as_ident,
! void *passthrough)
{
char *result;
const char *value;
diff --git a/src/bin/psql/common.h b/src/bin/psql/common.hindex a83bc69..3d8b8da 100644
*** a/src/bin/psql/common.h
--- b/src/bin/psql/common.h
***************
*** 16,22 ****
extern bool openQueryOutputFile(const char *fname, FILE **fout, bool *is_pipe);
extern bool setQFout(const char *fname);
! extern char *psql_get_variable(const char *varname, bool escape, bool as_ident);
extern void psql_error(const char *fmt,...) pg_attribute_printf(1, 2);
--- 16,23 ----
extern bool openQueryOutputFile(const char *fname, FILE **fout, bool *is_pipe);
extern bool setQFout(const char *fname);
! extern char *psql_get_variable(const char *varname, bool escape, bool as_ident,
! void *passthrough);
extern void psql_error(const char *fmt,...) pg_attribute_printf(1, 2);
diff --git a/src/bin/psql/psqlscanslash.l b/src/bin/psql/psqlscanslash.lindex 5b7953b..ba4a08d 100644
*** a/src/bin/psql/psqlscanslash.l
--- b/src/bin/psql/psqlscanslash.l
*************** other .
*** 243,249 ****
yyleng - 1);
value = cur_state->callbacks->get_variable(varname,
false,
! false);
free(varname);
/*
--- 243,250 ----
yyleng - 1);
value = cur_state->callbacks->get_variable(varname,
false,
! false,
! cur_state->cb_passthrough);
free(varname);
/*
diff --git a/src/fe_utils/psqlscan.l b/src/fe_utils/psqlscan.lindex 1b29341..19b3e57 100644
*** a/src/fe_utils/psqlscan.l
--- b/src/fe_utils/psqlscan.l
*************** other .
*** 700,706 ****
if (cur_state->callbacks->get_variable)
value = cur_state->callbacks->get_variable(varname,
false,
! false);
else
value = NULL;
--- 700,707 ----
if (cur_state->callbacks->get_variable)
value = cur_state->callbacks->get_variable(varname,
false,
! false,
! cur_state->cb_passthrough);
else
value = NULL;
*************** psql_scan_destroy(PsqlScanState state)
*** 923,928 ****
--- 924,942 ----
}
/*
+ * Set the callback passthrough pointer for the lexer.+ *+ * This could have been integrated into psql_scan_create, but keeping it+ * separate allows the application to change the pointer later, which might+ * be useful.+ */+ void+ psql_scan_set_passthrough(PsqlScanState state, void *passthrough)+ {+ state->cb_passthrough = passthrough;+ }+ + /*
* Set up to perform lexing of the given input line.
*
* The text at *line, extending for line_len bytes, will be scanned by
*************** psqlscan_escape_variable(PsqlScanState s
*** 1409,1415 ****
/* Variable lookup. */
varname = psqlscan_extract_substring(state, txt + 2, len - 3);
if (state->callbacks->get_variable)
! value = state->callbacks->get_variable(varname, true, as_ident);
else
value = NULL;
free(varname);
--- 1423,1430 ----
/* Variable lookup. */
varname = psqlscan_extract_substring(state, txt + 2, len - 3);
if (state->callbacks->get_variable)
! value = state->callbacks->get_variable(varname, true, as_ident,
! state->cb_passthrough);
else
value = NULL;
free(varname);
diff --git a/src/include/fe_utils/psqlscan.h b/src/include/fe_utils/psqlscan.hindex 21c4f22..0cc632b 100644
*** a/src/include/fe_utils/psqlscan.h
--- b/src/include/fe_utils/psqlscan.h
*************** typedef struct PsqlScanCallbacks
*** 53,59 ****
{
/* Fetch value of a variable, as a pfree'able string; NULL if unknown */
/* This pointer can be NULL if no variable substitution is wanted */
! char *(*get_variable) (const char *varname, bool escape, bool as_ident);
/* Print an error message someplace appropriate */
/* (very old gcc versions don't support attributes on function pointers) */
#if defined(__GNUC__) && __GNUC__ < 4
--- 53,60 ----
{
/* Fetch value of a variable, as a pfree'able string; NULL if unknown */
/* This pointer can be NULL if no variable substitution is wanted */
! char *(*get_variable) (const char *varname, bool escape,
! bool as_ident, void *passthrough);
/* Print an error message someplace appropriate */
/* (very old gcc versions don't support attributes on function pointers) */
#if defined(__GNUC__) && __GNUC__ < 4
*************** typedef struct PsqlScanCallbacks
*** 67,72 ****
--- 68,75 ----
extern PsqlScanState psql_scan_create(const PsqlScanCallbacks *callbacks);
extern void psql_scan_destroy(PsqlScanState state);
+ extern void psql_scan_set_passthrough(PsqlScanState state, void *passthrough);+
extern void psql_scan_setup(PsqlScanState state,
const char *line, int line_len,
int encoding, bool std_strings);
diff --git a/src/include/fe_utils/psqlscan_int.h b/src/include/fe_utils/psqlscan_int.hindex 0fddc7a..b4044e8 100644
*** a/src/include/fe_utils/psqlscan_int.h
--- b/src/include/fe_utils/psqlscan_int.h
*************** typedef struct PsqlScanStateData
*** 115,123 ****
char *dolqstart; /* current $foo$ quote start string */
/*
! * Callback functions provided by the program making use of the lexer.
*/
const PsqlScanCallbacks *callbacks;
} PsqlScanStateData;
--- 115,125 ----
char *dolqstart; /* current $foo$ quote start string */
/*
! * Callback functions provided by the program making use of the lexer,
! * plus a void* callback passthrough argument.
*/
const PsqlScanCallbacks *callbacks;
+ void *cb_passthrough;
} PsqlScanStateData;
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: tgl@sss.pgh.pa.us, corey.huinker@gmail.com, coelho@cri.ensmp.fr, stark@mit.edu, er@xs4all.nl, robertmhaas@gmail.com, daniel@manitou-mail.org, Jim.Nasby@bluetreble.com
Subject: Re: \if, \elseif, \else, \endif (was Re: PSQL commands: \quit_if, \quit_unless)
In-Reply-To: <10108.1489418309@sss.pgh.pa.us>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox