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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers