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)  (Corey Huinker <corey.huinker@gmail.com>)
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:

Previous
From: David Steele
Date:
Subject: Re: [HACKERS] [PATCH] ALTER DEFAULT PRIVILEGES with GRANT/REVOKE ON SCHEMAS
Next
From: David Steele
Date:
Subject: Re: [HACKERS] tuplesort_gettuple_common() and *should_free argument