pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
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-hackers

Attachments:

  [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.c
index 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.h
index 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.l
index 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.l
index 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.h
index 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.h
index 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;
  
  

view thread (232+ messages)  latest in thread

Message-ID: <10108.1489418309@sss.pgh.pa.us>
Permalink:  ../10108.1489418309@sss.pgh.pa.us/
Also on:    postgresql.org/message-id/10108.1489418309@sss.pgh.pa.us

 ·  · 

reply

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