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

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;
  
  
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to