Re: [HACKERS] \if, \elseif, \else, \endif (was Re: PSQL commands: \quit_if, \quit_unless) - Mailing list pgsql-hackers
From | Tom Lane |
---|---|
Subject | Re: [HACKERS] \if, \elseif, \else, \endif (was Re: PSQL commands: \quit_if, \quit_unless) |
Date | |
Msg-id | 10108.1489418309@sss.pgh.pa.us Whole thread Raw |
In response to | Re: [HACKERS] \if, \elseif, \else, \endif (was Re: PSQL commands: \quit_if, \quit_unless) (Tom Lane <tgl@sss.pgh.pa.us>) |
Responses |
Re: [HACKERS] \if, \elseif, \else, \endif (was Re: PSQL commands:\quit_if, \quit_unless)
|
List | pgsql-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 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
pgsql-hackers by date: