From 895e36bb3f36fdb7ec8e573be1a20d104fac820b Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 13 Mar 2017 17:14:46 -0400 Subject: [PATCH] Add a "void *" passthrough pointer for psqlscan.l's callback functions. The immediate motivation for this is to provide clean infrastructure for the proposed \if...\endif patch for psql; but it seems like a good thing to have even if that patch doesn't get in. Previously the callback functions could only make use of application-global state, which is a pretty severe handicap. For the moment, the pointer is only passed through to the get_variable callback function. I considered also passing it to the write_error callback, but for now let's not. Neither psql nor pgbench has a use for that, 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(). Discussion: https://postgr.es/m/10108.1489418309@sss.pgh.pa.us --- src/bin/psql/common.c | 6 +++++- src/bin/psql/common.h | 3 ++- src/bin/psql/psqlscanslash.l | 3 ++- src/fe_utils/psqlscan.l | 19 +++++++++++++++++-- src/include/fe_utils/psqlscan.h | 5 ++++- src/include/fe_utils/psqlscan_int.h | 4 +++- 6 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index 1aa56ab3a2..e9d4fe6786 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -119,9 +119,13 @@ setQFout(const char *fname) * 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) +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 a83bc69ab7..3d8b8da7fe 100644 --- a/src/bin/psql/common.h +++ b/src/bin/psql/common.h @@ -16,7 +16,8 @@ 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 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 5b7953bf7b..ba4a08d000 100644 --- a/src/bin/psql/psqlscanslash.l +++ b/src/bin/psql/psqlscanslash.l @@ -243,7 +243,8 @@ other . yyleng - 1); value = cur_state->callbacks->get_variable(varname, false, - false); + false, + cur_state->cb_passthrough); free(varname); /* diff --git a/src/fe_utils/psqlscan.l b/src/fe_utils/psqlscan.l index 1b29341fa8..19b3e57aa4 100644 --- a/src/fe_utils/psqlscan.l +++ b/src/fe_utils/psqlscan.l @@ -700,7 +700,8 @@ other . if (cur_state->callbacks->get_variable) value = cur_state->callbacks->get_variable(varname, false, - false); + false, + cur_state->cb_passthrough); else value = NULL; @@ -922,6 +923,19 @@ psql_scan_destroy(PsqlScanState state) free(state); } +/* + * 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. * @@ -1409,7 +1423,8 @@ psqlscan_escape_variable(PsqlScanState state, const char *txt, int len, /* 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); + 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 21c4f227a1..0cc632b821 100644 --- a/src/include/fe_utils/psqlscan.h +++ b/src/include/fe_utils/psqlscan.h @@ -53,7 +53,8 @@ typedef struct PsqlScanCallbacks { /* 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); + 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 @@ -67,6 +68,8 @@ typedef struct PsqlScanCallbacks 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 0fddc7a856..b4044e806a 100644 --- a/src/include/fe_utils/psqlscan_int.h +++ b/src/include/fe_utils/psqlscan_int.h @@ -115,9 +115,11 @@ typedef struct PsqlScanStateData char *dolqstart; /* current $foo$ quote start string */ /* - * Callback functions provided by the program making use of the lexer. + * Callback functions provided by the program making use of the lexer, + * plus a void* callback passthrough argument. */ const PsqlScanCallbacks *callbacks; + void *cb_passthrough; } PsqlScanStateData; -- 2.39.5