Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cnRkJ-0005EJ-Nc for pgsql-hackers@arkaria.postgresql.org; Mon, 13 Mar 2017 15:18:51 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84_2) (envelope-from ) id 1cnRkJ-0006uJ-76 for pgsql-hackers@arkaria.postgresql.org; Mon, 13 Mar 2017 15:18:51 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1cnRk9-0006hN-V4 for pgsql-hackers@postgresql.org; Mon, 13 Mar 2017 15:18:42 +0000 Received: from sss.pgh.pa.us ([66.207.139.130]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1cnRk7-0007dU-A9 for pgsql-hackers@postgresql.org; Mon, 13 Mar 2017 15:18:40 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.14.4/8.14.4) with ESMTP id v2DFIT32010109; Mon, 13 Mar 2017 11:18:29 -0400 From: Tom Lane To: Corey Huinker cc: Fabien COELHO , Greg Stark , Erik Rijkers , Robert Haas , Daniel Verite , Jim Nasby , PostgreSQL Subject: Re: \if, \elseif, \else, \endif (was Re: PSQL commands: \quit_if, \quit_unless) In-reply-to: <13293.1489279510@sss.pgh.pa.us> References: <13293.1489279510@sss.pgh.pa.us> Comments: In-reply-to Tom Lane message dated "Sat, 11 Mar 2017 19:45:10 -0500" MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-ID: <10062.1489418230.0@sss.pgh.pa.us> Date: Mon, 13 Mar 2017 11:18:29 -0400 Message-ID: <10108.1489418309@sss.pgh.pa.us> X-Pg-Spam-Score: -2.3 (--) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-hackers Precedence: bulk Sender: pgsql-hackers-owner@postgresql.org ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" Content-ID: <10062.1489418230.1@sss.pgh.pa.us> 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 ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name="psql-lexer-callback-passthrough.patch"; charset="us-ascii" Content-ID: <10062.1489418230.2@sss.pgh.pa.us> Content-Description: psql-lexer-callback-passthrough.patch Content-Transfer-Encoding: quoted-printable 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_passthr= ough. + * 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); =20=20 ! extern char *psql_get_variable(const char *varname, bool escape, bool as_= ident); =20=20 extern void psql_error(const char *fmt,...) pg_attribute_printf(1, 2); =20=20 --- 16,23 ---- extern bool openQueryOutputFile(const char *fname, FILE **fout, bool *is_= pipe); extern bool setQFout(const char *fname); =20=20 ! extern char *psql_get_variable(const char *varname, bool escape, bool as_= ident, ! void *passthrough); =20=20 extern void psql_error(const char *fmt,...) pg_attribute_printf(1, 2); =20=20 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 =3D cur_state->callbacks->get_variable(varname, false, ! false); free(varname); =20=20 /* --- 243,250 ---- yyleng - 1); value =3D cur_state->callbacks->get_variable(varname, false, ! false, ! cur_state->cb_passthrough); free(varname); =20=20 /* 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 =3D cur_state->callbacks->get_variable(varname, false, ! false); else value =3D NULL; =20=20 --- 700,707 ---- if (cur_state->callbacks->get_variable) value =3D cur_state->callbacks->get_variable(varname, false, ! false, ! cur_state->cb_passthrough); else value =3D NULL; =20=20 *************** psql_scan_destroy(PsqlScanState state) *** 923,928 **** --- 924,942 ---- } =20=20 /* + * 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 mig= ht + * be useful. + */ + void + psql_scan_set_passthrough(PsqlScanState state, void *passthrough) + { + state->cb_passthrough =3D passthrough; + } +=20 + /* * 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 =3D psqlscan_extract_substring(state, txt + 2, len - 3); if (state->callbacks->get_variable) ! value =3D state->callbacks->get_variable(varname, true, as_ident); else value =3D NULL; free(varname); --- 1423,1430 ---- /* Variable lookup. */ varname =3D psqlscan_extract_substring(state, txt + 2, len - 3); if (state->callbacks->get_variable) ! value =3D state->callbacks->get_variable(varname, true, as_ident, ! state->cb_passthrough); else value =3D NULL; free(varname); diff --git a/src/include/fe_utils/psqlscan.h b/src/include/fe_utils/psqlsca= n.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_iden= t); /* 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); =20=20 + extern void psql_scan_set_passthrough(PsqlScanState state, void *passthro= ugh); +=20 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/psq= lscan_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 */ =20=20 /* ! * Callback functions provided by the program making use of the lexer. */ const PsqlScanCallbacks *callbacks; } PsqlScanStateData; =20=20 =20=20 --- 115,125 ---- char *dolqstart; /* current $foo$ quote start string */ =20=20 /* ! * Callback functions provided by the program making use of the lexer, ! * plus a void* callback passthrough argument. */ const PsqlScanCallbacks *callbacks; + void *cb_passthrough; } PsqlScanStateData; =20=20 =20=20 ------- =_aaaaaaaaaa0 Content-Type: text/plain Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 -- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers ------- =_aaaaaaaaaa0--